@WidgetComponent

nm-edit-text-and-attributes

File

src/app/shared/widgets/apps/my-text-edit/edit-text-and-attributes/edit-text-and-attributes.component.ts

Implements

OnDestroy

Metadata

providers EditAttributeService
selector nm-edit-text-and-attributes
styleUrls edit-text-and-attributes.component.scss
templateUrl ./edit-text-and-attributes.component.html

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(_widgetframeService: WidgetframeService, _editAttributeService: EditAttributeService, _halService: HalService, _notificationService: CustomNotificationService, dialog: MatDialog, translateService: TranslateService, location: Location, localStorageService: LocalStorageService, router: Router)
Parameters :
Name Type Optional
_widgetframeService WidgetframeService no
_editAttributeService EditAttributeService no
_halService HalService no
_notificationService CustomNotificationService no
dialog MatDialog no
translateService TranslateService no
location Location no
localStorageService LocalStorageService no
router Router no

Methods

Protected configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure
Parameters :
Name Type Optional
configuration WidgetConfig no
Returns : void
deleteAttribute
deleteAttribute(attribute: )
Parameters :
Name Optional
attribute no
Returns : void
Private executeDelete
executeDelete(attribute: )
Parameters :
Name Optional
attribute no
Returns : void
filterOptions
filterOptions()
Returns : void
hideAttribute
hideAttribute(attribute: )
Parameters :
Name Optional
attribute no
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
onCloseSelect
onCloseSelect()
Returns : void
onSelectChange
onSelectChange()
Returns : void
openedChange
openedChange(open: )
Parameters :
Name Optional
open no
Returns : void
resetWidget
resetWidget()
Returns : any
setBoxWidth
setBoxWidth(index: )
Parameters :
Name Optional
index no
Returns : string

Properties

Public _editAttributeService
_editAttributeService: EditAttributeService
Type : EditAttributeService
Public _id
_id: string
Type : string
Decorators : WidgetId
Public action
action:
Default value : new Subject<any>()
Decorators : WidgetOutput
Private attributeListEntries
attributeListEntries: string
Type : string
Public attributes
attributes: Attribute[]
Type : Attribute[]
Private boxWidth
boxWidth: string
Type : string
Public changedAttributes
changedAttributes:
Default value : <any>{}
Public changedAttributesOutput
changedAttributesOutput:
Default value : new Subject<any>()
Decorators : WidgetOutput
Public cols
cols: any[]
Type : any[]
Public configuration
configuration: WidgetConfig
Type : WidgetConfig
Decorators : WidgetConfiguration
Private confirmed
confirmed: boolean
Type : boolean
Default value : false
Private contentNo
contentNo:
Public contentNoForEdit
contentNoForEdit:
Default value : new Subject<any>()
Decorators : WidgetInput
Public context
context: string
Type : string
Public deleteName
deleteName: string
Type : string
Default value : "delete-attribute"
Public dialog
dialog: MatDialog
Type : MatDialog
Public editLayout
editLayout: string
Type : string
Public filterCtrl
filterCtrl: FormControl
Type : FormControl
Default value : new FormControl()
Public filteredOptions
filteredOptions: Attribute[]
Type : Attribute[]
Public infoText
infoText: string
Type : string
Public infoWidth
infoWidth: string
Type : string
Public inputLink
inputLink: string
Type : string
Private loadOptionsLazy
loadOptionsLazy: boolean
Type : boolean
Public localStorageEntry
localStorageEntry: LocalStorageEntry
Type : LocalStorageEntry
Private maintenanceLevelId
maintenanceLevelId: string
Type : string
Public objectKeys
objectKeys:
Default value : Object.keys
Public productLevel
productLevel:
Default value : new Subject<any>()
Decorators : WidgetInput
Private productNo
productNo:
Public productNoForEdit
productNoForEdit:
Default value : new Subject<any>()
Decorators : WidgetInput
Public reload
reload:
Default value : new BehaviorSubject<any>(new Date())
Decorators : WidgetInput
Public reset
reset:
Default value : new BehaviorSubject<any>(new Date())
Decorators : WidgetInput
Public searchString
searchString: string
Type : string
Public selectedDataLocale
selectedDataLocale:
Default value : new ReplaySubject<any>()
Decorators : WidgetInput
Private selectedDataLocaleString
selectedDataLocaleString:
Public selectedUiLocale
selectedUiLocale:
Default value : new Subject<any>()
Decorators : WidgetInput
Public selection
selection: any[]
Type : any[]
Private sub
sub:
Public targets
targets:
Default value : new Subject<any>()
Decorators : WidgetInput
Private targetsInput
targetsInput: []
Type : []
Default value : []
Public title
title: string
Type : string
Public translateService
translateService: TranslateService
Type : TranslateService
Private unsubscribe
unsubscribe:
Default value : NgUnsubscribe.create()
Public uri
uri:
Default value : new Subject<any>()
Decorators : WidgetInput
Public widgetLocale
widgetLocale:
Default value : new Subject<any>()
Decorators : WidgetInput
Public wikiLink
wikiLink: string
Type : string
import {
  combineLatest as observableCombineLatest,
  Subject,
  ReplaySubject,
  BehaviorSubject,
  Observable,
} from "rxjs";

import { map, mergeMap, takeUntil, filter } from "rxjs/operators";
import { Component, OnDestroy } from "@angular/core";
import { FormControl } from "@angular/forms";
import { WidgetframeService } from "../../../widgetframe/widgetframe.service";
import { WidgetConfig } from "../../../widget.configuration";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetId,
  WidgetInput,
  WidgetOutput,
} from "../../../widget.metadata";
import { NgUnsubscribe } from "../../../../ng-unsubscribe";

import * as uriTemplates_ from "uri-templates";
import { Attribute } from "../../../../components/edit-attribute/attribute";
import { EditAttributeService } from "../../../../components/edit-attribute/edit-attribute.service";

import { HalService } from "../../../../components/hal/index";
import { CustomNotificationService } from "../../../../components/notification/customnotification.service";
import { MatDialog } from "@angular/material/dialog";
import { TranslateService } from "@ngx-translate/core";
import { ConfirmationDialogComponent } from "../../../../components/dialog/confirmationDialog.component";
import { Location } from "@angular/common";
import { Router } from "@angular/router";
import {
  DeletionMode,
  Scope,
} from "../../../../components/local-storage/local-storage-constants";
import {
  LocalStorageEntry,
  LocalStorageService,
} from "../../../../components/local-storage/local-storage.service";

const uriTemplates = uriTemplates_;

declare var $;
declare var jQuery: any;

@WidgetComponent("nm-edit-text-and-attributes")
@Component({
  selector: "nm-edit-text-and-attributes",
  templateUrl: "./edit-text-and-attributes.component.html",
  styleUrls: ["./edit-text-and-attributes.component.scss"],
  providers: [EditAttributeService],
})
export class EditTextAndAttributesWidgetComponent implements OnDestroy {
  public cols: any[];
  public attributes: Attribute[];
  public changedAttributes = <any>{};
  //needed for key value iteration
  public objectKeys = Object.keys;
  public selection: any[];
  public inputLink: string;
  public searchString: string;
  public filteredOptions: Attribute[];

  @WidgetConfiguration()
  public configuration: WidgetConfig;

  @WidgetInput()
  public productNoForEdit = new Subject<any>();

  @WidgetInput()
  public contentNoForEdit = new Subject<any>();

  @WidgetInput()
  public uri = new Subject<any>();

  @WidgetInput()
  public reload = new BehaviorSubject<any>(new Date());

  @WidgetInput()
  public reset = new BehaviorSubject<any>(new Date());

  @WidgetInput()
  public selectedDataLocale = new ReplaySubject<any>();

  @WidgetOutput("changedAttributesOutput")
  public changedAttributesOutput = new Subject<any>();

  @WidgetOutput("action")
  public action = new Subject<any>();

  @WidgetInput()
  public widgetLocale = new Subject<any>();

  @WidgetInput()
  public selectedUiLocale = new Subject<any>();

  @WidgetInput()
  public targets = new Subject<any>();

  @WidgetInput()
  public productLevel = new Subject<any>();

  @WidgetId()
  public _id: string;

  private unsubscribe = NgUnsubscribe.create();
  private sub;
  public editLayout: string;
  private boxWidth: string;
  private productNo;
  private contentNo;
  private selectedDataLocaleString;
  private attributeListEntries: string;
  public localStorageEntry: LocalStorageEntry;
  private targetsInput = [];
  private maintenanceLevelId: string;
  private loadOptionsLazy: boolean;
  public filterCtrl: FormControl = new FormControl();
  public infoText: string;
  public wikiLink: string;
  public title: string;
  public context: string;
  public infoWidth: string;
  private confirmed: boolean = false;
  public deleteName: string = "delete-attribute";

  constructor(
    private _widgetframeService: WidgetframeService,
    public _editAttributeService: EditAttributeService,
    private _halService: HalService,
    private _notificationService: CustomNotificationService,
    public dialog: MatDialog,
    public translateService: TranslateService,
    private location: Location,
    private localStorageService: LocalStorageService,
    private router: Router
  ) {
    this.cols = [
      { field: "description", header: "tab.head.att.name" },
      { field: "value", header: "" },
    ];
  }

  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    //FIXME TODO: This should maybe be introduced in a more general global approach
    // This gets rid of the URL params. Then a reload will not reload an old page state with an old productNo
    if (this.router.url.includes("?")) {
      this.location.replaceState(
        this.router.url.substring(0, this.router.url.indexOf("?"))
      );
    }

    this.loadOptionsLazy = configuration.configuration["loadOptionsLazy"];
    this.infoText = this.configuration.configuration["infoText"];
    this.wikiLink = this.configuration.configuration["wikiLink"];
    this.title = configuration.configuration["title"];
    this.context = configuration.configuration["context"];
    this.infoWidth = configuration.configuration["infoWidth"];

    this.changedAttributes.values = [];
    this.changedAttributes.targets = [];

    this.editLayout = configuration.configuration["edit-layout"];
    this.productNoForEdit
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        this.productNo = data;
      });
    this.contentNoForEdit
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        if (data[0]) {
          this.contentNo = data[0].identifier;
        }
      });

    this.selectedDataLocale
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        this.changedAttributesOutput.next(null);
        this.selectedDataLocaleString = data;
      });
    this.localStorageEntry = this.localStorageService.getLocalStorageEntry(
      configuration.configuration["local-storage-key"],
      Scope.GLOBAL,
      DeletionMode.RESET
    );
    this.maintenanceLevelId =
      configuration.configuration["maintenance-level-id"];
    this.targets.pipe(takeUntil(this.unsubscribe)).subscribe((targetsInput) => {
      this.targetsInput = targetsInput;
    });

    this.filterCtrl.valueChanges
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        this.filterOptions();
      });

    this._editAttributeService
      .getAttributeChangedEvent()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((attribute) => {
        let dublicate = this.changedAttributes.values.filter(
          (item) => item.identifier == attribute.identifier
        );
        if (dublicate.length === 1) {
          dublicate.source = attribute.source;
        } else {
          this.changedAttributes.values.push(attribute);
          if (this.targetsInput.length > 0) {
            this.changedAttributes.targets = this.targetsInput;
          } else {
            this.changedAttributes.targets = [];
            if (this.context == "content") {
              this.changedAttributes.targets.push({
                level: "content",
                identifier: this.contentNo,
              });
            } else {
              this.changedAttributes.targets.push({
                level: "product",
                identifier: this.productNo,
              });
            }
          }
          this.changedAttributes["locale"] = this.selectedDataLocaleString;
        }
        this.changedAttributesOutput.next(this.changedAttributes);
      });

    this._halService
      .getActionEvents()
      .pipe(
        filter(
          (event) => event.name === configuration.configuration["action-name"]
        ),
        map((event) => (<any>event).response),
        takeUntil(this.unsubscribe)
      )
      .subscribe((resp) => {
        this.changedAttributes = <any>{};
        this.changedAttributes.values = [];
        this.changedAttributes.targets = [];
        this.changedAttributesOutput.next(null);
        if (resp.message !== undefined) {
          if (resp.level === "ERROR") {
          }
          if (resp.level === "SUCCESS") {
            this.changedAttributes = <any>{};
            this.changedAttributes.values = [];
            this.changedAttributesOutput.next(null);
          }
        }
      });

    this.reset.pipe(takeUntil(this.unsubscribe)).subscribe((reset) => {
      this.resetWidget();
    });

    let template;
    let source = observableCombineLatest(
      this.uri.asObservable(),
      this.selectedDataLocale.asObservable(),
      this.selectedUiLocale.asObservable(),
      this.reload.asObservable(),
      (uri, selectedDataLocale, selectedUiLocale, reload) => {
        template = uriTemplates(uri);
        let uriParams = {};
        if (this.localStorageEntry.exists()) {
          let identifiers = JSON.parse(this.localStorageEntry.value);
          uriParams["visible-attributes"] = identifiers.join();
        }
        uriParams["maintenance-level-id"] =
          configuration.configuration["maintenance-level-id"];
        uriParams["data-locale"] = selectedDataLocale;
        uriParams["context"] = this.context;
        uriParams["locale"] = selectedUiLocale;
        return uriParams;
      }
    ).pipe(
      map((uriParams) => {
        let uri = template.fill(uriParams);
        return uri;
      }),
      mergeMap((href) => {
        return this._widgetframeService.getData(href);
      })
    );

    source.pipe(takeUntil(this.unsubscribe)).subscribe(
      (data) => {
        this.attributes = [].concat(data["values"]);
        this.filteredOptions = [].concat(data["values"]);

        this.selection = [];
        for (const item of this.attributes.filter((attribut) => {
          return attribut.visible === true;
        })) {
          this.selection.push(item.identifier);
        }

        if (data.hasOwnProperty("_actions")) {
          let template = uriTemplates(data["_actions"].save.href);
          let uriParams = {};

          if (this.context == "content") {
            uriParams["content"] = this.contentNo;
          } else {
            uriParams["productNo"] = this.productNo;
            uriParams["maintenance-level-id"] = this.maintenanceLevelId;
          }

          data["_actions"].save.href = template.fill(uriParams);
          this.action.next(data["_actions"].save);
        }
      },
      (error) => {
        this.attributes = null;
      }
    );

    this._halService
      .getActionEvents()
      .pipe(
        filter((event) => event.name === "delete-attribute"),
        takeUntil(this.unsubscribe)
      )
      .subscribe((resp) => {
        this._notificationService.fromJson(resp.response);
      });
  }

  filterOptions() {
    if (!this.filteredOptions) {
      return;
    }

    let search = this.filterCtrl.value.toLowerCase();
    if (search) {
      let filtered = this.attributes.filter((item) => {
        return (
          item.description.toLowerCase().indexOf(search) > -1 ||
          item.identifier.toLowerCase().indexOf(search) > -1 ||
          item.visible
        );
      });
      this.filteredOptions = filtered;
    } else {
      this.filteredOptions = this.attributes.slice();
    }
  }

  openedChange(open) {
    if (!open) {
      this.onCloseSelect();
    }
  }

  onCloseSelect() {
    this.searchString = "";
    this.filteredOptions = this.attributes;
  }

  onSelectChange() {
    this.localStorageEntry.value = JSON.stringify(this.selection);

    for (let attribute of this.attributes) {
      attribute.visible = false;

      for (let selectedidentifier of this.selection) {
        if (attribute.identifier === selectedidentifier) {
          attribute.visible = true;
        }
      }
    }
  }

  deleteAttribute(attribute) {
    if (this.context !== "content") {
      let title = "hl.confirmation";
      let message = "app.ipim-mytextedit.delete.confirmation";
      let dialogRef = this.dialog.open(ConfirmationDialogComponent);
      dialogRef.componentInstance["title"] = this.translateService.instant(
        title
      );
      dialogRef.componentInstance["message"] = this.translateService.instant(
        message
      );
      dialogRef.componentInstance[
        "buttonAcceptTitle"
      ] = this.translateService.instant("button.accept");
      dialogRef.componentInstance[
        "buttonCancelTitle"
      ] = this.translateService.instant("button.cancel");

      dialogRef
        .afterClosed()
        .pipe(takeUntil(this.unsubscribe))
        .subscribe((confirmed) => {
          if (confirmed) {
            if (attribute.hasOwnProperty("_actions")) {
              let template = uriTemplates(attribute._actions.delete.href);
              let uriParams = {};
              uriParams["productNo"] = this.productNo;

              if (this.context == "content") {
                uriParams["content"] = this.contentNo;
              } else {
                uriParams["productNo"] = this.productNo;
              }
              attribute._actions.delete.href = template.fill(uriParams);
              this.executeDelete(attribute);
            }
          } else {
            console.log("cancel delete");
          }
        });
    }
  }

  private executeDelete(attribute) {
    this._halService
      .execute("delete-attribute", attribute._actions.delete)
      .subscribe(
        (resp) => {
          if (resp.response.level === "SUCCESS") {
            let foundInChanged = this.changedAttributes.values.filter(
              (e) => e !== attribute
            );
            if (foundInChanged.length > 0) {
              this.changedAttributes.values = foundInChanged;
              this.changedAttributesOutput.next(this.changedAttributes);
            } else {
              this.changedAttributesOutput.next(null);
            }
            this.reload.next(new Date());
          } else {
            console.log(resp);
          }
        },
        (err) => {
          console.log(err);
        }
      );
  }

  hideAttribute(attribute) {
    let identifiers = [];
    if (this.localStorageEntry.exists()) {
      identifiers = JSON.parse(this.localStorageEntry.value);
    }
    identifiers = identifiers.filter((e) => e !== attribute.identifier);
    this.localStorageEntry.value = JSON.stringify(identifiers);
    this.selection = identifiers;
    attribute.visible = false;
  }

  resetWidget() {
    this.attributes = [];
    this.selection = [];
    this.changedAttributes.values = [];
    this.changedAttributes.targets = [];
    this.changedAttributesOutput.next(null);
    if (this.context != "content") {
      this.uri.next(" ");
    }
    return null;
  }

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

  setBoxWidth(index) {
    return 98 / index + "%";
  }
}
<nm-widgetframe
  [header]="configuration.configuration['header']"
  [configuration]="configuration"
  [infoTitle]="title"
  [infoText]="infoText"
  [infoWidth]="infoWidth"
  [infoPlacement]="'bottom'"
  [wikiLink]="wikiLink"
  widgetId="{{ _id }}"
>
  <div slot="title" class="nm-widgetframe__title">{{ title | translate }}</div>
  <div
    slot="content"
    class="nm-widgetframe__content"
    *ngIf="attributes !== null"
  >
    <div class="nm-attribute-list" *ngIf="editLayout === 'list'">
      <p-dataGrid
        [value]="attributes"
        [rows]="1000"
        [paginator]="false"
        emptyMessage=" "
      >
        <ng-template let-attribute pTemplate="body">
          <div class="nm-attribute-list-elements" *ngIf="attribute.visible">
            <div class="nm-attribute-list-description">
              <nm-ellipsis [content]="attribute.description"> </nm-ellipsis>
            </div>
            <div
              class="nm-attribute-list-value"
              *ngIf="configuration.configuration['context'] != 'content'"
            >
              <nm-edit-attribute
                [attribute]="attribute"
                [editLayout]="editLayout"
                [editAttributeService]="_editAttributeService"
                [loadOptionsLazy]="
                  configuration.configuration['loadOptionsLazy']
                "
              ></nm-edit-attribute>
            </div>
            <div
              class="nm-attribute-list-value"
              *ngIf="configuration.configuration['context'] == 'content'"
            >
              <nm-edit-attribute
                [dataLocale]="selectedDataLocale | async"
                [attribute]="attribute"
                [editLayout]="editLayout"
                [context]="'content'"
                [editAttributeService]="_editAttributeService"
                [loadOptionsLazy]="
                  configuration.configuration['loadOptionsLazy']
                "
              ></nm-edit-attribute>
            </div>

            <div
              *ngIf="attribute.group?.length > 1"
              class="nm-attribute-list-addtext"
              popover="{{ 'app.ipim-mytextedit.group' | translate }}{{ ':' }} {{
                attribute.group
              }}"
              placement="top"
              container="body"
              triggers="mouseenter:mouseleave"
            >
              {{ attribute.group }}
            </div>
            <span class="sortidx">{{ attribute.source[0]?.sortIdx }}</span>
            <div
              *ngIf="
                attribute.group === undefined && attribute.type !== 'TYPE_TEXT'
              "
              class="nm-attribute-list-addtext"
            ></div>
            <div
              class="
                nm-attribute-list-status
                traffic_light_grid traffic_light_grid_single
              "
              *ngIf="attribute.translations"
            >
              <ng-template #popTemplateTranslation>
                <ul class="translation-status-list">
                  <li
                    *ngFor="let key of objectKeys(attribute.translations)"
                    class="translation-status translation-status-{{
                      attribute.translations[key]
                    }}"
                  >
                    <mat-icon *ngIf="attribute.translations[key]"
                      >check</mat-icon
                    >
                    <mat-icon *ngIf="!attribute.translations[key]"></mat-icon>
                    {{ key }}
                  </li>
                </ul>
              </ng-template>

              <div
                class="traffic_light dropdown-menu-right"
                [popover]="popTemplateTranslation"
                popoverTitle="{{
                  'app.ipim-mytextedit.trafficlight.popover.title' | translate
                }}"
                placement="top"
                container="body"
                triggers="mouseenter:mouseleave"
              >
                <span
                  [ngClass]="{ active: attribute.translation_status == 'RED' }"
                  class="red"
                ></span>
                <span
                  [ngClass]="{
                    active: attribute.translation_status == 'YELLOW'
                  }"
                  class="yellow"
                ></span>
                <span
                  [ngClass]="{
                    active: attribute.translation_status == 'GREEN'
                  }"
                  class="green active"
                ></span>
              </div>
            </div>

            <div
              *ngIf="
                attribute.group === undefined && attribute.type !== 'TYPE_TEXT'
              "
              class="nm-attribute-list-addtext"
            ></div>

            <button
              mat-icon-button
              primary
              (click)="hideAttribute(attribute)"
              popover="{{
                configuration.configuration['remove-popover'] | translate
              }}"
              placement="top"
              container="body"
              triggers="mouseenter:mouseleave"
            >
              <mat-icon class="primary-color mat-24">close</mat-icon>
            </button>

            <nm-action-icon
              *ngIf="
                attribute._actions &&
                attribute._actions.delete &&
                context === 'content'
              "
              [action]="attribute._actions.delete"
              [name]="deleteName"
            ></nm-action-icon>
            <button
              *ngIf="context !== 'content'"
              mat-icon-button
              primary
              (click)="deleteAttribute(attribute)"
              popover="{{
                configuration.configuration['delete-popover'] | translate
              }}"
              placement="top"
              container="body"
              triggers="mouseenter:mouseleave"
              [disabled]="attribute['read-only']"
            >
              <mat-icon class="primary-color mat-24">not_interested</mat-icon>
            </button>
          </div>
        </ng-template>
      </p-dataGrid>
    </div>
    <div
      class="nm-select"
      style="max-width: 200px; z-index: 111; position: absolute; bottom: 0px"
    >
      <mat-form-field>
        <mat-select
          style="width: 100%"
          [(ngModel)]="selection"
          (selectionChange)="onSelectChange()"
          multiple
          (openedChange)="openedChange($event)"
          [placeholder]="
            configuration.configuration['select-placeholder'] | translate
          "
          [name]=""
          [id]=""
        >
          <mat-option>
            <ngx-mat-select-search
              [formControl]="filterCtrl"
              placeholderLabel="{{ 'placeholder.search' | translate }}"
            ></ngx-mat-select-search>
          </mat-option>
          <mat-option
            *ngFor="let attribute of filteredOptions"
            [value]="attribute.identifier"
          >
            {{ attribute.description }}
          </mat-option>
        </mat-select>
      </mat-form-field>
      <br />
    </div>
  </div>
</nm-widgetframe>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""