@alfresco/adf-content-services
Version:
Alfresco ADF content services
840 lines • 159 kB
JavaScript
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable rxjs/no-subject-value */
/* eslint-disable @typescript-eslint/naming-convention */
import { AppConfigService, ColumnsSelectorComponent, CustomEmptyContentTemplateDirective, CustomLoadingContentTemplateDirective, CustomNoPermissionTemplateDirective, DataColumnListComponent, DataSorting, DataTableComponent, DataTableSchema, DataTableService, EmptyListComponent, LoadingContentTemplateDirective, MainMenuDataTableTemplateDirective, NoContentTemplateDirective, NoPermissionTemplateDirective, ShowHeaderMode, ThumbnailService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { NodePaging, NodesApi, Pagination } from '@alfresco/js-api';
import { Component, ContentChild, DestroyRef, ElementRef, EventEmitter, HostListener, inject, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { BehaviorSubject, of, Subject } from 'rxjs';
import { ContentService, NodesApiService } from '../../common';
import { ShareDataTableAdapter } from '../data/share-datatable-adapter';
import { ContentActionModel } from '../models/content-action.model';
import { presetsDefaultModel } from '../models/preset.model';
import { DocumentListService } from '../services/document-list.service';
import { LockService } from '../services/lock.service';
import { ADF_DOCUMENT_PARENT_COMPONENT } from './document-list.token';
import { FileAutoDownloadComponent } from './file-auto-download/file-auto-download.component';
import { NodeEntityEvent, NodeEntryEvent } from './node.event';
import { CommonModule } from '@angular/common';
import { FilterHeaderComponent } from './filter-header/filter-header.component';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i0 from "@angular/core";
import * as i1 from "../services/document-list.service";
import * as i2 from "@alfresco/adf-core";
import * as i3 from "../../common";
import * as i4 from "../../services/alfresco-api.service";
import * as i5 from "../services/lock.service";
import * as i6 from "@angular/material/dialog";
import * as i7 from "@angular/common";
import * as i8 from "@ngx-translate/core";
import * as i9 from "@angular/material/icon";
import * as i10 from "@angular/material/progress-spinner";
const BYTES_TO_MB_CONVERSION_VALUE = 1048576;
export class DocumentListComponent extends DataTableSchema {
static { this.SINGLE_CLICK_NAVIGATION = 'click'; }
static { this.DOUBLE_CLICK_NAVIGATION = 'dblclick'; }
/**
* Custom function to choose whether to show or hide rows.
* See the [Row Filter Model](row-filter.model.md) page for
* more information.
*/
set rowFilter(rowFilter) {
this._rowFilter = rowFilter;
if (this.data) {
this.data.setFilter(this._rowFilter);
if (this.currentFolderId) {
this.reload();
}
}
}
get rowFilter() {
return this._rowFilter;
}
/** Sets columns visibility for DataTableSchema */
set setColumnsVisibility(columnsVisibility) {
this.columnsVisibility = columnsVisibility;
}
/** Sets columns width for DataTableSchema */
set setColumnsWidths(columnsWidths) {
this.columnsWidths = columnsWidths;
}
/** Sets columns order for DataTableSchema */
set setColumnsOrder(columnsOrder) {
this.columnsOrder = columnsOrder;
}
get nodesApi() {
this._nodesApi = this._nodesApi ?? new NodesApi(this.alfrescoApiService.getInstance());
return this._nodesApi;
}
constructor(documentListService, elementRef, appConfig, userPreferencesService, contentService, thumbnailService, alfrescoApiService, nodeService, dataTableService, lockService, dialog) {
super(appConfig, 'default', presetsDefaultModel);
this.documentListService = documentListService;
this.elementRef = elementRef;
this.appConfig = appConfig;
this.userPreferencesService = userPreferencesService;
this.contentService = contentService;
this.thumbnailService = thumbnailService;
this.alfrescoApiService = alfrescoApiService;
this.nodeService = nodeService;
this.dataTableService = dataTableService;
this.lockService = lockService;
this.dialog = dialog;
this.DEFAULT_PAGINATION = new Pagination({
hasMoreItems: false,
skipCount: 0,
maxItems: 25,
totalItems: 0
});
this.DEFAULT_SORTING = [new DataSorting('name', 'asc'), new DataSorting('isFolder', 'desc')];
/**
* Define a set of CSS styles to apply depending on the permission
* of the user on that node. See the Permission Style model
* page for further details and examples.
*/
this.permissionsStyle = [];
/** The default route for all the location-based columns (if declared). */
this.locationFormat = '/';
/** Toggles navigation to folder content or file preview */
this.navigate = true;
/** Toggles the header */
this.showHeader = ShowHeaderMode.Data;
/**
* User interaction for folder navigation or file preview.
* Valid values are "click" and "dblclick". Default value: "dblclick"
*/
this.navigationMode = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; // click|dblclick
/** Show document thumbnails rather than icons */
this.thumbnails = false;
/**
* Row selection mode. Can be null, `single` or `multiple`. For `multiple` mode,
* you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows.
*/
this.selectionMode = 'single'; // null|single|multiple
/** Toggles multiselect mode */
this.multiselect = false;
/** Toggles content actions for each row */
this.contentActions = false;
/** Position of the content actions dropdown menu. Can be set to "left" or "right". */
this.contentActionsPosition = 'right'; // left|right
/** Toggles context menus for each row */
this.contextMenuActions = false;
/** Custom image for empty folder. Default value: './assets/images/empty_doc_lib.svg' */
this.emptyFolderImageUrl = './assets/images/empty_doc_lib.svg';
/**
* When true, this enables you to drop files directly into subfolders shown
* as items in the list or into another file to trigger updating it's version.
* When false, the dropped file will be added to the
* current folder (ie, the one containing all the items shown in the list).
* See the Upload directive for further details about how the file drop is
* handled.
*/
this.allowDropFiles = false;
/**
* Defines default sorting. The format is an array of 2 strings `[key, direction]`
* i.e. `['name', 'desc']` or `['name', 'asc']`. Set this value only if you want to
* override the default sorting detected by the component based on columns.
*/
this.sorting = ['name', 'asc'];
/**
* Defines default sorting. The format is an array of strings `[key direction, otherKey otherDirection]`
* i.e. `['name desc', 'nodeType asc']` or `['name asc']`. Set this value if you want a base
* rule to be added to the sorting apart from the one driven by the header.
*/
this.additionalSorting = new DataSorting('isFolder', 'desc');
/**
* Defines sorting mode. Can be either `client` (items in the list
* are sorted client-side) or `server` (the ordering supplied by the
* server is used without further client-side sorting).
* Note that the `server` option *does not* request the server to sort the data
* before delivering it.
*/
this.sortingMode = 'server';
/**
* Toggles the loading state and animated spinners for the component. Used in
* combination with `navigate=false` to perform custom navigation and loading
* state indication.
*/
this.loading = false;
this._rowFilter = null;
/**
* Custom function to choose image file paths to show. See the
* [Image Resolver Model](image-resolver.model.md) page for
* more information.
*/
this.imageResolver = null;
/** Toggles the sticky header mode. */
this.stickyHeader = false;
/** Toggles the header filters mode. */
this.headerFilters = false;
/** The ID of the folder node to display or a reserved string alias for special sources */
this.currentFolderId = null;
/**
* Array of nodes to be pre-selected. All nodes in the
* array are pre-selected in multi selection mode, but only the first node
* is pre-selected in single selection mode.
*/
this.preselectNodes = [];
/** The Document list will show all the nodes contained in the NodePaging entity */
this.node = null;
/** Default value is stored in the user preference settings. Use this only if you are not using pagination. */
this.maxItems = this.DEFAULT_PAGINATION.maxItems;
/** Enables column resizing for datatable */
this.isResizingEnabled = false;
/** Enables blur when resizing datatable columns */
this.blurOnResize = true;
/** Display checkboxes in datatable rows on hover only */
this.displayCheckboxesOnHover = false;
/** Display drag and drop hint. */
this.displayDragAndDropHint = true;
/** Emitted when the user clicks a list node */
this.nodeClick = new EventEmitter();
/** Emitted when the user double-clicks a list node */
this.nodeDblClick = new EventEmitter();
/** Emitted when the current display folder changes */
this.folderChange = new EventEmitter();
/**
* Emitted when the user acts upon files with either single or double click
* (depends on `navigation-mode`). Useful for integration with the
* Viewer component.
*/
this.preview = new EventEmitter();
/** Emitted when the Document List has loaded all items and is ready for use */
this.ready = new EventEmitter();
/** Emitted when the API fails to get the Document List data */
this.error = new EventEmitter();
/** Emitted when the node selection change */
this.nodeSelected = new EventEmitter();
/** Emitted when a filter value is selected */
this.filterSelection = new EventEmitter();
/** Emitted when column widths change */
this.columnsWidthChanged = new EventEmitter();
/** Emitted when columns visibility change */
this.columnsVisibilityChanged = new EventEmitter();
/** Emitted when columns order change */
this.columnsOrderChanged = new EventEmitter();
/** Emitted when the selected row items count in the table changed. */
this.selectedItemsCountChanged = new EventEmitter();
this.actions = [];
this.contextActionHandler = new Subject();
this.noPermission = false;
this.selection = new Array();
this.$folderNode = new Subject();
this.allowFiltering = true;
this.orderBy = null;
this.preselectedRows = [];
this._pagination = this.DEFAULT_PAGINATION;
this.pagination = new BehaviorSubject(this.DEFAULT_PAGINATION);
this.sortingSubject = new BehaviorSubject(this.DEFAULT_SORTING);
this.rowMenuCache = {};
this.destroyRef = inject(DestroyRef);
this.nodeService.nodeUpdated.pipe(takeUntilDestroyed()).subscribe((node) => {
this.dataTableService.rowUpdate.next({ id: node.id, obj: { entry: node } });
});
this.userPreferencesService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntilDestroyed())
.subscribe((pagSize) => {
this.maxItems = this._pagination.maxItems = pagSize;
});
}
getContextActions(node) {
if (node?.entry) {
const actions = this.getNodeActions(node);
if (actions && actions.length > 0) {
return actions.map((currentAction) => ({
model: currentAction,
node,
subject: this.contextActionHandler
}));
}
}
return null;
}
getDefaultSorting() {
let defaultSorting;
if (Array.isArray(this.sorting)) {
const [key, direction] = this.sorting;
defaultSorting = new DataSorting(key, direction);
}
else {
defaultSorting = new DataSorting(this.sorting.key, this.sorting.direction);
}
return defaultSorting;
}
isMobile() {
return !!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
isEmpty() {
return !this.data || this.data.getRows().length === 0;
}
ngOnInit() {
this.rowMenuCache = {};
this.loadLayoutPresets();
this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode, this.allowDropFiles);
this.data.thumbnails = this.thumbnails;
this.data.permissionsStyle = this.permissionsStyle;
if (this._rowFilter) {
this.data.setFilter(this._rowFilter);
}
if (this.imageResolver) {
this.data.setImageResolver(this.imageResolver);
}
this.contextActionHandler.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((val) => this.contextActionCallback(val));
this.enforceSingleClickNavigationForMobile();
if (this.filterValue && Object.keys(this.filterValue).length > 0) {
this.showHeader = ShowHeaderMode.Always;
}
if (this.columnsPresetKey) {
this.setPresetKey(this.columnsPresetKey);
}
this.documentListService.reload$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.resetSelection();
this.reload();
});
this.documentListService.resetSelection$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.resetSelection();
});
}
ngAfterContentInit() {
if (this.columnList) {
this.columnList.columns.changes.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.createColumns();
this.data.setColumns(this.columns);
});
}
this.createDatatableSchema();
this.data.setColumns(this.columns);
}
ngOnChanges(changes) {
if (!changes['preselectNodes']) {
this.resetSelection();
}
if (Array.isArray(this.sorting)) {
const [key, direction] = this.sorting;
this.orderBy = this.buildOrderByArray(key, direction);
}
else {
this.orderBy = this.buildOrderByArray(this.sorting.key, this.sorting.direction);
}
if (this.data) {
this.data.thumbnails = this.thumbnails;
}
if (changes.sortingMode && !changes.sortingMode.firstChange && this.data) {
this.data.sortingMode = changes.sortingMode.currentValue;
}
if (changes.sorting && !changes.sorting.firstChange && this.data) {
const newValue = changes.sorting.currentValue;
if (newValue && newValue.length > 0) {
const [key, direction] = newValue;
this.data.setSorting(new DataSorting(key, direction));
}
}
if (this.currentFolderId && changes['currentFolderId']?.currentValue !== changes['currentFolderId']?.previousValue) {
this.loadFolder();
}
if (this.data) {
if (changes.node?.currentValue) {
const merge = this._pagination ? this._pagination.merge : false;
this.data.loadPage(changes.node.currentValue, merge, null);
this.preserveExistingSelection();
this.onPreselectNodes();
this.onDataReady(changes.node.currentValue);
}
else if (changes.imageResolver) {
this.data.setImageResolver(changes.imageResolver.currentValue);
}
}
}
reload(hideLoadingSpinner = false) {
this.resetSelection();
this.reloadWithoutResettingSelection(hideLoadingSpinner);
}
reloadWithoutResettingSelection(hideLoadingSpinner = false) {
if (this.node) {
if (this.data) {
this.data.loadPage(this.node, this._pagination.merge, null);
this.preserveExistingSelection();
}
this.onPreselectNodes();
this.syncPagination();
this.onDataReady(this.node);
}
else {
this.loadFolder(hideLoadingSpinner);
}
}
contextActionCallback(action) {
if (action) {
this.executeContentAction(action.node, action.model);
}
}
getNodeActions(node) {
if (node?.entry) {
let target = null;
if (node.entry.isFile) {
target = 'document';
}
else if (node.entry.isFolder) {
target = 'folder';
}
if (target) {
const actions = this.rowMenuCache[node.entry.id];
if (actions) {
actions.forEach((action) => {
this.refreshAction(action, node);
});
return actions;
}
const actionsByTarget = this.actions
.filter((entry) => {
const isVisible = typeof entry.visible === 'function' ? entry.visible(node) : entry.visible;
return isVisible && entry.target.toLowerCase() === target;
})
.map((action) => new ContentActionModel(action));
actionsByTarget.forEach((action) => {
this.refreshAction(action, node);
});
this.rowMenuCache[node.entry.id] = actionsByTarget;
return actionsByTarget;
}
}
return [];
}
refreshAction(action, node) {
action.disabled = this.isActionDisabled(action, node);
action.visible = this.isActionVisible(action, node);
}
isActionVisible(action, node) {
if (typeof action.visible === 'function') {
return action.visible(node);
}
return action.visible;
}
isActionDisabled(action, node) {
if (typeof action.disabled === 'function') {
return action.disabled(node);
}
if ((action.permission && action.disableWithNoPermission && !this.contentService.hasAllowableOperations(node.entry, action.permission)) ||
this.lockService.isLocked(node.entry)) {
return true;
}
else {
return action.disabled;
}
}
onShowContextMenu(e) {
if (e && this.contextMenuActions) {
e.preventDefault();
}
}
navigateTo(node) {
if (typeof node === 'string') {
this.resetNewFolderPagination();
this.currentFolderId = node;
this.folderChange.emit(new NodeEntryEvent({ id: node }));
this.reload();
return true;
}
else {
if (this.canNavigateFolder(node)) {
this.resetNewFolderPagination();
this.currentFolderId = this.getNodeFolderDestinationId(node);
this.folderChange.emit(new NodeEntryEvent({ id: this.currentFolderId }));
this.reload();
return true;
}
}
return false;
}
getNodeFolderDestinationId(node) {
return this.isLinkFolder(node) ? node.properties['cm:destination'] : node.id;
}
isLinkFolder(node) {
return node.nodeType === 'app:folderlink' && node.properties?.['cm:destination'];
}
updateCustomSourceData(nodeId) {
this.currentFolderId = nodeId;
}
/**
* Invoked when executing content action for a document or folder.
*
* @param node Node to be the context of the execution.
* @param action Action to be executed against the context.
*/
executeContentAction(node, action) {
if (node?.entry && action) {
const handlerSub = typeof action.handler === 'function' ? action.handler(node, this, action.permission) : of(true);
if (typeof action.execute === 'function' && handlerSub) {
handlerSub.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => action.execute(node));
}
}
}
setLoadingState(value) {
if (this.data?.getRows().length > 0) {
if (value) {
clearTimeout(this.loadingTimeout);
this.loadingTimeout = setTimeout(() => {
this.loading = true;
}, 1000);
}
else {
clearTimeout(this.loadingTimeout);
this.loading = false;
}
}
else {
clearTimeout(this.loadingTimeout);
this.loading = value;
}
}
loadFolder(hideLoadingSpinner = false) {
if (!hideLoadingSpinner) {
this.setLoadingState(true);
}
if (this.documentListService.isCustomSourceService(this.currentFolderId)) {
this.updateCustomSourceData(this.currentFolderId);
}
this.documentListService.loadFolderByNodeId(this.currentFolderId, this._pagination, this.includeFields, this.where, this.orderBy).subscribe((documentNode) => {
if (documentNode.currentNode) {
this.folderNode = documentNode.currentNode.entry;
this.$folderNode.next(documentNode.currentNode.entry);
}
this.onPageLoaded(documentNode.children);
}, (err) => {
this.handleError(err);
});
}
resetSelection() {
this.dataTable.resetSelection();
this.selection = [];
this.noPermission = false;
}
onPageLoaded(nodePaging) {
if (nodePaging) {
if (this.data) {
this.data.loadPage(nodePaging, this._pagination.merge, this.allowDropFiles);
this.preserveExistingSelection();
}
this.onPreselectNodes();
this.setLoadingState(false);
this.onDataReady(nodePaging);
}
}
onSortingChanged(event) {
this.orderBy = this.buildOrderByArray(event.detail.sortingKey, event.detail.direction);
this.sorting = [event.detail.sortingKey, event.detail.direction];
this.sortingSubject.next([this.additionalSorting, event.detail]);
if (this.sortingMode === 'server') {
this.reload();
}
}
buildOrderByArray(currentKey, currentDirection) {
return [`${this.additionalSorting.key} ${this.additionalSorting.direction}`, `${currentKey} ${currentDirection}`];
}
onPreviewFile(node) {
if (node) {
const sizeInMB = node.entry?.content?.sizeInBytes / BYTES_TO_MB_CONVERSION_VALUE;
const fileAutoDownloadFlag = this.appConfig.get('viewer.enableFileAutoDownload', true);
const sizeThreshold = this.appConfig.get('viewer.fileAutoDownloadSizeThresholdInMB', 15);
if (fileAutoDownloadFlag && sizeInMB && sizeInMB > sizeThreshold) {
this.dialog.open(FileAutoDownloadComponent, { disableClose: true, data: node });
}
else {
this.preview.emit(new NodeEntityEvent(node));
}
}
}
onColumnsVisibilityChange(columns) {
this.columnsVisibility = columns.reduce((visibleColumnsMap, column) => {
if (column.isHidden !== undefined) {
visibleColumnsMap[column.id] = !column.isHidden;
}
return visibleColumnsMap;
}, {});
this.createColumns();
this.data.setColumns(this.columns);
this.columnsVisibilityChanged.emit(this.columnsVisibility);
}
onColumnOrderChange(columnsWithNewOrder) {
this.columnsOrder = columnsWithNewOrder.map((column) => column.id);
this.createColumns();
this.columnsOrderChanged.emit(this.columnsOrder);
}
onColumnsWidthChange(columns) {
const newColumnsWidths = columns.reduce((widthsColumnsMap, column) => {
if (column.width) {
widthsColumnsMap[column.id] = Math.ceil(column.width);
}
return widthsColumnsMap;
}, {});
this.columnsWidths = { ...this.columnsWidths, ...newColumnsWidths };
this.createColumns();
this.columnsWidthChanged.emit(this.columnsWidths);
}
onSelectedItemsCountChanged(count) {
this.selectedItemsCountChanged.emit(count);
}
onNodeClick(nodeEntry) {
const domEvent = new CustomEvent('node-click', {
detail: {
sender: this,
node: nodeEntry
},
bubbles: true
});
this.elementRef.nativeElement.dispatchEvent(domEvent);
const event = new NodeEntityEvent(nodeEntry);
this.nodeClick.emit(event);
if (!event.defaultPrevented) {
if (this.navigate && this.navigationMode === DocumentListComponent.SINGLE_CLICK_NAVIGATION) {
this.executeActionClick(nodeEntry);
}
}
}
onNodeDblClick(nodeEntry) {
const domEvent = new CustomEvent('node-dblclick', {
detail: {
sender: this,
node: nodeEntry
},
bubbles: true
});
this.elementRef.nativeElement.dispatchEvent(domEvent);
const event = new NodeEntityEvent(nodeEntry);
this.nodeDblClick.emit(event);
if (!event.defaultPrevented) {
if (this.navigate && this.navigationMode === DocumentListComponent.DOUBLE_CLICK_NAVIGATION) {
this.executeActionClick(nodeEntry);
}
}
}
executeActionClick(nodeEntry) {
if (nodeEntry?.entry) {
if (nodeEntry.entry.isFile) {
this.onPreviewFile(nodeEntry);
}
if (nodeEntry.entry.isFolder) {
this.navigateTo(nodeEntry.entry);
}
if (nodeEntry.entry['guid']) {
const options = {
include: this.includeFields
};
this.nodesApi.getNode(nodeEntry.entry['guid'], options).then((node) => {
this.navigateTo(node.entry);
});
}
}
}
onNodeSelect(event) {
this.selection = event.selection.map((entry) => entry.node);
const domEvent = new CustomEvent('node-select', {
detail: {
node: event.row ? event.row.node : null,
selection: this.selection
},
bubbles: true
});
this.nodeSelected.emit(this.selection);
this.elementRef.nativeElement.dispatchEvent(domEvent);
}
onNodeUnselect(event) {
this.selection = event.selection.map((entry) => entry.node);
const domEvent = new CustomEvent('node-unselect', {
detail: {
node: event.row ? event.row.node : null,
selection: this.selection
},
bubbles: true
});
this.nodeSelected.emit(this.selection);
this.elementRef.nativeElement.dispatchEvent(domEvent);
}
onShowRowContextMenu(event) {
if (this.contextMenuActions) {
const args = event.value;
const node = args.row.node;
if (node) {
args.actions = this.getContextActions(node) || [];
}
}
}
onShowRowActionsMenu(event) {
if (this.contentActions) {
const args = event.value;
const node = args.row.node;
if (node) {
args.actions = this.getNodeActions(node) || [];
}
}
}
onExecuteRowAction(event) {
if (this.contentActions) {
const args = event.value;
const node = args.row.node;
const action = args.action;
this.executeContentAction(node, action);
}
}
enforceSingleClickNavigationForMobile() {
if (this.isMobile()) {
this.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION;
}
}
canNavigateFolder(node) {
let canNavigateFolder = false;
if (node?.isFolder) {
canNavigateFolder = true;
}
return canNavigateFolder;
}
onDataReady(nodePaging) {
this.ready.emit(nodePaging);
this.pagination.next(nodePaging.list.pagination);
}
updatePagination(requestPaginationModel) {
this._pagination.maxItems = requestPaginationModel.maxItems;
this._pagination.skipCount = requestPaginationModel.skipCount;
this.reload(requestPaginationModel.merge);
}
syncPagination() {
this.node.list.pagination.maxItems = this._pagination.maxItems;
this.node.list.pagination.skipCount = this._pagination.skipCount;
}
onFilterSelectionChange(activeFilters) {
this.filterSelection.emit(activeFilters);
}
resetNewFolderPagination() {
this._pagination.skipCount = 0;
this._pagination.maxItems = this.maxItems;
}
handleError(err) {
if (err.message) {
try {
if (JSON.parse(err.message).error.statusCode === 403) {
this.noPermission = true;
}
}
catch (error) {
/* empty */
}
}
this.setLoadingState(false);
this.error.emit(err);
}
getPreselectedNodesBasedOnSelectionMode() {
return this.hasPreselectedNodes() ? (this.isSingleSelectionMode() ? [this.preselectNodes[0]] : this.preselectNodes) : [];
}
getPreselectedRowsBasedOnSelectionMode() {
return this.hasPreselectedRows() ? (this.isSingleSelectionMode() ? [this.preselectedRows[0]] : this.preselectedRows) : [];
}
getSelectionBasedOnSelectionMode() {
return this.hasPreselectedRows()
? this.isSingleSelectionMode()
? [this.preselectedRows[0]]
: this.data.getSelectedRows()
: this.data.getSelectedRows();
}
onPreselectNodes() {
if (this.hasPreselectedNodes()) {
this.preselectRowsOfPreselectedNodes();
const preselectedRows = this.getPreselectedRowsBasedOnSelectionMode();
const selection = this.data.getSelectedRows();
for (const node of preselectedRows) {
this.dataTable.selectRow(node, true);
}
this.onNodeSelect({ row: undefined, selection });
}
}
preserveExistingSelection() {
if (this.isMultipleSelectionMode()) {
for (const selection of this.selection) {
const rowOfSelection = this.data.getRowByNodeId(selection.entry.id);
if (rowOfSelection) {
rowOfSelection.isSelected = true;
}
}
}
}
preselectRowsOfPreselectedNodes() {
this.preselectedRows = [];
const preselectedNodes = this.getPreselectedNodesBasedOnSelectionMode();
preselectedNodes.forEach((preselectedNode) => {
const rowOfPreselectedNode = this.data.getRowByNodeId(preselectedNode.entry.id);
if (rowOfPreselectedNode) {
rowOfPreselectedNode.isSelected = true;
this.preselectedRows.push(rowOfPreselectedNode);
}
});
}
unselectRowFromNodeId(nodeId) {
const rowToUnselect = this.data.getRowByNodeId(nodeId);
if (rowToUnselect?.isSelected) {
rowToUnselect.isSelected = false;
this.dataTable.selectRow(rowToUnselect, false);
const selection = this.getSelectionBasedOnSelectionMode();
this.onNodeUnselect({ row: undefined, selection });
}
}
isSingleSelectionMode() {
return this.selectionMode === 'single';
}
isMultipleSelectionMode() {
return this.selectionMode === 'multiple';
}
hasPreselectedNodes() {
return this.preselectNodes?.length > 0;
}
hasPreselectedRows() {
return this.preselectedRows?.length > 0;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DocumentListComponent, deps: [{ token: i1.DocumentListService }, { token: i0.ElementRef }, { token: i2.AppConfigService }, { token: i2.UserPreferencesService }, { token: i3.ContentService }, { token: i2.ThumbnailService }, { token: i4.AlfrescoApiService }, { token: i3.NodesApiService }, { token: i2.DataTableService }, { token: i5.LockService }, { token: i6.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DocumentListComponent, isStandalone: true, selector: "adf-document-list", inputs: { includeFields: "includeFields", where: "where", permissionsStyle: "permissionsStyle", locationFormat: "locationFormat", navigate: "navigate", showHeader: "showHeader", navigationMode: "navigationMode", thumbnails: "thumbnails", selectionMode: "selectionMode", multiselect: "multiselect", contentActions: "contentActions", contentActionsPosition: "contentActionsPosition", contextMenuActions: "contextMenuActions", emptyFolderImageUrl: "emptyFolderImageUrl", allowDropFiles: "allowDropFiles", sorting: "sorting", additionalSorting: "additionalSorting", sortingMode: "sortingMode", rowStyle: "rowStyle", rowStyleClass: "rowStyleClass", loading: "loading", _rowFilter: "_rowFilter", rowFilter: "rowFilter", imageResolver: "imageResolver", stickyHeader: "stickyHeader", headerFilters: "headerFilters", filterValue: "filterValue", currentFolderId: "currentFolderId", preselectNodes: "preselectNodes", node: "node", maxItems: "maxItems", columnsPresetKey: "columnsPresetKey", setColumnsVisibility: "setColumnsVisibility", setColumnsWidths: "setColumnsWidths", setColumnsOrder: "setColumnsOrder", maxColumnsVisible: "maxColumnsVisible", isResizingEnabled: "isResizingEnabled", blurOnResize: "blurOnResize", displayCheckboxesOnHover: "displayCheckboxesOnHover", displayDragAndDropHint: "displayDragAndDropHint" }, outputs: { nodeClick: "nodeClick", nodeDblClick: "nodeDblClick", folderChange: "folderChange", preview: "preview", ready: "ready", error: "error", nodeSelected: "nodeSelected", filterSelection: "filterSelection", columnsWidthChanged: "columnsWidthChanged", columnsVisibilityChanged: "columnsVisibilityChanged", columnsOrderChanged: "columnsOrderChanged", selectedItemsCountChanged: "selectedItemsCountChanged" }, host: { listeners: { "contextmenu": "onShowContextMenu($event)" }, classAttribute: "adf-document-list" }, providers: [
{
provide: ADF_DOCUMENT_PARENT_COMPONENT,
useExisting: DocumentListComponent
},
DataTableService
], queries: [{ propertyName: "columnList", first: true, predicate: DataColumnListComponent, descendants: true }, { propertyName: "customLoadingContent", first: true, predicate: CustomLoadingContentTemplateDirective, descendants: true }, { propertyName: "customNoPermissionsTemplate", first: true, predicate: CustomNoPermissionTemplateDirective, descendants: true }, { propertyName: "customNoContentTemplate", first: true, predicate: CustomEmptyContentTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "dataTable", first: true, predicate: ["dataTable"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<adf-datatable\n #dataTable\n [selectionMode]=\"selectionMode\"\n [data]=\"data\"\n [actions]=\"contentActions\"\n [actionsPosition]=\"contentActionsPosition\"\n [multiselect]=\"multiselect\"\n [contextMenu]=\"contextMenuActions\"\n [rowStyle]=\"rowStyle\"\n [rowStyleClass]=\"rowStyleClass\"\n [showMainDatatableActions]=\"true\"\n [loading]=\"loading\"\n [noPermission]=\"noPermission\"\n [showHeader]=\"showHeader\"\n [rowMenuCacheEnabled]=\"false\"\n [stickyHeader]=\"stickyHeader\"\n [allowFiltering]=\"allowFiltering\"\n [isResizingEnabled]=\"isResizingEnabled\"\n [blurOnResize]=\"blurOnResize\"\n [displayCheckboxesOnHover]=\"displayCheckboxesOnHover\"\n (showRowContextMenu)=\"onShowRowContextMenu($event)\"\n (showRowActionsMenu)=\"onShowRowActionsMenu($event)\"\n (executeRowAction)=\"onExecuteRowAction($event)\"\n (columnsWidthChanged)=\"onColumnsWidthChange($event)\"\n (columnOrderChanged)=\"onColumnOrderChange($event)\"\n (selectedItemsCountChanged)=\"onSelectedItemsCountChanged($event)\"\n (rowClick)=\"onNodeClick($event.value?.node)\"\n (rowDblClick)=\"onNodeDblClick($event.value?.node)\"\n (row-select)=\"onNodeSelect($any($event).detail)\"\n (row-unselect)=\"onNodeUnselect($any($event).detail)\"\n (sorting-changed)=\"onSortingChanged($any($event))\"\n [class.adf-datatable-gallery-thumbnails]=\"data.thumbnails\">\n\n <div *ngIf=\"headerFilters\">\n <adf-filter-header\n [currentFolderId]=\"currentFolderId\"\n [value]=\"filterValue\"\n (filterSelection)=\"onFilterSelectionChange($event)\" />\n </div>\n\n <adf-no-content-template>\n <ng-template>\n <adf-empty-list *ngIf=\"!customNoContentTemplate\">\n <div class=\"adf-empty-list_template adf-empty-folder\">\n <div class=\"adf-empty-folder-this-space-is-empty\">{{'ADF-DOCUMENT-LIST.EMPTY.HEADER' | translate}}</div>\n <ng-container *ngIf=\"displayDragAndDropHint\">\n <div class=\"adf-empty-folder-drag-drop\">{{ 'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate }}</div>\n <div class=\"adf-empty-folder-any-files-here-to-add\">{{ 'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.SUBTITLE' | translate }}</div>\n </ng-container>\n <img [alt]=\"'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate\" class=\"adf-empty-folder-image\" [src]=\"emptyFolderImageUrl\">\n </div>\n </adf-empty-list>\n <ng-content select=\"adf-custom-empty-content-template, empty-folder-content\" />\n </ng-template>\n </adf-no-content-template>\n\n <adf-no-permission-template>\n <ng-template>\n <div class=\"adf-no-permission__template\" *ngIf=\"!customNoPermissionsTemplate\">\n <mat-icon>error</mat-icon>\n <p class=\"adf-no-permission__template--text\">{{ 'ADF-DOCUMENT-LIST.NO_PERMISSION' | translate }}</p>\n </div>\n <ng-content select=\"adf-custom-no-permission-template, no-permission-content\" />\n </ng-template>\n </adf-no-permission-template>\n\n <adf-loading-content-template>\n <ng-template>\n <div class=\"adf-document-list-loading-container\" *ngIf=\"!customLoadingContent\">\n <mat-progress-spinner\n id=\"adf-document-list-loading\"\n class=\"adf-document-list-loading-margin\"\n [attr.aria-label]=\"'ADF-DOCUMENT-LIST.LOADER_LABEL' | translate\"\n [color]=\"'primary'\"\n [mode]=\"'indeterminate'\" />\n </div>\n <ng-content select=\"adf-custom-loading-content-template\" />\n </ng-template>\n </adf-loading-content-template>\n\n <adf-main-menu-datatable-template>\n <ng-template let-mainMenuTrigger>\n <adf-datatable-column-selector\n [columns]=\"columns\"\n [mainMenuTrigger]=\"mainMenuTrigger\"\n [columnsSorting]=\"false\"\n [maxColumnsVisible]=\"maxColumnsVisible\"\n (submitColumnsVisibility)=\"onColumnsVisibilityChange($event)\" />\n </ng-template>\n </adf-main-menu-datatable-template>\n\n</adf-datatable>\n", styles: [".adf-document-list{min-height:0;height:100%;background-color:var(--theme-background-color)}.adf-sticky-document-list{height:310px;overflow-y:auto}.adf-datatable-card .adf-datatable-selected>svg{fill:var(--theme-accent-color);width:30px;height:30px;position:absolute;top:10px}.adf-datatable-list .adf-datatable-selected{display:inline-table}.adf-datatable-list .adf-datatable-selected>svg{fill:var(--theme-accent-color);width:30px;height:30px}.adf-document-list_empty_template{text-align:center;margin-top:20px;margin-bottom:20px}.adf-no-permission__template{display:flex;align-items:center;justify-content:center;flex-direction:column;width:100%;height:100%;min-height:300px}.adf-no-permission__template mat-icon{font-size:52px;height:52px;width:52px}.adf-no-permission__template--text{color:var(--adf-theme-foreground-text-color);font-size:var(--theme-subheading-2-font-size)}.adf-document-list__this-space-is-empty{height:32px;opacity:.26;font-size:var(--theme-headline-font-size);line-height:1.33;letter-spacing:-1px;color:var(--adf-theme-foreground-text-color)}.adf-document-list__drag-drop{height:56px;opacity:.54;font-size:56px;line-height:1;letter-spacing:-2px;color:var(--adf-theme-foreground-text-color);margin-top:40px}.adf-document-list__any-files-here-to-add{height:24px;opacity:.54;font-size:var(--theme-subheading-2-font-size);line-height:1.5;letter-spacing:-.4px;color:var(--adf-theme-foreground-text-color);margin-top:17px}.adf-document-list__empty_doc_lib{width:565px;height:161px;object-fit:contain;margin-top:17px}.adf-document-list-loading-margin{margin:auto}.adf-document-list-loading-container{min-height:300px;display:flex;flex-direction:row;height:100%}.adf-empty-list-header{height:32px;opacity:.26;font-size:var(--theme-headline-font-size);line-height:1.33;letter-spacing:-1px;color:var(--adf-theme-foreground-text-color)}.adf-documentlist-pagination{color:var(--adf-theme-foreground-text-color)}.adf-documentlist-pagination .adf-pagination__block{border-right:none}.adf-empty-folder-this-space-is-empty{height:32px;font-size:var(--theme-headline-font-size);line-height:1.33;letter-spacing:-1px;color:var(--adf-theme-foreground-text-color-054)}.adf-empty-folder-drag-drop{min-height:56px;font-size:53px;line-height:1;letter-spacing:-2px;color:var(--adf-theme-foreground-text-color);margin-top:40px;word-break:break-all;white-space:pre-line}@media (max-width: 599.9px){.adf-empty-folder-drag-drop{font-size:48px}}.adf-empty-folder-any-files-here-to-add{min-height:24px;font-size:var(--theme-subheading-2-font-size);line-height:1.5;letter-spacing:-.4px;color:var(--adf-theme-foreground-text-color);margin-top:17px;word-break:break-all;white-space:pre-line}.adf-empty-folder-image{width:565px;max-width:100%;object-fit:contain;margin-top:17px}@media (max-width: 599.9px){.adf-empty-folder-image{width:250px}}@media (max-width: 959.9px){.adf-empty-folder-drag-drop,.adf-empty-folder-any-files-here-to-add{display:none}}.adf-datatable-gallery-thumbnails .adf-datatable-card .adf-datatable-row:is(adf-datatable-row){height:300px}.adf-datatable-gallery-thumbnails .adf-datatable-card .adf-datatable-row:is(adf-datatable-row) img{height:130px}.adf-datatable-gallery-thumbnails .adf-datatable-card .adf-datatable-row:is(adf-datatable-row) .adf-datatable-cell{overflow:visible}.adf-datatable-gallery-thumbnails .adf-datatable-card .adf-datatable-row:is(adf-datatable-row) .adf-datatable-cell.adf-datatable-cell--image{flex:0 0 auto;display:flex;flex-direction:column-reverse;justify-content:space-between}.adf-datatable-gallery-thumbnails .adf-datatable-card .adf-datatable-row:is(adf-datatable-row) .adf-datatable-cell.adf-datatable-cell--image .adf-cell-value{display:flex;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DataTableComponent, selector: "adf-datatable", inputs: ["data", "rows", "sorting", "columns", "selectionMode", "multiselect", "mainTableAction", "actions", "showMainDatatableActions", "showProvidedActions", "actionsPosition", "actionsVisibleOnHover", "fallbackThumbnail", "contextMenu", "rowStyle", "rowStyleClass", "showHeader", "stickyHeader", "loading", "noPermission", "rowMenuCacheEnabled", "resolverFn", "allowFiltering", "isResizingEnabled", "blurOnResize", "displayCheckboxesOnHover", "enableDragRows"], outputs: ["rowClick", "rowDblClick", "showRowContextMenu", "showRowActionsMenu", "executeRowAction", "columnOrderChanged", "columnsWidthChanged", "selectedItemsCountChanged", "dragDropped"] }, { kind: "component", type: FilterHeaderComponent, selector: "adf-filter-header", inputs: ["value", "currentFolderId"], outputs: ["filterSelection"] }, { kind: "directive", type: NoContentTemplateDirective, selector: "adf-no-content-template, no-content-template" }, { kind: "component", type: EmptyListComponent, selector: "adf-empty-list" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }, { kind: "directive", type: NoPermissionTemplateDirective, selector: "adf-no-permission-template, no-permission-template" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: LoadingContentTemplateDirective, selector: "adf-loading-content-template, loading-content-template" }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i10.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: MainMenuDataTableTemplateDirective, selector: "adf-main-menu-datatable-template" }, { kind: "component", type: ColumnsSelectorComponent, selector: "adf-datatable-column-selector", inputs: ["columns", "mainMenuTrigger", "columnsSorting", "maxColumnsVisible"], outputs: ["submitColumnsVisibility"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DocumentListComponent, decorators: [{
type: Component,
args: [{ selector: 'adf-document-list', standalone: true, imports: [
CommonModule,
DataTableComponent,
FilterHeaderComponent,
NoContentTemplateDirective,
EmptyListComponent,
TranslateModule,
NoPermissionTemplateDirective,
MatIconModule,
LoadingContentTemplateDirective,
MatProgressSpinnerModule,
MainMenuDataTableTemplateDirective,
ColumnsSelectorComponent
], providers: [
{
provide: ADF_DOCUMENT_PARENT_COMPONENT,
useExisting: DocumentListComponent
},
DataTableService
], encapsulation: ViewEncapsulation.None, host: { class: 'adf-document-list' }, template: "<adf-datatable\n #dataTable\n [selectionMode]=\"selectionMode\"\n [data]=\"data\"\n [actions]=\"contentActions\"\n [actionsPosition]=\"contentActionsPosition\"\n [multiselect]=\"multiselect\"\n [contextMenu]=\"contextMenuActions\"\n [rowStyle]=\"rowStyle\"\n [rowStyleClass]=\"rowStyleClass\"\n [showMainDatatableActions]=\"true\"\n [loading]=\"loading\"\n [noPermission]=\"noPermission\"\n [showHeader]=\"showHeader\"\n [rowMenuCacheEnabled]=\"false\"\n [stickyHeader]=\"stickyHeader\"\n [allowFiltering]=\"allowFiltering\"\n [isResizingEnabled]=\"isResizingEnabled\"\n [blurOnResize]=\"blurOnResize\"\n [displayCheckboxesOnHover]=\"displayCheckboxesOnHover\"\n (showRowContextMenu)=\"onShowRowContextMenu($event)\"\n (showRowActionsMenu)=\"onShowRowActionsMenu($event)\"\n (executeRowAction)=\"onExecuteRowAction($event)\"\n (column