File

src/app/shared/widgets/dynamic-form/dynamic-form-tabs-dialog/dynamic-form-tabs-dialog.component.ts

Extends

DynamicFormField

Index

Properties

Properties

tab
tab: string
Type : string
Optional
import {
  OnDestroy,
  Component,
  OnInit,
  Inject,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  HostListener,
} from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { WidgetframeService } from "../../widgetframe/widgetframe.service";
import { mapToLocalesFields } from "../../../components/util/";
import { DynamicFormField } from "../dynamic-form-component/dynamic-form-fields.component";
import { Subject } from "rxjs";
import { NgUnsubscribe } from "../../../ng-unsubscribe";
import { takeUntil } from "rxjs/operators";
import { EditAttributeService } from "../../../components/edit-attribute";
import { Attribute } from "../../../components/edit-attribute/attribute";
import { deepCopy } from "../../../components/util/util.service";

const TAB = {
  localizedtext: "localizedtext",
  listFolder: "listFolder",
  userRights: "userRights",
};

const TAB_INDEX = new Map([
  [TAB.localizedtext, 1],
  [TAB.listFolder, 2],
  [TAB.userRights, 3],
]);

export let DynamicFormTabsContext = {
  saveClicked: new Subject<any>(),
  saveSuccessful: new Subject<any>(),
  enableSave: new Subject<any>(),
  valueChanged: new Subject<any>(),
  resetLookup: new Subject<any>(),
  lookupOptions: new Subject<any>(),
  addFields: new Subject<any>(),
  removeFields: new Subject<any>(),
  triggerValidation: new Subject(),
  setDisabled: new Subject<any>(),
  valueSetter: new Subject<any>(),
  onClick: new Subject<any>(),
  unsubscribe: null,
};

export interface DynamicFormTabsField extends DynamicFormField {
  tab?: string;
}

interface AttributeField {
  header: string;
  attribute: Attribute;
}

@Component({
  selector: "nm-dynamic-form-tabs-dialog",
  templateUrl: "./dynamic-form-tabs-dialog.component.html",
  styleUrls: ["./dynamic-form-tabs-dialog.component.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DynamicFormTabsDialog implements OnDestroy, OnInit {
  private unsubscribe = NgUnsubscribe.create();

  public selectedIndex = 0;
  public selectedTab: string;

  public isValid: boolean = false;
  public valueSetter = new Subject<{ field: string; value: any }>();
  public lookupOptions = new Subject<any>();
  public addFields = new Subject<any>();
  public removeFields = new Subject<any>();
  public setDisabled = new Subject<any>();
  public resetLookup = new Subject<any>();
  public triggerValidation = new Subject();
  public tabInitialized = new Subject<{ init: boolean; value: any }>();
  private values: any = {};
  private restoreValues: any = {};

  public attributeFields: AttributeField[] = [];
  private editedAttributeValues = new Map<string, any>();

  public localeFields: any[] = [];
  public localeValueSetter = new Subject<{ field: string; value: any }>();
  public localeTabInitialized = new Subject<{ init: boolean; value: any }>();
  private localeValues: any = {};
  private restoreLocaleValues: any = {};
  private firstLocalesLoad: boolean = true;

  public listFolderType: string;
  public listFolderDataType: string;
  public listFolderLocalStorageState: string;
  public listFolderLocalStorageSearch: string;
  private listFolderSelection = [];

  public userRights: any;
  private userRightsSelection: any = {};
  public context: string = "";

  private tabContext: { field: any; value?: any };

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    public dialogRef: MatDialogRef<DynamicFormTabsDialog>,
    public _widgetframeService: WidgetframeService,
    public editAttributeService: EditAttributeService,
    protected cdr: ChangeDetectorRef
  ) {
    DynamicFormTabsContext.unsubscribe = NgUnsubscribe.create();
  }

  ngOnInit() {
    if (!this.data) {
      console.log("[nm-dynamic-form-tabs-dialog] no data");
    }

    this.setDefaultValues();
    this.subscribeToContextInputs();

    this.initLocalesFields();
    this.loadUserRights();

    this.tabInitialized
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        if (data && data.init && !data.value && this.restoreValues) {
          Object.keys(this.restoreValues).forEach((key) =>
            this.valueSetter.next({
              field: key,
              value: this.restoreValues[key],
            })
          );
          this.loadTabData(this.selectedTab);
        } else if (data && !data.init && data.value) {
          this.restoreValues = data.value;
        }

        data["context"] = this.data.id;
        this.context = this.data.id;
      });

    this.setUpdateValues();

    if (this.data.attributeValues) {
      this.populateAttributeValues(this.data.attributeValues);

      this.editAttributeService
        .getAttributeChangedEvent()
        .pipe(takeUntil(this.unsubscribe))
        .subscribe((attribute) => {
          this.editedAttributeValues.set(attribute.identifier, attribute);
        });
    }
  }

  private setDefaultValues() {
    if (!this.data.localesUrl) {
      this.data.localesUrl = "/api/public/locales?type=ipim";
    }

    if (!this.data.saveButtonText) {
      this.data.saveButtonText = "button.save";
    }

    if (!this.data.closeOnSave) {
      this.data.closeOnSave = true;
    }
  }

  private initLocalesFields() {
    if (!this.data.localesUrl) {
      return;
    }

    let localizationTabs = this.data.dialogConfig.tabs.filter(
      (tab) => tab.type === "localizedtext"
    );

    if (localizationTabs && localizationTabs.length > 0) {
      this._widgetframeService
        .getData(this.data.localesUrl)
        .subscribe((response) => {
          localizationTabs.forEach((tab) => {
            this.localeFields = mapToLocalesFields(
              response._embedded.locales,
              "plain",
              tab.floatingLabel
            );
          });
        });
    }
  }

  public getLocaleFields() {
    if (this.localeFields && this.localeFields.length > 0) {
      this.localeFields[0].autofocus = true;
    }
    return this.localeFields;
  }

  private loadUserRights() {
    if (!this.data.userRightsUrl) {
      return;
    }

    this._widgetframeService
      .getData(this.data.userRightsUrl)
      .subscribe((response) => {
        this.userRights = response._embedded[response.type];
      });
  }

  private subscribeToContextInputs() {
    DynamicFormTabsContext.saveSuccessful
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => this.dialogRef.close(data));

    DynamicFormTabsContext.resetLookup
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => this.resetLookup.next(data));

    DynamicFormTabsContext.lookupOptions
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => this.lookupOptions.next(data));

    DynamicFormTabsContext.addFields
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((fields) => this.addFields.next(fields));

    DynamicFormTabsContext.removeFields
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((fields) => this.removeFields.next(fields));

    DynamicFormTabsContext.triggerValidation
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => this.triggerValidation.next());

    DynamicFormTabsContext.setDisabled
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((field) => this.setDisabled.next(field));

    DynamicFormTabsContext.valueSetter
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((field) => this.valueSetter.next(field));

    DynamicFormTabsContext.enableSave
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((isValid) => {
        this.onValidChange(isValid);
      });
  }

  private populateAttributeValues(data) {
    let attributeValues = data ? data : [];
    attributeValues.forEach((av) => {
      this.handleAttribute(av);
    });
  }

  private handleAttribute(attribute: any) {
    if (attribute["read-only"]) {
      return;
    }

    const field = {
      header: attribute.description,
      attribute: deepCopy(attribute),
    };

    this.attributeFields.push(field);
  }

  private setUpdateValues() {
    if (!this.data.update) {
      return;
    }

    if (this.data.localeValues) {
      let restoredValues: any = {};

      Object.keys(this.data.localeValues).forEach((key) => {
        let values: any = {};

        this.data.localeValues[key].forEach((value) => {
          values[value.field] = value.value;
        });

        restoredValues[key] = values;
      });
      this.restoreLocaleValues = restoredValues;
    }

    if (this.data.userRights) {
      this.userRightsSelection = this.data.userRights;
    }
  }

  private setTabData(tab: string) {
    switch (tab) {
      case TAB.localizedtext:
        this.tabContext.value = this.localeValues;
        break;
      case TAB.listFolder:
        this.tabContext.value = this.listFolderSelection
          ? this.listFolderSelection
          : null;
        break;
      case TAB.userRights:
        if (
          !this.userRightsSelection[this.tabContext.field] ||
          this.userRightsSelection[this.tabContext.field].length === 0
        ) {
          this.tabContext.value = this.values[this.tabContext.field];
          return;
        }
        this.tabContext.value = this.userRightsSelection[this.tabContext.field];
        break;
      default:
        return;
    }
  }

  private loadTabData(tab: string) {
    if (!tab) {
      return;
    }

    switch (tab) {
      case TAB.listFolder:
        if (this.tabContext.value && this.tabContext.value.length !== 0) {
          this.valueSetter.next({
            field: this.tabContext.field,
            value: [this.tabContext.value],
          });
        }
        break;
      default:
        this.valueSetter.next({
          field: this.tabContext.field,
          value: this.tabContext.value,
        });
        return;
    }
    this.cdr.markForCheck();
  }

  toMainForm(tab: string) {
    this.setTabData(tab);
    this.selectedIndex = 0;
  }

  toLocalizationForm(field: DynamicFormTabsField) {
    this.tabContext = { field: field.field };

    this.localeTabInitialized
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        if (
          data &&
          data.init &&
          !data.value &&
          this.restoreLocaleValues &&
          this.restoreLocaleValues[this.tabContext.field]
        ) {
          Object.keys(this.restoreLocaleValues[this.tabContext.field]).forEach(
            (key) =>
              this.localeValueSetter.next({
                field: key,
                value: this.restoreLocaleValues[this.tabContext.field][key],
              })
          );
        } else if (data && !data.init && data.value) {
          this.restoreLocaleValues[this.tabContext.field] = data.value;
        }

        this.updateLocalizationFormValues();
      });
  }

  private updateLocalizationFormValues() {
    if (
      !this.firstLocalesLoad ||
      !this.data.update ||
      !this.data.localeValues ||
      !this.data.localeValues[this.tabContext.field]
    ) {
      return;
    }

    this.data.localeValues[this.tabContext.field].forEach((value) =>
      this.localeValueSetter.next(value)
    );

    this.firstLocalesLoad = false;
  }

  toListFolderForm(field: DynamicFormTabsField) {
    this.tabContext = { field: field.field };
    this.listFolderType = field.listfolderType;
    this.listFolderDataType = field.dataType;
    this.listFolderLocalStorageState = field.field + "LocalStorageState";
    this.listFolderLocalStorageSearch = field.field + "LocalStorageSearch";
  }

  toUserRightsForm(field: DynamicFormTabsField) {
    this.tabContext = { field: field.field };
  }

  onInit(value) {
    this.tabInitialized.next(value);
  }

  onLocaleInit(value) {
    this.localeTabInitialized.next(value);
  }

  onClick(field: DynamicFormTabsField) {
    if (field.type === "password") {
      DynamicFormTabsContext.onClick.next(true);
      return;
    }

    if (!field.tab) {
      return;
    }

    this.switchTab(field);
  }

  switchTab(field: DynamicFormTabsField) {
    this.selectedTab = field.tab;
    const index = TAB_INDEX.get(TAB[field.tab]);

    switch (index) {
      case 1: {
        this.toLocalizationForm(field);
        break;
      }
      case 2: {
        this.toListFolderForm(field);
        break;
      }
      case 3: {
        this.toUserRightsForm(field);
        break;
      }
      default: {
        this.tabContext = { field: field.field };
      }
    }

    this.selectedIndex = index;
  }

  onValueChange(data: any) {
    this.values = data.value;
    DynamicFormTabsContext.valueChanged.next(data);
  }

  onValidChange(data: any) {
    this.isValid = data;
  }

  onLocaleValueChange(tab: any, data: any) {
    this.localeValues = data.value;
  }

  onListFolderSelect(tab: any, data: any) {
    if (!data || !data.isNode) {
      return;
    }

    this.listFolderSelection = data;
    this.toMainForm(tab.type);
  }

  onUserRightsSelect(tab: any, rights: any) {
    if (!rights || rights.length === 0) {
      return;
    }

    this.userRightsSelection[this.tabContext.field] = rights;

    if (tab.multiSelection) {
      return;
    }

    this.toMainForm(tab.type);
  }

  onSave() {
    const data = {
      id: this.data.id,
      values: this.values,
      attributeValues: this.editedAttributeValues,
      localeValues: this.restoreLocaleValues,
      listFolders: this.listFolderSelection,
      userRights: this.userRightsSelection,
    };

    if (this.data.closeOnSave) {
      this.dialogRef.close(data);
    } else {
      DynamicFormTabsContext.saveClicked.next(data);
    }
  }

  isBackButtonNeeded() {
    return this.selectedIndex > 0;
  }

  onCancel() {
    this.dialogRef.close();
  }

  @HostListener("document:keydown.escape", ["$event"]) onKeydownHandler(event) {
    // cant focus lastFocused element (not known)
    this.onCancel();
  }

  ngOnDestroy() {
    DynamicFormTabsContext.unsubscribe.destroy();
    this.unsubscribe.destroy();
  }
}

results matching ""

    No results matching ""