@linid-dm/directory-manager-client-core
Version:
Core package by providing a set of angular components for the Directory Manager app.
393 lines • 97.7 kB
JavaScript
import { __decorate } from "tslib";
/**
* Copyright (C) 2020-2024 Linagora
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version, provided you comply with the Additional Terms applicable for
* LinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU
* Affero General Public License, subsections (b), (c), and (e), pursuant to
* which these Appropriate Legal Notices must notably (i) retain the display of
* the "LinID™" trademark/logo at the top of the interface window, the display
* of the “You are using the Open Source and free version of LinID™, powered by
* Linagora © 2009–2013. Contribute to LinID R&D by subscribing to an Enterprise
* offer!” infobox and in the e-mails sent with the Program, notice appended to
* any type of outbound messages (e.g. e-mail and meeting requests) as well as
* in the LinID Directory Manager user interface, (ii) retain all hypertext
* links between LinID Directory Manager and https://linid.org/, as well as
* between LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA
* intellectual property rights over its trademarks and commercial brands. Other
* Additional Terms apply, see <http://www.linagora.com/licenses/> for more
* details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License and
* its applicable Additional Terms for LinID Directory Manager along with this
* program. If not, see <http://www.gnu.org/licenses/> for the GNU Affero
* General Public License version 3 and <http://www.linagora.com/licenses/> for
* the Additional Terms applicable to the LinID Directory Manager software.
*/
import { SelectionModel } from '@angular/cdk/collections';
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewChildren, } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatRow } from '@angular/material/table';
import { Select } from '@ngxs/store';
import { Subject, debounceTime, distinctUntilChanged, filter, map, takeUntil, tap, } from 'rxjs';
import { Data, DataState, UiState, canDeleteEntry, canMoveEntry, emptyJsTable, getSelectedElementIds, getSelectedElementsDependsOnMode, getUpdatedDisplayedColumns, isRowEditable, mergeInto, optionsPaginator, sortData, } from '../../shared';
import * as i0 from "@angular/core";
import * as i1 from "@ngxs/store";
import * as i2 from "@angular/router";
import * as i3 from "@angular/common";
import * as i4 from "@angular/forms";
import * as i5 from "@angular/flex-layout/flex";
import * as i6 from "@angular/flex-layout/extended";
import * as i7 from "@angular/material/button";
import * as i8 from "@angular/material/checkbox";
import * as i9 from "@angular/material/form-field";
import * as i10 from "@angular/material/icon";
import * as i11 from "@angular/material/input";
import * as i12 from "@angular/material/paginator";
import * as i13 from "@angular/material/sort";
import * as i14 from "@angular/material/table";
import * as i15 from "@angular/material/tooltip";
import * as i16 from "../../shared/pipes/type-casting";
/**
* This class is a generic and configurable table to be used for every data table.
*/
export class GenericArrayComponent {
set selectedElementsUiIds(selectedElementsUiIds) {
if (selectedElementsUiIds) {
this._selectedElementsUiIds = selectedElementsUiIds;
}
}
get selectedElementsUiIds() {
return this._selectedElementsUiIds;
}
set dataSource(dataSource) {
if (dataSource) {
this._dataSource = dataSource;
this.dataSource.data = this.dataSource.data.map((row) => {
const canEditRow = isRowEditable(this.isAttributeArray, this.updateAffectAnotherResourceType, this.fieldForUpdate, this.isEditableArray, row);
return {
...row,
isRowEditable: canEditRow,
canMoveEntry: canMoveEntry(this.actions, this.canAssignOrMoveEntries, this.isSelectOnlyModeEnabled, canEditRow),
canDeleteEntry: canDeleteEntry(this.actions, this.isSelectOnlyModeEnabled, canEditRow),
selectionIds: getSelectedElementIds(row, this.selectionColumnId),
};
});
this.displayedColumns = getUpdatedDisplayedColumns(this.actions, this.initialDisplayedColumns, this.isSelectOnlyModeEnabled, this.canAssignOrMoveEntries, this.isEditableArray, this.updateAffectAnotherResourceType, this.isAttributeArray, this.dataSource.data);
this.dataSource.filterPredicate = (data, filter) => this.initialDisplayedColumns
.filter((columnId) => columnId !== 'select' && columnId !== 'actions')
.some((columnId) => !!data[columnId] &&
((Array.isArray(data[columnId]) &&
data[columnId].some((cellElt) => {
const value = typeof cellElt === 'string' ? cellElt : cellElt.value;
return value
.getRidOfDiacritics()
.toLocaleUpperCase()
.includes(filter.getRidOfDiacritics().toLocaleUpperCase());
})) ||
(typeof data[columnId] === 'string' &&
data[columnId]
.getRidOfDiacritics()
.toLocaleUpperCase()
.includes(filter.getRidOfDiacritics().toLocaleUpperCase()))));
this.dataSource.sortData = (data, sort) => sortData(data, sort);
if (this.filter && this.filter !== '') {
this.dataSource.filter = this.filter.trim();
}
const nbTotalResults = dataSource.data.length;
this.optionsNbItemsPerPage = optionsPaginator(nbTotalResults);
const pageSize = nbTotalResults > 10 ? 10 : nbTotalResults;
this.paginator._changePageSize(pageSize);
this._dataSource.paginator = this.paginator;
}
this.selection = new SelectionModel(true, this._selectedElementsUiIds && this._selectedElementsUiIds.length > 0
? this.dataSource.filteredData.filter((elt) => this._selectedElementsUiIds.find((selectedElementUiIds) => selectedElementUiIds.id === elt.selectionIds.id))
: []);
}
get dataSource() {
return this._dataSource;
}
set selectedResourceRootTypeId(selectedResourceRootTypeId) {
if (selectedResourceRootTypeId) {
this.filter = this._dataJsTable.byId[selectedResourceRootTypeId]
? this._dataJsTable.byId[selectedResourceRootTypeId].filterValue
: '';
this._selectedResourceRootTypeId = selectedResourceRootTypeId;
}
}
get selectedResourceRootTypeId() {
return this._selectedResourceRootTypeId;
}
constructor(_store$, _router) {
this._store$ = _store$;
this._router = _router;
this.filter = '';
this.isClickableRow = false;
this.isSelectOnlyModeEnabled = false;
this.canAssignOrMoveEntries = false;
this.isAttributeArray = false;
this.isEditableArray = false;
this.selectedData = new EventEmitter();
this.optionsNbItemsPerPage = [];
this.displayEllipsisFromTableRow = true;
this._selectedDataBeforeApplyFilter = new Set();
this._dataJsTable = emptyJsTable();
this._modelChanged = new Subject();
this._onDestroy$ = new Subject();
}
ngOnInit() {
if (!this.isAttributeArray) {
this._modelChanged
.pipe(debounceTime(300), takeUntil(this._onDestroy$), tap((currentSearch) => {
this._store$.dispatch(new Data.SetFilterValue({
filterValue: currentSearch,
dataTypeId: this.selectedResourceRootTypeId,
}));
}))
.subscribe();
this.dataJsTable$
.pipe(takeUntil(this._onDestroy$), map((dataJsTable) => {
this._dataJsTable = mergeInto(this._dataJsTable, dataJsTable);
return !!this.selectedResourceRootTypeId &&
this._dataJsTable.byId[this.selectedResourceRootTypeId]
?.filterValue
? this._dataJsTable.byId[this.selectedResourceRootTypeId]
.filterValue
: '';
}), distinctUntilChanged((prev, curr) => prev === curr), filter((filterValue) => !this.isSelectOnlyModeEnabled &&
filterValue !== undefined &&
filterValue !== null), tap((filterValue) => {
this.filter = filterValue;
this.applyFilter();
}))
.subscribe();
}
}
ngAfterViewInit() {
if (this._dataSource != null) {
this._dataSource.sort = this.sort;
}
}
updateArraySearch(search) {
if (this.isAttributeArray) {
this.filter = search;
this.applyFilter();
}
else {
this._modelChanged.next(search);
}
}
applyFilter() {
this.dataSource.filter = this.filter;
this.displayedColumns = getUpdatedDisplayedColumns(this.actions, this.initialDisplayedColumns, this.isSelectOnlyModeEnabled, this.canAssignOrMoveEntries, this.isEditableArray, this.updateAffectAnotherResourceType, this.isAttributeArray, this.dataSource.filteredData);
const filteredDataIds = this.dataSource.filteredData.map((data) => data.id);
this.selection.selected.forEach((selectedData) => {
if (!filteredDataIds.includes(selectedData.id)) {
this._selectedDataBeforeApplyFilter.add(selectedData);
this.selection.deselect(selectedData);
}
});
this._resetSelectedElementsBeforeFiltering(filteredDataIds);
this.selectedData.emit(getSelectedElementsDependsOnMode(this.isSelectOnlyModeEnabled, this.selection));
}
clearFilterInput() {
this._modelChanged.next('');
this.filter = '';
this.dataSource.filter = '';
this.displayedColumns = getUpdatedDisplayedColumns(this.actions, this.initialDisplayedColumns, this.isSelectOnlyModeEnabled, this.canAssignOrMoveEntries, this.isEditableArray, this.updateAffectAnotherResourceType, this.isAttributeArray, this.dataSource.filteredData);
this._resetSelectedElementsBeforeFiltering(this.dataSource.filteredData.map((data) => data.id));
this.selectedData.emit(getSelectedElementsDependsOnMode(this.isSelectOnlyModeEnabled, this.selection));
}
/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
let numSelected = 0;
let numRows = 0;
if (this.dataSource) {
numSelected = this.selection.selected.length;
numRows =
this.dataSource.filteredData &&
this.dataSource.filteredData !== undefined
? this.dataSource.filteredData.filter((data) => data.isRowEditable).length
: 0;
}
return numSelected === numRows && numSelected !== 0 && numRows !== 0;
}
/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
if (this.dataSource) {
this.isAllSelected()
? this.selection.clear()
: this.dataSource.filteredData.forEach((row) => {
if (row.isRowEditable) {
this.selection.select(row);
}
});
}
else {
this.selection.clear();
}
this.selectedData.emit(getSelectedElementsDependsOnMode(this.isSelectOnlyModeEnabled, this.selection));
}
/** The label for the checkbox on the passed row */
checkboxLabel(row) {
const arrayGenericAccessibility = this._store$.selectSnapshot(UiState.getArrayAccessibility);
if (!row) {
return this.isAllSelected()
? arrayGenericAccessibility.multipleDeselectionLabel
: arrayGenericAccessibility.multipleSelectionLabel;
}
return `${this.selection.isSelected(row)
? arrayGenericAccessibility.singleDeselectionLabel
: arrayGenericAccessibility.singleSelectionLabel} ${row.externalId}`;
}
checkSelection() {
this.selectedData.emit(getSelectedElementsDependsOnMode(this.isSelectOnlyModeEnabled, this.selection));
}
onKeyRedirect(link, id) {
this._router.navigateByUrl(link);
this.setEntryIdInStore(id);
}
onKeyRedirectFromRow(link, ids) {
this._router.navigateByUrl(link);
this.setEntryIdsInStore(ids);
}
onKeyArrowDown(index) {
if (index < this.matRows.length - 1) {
const newRow = this.matRows.get(index + 1).nativeElement;
if (newRow) {
newRow.focus();
}
}
}
onKeyArrowUp(index) {
if (index > 0) {
const newRow = this.matRows.get(index - 1).nativeElement;
if (newRow) {
newRow.focus();
}
}
}
getRowLink(externalId) {
let link = '';
return link.concat('/home', '/', this.endpoint, '/', encodeURIComponent(externalId));
}
isCellValueAnArray(elementValue) {
return Array.isArray(elementValue);
}
getDisplayedValueForArray(index, arrayLength, currentValue) {
return index === arrayLength - 1 ? currentValue : currentValue.concat(', ');
}
setEntryIdInStore(id, event = null) {
this._store$.dispatch(new Data.SetSelectedEntryId({ id }));
if (event !== null) {
event.stopPropagation();
}
}
setEntryIdsInStore(ids) {
this._store$.dispatch(new Data.SetSelectedEntryIds({ ids }));
}
getCellTitle(cellValue) {
if (cellValue == null) {
return '';
}
return Array.isArray(cellValue)
? cellValue.map((elt) => elt.value).join(', ')
: cellValue;
}
getTableMinHeight() {
const rowHeight = 48;
const tableHeaderHeight = 56;
let minHeight = 0;
if (!this.isSelectOnlyModeEnabled) {
minHeight =
this.dataSource.filteredData.length < 10
? tableHeaderHeight + rowHeight * this.dataSource.filteredData.length
: tableHeaderHeight + rowHeight * 10;
}
return minHeight;
}
_resetSelectedElementsBeforeFiltering(filteredIds) {
this._selectedDataBeforeApplyFilter.forEach((selectedData) => {
if (filteredIds.includes(selectedData.id)) {
this.selection.select(selectedData);
this._selectedDataBeforeApplyFilter.delete(selectedData);
}
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: GenericArrayComponent, deps: [{ token: i1.Store }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: GenericArrayComponent, selector: "dm-generic-array", inputs: { isClickableRow: "isClickableRow", isSelectOnlyModeEnabled: "isSelectOnlyModeEnabled", selectedElementsUiIds: "selectedElementsUiIds", dataSource: "dataSource", columns: "columns", initialDisplayedColumns: "initialDisplayedColumns", processingRequest$: "processingRequest$", actions: "actions", resourcesTypesProperties: "resourcesTypesProperties", configs: "configs", accessibility: "accessibility", endpoint: "endpoint", canAssignOrMoveEntries: "canAssignOrMoveEntries", selectedResourceRootTypeId: "selectedResourceRootTypeId", isAttributeArray: "isAttributeArray", updateAffectAnotherResourceType: "updateAffectAnotherResourceType", fieldForUpdate: "fieldForUpdate", isEditableArray: "isEditableArray", selectionColumnId: "selectionColumnId", actionsColumnTemplate: "actionsColumnTemplate" }, outputs: { selectedData: "selectedData" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, static: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "matRows", predicate: MatRow, descendants: true, read: ElementRef }], ngImport: i0, template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<div fxLayout=\"row wrap\" class=\"div-table-filter\">\n <mat-form-field\n *ngIf=\"filterAccessibility$ | async as filterAccessibility\"\n color=\"accent\"\n class=\"filter\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">filter_list_alt</mat-icon>\n {{ filterAccessibility.label }}\n </mat-label>\n <input\n type=\"text\"\n matInput\n [ngModel]=\"filter\"\n (ngModelChange)=\"updateArraySearch($event)\"\n />\n <button\n *ngIf=\"filter\"\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"filterAccessibility.clearSearch\"\n (click)=\"clearFilterInput()\"\n class=\"reset-input-btn\"\n matTooltip=\"{{ filterAccessibility.clearSearch }}\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </mat-form-field>\n <mat-paginator\n color=\"accent\"\n [pageSizeOptions]=\"optionsNbItemsPerPage\"\n showFirstLastButtons\n ></mat-paginator>\n</div>\n<div\n *ngIf=\"arrayGenericAccessibility$ | async as arrayGenericAccessibility\"\n class=\"div-table\"\n>\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n [attr.role]=\"accessibility.table\"\n >\n <caption>\n {{\n accessibility.table\n }}\n </caption>\n <ng-container matColumnDef=\"select\">\n <th\n mat-header-cell\n [attr.role]=\"arrayGenericAccessibility.selectColumn\"\n scope=\"col\"\n *matHeaderCellDef\n >\n <mat-checkbox\n [aria-label]=\"checkboxLabel()\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? masterToggle() : null\"\n >\n </mat-checkbox>\n </th>\n <td\n mat-cell\n [attr.role]=\"arrayGenericAccessibility.selectRow\"\n *matCellDef=\"let row\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-checkbox\n *ngIf=\"row.isRowEditable\"\n [aria-label]=\"checkboxLabel(row)\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null; checkSelection()\"\n >\n </mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container [matColumnDef]=\"column.id\" *ngFor=\"let column of columns\">\n <th\n mat-header-cell\n scope=\"col\"\n [attr.role]=\"\n arrayGenericAccessibility.columnHeader +\n column.label.toLocaleLowerCase()\n \"\n *matHeaderCellDef\n mat-sort-header\n [style.width]=\"column.width\"\n >\n {{ column.label }}\n </th>\n <td\n mat-cell\n [attr.role]=\"\n arrayGenericAccessibility.cell + column.label.toLocaleLowerCase()\n \"\n [title]=\"getCellTitle(element[column.id])\"\n [style.width]=\"column.width\"\n *matCellDef=\"let element\"\n >\n <div\n *ngIf=\"isCellValueAnArray(element[column?.id]); else oneStringValue\"\n >\n <span\n *ngFor=\"let cellObject of element[column.id]; let i = index\"\n [ngClass]=\"{\n 'element-link':\n !isSelectOnlyModeEnabled && cellObject.isClickable,\n element: i > 0\n }\"\n [routerLink]=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? cellObject.routerLinkValue\n : []\n \"\n (click)=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? setEntryIdInStore(cellObject.id, $event)\n : null\n \"\n (keydown.enter)=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? onKeyRedirect(cellObject.routerLinkValue, cellObject.id)\n : null\n \"\n >\n {{\n getDisplayedValueForArray(\n i,\n element[column.id].length,\n cellObject.value || cellObject\n )\n }}\n </span>\n </div>\n <ng-template #oneStringValue>\n <span>\n {{ element[column.id] }}\n </span>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container *ngIf=\"actionsColumnTemplate != null\" matColumnDef=\"actions\">\n <th\n mat-header-cell\n [attr.role]=\"arrayGenericAccessibility.actionsColumn\"\n scope=\"col\"\n *matHeaderCellDef\n >\n {{ arrayGenericAccessibility.actionsColumnLabel }}\n </th>\n <td\n mat-cell\n [attr.role]=\"arrayGenericAccessibility.actionsMenu\"\n *matCellDef=\"let row\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"actionsColumnTemplate\"\n [ngTemplateOutletContext]=\"{\n row\n }\"\n >\n </ng-container></td\n ></ng-container>\n\n <tr\n mat-header-row\n [attr.role]=\"accessibility.headerRow\"\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns; let i = index\"\n [id]=\"i\"\n [attr.role]=\"\n row.externalId ? accessibility.row + row.externalId : accessibility.row\n \"\n [ngClass]=\"{\n highlighted: selection.isSelected(row),\n hovered: !selection.isSelected(row) && isClickableRow,\n 'clickable-row-pointer': isClickableRow\n }\"\n [routerLink]=\"isClickableRow ? getRowLink(row.externalId) : []\"\n (click)=\"\n isClickableRow\n ? setEntryIdsInStore({ id: row.id, externalId: row.externalId })\n : null\n \"\n (keydown.enter)=\"\n isClickableRow\n ? onKeyRedirectFromRow(getRowLink(row.externalId), {\n id: row.id,\n externalId: row.externalId\n })\n : null\n \"\n (keydown.arrowdown)=\"onKeyArrowDown(i)\"\n (keydown.arrowup)=\"onKeyArrowUp(i)\"\n ></tr>\n\n <tr class=\"mat-row\" *matNoDataRow>\n <div fxLayoutAlign=\"center start\">\n <span\n class=\"placeholder-text\"\n [ngClass]=\"{ 'placeholder-detail-page-text': isAttributeArray }\"\n >\n {{\n isSelectOnlyModeEnabled && isAttributeArray\n ? (actions | asAttributeActions).assign.noFilterResult\n : actions.search.filter.noResult\n }}\n </span>\n </div>\n </tr>\n </table>\n</div>\n", styles: ["@charset \"UTF-8\";:host{min-width:100%;width:fit-content;display:flex;flex-direction:column}.div-table-filter{min-width:fit-content}table{box-shadow:none}table th:not(.mat-column-select,.mat-column-actions){cursor:pointer}.clickable-row-pointer{cursor:pointer}.filter{min-width:auto;flex-grow:1}.element{padding-left:4px}.element-link{cursor:pointer}.element-link:hover,.element-link:focus{font-weight:700}caption{margin:20px 0 10px;font-weight:700}mat-label{display:flex}.reset-input-btn{height:1.5em;width:1.5em;padding:0;display:flex;align-items:center;justify-content:center}.reset-input-btn mat-icon{font-size:inherit;height:auto;width:auto}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i5.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i5.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i6.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i8.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "directive", type: i9.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i14.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "directive", type: i15.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i16.CastToIAttributeActions, name: "asAttributeActions" }] }); }
}
__decorate([
Select(DataState.getDataJsTable)
], GenericArrayComponent.prototype, "dataJsTable$", void 0);
__decorate([
Select(UiState.getFilterAccessibility)
], GenericArrayComponent.prototype, "filterAccessibility$", void 0);
__decorate([
Select(UiState.getArrayAccessibility)
], GenericArrayComponent.prototype, "arrayGenericAccessibility$", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: GenericArrayComponent, decorators: [{
type: Component,
args: [{ selector: 'dm-generic-array', template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<div fxLayout=\"row wrap\" class=\"div-table-filter\">\n <mat-form-field\n *ngIf=\"filterAccessibility$ | async as filterAccessibility\"\n color=\"accent\"\n class=\"filter\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">filter_list_alt</mat-icon>\n {{ filterAccessibility.label }}\n </mat-label>\n <input\n type=\"text\"\n matInput\n [ngModel]=\"filter\"\n (ngModelChange)=\"updateArraySearch($event)\"\n />\n <button\n *ngIf=\"filter\"\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"filterAccessibility.clearSearch\"\n (click)=\"clearFilterInput()\"\n class=\"reset-input-btn\"\n matTooltip=\"{{ filterAccessibility.clearSearch }}\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </mat-form-field>\n <mat-paginator\n color=\"accent\"\n [pageSizeOptions]=\"optionsNbItemsPerPage\"\n showFirstLastButtons\n ></mat-paginator>\n</div>\n<div\n *ngIf=\"arrayGenericAccessibility$ | async as arrayGenericAccessibility\"\n class=\"div-table\"\n>\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n [attr.role]=\"accessibility.table\"\n >\n <caption>\n {{\n accessibility.table\n }}\n </caption>\n <ng-container matColumnDef=\"select\">\n <th\n mat-header-cell\n [attr.role]=\"arrayGenericAccessibility.selectColumn\"\n scope=\"col\"\n *matHeaderCellDef\n >\n <mat-checkbox\n [aria-label]=\"checkboxLabel()\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? masterToggle() : null\"\n >\n </mat-checkbox>\n </th>\n <td\n mat-cell\n [attr.role]=\"arrayGenericAccessibility.selectRow\"\n *matCellDef=\"let row\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-checkbox\n *ngIf=\"row.isRowEditable\"\n [aria-label]=\"checkboxLabel(row)\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null; checkSelection()\"\n >\n </mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container [matColumnDef]=\"column.id\" *ngFor=\"let column of columns\">\n <th\n mat-header-cell\n scope=\"col\"\n [attr.role]=\"\n arrayGenericAccessibility.columnHeader +\n column.label.toLocaleLowerCase()\n \"\n *matHeaderCellDef\n mat-sort-header\n [style.width]=\"column.width\"\n >\n {{ column.label }}\n </th>\n <td\n mat-cell\n [attr.role]=\"\n arrayGenericAccessibility.cell + column.label.toLocaleLowerCase()\n \"\n [title]=\"getCellTitle(element[column.id])\"\n [style.width]=\"column.width\"\n *matCellDef=\"let element\"\n >\n <div\n *ngIf=\"isCellValueAnArray(element[column?.id]); else oneStringValue\"\n >\n <span\n *ngFor=\"let cellObject of element[column.id]; let i = index\"\n [ngClass]=\"{\n 'element-link':\n !isSelectOnlyModeEnabled && cellObject.isClickable,\n element: i > 0\n }\"\n [routerLink]=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? cellObject.routerLinkValue\n : []\n \"\n (click)=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? setEntryIdInStore(cellObject.id, $event)\n : null\n \"\n (keydown.enter)=\"\n !isSelectOnlyModeEnabled && cellObject.isClickable\n ? onKeyRedirect(cellObject.routerLinkValue, cellObject.id)\n : null\n \"\n >\n {{\n getDisplayedValueForArray(\n i,\n element[column.id].length,\n cellObject.value || cellObject\n )\n }}\n </span>\n </div>\n <ng-template #oneStringValue>\n <span>\n {{ element[column.id] }}\n </span>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container *ngIf=\"actionsColumnTemplate != null\" matColumnDef=\"actions\">\n <th\n mat-header-cell\n [attr.role]=\"arrayGenericAccessibility.actionsColumn\"\n scope=\"col\"\n *matHeaderCellDef\n >\n {{ arrayGenericAccessibility.actionsColumnLabel }}\n </th>\n <td\n mat-cell\n [attr.role]=\"arrayGenericAccessibility.actionsMenu\"\n *matCellDef=\"let row\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"actionsColumnTemplate\"\n [ngTemplateOutletContext]=\"{\n row\n }\"\n >\n </ng-container></td\n ></ng-container>\n\n <tr\n mat-header-row\n [attr.role]=\"accessibility.headerRow\"\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns; let i = index\"\n [id]=\"i\"\n [attr.role]=\"\n row.externalId ? accessibility.row + row.externalId : accessibility.row\n \"\n [ngClass]=\"{\n highlighted: selection.isSelected(row),\n hovered: !selection.isSelected(row) && isClickableRow,\n 'clickable-row-pointer': isClickableRow\n }\"\n [routerLink]=\"isClickableRow ? getRowLink(row.externalId) : []\"\n (click)=\"\n isClickableRow\n ? setEntryIdsInStore({ id: row.id, externalId: row.externalId })\n : null\n \"\n (keydown.enter)=\"\n isClickableRow\n ? onKeyRedirectFromRow(getRowLink(row.externalId), {\n id: row.id,\n externalId: row.externalId\n })\n : null\n \"\n (keydown.arrowdown)=\"onKeyArrowDown(i)\"\n (keydown.arrowup)=\"onKeyArrowUp(i)\"\n ></tr>\n\n <tr class=\"mat-row\" *matNoDataRow>\n <div fxLayoutAlign=\"center start\">\n <span\n class=\"placeholder-text\"\n [ngClass]=\"{ 'placeholder-detail-page-text': isAttributeArray }\"\n >\n {{\n isSelectOnlyModeEnabled && isAttributeArray\n ? (actions | asAttributeActions).assign.noFilterResult\n : actions.search.filter.noResult\n }}\n </span>\n </div>\n </tr>\n </table>\n</div>\n", styles: ["@charset \"UTF-8\";:host{min-width:100%;width:fit-content;display:flex;flex-direction:column}.div-table-filter{min-width:fit-content}table{box-shadow:none}table th:not(.mat-column-select,.mat-column-actions){cursor:pointer}.clickable-row-pointer{cursor:pointer}.filter{min-width:auto;flex-grow:1}.element{padding-left:4px}.element-link{cursor:pointer}.element-link:hover,.element-link:focus{font-weight:700}caption{margin:20px 0 10px;font-weight:700}mat-label{display:flex}.reset-input-btn{height:1.5em;width:1.5em;padding:0;display:flex;align-items:center;justify-content:center}.reset-input-btn mat-icon{font-size:inherit;height:auto;width:auto}\n"] }]
}], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }], propDecorators: { dataJsTable$: [], filterAccessibility$: [], arrayGenericAccessibility$: [], isClickableRow: [{
type: Input
}], isSelectOnlyModeEnabled: [{
type: Input
}], selectedElementsUiIds: [{
type: Input
}], dataSource: [{
type: Input
}], columns: [{
type: Input
}], initialDisplayedColumns: [{
type: Input
}], processingRequest$: [{
type: Input
}], actions: [{
type: Input
}], resourcesTypesProperties: [{
type: Input
}], configs: [{
type: Input
}], accessibility: [{
type: Input
}], endpoint: [{
type: Input
}], canAssignOrMoveEntries: [{
type: Input
}], selectedResourceRootTypeId: [{
type: Input
}], isAttributeArray: [{
type: Input
}], updateAffectAnotherResourceType: [{
type: Input
}], fieldForUpdate: [{
type: Input
}], isEditableArray: [{
type: Input
}], selectionColumnId: [{
type: Input
}], actionsColumnTemplate: [{
type: Input
}], selectedData: [{
type: Output
}], paginator: [{
type: ViewChild,
args: [MatPaginator, { static: true }]
}], sort: [{
type: ViewChild,
args: [MatSort]
}], matRows: [{
type: ViewChildren,
args: [MatRow, { read: ElementRef }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJpYy1hcnJheS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9saWJzL2NsaWVudC1jb3JlL3NyYy9saWIvZmVhdHVyZS9nZW5lcmljLWFycmF5L2dlbmVyaWMtYXJyYXkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvbGlicy9jbGllbnQtY29yZS9zcmMvbGliL2ZlYXR1cmUvZ2VuZXJpYy1hcnJheS9nZW5lcmljLWFycmF5LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ0c7QUFFSCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDMUQsT0FBTyxFQUVMLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBR04sU0FBUyxFQUNULFlBQVksR0FDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxNQUFNLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFFckUsT0FBTyxFQUFFLE1BQU0sRUFBUyxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBRUwsT0FBTyxFQUNQLFlBQVksRUFDWixvQkFBb0IsRUFDcEIsTUFBTSxFQUNOLEdBQUcsRUFDSCxTQUFTLEVBQ1QsR0FBRyxHQUNKLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUNMLElBQUksRUFDSixTQUFTLEVBZVQsT0FBTyxFQUNQLGNBQWMsRUFDZCxZQUFZLEVBQ1osWUFBWSxFQUNaLHFCQUFxQixFQUNyQixnQ0FBZ0MsRUFDaEMsMEJBQTBCLEVBQzFCLGFBQWEs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