File

src/app/app.component.ts

Description

App component

Implements

OnDestroy OnInit

Metadata

Index

Properties
Methods
HostListeners
Accessors

Constructor

constructor(model: ModelState, page: PageState, consentService: ConsentService, snackbar: MatSnackBar, theming: ThemingService, el: ElementRef<>, injector: Injector, globalConfig: GlobalConfigState, cdr: ChangeDetectorRef)
Parameters :
Name Type Optional
model ModelState No
page PageState No
consentService ConsentService No
snackbar MatSnackBar No
theming ThemingService No
el ElementRef<> No
injector Injector No
globalConfig GlobalConfigState<AppOptions> No
cdr ChangeDetectorRef No

HostListeners

document:keydown
Arguments : '$event'
document:keydown(target: KeyboardEvent)

Shifts block position when certain keys are pressed

Parameters :
Name Optional Description
target No

The keyboard event

document:mousedown
Arguments : '$event.target'
document:mousedown(target: HTMLElement)

Disables block position change if an input element is clicked

Parameters :
Name Optional Description
target No

The element clicked

Methods

handleClick
handleClick(target: HTMLElement)
Decorators :
@HostListener('document:mousedown', ['$event.target'])

Disables block position change if an input element is clicked

Parameters :
Name Type Optional Description
target HTMLElement No

The element clicked

Returns : void
handleKey
handleKey(target: KeyboardEvent)
Decorators :
@HostListener('document:keydown', ['$event'])

Shifts block position when certain keys are pressed

Parameters :
Name Type Optional Description
target KeyboardEvent No

The keyboard event

Returns : void
registrationToggle
registrationToggle(event: boolean)
Parameters :
Name Type Optional
event boolean No
Returns : void
toggleScheme
toggleScheme()

Toggles scheme between light and dark mode

Returns : void

Properties

disablePositionChange
Default value : false

Disables changes in block position

Readonly header$
Default value : this.globalConfig.getOption('header')
homeUrl
Type : string
Readonly homeUrl$
Default value : this.globalConfig.getOption('homeUrl')
logoTooltip
Type : string
Readonly logoTooltip$
Default value : this.globalConfig.getOption('logoTooltip')
registrationExpanded
Default value : false
registrationStarted
Default value : false

False until the initial registration modal is closed

theme
Type : string
Readonly theme$
Default value : this.globalConfig.getOption('theme')
Readonly themeMode$
Default value : new ReplaySubject<'light' | 'dark'>(1)

Accessors

isLightTheme
getisLightTheme()
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef,
  HostListener,
  Injector,
  OnDestroy,
  OnInit,
} from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { GlobalConfigState, TrackingPopupComponent } from 'ccf-shared';
import { ConsentService } from 'ccf-shared/analytics';
import { ReplaySubject, Subscription, combineLatest } from 'rxjs';

import { GlobalConfig } from './core/services/config/config';
import { ThemingService } from './core/services/theming/theming.service';
import { ModelState } from './core/store/model/model.state';
import { PageState } from './core/store/page/page.state';

export interface User {
  firstName: string;
  lastName: string;
}

interface AppOptions extends GlobalConfig {
  theme?: string;
  header?: boolean;
  homeUrl?: string;
  logoTooltip?: string;
}

/**
 * App component
 */
@Component({
  selector: 'ccf-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnDestroy, OnInit {
  /** False until the initial registration modal is closed */
  registrationStarted = false;

  /** Disables changes in block position */
  disablePositionChange = false;

  registrationExpanded = false;

  get isLightTheme(): boolean {
    return this.theming.getTheme().endsWith('light');
  }

  readonly theme$ = this.globalConfig.getOption('theme');
  readonly themeMode$ = new ReplaySubject<'light' | 'dark'>(1);

  readonly header$ = this.globalConfig.getOption('header');
  readonly homeUrl$ = this.globalConfig.getOption('homeUrl');
  readonly logoTooltip$ = this.globalConfig.getOption('logoTooltip');

  theme!: string;

  homeUrl!: string;

  logoTooltip!: string;

  /** All subscriptions managed by the container. */
  private readonly subscriptions = new Subscription();

  constructor(
    readonly model: ModelState,
    readonly page: PageState,
    readonly consentService: ConsentService,
    readonly snackbar: MatSnackBar,
    readonly theming: ThemingService,
    el: ElementRef<unknown>,
    injector: Injector,
    private readonly globalConfig: GlobalConfigState<AppOptions>,
    cdr: ChangeDetectorRef,
  ) {
    theming.initialize(el, injector);
    this.subscriptions.add(
      page.registrationStarted$.subscribe((registrationStarted) => {
        this.registrationStarted = registrationStarted;
      }),
    );
    this.theme$.subscribe((theme) => {
      this.theme = theme ?? 'light';
    });
    this.globalConfig.getOption('homeUrl').subscribe((url) => {
      this.homeUrl = url ?? '';
    });
    this.globalConfig.getOption('logoTooltip').subscribe((tooltip) => {
      this.logoTooltip = tooltip ?? '';
    });

    combineLatest([this.theme$, this.themeMode$]).subscribe(([theme, mode]) => {
      this.theming.setTheme(`${theme}-theme-${mode}`);
      cdr.markForCheck();
    });
  }

  ngOnInit(): void {
    const snackBar = this.snackbar.openFromComponent(TrackingPopupComponent, {
      data: {
        preClose: () => {
          snackBar.dismiss();
        },
      },
      duration: this.consentService.consent === 'not-set' ? Infinity : 3000,
    });

    this.themeMode$.next('light');

    this.theming.setTheme(`${this.theme}-theme-light`);
  }

  /**
   * Toggles scheme between light and dark mode
   */
  toggleScheme(): void {
    this.themeMode$.next(this.isLightTheme ? 'dark' : 'light');
  }

  registrationToggle(event: boolean): void {
    this.registrationExpanded = event;
    if (!this.registrationExpanded) {
      this.disablePositionChange = false;
    }
  }

  /**
   * Shifts block position when certain keys are pressed
   *
   * @param target The keyboard event
   */
  @HostListener('document:keydown', ['$event'])
  handleKey(target: KeyboardEvent): void {
    const oldPosition = this.model.snapshot.position;
    if (this.disablePositionChange || !this.registrationStarted) {
      return;
    }
    target.preventDefault();
    const delta = target.repeat ? 1.0 : 0.5;
    let newPosition = oldPosition;
    switch (target.key) {
      case 'q':
        newPosition = { ...oldPosition, z: oldPosition.z + delta };
        break;
      case 'e':
        newPosition = { ...oldPosition, z: oldPosition.z - delta };
        break;
      case 'w':
        newPosition = { ...oldPosition, y: oldPosition.y + delta };
        break;
      case 's':
        newPosition = { ...oldPosition, y: oldPosition.y - delta };
        break;
      case 'a':
        newPosition = { ...oldPosition, x: oldPosition.x - delta };
        break;
      case 'd':
        newPosition = { ...oldPosition, x: oldPosition.x + delta };
        break;
      default:
        break;
    }
    this.model.setPosition(newPosition);
  }

  /**
   * Disables block position change if an input element is clicked
   *
   * @param target The element clicked
   */
  @HostListener('document:mousedown', ['$event.target'])
  handleClick(target: HTMLElement): void {
    const disableWhenClicked = ['mat-mdc-input-element', 'form-input-label'];
    for (const className of disableWhenClicked) {
      if (typeof target.className === 'string' && target.className.includes(className)) {
        this.disablePositionChange = true;
        return;
      }
    }
    this.disablePositionChange = false;
  }

  /**
   * Cleans up all subscriptions.
   */
  ngOnDestroy(): void {
    this.subscriptions.unsubscribe();
  }
}
<ccf-registration-modal></ccf-registration-modal>
<ccf-header
  [class.header-hidden]="(header$ | async) === false"
  [logoTooltip]="(logoTooltip$ | async) ?? ''"
  [homeUrl]="(homeUrl$ | async) ?? ''"
></ccf-header>

<ccf-drawer-container>
  <ccf-drawer opened>
    <ccf-left-sidebar [modalClosed]="registrationStarted"> </ccf-left-sidebar>
    <ccf-drawer-toggle-button></ccf-drawer-toggle-button>
  </ccf-drawer>
  <ccf-drawer position="end" opened>
    <ccf-right-sidebar
      [modalClosed]="registrationStarted"
      (registrationExpanded)="registrationToggle($event)"
    ></ccf-right-sidebar>
    <ccf-drawer-toggle-button></ccf-drawer-toggle-button>
  </ccf-drawer>

  <ccf-drawer-content>
    <ccf-content class="stage-content" [disablePositionChange]="disablePositionChange"></ccf-content>
  </ccf-drawer-content>
</ccf-drawer-container>

./app.component.scss

:host {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  font-size: 1rem;
  color: black;

  .header-hidden {
    display: none;
  }

  ccf-drawer-container {
    height: 100%;

    ccf-drawer {
      width: 25.5rem;
    }

    ccf-drawer-content {
      position: relative;
      z-index: 1;

      .selector-drawer {
        top: 0rem;
        display: flex;
        flex-direction: column;
        position: relative;
        height: 5.688rem;
        transition: all 0.5s ease-in-out;

        &.expanded {
          height: 15rem;
        }

        ccf-organ-selector {
          height: 100%;
          padding-top: 0.5rem;
          transition: all 0.5s;

          &.closed {
            padding-top: 0;
          }
        }

        .close-button-wrapper {
          display: flex;
          justify-content: center;
          height: 0;
          z-index: 2;

          .close-button {
            cursor: pointer;
            transition: 0.6s;

            .expand-collapse-icon {
              width: 3rem;
              height: 1.2rem;
              display: flex;
              justify-content: center;
              align-items: center;
              cursor: pointer;
              background-color: white;
              border-bottom-left-radius: 0.2rem;
              border-bottom-right-radius: 0.2rem;
              transition: 0.6s;

              &:hover {
                background-color: #ececec;
              }
            }
          }
        }

        &.closed {
          height: 3rem;
          top: -2.9rem;
        }
      }

      .stage-content {
        border-radius: 0.5rem;
        height: calc(100% - 2.5rem);
      }

      .expanded-stage {
        height: calc(100% - 1.5rem);
        padding-bottom: 1rem;
      }

      .retracted-stage {
        height: calc(100% - 2.688rem - 14rem);
      }
    }

    ccf-content {
      // top: 0rem;
      position: absolute;
      transition-duration: 0.5s;
      transition-timing-function: ease-in-out;
      transition-property: all;
      bottom: 1.5rem;
      z-index: 1;
    }
  }
}

::ng-deep .mdc-snackbar__surface {
  box-shadow: none !important;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""