From 6f2cbdf6978160378974425cf489802959ea9e98 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Mon, 11 Jun 2018 12:53:09 +0100 Subject: [PATCH] [ADF-2859] fixes for the conditional visibility and disabled states (#3465) * fixes for the conditional visibility and disabled states * update docs * cleanup code * remove unused code --- .../app/components/files/files.component.html | 14 +---- .../app/components/files/files.component.ts | 5 +- .../content-action.component.md | 56 ++----------------- .../content-action-list.component.ts | 11 ++++ .../content-action.component.ts | 18 +++++- .../components/document-list.component.html | 1 + .../components/document-list.component.ts | 31 +++++++++- .../context-menu-holder.component.ts | 16 +++--- .../datatable/datatable.component.ts | 21 ++++++- 9 files changed, 89 insertions(+), 84 deletions(-) diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index adb0f167f5..e647786835 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -279,13 +279,13 @@ + - - - -
- - Toggle custom download action - -
-
{{'DOCUMENT_LIST.MULTISELECT_CHECKBOXES' | translate}} diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index ce68352e58..d0ac5ae6eb 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -170,9 +170,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { @ViewChild(InfinitePaginationComponent) infinitePaginationComponent: InfinitePaginationComponent; - @Input() - showCustomDownloadAction = false; - permissionsStyle: PermissionStyleModel[] = []; infiniteScrolling: boolean; supportedPages: number[]; @@ -514,7 +511,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { } canDownloadNode = (node: MinimalNodeEntity): boolean => { - if (node && node.entry && node.entry.name === 'For Sale.docx') { + if (node && node.entry && node.entry.name === 'custom') { return true; } return false; diff --git a/docs/content-services/content-action.component.md b/docs/content-services/content-action.component.md index b5a59ad899..1776a46c78 100644 --- a/docs/content-services/content-action.component.md +++ b/docs/content-services/content-action.component.md @@ -324,12 +324,10 @@ allow the item being copied/moved to be the destination if it is itself a folder ### Conditional visibility -The Content-action component allows you to control visibility with the help of the `visible` -property which can receive its value in three main ways: +The `` component allows you to control visibility with the help of the `visible` property and supports the following scenarios: -- direct `boolean` value -- binding to a `boolean` property -- binding to a `Function` property that evaluates the condition and returns a `boolean` value +- direct value of `boolean` type +- binding to a property of the `Function` type that evaluates condition and returns `boolean` value #### Using direct boolean value @@ -342,30 +340,7 @@ property which can receive its value in three main ways: ``` -#### Binding to a boolean property - -```html - - -``` - -The markup above relies on the `showCustomDownloadAction` property declared in your -component class: - -```ts -export class MyComponent { - - @Input() - showCustomDownloadAction = true; - -} -``` - -#### Binding to a Function property +#### Using a property of the Function type ```html { Similar to `visible` property, it is possible to control the `disabled` state with the following scenarios: - direct value of `boolean` type -- binding to a property of the `boolean` type - binding to a property of the `Function` type that evaluates condition and returns `boolean` value #### Using direct value of boolean type @@ -423,28 +397,6 @@ Similar to `visible` property, it is possible to control the `disabled` state wi ``` -#### Using a property of the boolean type - -```html - - -``` - -The markup above relies on the `shouldDisableAction` property declared at your component class level: - -```ts -export class MyComponent { - - @Input() - shouldDisableAction = true; - -} -``` - #### Using a property of the Function type ```html diff --git a/lib/content-services/document-list/components/content-action/content-action-list.component.ts b/lib/content-services/document-list/components/content-action/content-action-list.component.ts index 1b5d5068cd..6f4ebee808 100644 --- a/lib/content-services/document-list/components/content-action/content-action-list.component.ts +++ b/lib/content-services/document-list/components/content-action/content-action-list.component.ts @@ -42,4 +42,15 @@ export class ContentActionListComponent { } return false; } + + unregisterAction(action: ContentActionModel): boolean { + if (this.documentList && action) { + const idx = this.documentList.actions.indexOf(action); + if (idx >= 0) { + this.documentList.actions.splice(idx, 1); + return true; + } + } + return false; + } } diff --git a/lib/content-services/document-list/components/content-action/content-action.component.ts b/lib/content-services/document-list/components/content-action/content-action.component.ts index b599826e83..f7d1221241 100644 --- a/lib/content-services/document-list/components/content-action/content-action.component.ts +++ b/lib/content-services/document-list/components/content-action/content-action.component.ts @@ -132,8 +132,15 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy { this.subscriptions.forEach(subscription => subscription.unsubscribe()); this.subscriptions = []; - this.documentActionModel = null; - this.folderActionModel = null; + if (this.documentActionModel) { + this.unregister(this.documentActionModel); + this.documentActionModel = null; + } + + if (this.folderActionModel) { + this.unregister(this.folderActionModel); + this.folderActionModel = null; + } } register(model: ContentActionModel): boolean { @@ -143,6 +150,13 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy { return false; } + unregister(model: ContentActionModel): boolean { + if (this.list) { + return this.list.unregisterAction(model); + } + return false; + } + private generateAction(target: string): ContentActionModel { const model = new ContentActionModel({ title: this.title, diff --git a/lib/content-services/document-list/components/document-list.component.html b/lib/content-services/document-list/components/document-list.component.html index 4b67ed60d1..8e23555af5 100644 --- a/lib/content-services/document-list/components/document-list.component.html +++ b/lib/content-services/document-list/components/document-list.component.html @@ -13,6 +13,7 @@ [display]="display" [noPermission]="noPermission" [showHeader]="!isEmpty() && showHeader" + [rowMenuCacheEnabled]="false" (showRowContextMenu)="onShowRowContextMenu($event)" (showRowActionsMenu)="onShowRowActionsMenu($event)" (executeRowAction)="onExecuteRowAction($event)" diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index c8fba28479..5487b830a0 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -236,6 +236,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte private _pagination: BehaviorSubject; private layoutPresets = {}; private subscriptions: Subscription[] = []; + private rowMenuCache: { [key: string]: ContentActionModel[] } = {}; constructor(private documentListService: DocumentListService, private ngZone: NgZone, @@ -333,6 +334,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } ngOnInit() { + this.rowMenuCache = {}; this.loadLayoutPresets(); this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, null, this.getDefaultSorting(), this.sortingMode); this.data.thumbnails = this.thumbnails; @@ -444,9 +446,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } getNodeActions(node: MinimalNodeEntity | any): ContentActionModel[] { - let target = null; if (node && node.entry) { + let target = null; + if (node.entry.isFile) { target = 'document'; } else if (node.entry.isFolder) { @@ -454,6 +457,14 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } if (target) { + const actions = this.rowMenuCache[node.entry.id]; + if (actions) { + actions.forEach(action => { + this.refreshAction(action, node); + }); + return actions; + } + let actionsByTarget = this.actions .filter(entry => { const isVisible = (typeof entry.visible === 'function') @@ -465,9 +476,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte .map(action => new ContentActionModel(action)); actionsByTarget.forEach((action) => { - action.disabled = this.isActionDisabled(action, node); + this.refreshAction(action, node); }); + this.rowMenuCache[node.entry.id] = actionsByTarget; return actionsByTarget; } } @@ -475,6 +487,19 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte return []; } + private refreshAction(action: ContentActionModel, node: MinimalNodeEntity) { + action.disabled = this.isActionDisabled(action, node); + action.visible = this.isActionVisible(action, node); + } + + private isActionVisible(action: ContentActionModel, node: MinimalNodeEntity): boolean { + if (typeof action.visible === 'function') { + return action.visible(node); + } + + return action.visible; + } + private isActionDisabled(action: ContentActionModel, node: MinimalNodeEntity): boolean { if (typeof action.disabled === 'function') { return action.disabled(node); @@ -484,7 +509,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte return true; } - return false; + return action.disabled; } @HostListener('contextmenu', ['$event']) diff --git a/lib/core/context-menu/context-menu-holder.component.ts b/lib/core/context-menu/context-menu-holder.component.ts index 523190e045..e0eb824e52 100644 --- a/lib/core/context-menu/context-menu-holder.component.ts +++ b/lib/core/context-menu/context-menu-holder.component.ts @@ -29,13 +29,15 @@ import { ContextMenuService } from './context-menu.service'; template: ` - + + + ` }) diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 7fce72ffa5..65569b3d67 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -155,6 +155,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, @Input() noPermission: boolean = false; + @Input() + rowMenuCacheEnabled = true; + noContentTemplate: TemplateRef; noPermissionTemplate: TemplateRef; loadingTemplate: TemplateRef; @@ -166,6 +169,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, private click$: Observable; private differ: any; + private rowMenuCache: object = {}; + private subscriptions: Subscription[] = []; private singleClickStreamSub: Subscription; private multiClickStreamSub: Subscription; @@ -297,6 +302,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, private initTable() { this.data = new ObjectDataTableAdapter(this.rows, this.columns); this.setupData(this.data); + this.rowMenuCache = {}; } private setupData(adapter: DataTableAdapter) { @@ -553,9 +559,18 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, } getRowActions(row: DataRow, col: DataColumn): any[] { - let event = new DataCellEvent(row, col, []); - this.showRowActionsMenu.emit(event); - return event.value.actions; + const id = row.getValue('id'); + + if (!this.rowMenuCache[id]) { + let event = new DataCellEvent(row, col, []); + this.showRowActionsMenu.emit(event); + if (!this.rowMenuCacheEnabled) { + return event.value.actions; + } + this.rowMenuCache[id] = event.value.actions; + } + + return this.rowMenuCache[id]; } onExecuteRowAction(row: DataRow, action: any) {