File

libs/common/frame/src/services/frame-layout.service.ts

Index

Properties
Methods

Constructor

constructor(viewportService: NxViewportService, _channel: CHANNEL)
Parameters :
Name Type Optional
viewportService NxViewportService No
_channel CHANNEL No

Methods

init
init()
Returns : void
toggleNavigation
toggleNavigation(force?: boolean)
Parameters :
Name Type Optional
force boolean Yes
Returns : void

Properties

collapseNavigationUser$
Type : Observable<boolean>
compactNavigationBreakpoint$
Type : Observable<boolean>
hideSidebarBreakpoint$
Type : Observable<boolean>
isStackedLayoutObservable
Type : Observable<boolean>
import { CHANNEL, CHANNEL_TOKEN } from '@allianz/taly-core';
import { Inject, Injectable } from '@angular/core';
import { NxBreakpoints, NxViewportService } from '@aposin/ng-aquila/utils';
import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged, map, scan, startWith } from 'rxjs/operators';

const createBreakpointFactory = (service: NxViewportService) => (breakpoint: NxBreakpoints) => {
  return service
    .max(breakpoint)
    .pipe(startWith(window.innerWidth <= breakpoint), distinctUntilChanged());
};

@Injectable()
export class TalyFrameLayoutService {
  isStackedLayoutObservable!: Observable<boolean>;
  compactNavigationBreakpoint$!: Observable<boolean>;

  private _collapseNavigationUser$ = new Subject<boolean | undefined>();
  collapseNavigationUser$!: Observable<boolean>;

  hideSidebarBreakpoint$!: Observable<boolean>;

  constructor(
    private viewportService: NxViewportService,
    @Inject(CHANNEL_TOKEN) private _channel: CHANNEL
  ) {
    this.init();
  }

  init() {
    const breakpointFactory = createBreakpointFactory(this.viewportService);

    /**
     * this will be forwarded to the navigation to make it very compact when the screen is far too small
     * for any other view (vertical or horizontal, determined by the being stacked or not value, see observable below)
     */

    this.compactNavigationBreakpoint$ = breakpointFactory(NxBreakpoints.BREAKPOINT_MEDIUM);
    /**
     * this will take care of the overall layout and is consumed in the frame component itself
     * to assign different css classes to swap the layout
     */
    const collapseLayoutBreakpoint$ = breakpointFactory(NxBreakpoints.BREAKPOINT_LARGE);
    this.isStackedLayoutObservable = createStackedLayoutObservable(
      collapseLayoutBreakpoint$,
      this._channel
    );

    this.hideSidebarBreakpoint$ = breakpointFactory(NxBreakpoints.BREAKPOINT_XLARGE);

    // Create a stream of true & false values depending on the collapsed status.
    // The involved subject can emit if a specific status is being forced,
    // otherwise the stream will constantly invert any previous value to achieve the toggle mechanism.
    this.collapseNavigationUser$ = this._collapseNavigationUser$.pipe(
      scan((acc: boolean, value: boolean | undefined) => value ?? !acc, false)
    );
  }

  toggleNavigation(force?: boolean) {
    this._collapseNavigationUser$.next(force);
  }
}

/**
 * Create an observable that combines the information about the active channel and the
 * available screen estate defined by a breaking point. With those information we can easily
 * decide if we want to switch the layout to be stacked (one column) or keep the "holy grail layout"
 * with the three columns in the center and footer/header above and below
 *
 * Combinations:
 * SCREEN_TOO_SMALL + EXPERT = stacked
 * SCREEN_TOO_SMALL + RETAIL = stacked
 * SCREEN OKAY + RETAIL = stacked
 * SCREEN OKAY + EXPERT = holy grail
 *
 */

function createStackedLayoutObservable(breakpoint$: Observable<boolean>, channel: CHANNEL) {
  return breakpoint$.pipe(
    map((limitedScreenEstate) => {
      return limitedScreenEstate || channel === CHANNEL.RETAIL;
    })
  );
}

results matching ""

    No results matching ""