@WidgetComponent

nm-color-list-sort

File

src/app/shared/widgets/apps/my-shop-md/color-list-sort/color-list-sort.component.ts

Implements

OnInit OnDestroy AfterViewInit

Metadata

changeDetection ChangeDetectionStrategy.OnPush
host {
}
selector nm-color-list-sort
styleUrls color-list-sort.component.scss
templateUrl ./color-list-sort.component.html

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(_shopCategoryService: ShopCategoryService, _progressbarService: ProgressbarService, halService: HalService, zone: NgZone, dragAndDrop: DragAndDropService, _notificationService: CustomNotificationService, localStorageService: LocalStorageService, _changeDetectorRef: ChangeDetectorRef, dialog: MatDialog)
Parameters :
Name Type Optional
_shopCategoryService ShopCategoryService no
_progressbarService ProgressbarService no
halService HalService no
zone NgZone no
dragAndDrop DragAndDropService no
_notificationService CustomNotificationService no
localStorageService LocalStorageService no
_changeDetectorRef ChangeDetectorRef no
dialog MatDialog no

Methods

Private acceptsDragFrom
acceptsDragFrom(source: )
Parameters :
Name Optional
source no
Returns : boolean
beginDragging
beginDragging()
Returns : void
Private canDrag
canDrag()
Returns : boolean
Private canStartDrag
canStartDrag()
Returns : boolean
clearAllSelectedRows
clearAllSelectedRows()
Returns : void
Protected configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure
Parameters :
Name Type Optional
configuration WidgetConfig no
Returns : void
getRowStyleClass
getRowStyleClass(result: )
Parameters :
Name Optional
result no
Returns : any
initDnD
initDnD()
Returns : void
initInputChannel
initInputChannel()
Returns : void
isEmpty
isEmpty(obj: )
Parameters :
Name Optional
obj no
Returns : boolean
keydown
keydown(event: any)
Parameters :
Name Type Optional
event any no
Returns : void
keyup
keyup(event: any)
Parameters :
Name Type Optional
event any no
Returns : void
loadMore
loadMore()
Returns : void
Private mapResult
mapResult(data: )
Parameters :
Name Optional
data no
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onFilter
onFilter(event: )
Parameters :
Name Optional
event no
Returns : void
reload
reload()
Returns : void
resetInputChannel
resetInputChannel()
Returns : void
selectRowsBetweenIndexes
selectRowsBetweenIndexes(indexes: )
Parameters :
Name Optional
indexes no
Returns : void
showDetailsPopup
showDetailsPopup()
Returns : void
sortTable
sortTable(identifiers: )
Parameters :
Name Optional
identifiers no
Returns : void
toggleRow
toggleRow(result: )
Parameters :
Name Optional
result no
Returns : void
trim
trim(arr: , key: )
Parameters :
Name Optional
arr no
key no
Returns : any

Properties

Public _id
_id:
Decorators : WidgetId
Private acceptDragFrom
acceptDragFrom: string[]
Type : string[]
Public addDetailsPopup
addDetailsPopup: boolean
Type : boolean
Private allowDragPreInit
allowDragPreInit: boolean
Type : boolean
Public attachActionIdentifier
attachActionIdentifier: string
Type : string
Public categoryDescription
categoryDescription: string
Type : string
Public categoryDescriptionNeedsTooltip
categoryDescriptionNeedsTooltip: boolean
Type : boolean
Private clearSelectionChannel
clearSelectionChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput
Public cols
cols: Subject<any[]>
Type : Subject<any[]>
Default value : new BehaviorSubject([])
Public configuration
configuration: WidgetConfig
Type : WidgetConfig
Decorators : WidgetConfiguration
Public ctrlIsPressed
ctrlIsPressed: boolean
Type : boolean
Private data
data: any
Type : any
Public dialog
dialog: MatDialog
Type : MatDialog
Public input
input:
Default value : new Subject<any>()
Decorators : WidgetInput
Private inputChannel
inputChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput
Private inputChannelSub
inputChannelSub:
Private isLoading
isLoading:
Default value : false
Private isLoadingMore
isLoadingMore:
Default value : false
Public isMultiselectActionNeeded
isMultiselectActionNeeded: boolean
Type : boolean
Default value : false
Public isRestoreState
isRestoreState: boolean
Type : boolean
Default value : true
Public lastSelectedRow
lastSelectedRow: Result
Type : Result
Private lastUriEntry
lastUriEntry: LocalStorageEntry
Type : LocalStorageEntry
Public loadMoreUri
loadMoreUri: string
Type : string
Default value : ""
Public multiselectaction
multiselectaction: Subject<any>
Type : Subject<any>
Default value : new BehaviorSubject({})
Public multiselectpayload
multiselectpayload: Subject<any>
Type : Subject<any>
Default value : new BehaviorSubject({})
Public popupfilter
popupfilter: any[]
Type : any[]
Private reloadChannel
reloadChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput
Public removeActionIdentifier
removeActionIdentifier: string
Type : string
Public removeMultipleActionIdentifier
removeMultipleActionIdentifier: string
Type : string
Private resetChannel
resetChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput
Public results
results: Subject<Result[]>
Type : Subject<Result[]>
Default value : new BehaviorSubject([])
Public rowStyleClassFunction
rowStyleClassFunction: null
Type : null
Default value : null
Public rowStyleClassFunctionInput
rowStyleClassFunctionInput:
Default value : new Subject<any>()
Decorators : WidgetInput

Input for a function that will be used to compute the style class of a row

Private selectedItems
selectedItems: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetOutput
Public selectedRowIndex
selectedRowIndex: Number
Type : Number
Public selectedRows
selectedRows: Result[]
Type : Result[]
Default value : []
setClickedRow
setClickedRow:
Default value : function (index, result) { if (this.ctrlIsPressed) { this.toggleRow(result); } if (this.shiftIsPressed) { this.selectRowsBetweenIndexes([ this.totalresults._embedded[this.dataType].indexOf( this.lastSelectedRow ), index, ]); } if (!this.ctrlIsPressed && !this.shiftIsPressed) { this.clearAllSelectedRows(); this.toggleRow(result); } }
Public shiftIsPressed
shiftIsPressed: boolean
Type : boolean
Public showReload
showReload: boolean
Type : boolean
Public title
title: string
Type : string
Public total
total: BehaviorSubject<number>
Type : BehaviorSubject<number>
Default value : new BehaviorSubject(null)
Public totalresults
totalresults: any
Type : any
Public trimmed
trimmed: any
Type : any
Private unsubscribe
unsubscribe:
Default value : NgUnsubscribe.create()
Public wikiLink
wikiLink: string
Type : string
import { mergeMap, takeUntil, filter, switchMap, tap } from "rxjs/operators";
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  Input,
  NgZone,
  OnDestroy,
  OnInit,
} from "@angular/core";
import { Subject, BehaviorSubject } from "rxjs";
import { ProgressbarService } from "../../../../components/progressbar/progressbar.service";
import { getOrDefault, WidgetConfig } from "../../../widget.configuration";
import { ShopCategoryService } from "../shop-category/shop-category.service";
import { HalService } from "../../../../components/hal/hal.service";
import { MatDialog } from "@angular/material/dialog";
import { ShopCategoryDetailsPopupComponent } from "../shop-category/shop-category-details-popup.component";

import { CustomNotificationService } from "../../../../components/notification/customnotification.service";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetId,
  WidgetInput,
  WidgetOutput,
} from "../../../widget.metadata";

import { Result } from "../../../interfaces/list.interfaces";
import { NgUnsubscribe } from "../../../../ng-unsubscribe";
import { ActionRequest } from "../../../../components/hal/actionRequest";
import { DragAndDropService } from "../../../../components/util/drag-and-drop.service";
import {
  DeletionMode,
  Scope,
} from "../../../../components/local-storage/local-storage-constants";
import {
  LocalStorageEntry,
  LocalStorageService,
} from "../../../../components/local-storage/local-storage.service";

declare var $;
declare var jQuery: any;

@WidgetComponent("nm-color-list-sort")
@Component({
  selector: "nm-color-list-sort",
  templateUrl: "./color-list-sort.component.html",
  styleUrls: ["./color-list-sort.component.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    "(window:keydown)": "keydown($event)",
    "(window:keyup)": "keyup($event)",
  },
})
export class ColorListSortWidgetComponent
  implements OnInit, OnDestroy, AfterViewInit {
  public results: Subject<Result[]> = new BehaviorSubject([]);
  public multiselectaction: Subject<any> = new BehaviorSubject({});
  public multiselectpayload: Subject<any> = new BehaviorSubject({});
  public isMultiselectActionNeeded: boolean = false;
  public total: BehaviorSubject<number> = new BehaviorSubject(null);
  public cols: Subject<any[]> = new BehaviorSubject([]);

  public showReload: boolean;
  public addDetailsPopup: boolean;
  public totalresults: any;
  public selectedRows: Result[] = [];
  public shiftIsPressed: boolean;
  public ctrlIsPressed: boolean;

  public lastSelectedRow: Result;

  public wikiLink: string;
  public title: string;
  public categoryDescription: string;
  public loadMoreUri: string = "";

  public selectedRowIndex: Number;
  public categoryDescriptionNeedsTooltip: boolean;

  public attachActionIdentifier: string;
  public removeActionIdentifier: string;
  public removeMultipleActionIdentifier: string;
  public trimmed: any;
  public popupfilter: any[];
  public isRestoreState: boolean = true;
  private acceptDragFrom: string[];
  private allowDragPreInit: boolean;
  public rowStyleClassFunction = null;

  @Input("inputLink") inputLink: string;

  @Input("dataType") dataType: string = "products";

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

  @WidgetId()
  public _id;

  @WidgetConfiguration()
  public configuration: WidgetConfig;

  @WidgetInput("uri")
  private inputChannel: Subject<any> = new Subject<any>();

  @WidgetInput("reload")
  private reloadChannel: Subject<any> = new Subject<any>();

  @WidgetInput("clearSelection")
  private clearSelectionChannel: Subject<any> = new Subject<any>();

  @WidgetOutput("selectedItems")
  private selectedItems: Subject<any> = new Subject<any>();

  @WidgetInput("reset")
  private resetChannel: Subject<any> = new Subject<any>();

  /**
   * Input for a function that will be used to compute the style class of a row
   */
  @WidgetInput("rowStyleClassFunction")
  public rowStyleClassFunctionInput = new Subject<any>();

  private unsubscribe = NgUnsubscribe.create();
  private data: any;

  private lastUriEntry: LocalStorageEntry;
  private isLoading = false;
  private isLoadingMore = false;
  private inputChannelSub;

  constructor(
    private _shopCategoryService: ShopCategoryService,
    private _progressbarService: ProgressbarService,
    private halService: HalService,
    private zone: NgZone,
    private dragAndDrop: DragAndDropService,
    private _notificationService: CustomNotificationService,
    private localStorageService: LocalStorageService,
    private _changeDetectorRef: ChangeDetectorRef,
    public dialog: MatDialog
  ) {}

  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    this.cols.next(
      configuration.configuration["profiles"][
        configuration.configuration["default-profile"]
      ]
    );
    this.dataType = configuration.configuration["dataType"];
    this.title = this.configuration.configuration["title"];
    this.lastUriEntry = this.localStorageService.getLocalStorageEntry(
      "nm-lasturi-" + this.title,
      Scope.GLOBAL,
      DeletionMode.LOGIN
    );
    this.wikiLink = this.configuration.configuration["wikiLink"];

    this.showReload = getOrDefault(
      configuration.configuration["showReload"],
      true
    );

    this.attachActionIdentifier = this.configuration.configuration[
      "attachActionIdentifier"
    ];
    this.removeActionIdentifier = this.configuration.configuration[
      "removeActionIdentifier"
    ];
    this.removeMultipleActionIdentifier = this.configuration.configuration[
      "removeMultipleActionIdentifier"
    ];
    this.popupfilter = this.configuration.configuration["popupfilter"];
    this.isRestoreState =
      configuration.configuration["restoreState"] !== undefined
        ? configuration.configuration["restoreState"]
        : true;
    this.addDetailsPopup =
      this.configuration.configuration["addDetailsPopup"] != undefined
        ? this.configuration.configuration["addDetailsPopup"]
        : false;
    const acceptDragFrom = configuration.configuration["acceptDragFrom"];
    if (acceptDragFrom && !Array.isArray(acceptDragFrom)) {
      this.acceptDragFrom = [acceptDragFrom];
    } else {
      this.acceptDragFrom = acceptDragFrom;
    }
    this.allowDragPreInit = getOrDefault(
      configuration.configuration["allowDragPreInit"],
      false
    );

    //this.headerAction = this.configuration.configuration['headerAction']

    this.resetChannel.asObservable().subscribe((reset) => {
      this.total.next(null);
      this.results.next([]);
      this.lastUriEntry.clear();
      this.resetInputChannel();
    });

    this.reloadChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reload) => {
        this.reload();
      });
  }

  initInputChannel() {
    this.inputChannelSub = this.inputChannel
      .pipe(
        tap((resp) => {
          this.lastUriEntry.value = resp;
          this._shopCategoryService.setCurrentDimensionUri(this._id, resp);
          if (this.isLoading) {
            this._progressbarService.requestFinished();
          }
          this.isLoading = true;
        }),
        mergeMap((resp) => {
          return this._shopCategoryService.loadOrderedResults(resp);
        }),
        takeUntil(this.unsubscribe)
      )
      .subscribe((data) => {
        this.isLoading = false;
        this._shopCategoryService.setOrderedResults(this._id, data);
        this._changeDetectorRef.markForCheck();
      });
  }

  resetInputChannel() {
    this.inputChannelSub.unsubscribe();
    if (this.isLoading) {
      this._progressbarService.requestFinished();
      this.isLoading = false;
    }

    this.initInputChannel();
  }

  ngOnInit() {
    this.initInputChannel();
    if (this.isRestoreState) {
      const lastUri = this.lastUriEntry.value;
      if (lastUri) {
        this.inputChannel.next(lastUri);
      }
    }

    this.halService
      .getActionEvents()
      .pipe(
        takeUntil(this.unsubscribe),
        filter((event) => event.name === this.removeActionIdentifier),
        switchMap((resp) => {
          let payload = resp.action.payload;
          let action = payload.action;

          let identifiers = new Set();
          if (this.selectedRows.length > 0) {
            this.selectedRows.forEach((item) =>
              identifiers.add(item.identifier)
            );
          } else {
            identifiers.add(payload.dimension);
          }
          this.selectedRows = [];
          action.payload = { identifiers: Array.from(identifiers) };
          return this.halService.execute(
            this.removeMultipleActionIdentifier,
            action
          );
        })
      )
      .subscribe();

    this.halService
      .getActionEvents()
      .pipe(
        takeUntil(this.unsubscribe),
        filter((event) => event.name === this.removeMultipleActionIdentifier)
      )
      .subscribe((resp) => {
        this._notificationService.fromJson(resp.response);
        this.reload();
      });

    this._shopCategoryService
      .getOrderedResults(this._id)
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        this.results.next(null);
        this.mapResult(data);
      });

    this.rowStyleClassFunctionInput
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((fn) => (this.rowStyleClassFunction = fn));
  }

  getRowStyleClass(result) {
    return this.rowStyleClassFunction
      ? this.rowStyleClassFunction.call(this, result)
      : "";
  }

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

  ngAfterViewInit(): void {
    this.initDnD();
  }

  initDnD(): void {
    let self = this;
    //TODO:  remove this if backend algorithmen is improved. Meanwihle this dislables multiselect in same table;
    let notConsecuciveMultiselecting: boolean = false;
    this.zone.runOutsideAngular(() => {
      let table = jQuery("#" + self._id + " .nm-color-list-sort tbody");
      if (!!table.sortable("instance")) {
        table.sortable("destroy");
      }

      table.sortable({
        placeholder: "ui-state-placeholder",
        cursor: "grabbing",
        delay: 50,
        accept: ".ui-widget-content.ui-state-highlight", // prevent drops from details-popup
        revert: false,
        receive: function (event, element) {
          if (!self.canDrag()) {
            $(this).sortable("cancel");
          }
        },
        helper: function (event, element) {
          var selected = $(
            "#" + self._id + " .nm-color-list-sort tr.ui-state-highlight"
          );
          notConsecuciveMultiselecting = false;
          if (selected.length === 0) {
            return element.clone();
          }
          const index = selected.index(element);
          if (index === -1) {
            return element.clone();
          }
          if (selected.length > 1) {
            for (let selectedRow of self.selectedRows) {
              self.totalresults._embedded[self.dataType].indexOf(selectedRow);
            }

            for (let index = 0; index < self.selectedRows.length; index++) {
              let element = self.selectedRows[index];
              let indexOfSelectedRow = self.totalresults._embedded[
                self.dataType
              ].indexOf(self.selectedRows[index]);
              if (self.selectedRows[index + 1] != undefined) {
                if (
                  indexOfSelectedRow -
                    self.totalresults._embedded[self.dataType].indexOf(
                      self.selectedRows[index + 1]
                    ) !==
                  -1
                ) {
                  notConsecuciveMultiselecting = true;
                }
              }
            }
          }
          var container = $("<tr/>").attr("id", "draggingContainer");
          container.append(selected.clone());
          return container;
        },
        start: function (e, ui) {
          if (!self.canStartDrag()) {
            return;
          }

          self.beginDragging();
          $(".custom-node.ui-droppable").removeClass("ui-droppable-hover");
        },

        stop: function (e, ui) {
          if (!self.canDrag()) {
            return;
          }
          let dragged = self.dragAndDrop.completeDrag();
          if (!dragged) {
            return;
          }
          if (notConsecuciveMultiselecting) {
            notConsecuciveMultiselecting = false;
            table.sortable("cancel");
          } else {
            notConsecuciveMultiselecting = false;
            let prev = jQuery(ui.item[0]).prev();

            var prevId = null;
            if (prev.length > 0) {
              const id = jQuery(prev[0]).attr("id");
              if (id) {
                prevId = jQuery(prev[0]).attr("id").trim();
              }
            }

            ui.placeholder.remove();
            if (ui.helper) {
              ui.helper.remove();
            }

            if (ui.item && dragged && dragged.source !== "color-list-sort") {
              ui.item.remove();
            }
            // Make a deep copy of the dragged elements to prevent modifying actions of an item that is still diplayed in another list
            let draggedColors = JSON.parse(
              JSON.stringify(<Result[]>dragged.data)
            );
            let identifiers: Set<string> = new Set<string>(
              draggedColors.map((item) => item.identifier)
            );
            var action: ActionRequest;
            if (!self.totalresults) {
              if (!self.allowDragPreInit) {
                return;
              }
            } else {
              // remove moved objects
              let result = Object.assign({}, self.totalresults);
              let dimensions = result._embedded[self.dataType].filter(
                (item) => !identifiers.has(item.identifier)
              );

              let index = !!prevId
                ? dimensions.findIndex((item) => item.identifier == prevId) + 1
                : 0;
              draggedColors.forEach((color) => {
                const anyd = <any>color;
                anyd._actions = {};
              });
              dimensions.splice(index, 0, ...draggedColors);
              result._embedded[self.dataType] = dimensions;
              self.zone.run(() => {
                self._shopCategoryService.setOrderedResults(self._id, result);
              });
              // find action to save data to ipim
              action = result._actions[self.attachActionIdentifier];
            }

            if (!action) {
              // We have no action! This can have two reasons
              // 1. This list allows preDragInit, which means we wont get the actions via rest but need to build it ourself
              // 2. The backend is broken and forgot to send the action
              if (self.allowDragPreInit) {
                action = {
                  type: "event",
                  method: null,
                  payload: {},
                  title: null,
                  href: null,
                };
              } else {
                console.error(
                  "No action found to handle attach action in color-list-sort"
                );
              }
            }
            action.payload.identifiers = Array.from(identifiers);
            // action may be pre-filled from previous execution of the same action
            // reset all values
            if (!prevId) {
              action.payload.anchor = null;
            } else {
              action.payload.anchor = prevId;
            }
            self.zone.run(() => {
              self.halService
                .execute(self.attachActionIdentifier, action)
                .subscribe();
            });
          }
        },
      });
      table.disableSelection();
    });
  }

  beginDragging(): void {
    if (!this.totalresults) {
      return;
    }
    const rows = $("tr:hover");
    const dataIndex = rows.parent().children().index(rows);
    const hoveredRow = this.totalresults["_embedded"][this.dataType][dataIndex];

    if (this.selectedRows.length === 0) {
      this.dragAndDrop.registerDrag("color-list-sort", [].concat([hoveredRow]));
    } else {
      var selected = $(
        "#" + this._id + " .nm-color-list-sort tr.ui-state-highlight"
      );
      const index = selected.index(rows);
      if (index === -1) {
        // We are dragging a non selected row
        this.dragAndDrop.registerDrag("color-list-sort", [].concat(hoveredRow));
      } else {
        this.dragAndDrop.registerDrag(
          "color-list-sort",
          [].concat(this.selectedRows)
        );
      }
    }
  }

  private canStartDrag() {
    //If there is nothing dragged this means that we are the one starting to drag
    if (!this.dragAndDrop.current) {
      return true;
    }
    return this.canDrag();
  }

  private canDrag() {
    const dragged = this.dragAndDrop.current;
    if (!dragged) {
      return true;
    }
    if (dragged.sourceWidget && this.acceptDragFrom) {
      if (!this.acceptsDragFrom(dragged.sourceWidget)) {
        return false;
      }
    }
    return true;
  }

  private acceptsDragFrom(source) {
    return this.acceptDragFrom.indexOf(source) !== -1;
  }

  private mapResult(data) {
    let count = data._embedded[this.dataType].length;
    if (count > 0) {
      data._actions = data._actions || {};
      for (var result of data._embedded[this.dataType]) {
        result["selected"] = false;

        result._actions = result._actions || {};
        result._actions[this.removeActionIdentifier] = {
          type: "event",
          payload: {
            action: data._actions[this.removeMultipleActionIdentifier],
            dimension: result.identifier,
          },
        };
        if (result.attributes) {
          for (var attribute of result.attributes.default) {
            result[attribute.identifier] = attribute.value;
          }
        }
      }
    }
    this.data = data;

    if (this.data["category-path"]) {
      let categoryString: string = this.data["category-path"].join("/");
      if (categoryString.length > 37) {
        this.categoryDescriptionNeedsTooltip = true;
      } else {
        this.categoryDescriptionNeedsTooltip = false;
      }

      this.categoryDescription = categoryString;
    }

    this.total.next(count);

    let trimmed = this.trim(data._embedded[this.dataType], "identifier");
    data._embedded[this.dataType] = trimmed;

    if (
      data._links != undefined &&
      data._links["dimensions-all"] != undefined
    ) {
      this.loadMoreUri = data._links["dimensions-all"].href.toString();
    } else {
      this.loadMoreUri = "";
    }
    this.totalresults = data;
    setTimeout(() => {
      this.results.next(trimmed);
    }, 1);
  }

  reload() {
    if (this._shopCategoryService.getCurrentDimensionUri(this._id)) {
      this._shopCategoryService
        .loadOrderedResults(
          this._shopCategoryService.getCurrentDimensionUri(this._id)
        )
        .subscribe((data) => {
          this._shopCategoryService.setOrderedResults(this._id, data);
          this._changeDetectorRef.markForCheck();
        });
    }
  }

  loadMore() {
    if (this.loadMoreUri.length === 0) {
      return;
    }
    this._shopCategoryService.setCurrentDimensionUri(
      this._id,
      this.loadMoreUri
    );
    if (this.isLoadingMore) {
      this._progressbarService.requestFinished();
    }
    this.isLoadingMore = true;
    this._shopCategoryService
      .loadOrderedResults(this.loadMoreUri)
      .subscribe((data) => {
        this._shopCategoryService.setOrderedResults(this._id, data);
        this._changeDetectorRef.markForCheck();
        this.isLoadingMore = false;
        this.loadMoreUri = "";
      });
  }

  isEmpty(obj) {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) return false;
    }
    return true;
  }

  keydown(event: any) {
    if (event.keyCode === 16) {
      this.shiftIsPressed = true;
    }

    if (event.keyCode === 17) {
      this.ctrlIsPressed = true;
    }
  }

  keyup(event: any) {
    if (event.keyCode === 16) {
      this.shiftIsPressed = false;
    }
    if (event.keyCode === 17) {
      this.ctrlIsPressed = false;
    }
  }

  setClickedRow = function (index, result) {
    if (this.ctrlIsPressed) {
      this.toggleRow(result);
    }

    if (this.shiftIsPressed) {
      this.selectRowsBetweenIndexes([
        this.totalresults._embedded[this.dataType].indexOf(
          this.lastSelectedRow
        ),
        index,
      ]);
    }

    if (!this.ctrlIsPressed && !this.shiftIsPressed) {
      this.clearAllSelectedRows();
      this.toggleRow(result);
    }
  };

  toggleRow(result) {
    result["selected"] = !result["selected"];
    this.selectedRows = this.totalresults._embedded[this.dataType].filter(
      (row) => row["selected"] == true
    );
    this.lastSelectedRow = result;
  }

  clearAllSelectedRows() {
    this.selectedRows = [];
    for (var result of this.totalresults._embedded[this.dataType]) {
      result["selected"] = false;
    }
  }

  selectRowsBetweenIndexes(indexes) {
    indexes.sort(function (a, b) {
      return a - b;
    });

    for (var i = indexes[0]; i <= indexes[1]; i++) {
      this.totalresults._embedded[this.dataType][i]["selected"] = true;
    }
    this.selectedRows = this.totalresults._embedded[this.dataType].filter(
      (row) => row["selected"] == true
    );
  }

  showDetailsPopup() {
    this.dialog.closeAll();
    let dialogRef = this.dialog.open(ShopCategoryDetailsPopupComponent);
    dialogRef.componentInstance.link = this._shopCategoryService.getCurrentDimensionUri(
      this._id
    );
    dialogRef.componentInstance.popupfilter = this.popupfilter;
    dialogRef.componentInstance.colorListIdentifier = this._id;
    dialogRef.componentInstance.attachActionIdentifier = this.attachActionIdentifier;
    dialogRef.componentInstance.slidevalue = getOrDefault(
      this.configuration.configuration["dialogDefaultSlideValue"],
      3
    );
    dialogRef.afterClosed().subscribe((response) => {
      this._changeDetectorRef.markForCheck();
    });
  }

  sortTable(identifiers) {
    let orderedtotalresults = [];

    for (var ident of identifiers) {
      for (var result of this.totalresults._embedded[this.dataType]) {
        if (ident.trim() == result.identifier) {
          orderedtotalresults.push(result);
          break;
        }
      }
    }
    this.totalresults._embedded[this.dataType] = orderedtotalresults;
    this._shopCategoryService.setOrderedResults(
      this._id,
      this.totalresults._embedded[this.dataType]
    );
  }

  onFilter(event) {
    if (event.filters != {}) {
      jQuery(".nm-color-list-sort tbody").sortable("disable");
    } else {
      jQuery(".nm-color-list-sort tbody").sortable("enable");
    }
  }

  trim(arr, key) {
    var values = {};
    return arr.filter(function (item) {
      var val = item[key];
      var exists = values[val];
      values[val] = true;
      return !exists;
    });
  }
}
<nm-widgetframe [header]="configuration.configuration['header']">
  <div
    slot="title"
    class="nm-widgetframe__title nm-widgetframe__title-dimension-list"
  >
    {{ title | translate }}
    <span *ngIf="total | async as totalValue">&nbsp;({{ totalValue }})</span>
    <span
      class="nm-widgetframe-categoryPath"
      *ngIf="categoryDescription != null"
      popover="{{ categoryDescription }}"
      >&nbsp;in&nbsp;{{ categoryDescription }}</span
    >
    <div
      style="position: absolute; display: inline; right: 54px; margin-top: -8px"
    >
      <button
        *ngIf="addDetailsPopup"
        popover=" {{
          'app.ipim-my-shop-md.placeholder.addDetailsPopup' | translate
        }}"
        placement="left"
        container="body"
        triggers="mouseenter:mouseleave"
        mat-icon-button
        (click)="showDetailsPopup()"
      >
        <mat-icon>remove_red_eye</mat-icon>
      </button>
      <button
        *ngIf="loadMoreUri.length > 0"
        popover=" {{ 'app.ipim-my-shop-md.placeholder.loadmore' | translate }}"
        placement="left"
        container="body"
        triggers="mouseenter:mouseleave"
        mat-icon-button
        (click)="loadMore()"
      >
        <mat-icon>more</mat-icon>
      </button>
      <button
        *ngIf="showReload && (total | async)"
        mat-icon-button
        (click)="reload()"
      >
        <mat-icon>refresh</mat-icon>
      </button>
      <nm-help-icon
        [info-text]="configuration.configuration['infoText'] | translate"
        [info-title]="configuration.configuration['title'] | translate"
        [info-placement]="'left'"
        [wiki-link]="configuration.configuration['wikiLink']"
      ></nm-help-icon>
    </div>
  </div>

  <div
    slot="content"
    class="nm-widgetframe__content"
    class="nm-color-list-sort"
    style="overflow: hidden"
  >
    <table style="width: 100%; table-layout: fixed">
      <thead class="ui-datatable-thead">
        <tr class="ui-state-default ui-draggable ui-draggable-handle">
          <th
            class="ui-state-default nm-table-header"
            *ngFor="let col of cols | async"
            style="
              text-overflow: ellipsis;
              white-space: nowrap;
              overflow: hidden;
            "
          >
            <span
              style="
                text-overflow: ellipsis;
                white-space: nowrap;
                overflow: hidden;
              "
            >
              {{ col.header | translate }}
            </span>
          </th>
        </tr>
      </thead>

      <tbody
        class="ui-datatable-data ui-widget-content ui-datatable-hoverable-rows"
      >
        <tr
          id="{{ result.identifier }}"
          class="ui-widget-content"
          *ngFor="let result of results | async; let i = index"
          [ngClass]="getRowStyleClass(result)"
          (click)="setClickedRow(i, result)"
          [class.ui-state-highlight]="result.selected === true"
        >
          <td *ngFor="let col of cols | async">
            <ng-container [ngSwitch]="col.field">
              <nm-image
                *ngSwitchCase="'main-asset'"
                [container]="result"
                asset="main-asset"
                size="thumbnail"
                width="auto"
                height="auto"
                max-width="48px"
                max-height="48px"
              ></nm-image>

              <div class="nm-actions" *ngSwitchCase="'links'">
                <span *ngFor="let act of result._actions | iterable">
                  <nm-action-icon
                    *ngIf="
                      act.key != 'my-shopMd-move-after' ||
                      act.key != '_$visited'
                    "
                    [action]="act.value"
                    [name]="act.key"
                  >
                  </nm-action-icon>
                </span>
              </div>

              <div
                class="nm-break"
                *ngSwitchDefault
                pTooltip="{{ result[col.field] }}"
              >
                {{ result[col.field] }}
              </div>
            </ng-container>
          </td>
        </tr>
        <tr
          class="ui-widget-content empty-message-container"
          *ngIf="!(total | async)"
        >
          <td colspan="6" class="nm-table-empty-message">
            {{ "table.emptytext.product" | translate }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</nm-widgetframe>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""