@WidgetComponent

nm-interaction-layout

File

src/app/shared/widgets/layoutcontainer/layoutcontainer.component.ts

Description

layout implementation that allows the display and switching between multiple interactions.

The widget input "interaction" can be used to assign individual interactions the layout. While only the latest interaction will actually be visible, all interactions set via the input will be loaded but hidden.

Each interaction (identified by "identifier" or its JSON representation) will only be loaded_once_.

This allows the implementation of externally displayed tab components, without having to re-instantiate the interaction every time the active interaction is switched.

To further reduce resources, interactions can be detached from the app-service, by setting the widget's "keep-attached" configuration property to false. When a detached interaction is re-activated (i.e., when the interaction is submitted using the "interaction" input), all connections are re-subscribed withint the app-service.

Metadata

selector nm-interaction-layout
template
<ng-container
  *ngFor="let entry of interactions | keyvalue; trackBy: trackByFn"
>
  <nm-interaction
    [configuration]="entry.value"
    [param]="param | async"
    [is-attached]="keepAttached || entry.key == active"
    [hidden]="entry.key != active"
  >
  </nm-interaction>
</ng-container>

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(cdr: ChangeDetectorRef)
Parameters :
Name Type Optional
cdr ChangeDetectorRef no

Methods

Public configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure
Parameters :
Name Type Optional
configuration WidgetConfig<InteractionLayoutConfiguration> no
Returns : void
Public trackByFn
trackByFn(index: , item: )
Parameters :
Name Optional
index no
item no
Returns : any

Properties

Public active
active: string
Type : string
Public id
id:
Decorators : WidgetId
Public interaction
interaction: Subject<Content>
Type : Subject<Content>
Default value : new ReplaySubject(1)
Decorators : WidgetInput
Public interactions
interactions: Map<string | Content>
Type : Map<string | Content>
Default value : new Map<string, Content>()
Public keepAttached
keepAttached: boolean
Type : boolean
Public param
param: Subject<any>
Type : Subject<any>
Default value : new ReplaySubject(1)
Decorators : WidgetInput
import { ChangeDetectorRef, Component, OnDestroy } from "@angular/core";
import { getOrDefault, WidgetConfig } from "../widget.configuration";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetId,
  WidgetInput,
} from "../widget.metadata";
import { ReplaySubject, Subject } from "rxjs";
import { distinctUntilChanged, filter, takeUntil } from "rxjs/operators";
import { NgUnsubscribe } from "../../ng-unsubscribe";
import {
  DeletionMode,
  Scope,
} from "../../components/local-storage/local-storage-constants";
import { LocalStorageEntryConfig } from "../../components/local-storage/local-storage.service";
import { Content } from "../../components/app-context/api";
import { BaseConfiguration } from "../widgetframe/widgetframe.component";

export const densityStorageConfig: LocalStorageEntryConfig = {
  scope: Scope.UNSCOPED,
  key: "nm-toolbox-table-density",
  deletionMode: DeletionMode.NEVER,
};

export const fontSizeStorageConfig: LocalStorageEntryConfig = {
  scope: Scope.UNSCOPED,
  key: "nm-toolbox-table-fontsize",
  deletionMode: DeletionMode.NEVER,
};

export interface EmptyWidgetConfiguration {
  /**
   * Sets the title shown in the empty widget header
   */
  title: string;

  /**
   * Sets CSS class name for the embedded header component
   */
  header: string;

  /**
   * Shows / Hides the border around the empty widget
   */
  withBorder: boolean;

  /**
   * Sets the Info text
   */
  infoText: string;

  /**
   * Sets the title shown for the info icon
   */
  infoTitle: string;

  /**
   * Sets the link to external wiki system for more information
   */
  wikiLink: string;

  /**
   * Shows / Hides the empty widget header @default(true)
   */
  withHeader?: boolean;

  /**
   * Shows / Hides the empty widget @default(false)
   */
  hideWidget?: boolean;
}
@WidgetComponent("nm-empty-widget")
@Component({
  selector: "nm-empty-widget",
  template: `
    <nm-widgetframe
      [header]="_widgetConfiguration.configuration['header']"
      [toolbarInvisible]="!withHeader"
      [visible]="!hideWidget"
      [withBorder]="_widgetConfiguration.configuration.withBorder"
      [infoText]="_widgetConfiguration.configuration['infoText']"
      [infoTitle]="_widgetConfiguration.configuration['infoTitle']"
      [infoWidth]="_widgetConfiguration.configuration['infoWidth']"
      [infoHeight]="_widgetConfiguration.configuration['infoHeight']"
      [title]="_widgetConfiguration.configuration.title | translate"
      [configuration]="_widgetConfiguration"
    >
      <ng-container slot="title">
        {{ _widgetConfiguration.configuration["title"] | translate }}
        {{ widgetTitle | translate }}
      </ng-container>

      <nm-container
        style="position: absolute; display: inline; right: 53px;"
        class="header"
        *ngIf="_widgetConfiguration && _widgetConfiguration.header"
        [configuration]="
          _widgetConfiguration.header | widgetFor: _widgetConfiguration
        "
        [parent]="id"
        id="header"
      >
      </nm-container>
      <nm-help-icon
        *ngIf="_widgetConfiguration.configuration['infoText']"
        style="position: absolute; display: inline; right: 47px; z-index: 666;"
        [info-text]="_widgetConfiguration.configuration['infoText'] | translate"
        [info-title]="_widgetConfiguration.configuration['title'] | translate"
        [info-width]="_widgetConfiguration.configuration['infoWidth']"
        [info-height]="_widgetConfiguration.configuration['infoHeight']"
        [info-placement]="'left'"
        [wiki-link]="_widgetConfiguration.configuration['wikiLink']"
      ></nm-help-icon>
    </nm-widgetframe>
  `,
})
export class EmptyWidgetComponent {
  @WidgetId()
  public id;

  public withHeader: boolean = true;

  @WidgetConfiguration()
  public _widgetConfiguration: WidgetConfig<EmptyWidgetConfiguration>;

  /**
   * Shows / Hides the empty widget
   */
  @WidgetInput("hide")
  public hide: Subject<any> = new ReplaySubject<any>();

  /**
   * Appends text to the title shown in the empty widget header
   */
  @WidgetInput("title")
  public title: Subject<any> = new ReplaySubject<any>();

  public hideWidget: boolean = false;
  public widgetTitle: string;

  private unsubscribe = NgUnsubscribe.create();

  @WidgetConfigure()
  protected configureWidget(
    configuration: WidgetConfig<EmptyWidgetConfiguration>
  ) {
    if (this._widgetConfiguration.configuration.withHeader != undefined) {
      this.withHeader = this._widgetConfiguration.configuration.withHeader;
    }

    if (this._widgetConfiguration.configuration.hideWidget != undefined) {
      this.hideWidget = this._widgetConfiguration.configuration.hideWidget;
    }

    this.hide
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((hide) => {
        this.hideWidget = hide;
      });

    this.title
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((title) => {
        this.widgetTitle = title;
      });
  }
}

@WidgetComponent("nm-switch-layout")
@Component({
  selector: "nm-switch-layout",
  template: `
    <nm-container
      *ngIf="!!component"
      [configuration]="component | widgetFor: _widgetConfiguration"
      [parent]="id"
      [id]="component"
    >
    </nm-container>
  `,
})
export class SwitchLayoutWidgetComponent implements OnDestroy {
  @WidgetId()
  public id;

  @WidgetConfiguration()
  public _widgetConfiguration: WidgetConfig;

  /**
   * The component id to display inside the placeholder widget
   */
  @WidgetInput("active-component")
  public activeComponent: Subject<string> = new ReplaySubject(1);

  public component: string;
  private unsubscribe = NgUnsubscribe.create();

  constructor(private cdr: ChangeDetectorRef) {}

  @WidgetConfigure()
  public configureWidget(configuration: WidgetConfig) {
    this.activeComponent
      .pipe(
        filter((component) => !!component),
        distinctUntilChanged(),
        takeUntil(this.unsubscribe)
      )
      .subscribe((component) => {
        this.component = component;
        this.cdr.markForCheck();
      });
  }

  ngOnDestroy(): void {
    this.unsubscribe.destroy();
  }
}

export interface InteractionLayoutConfiguration extends BaseConfiguration {
  /**
   * If set to false, inactive interactions will not receive any events over the connected channels.
   * Once the interaction is re-activated, all channels will be re-subscribed and emit their latest values.
   *
   * @default(true)
   */
  "keep-attached": boolean;
}

/**
 * layout implementation that allows the display and switching between multiple interactions.
 *
 * The widget input "interaction" can be used to assign individual interactions the layout.
 * While only the latest interaction will actually be visible, _all_ interactions set via
 * the input will be loaded but hidden.
 *
 * Each interaction (identified by "identifier" or its JSON representation) will only
 * be loaded_once_.
 *
 * This allows the implementation of externally displayed tab components, without having to
 * re-instantiate the interaction every time the active interaction is switched.
 *
 * To further reduce resources, interactions can be detached from the app-service, by setting the
 * widget's "keep-attached" configuration property to false.
 * When a detached interaction is re-activated (i.e., when the interaction is submitted using
 * the "interaction" input), all connections are re-subscribed withint the app-service.
 */
@WidgetComponent("nm-interaction-layout")
@Component({
  selector: "nm-interaction-layout",
  template: `
    <ng-container
      *ngFor="let entry of interactions | keyvalue; trackBy: trackByFn"
    >
      <nm-interaction
        [configuration]="entry.value"
        [param]="param | async"
        [is-attached]="keepAttached || entry.key == active"
        [hidden]="entry.key != active"
      >
      </nm-interaction>
    </ng-container>
  `,
})
export class InteractionLayoutWidgetComponent {
  public interactions: Map<string, Content> = new Map<string, Content>();
  public active: string;

  @WidgetId()
  public id;

  @WidgetInput("interaction")
  public interaction: Subject<Content> = new ReplaySubject(1);

  @WidgetInput("param")
  public param: Subject<any> = new ReplaySubject(1);

  public keepAttached: boolean;

  constructor(private cdr: ChangeDetectorRef) {}

  @WidgetConfigure()
  public configureWidget(
    configuration: WidgetConfig<InteractionLayoutConfiguration>
  ) {
    this.keepAttached = getOrDefault(
      configuration.configuration["keep-attached"],
      true
    );

    this.interaction.subscribe((content) => {
      let key = content.identifier || JSON.stringify(content);

      this.active = key;
      this.cdr.detectChanges();

      if (!this.interactions.has(key)) {
        this.interactions.set(key, content);
      }
      this.cdr.markForCheck();
    });
  }

  public trackByFn(index, item) {
    return item.key;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""