From c17241fedcd9ad23da047d33e01e4351299ef763 Mon Sep 17 00:00:00 2001 From: Suzana Dirla Date: Sun, 13 Jan 2019 20:25:01 +0200 Subject: [PATCH] [ADF-3854] Destination picker - exclude site content option (#4130) --- .../content-node-selector.component.html | 33 +++++++++++++++++++ .../content-node-selector.component.ts | 3 +- .../content-node-selector-panel.component.md | 1 + .../content-node-dialog.service.ts | 12 ++++++- ...tent-node-selector-panel.component.spec.ts | 15 +++++++++ .../content-node-selector-panel.component.ts | 33 +++++++++++++++++++ ...-node-selector.component-data.interface.ts | 1 + .../content-node-selector.component.html | 1 + .../content-node-selector.component.spec.ts | 2 +- 9 files changed, 98 insertions(+), 3 deletions(-) diff --git a/demo-shell/src/app/components/content-node-selector/content-node-selector.component.html b/demo-shell/src/app/components/content-node-selector/content-node-selector.component.html index 63dd8ef33a..41812d1e8d 100644 --- a/demo-shell/src/app/components/content-node-selector/content-node-selector.component.html +++ b/demo-shell/src/app/components/content-node-selector/content-node-selector.component.html @@ -112,6 +112,39 @@ + + + +

Exclude Site Content

+
+ + + +
+
+ +
+
+ +
+
+ + Show Files + + + Show Folders + + +
+ + +
+
diff --git a/demo-shell/src/app/components/content-node-selector/content-node-selector.component.ts b/demo-shell/src/app/components/content-node-selector/content-node-selector.component.ts index 62738bfed9..b6208cbfc1 100644 --- a/demo-shell/src/app/components/content-node-selector/content-node-selector.component.ts +++ b/demo-shell/src/app/components/content-node-selector/content-node-selector.component.ts @@ -17,7 +17,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { SitePaging, SiteEntry, MinimalNodeEntryEntity } from '@alfresco/js-api'; -import { ShareDataRow } from '@alfresco/adf-content-services'; +import { ContentNodeDialogService, ShareDataRow } from '@alfresco/adf-content-services'; import { DataRow, DataColumn, ThumbnailService } from '@alfresco/adf-core'; @Component({ @@ -41,6 +41,7 @@ export class ContentNodeSelectorComponent { actualPageSize = 2; rowFilterFunction: any = null; + excludeSiteContentList: string[] = ContentNodeDialogService.nonDocumentSiteContent; customImageResolver: any = null; defaultSites: SiteEntry[] = [ diff --git a/docs/content-services/content-node-selector-panel.component.md b/docs/content-services/content-node-selector-panel.component.md index cc68131f63..297092450b 100644 --- a/docs/content-services/content-node-selector-panel.component.md +++ b/docs/content-services/content-node-selector-panel.component.md @@ -38,6 +38,7 @@ Opens a Content Node Selector in its own dialog window. | isSelectionValid | `ValidationFunction` | defaultValidation | Function used to decide if the selected node has permission to be selected. Default value is a function that always returns true. | | pageSize | `number` | | Number of items shown per page in the list. | | rowFilter | `RowFilter` | null | Custom row filter function. See the [Document List component](document-list.component.md#custom-row-filter) for more information. | +| excludeSiteContent | string[] | [] | Custom list of site content componentIds that is used to filter out their corresponding items from the displayed nodes. | ### Events diff --git a/lib/content-services/content-node-selector/content-node-dialog.service.ts b/lib/content-services/content-node-selector/content-node-dialog.service.ts index 9b13a503a6..b15edb689e 100644 --- a/lib/content-services/content-node-selector/content-node-dialog.service.ts +++ b/lib/content-services/content-node-selector/content-node-dialog.service.ts @@ -32,6 +32,14 @@ import { switchMap } from 'rxjs/operators'; providedIn: 'root' }) export class ContentNodeDialogService { + static nonDocumentSiteContent = [ + 'blog', + 'calendar', + 'dataLists', + 'discussions', + 'links', + 'wiki' + ]; /** Emitted when an error occurs. */ @Output() @@ -117,9 +125,10 @@ export class ContentNodeDialogService { * @param action Name of the action (eg, "Copy" or "Move") to show in the title * @param contentEntry Item to be copied or moved * @param permission Permission for the operation + * @param excludeSiteContent The site content that should be filtered out * @returns Information about files that were copied/moved */ - openCopyMoveDialog(action: string, contentEntry: Node, permission?: string): Observable { + openCopyMoveDialog(action: string, contentEntry: Node, permission?: string, excludeSiteContent?: string[]): Observable { if (this.contentService.hasPermission(contentEntry, permission)) { const select = new Subject(); @@ -136,6 +145,7 @@ export class ContentNodeDialogService { imageResolver: this.imageResolver.bind(this), rowFilter: this.rowFilter.bind(this, contentEntry.id), isSelectionValid: this.isCopyMoveSelectionValid.bind(this), + excludeSiteContent: excludeSiteContent || ContentNodeDialogService.nonDocumentSiteContent, select: select }; diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts index 658545b2cc..9b2ef3cfea 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts @@ -107,6 +107,21 @@ describe('ContentNodeSelectorComponent', () => { component.chosenNode = expectedNode; }); + + it('should be able to filter out the exclude site content', () => { + component.excludeSiteContent = ['blog']; + fixture.detectChanges(); + + const testSiteContent = new Node({id: 'blog-id', properties: { 'st:componentId': 'blog' }}); + expect(component.rowFilter( {node: {entry: testSiteContent}}, null, null)).toBe(false); + }); + + it('should NOT filter out any site content by default', () => { + fixture.detectChanges(); + + const testSiteContent = new Node({id: 'blog-id', properties: { 'st:componentId': 'blog' }}); + expect(component.rowFilter( {node: {entry: testSiteContent}}, null, null)).toBe(true); + }); }); describe('Breadcrumbs', () => { diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.ts b/lib/content-services/content-node-selector/content-node-selector-panel.component.ts index f0de915d95..ae8a10e9a2 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.ts +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.ts @@ -29,6 +29,7 @@ import { ContentNodeSelectorService } from './content-node-selector.service'; import { debounceTime } from 'rxjs/operators'; import { BehaviorSubject } from 'rxjs'; import { CustomResourcesService } from '../document-list/services/custom-resources.service'; +import { ShareDataRow } from '../document-list'; export type ValidationFunction = (entry: Node) => boolean; @@ -68,6 +69,12 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo @Input() rowFilter: RowFilter = null; + /** Custom list of site content componentIds. + * Used to filter out the corresponding items from the displayed nodes + */ + @Input() + excludeSiteContent: string[] = []; + /** Custom image resolver function. See the * [Document List component](document-list.component.md#custom-row-filter) * for more information. @@ -159,6 +166,32 @@ export class ContentNodeSelectorPanelComponent implements OnInit, PaginatedCompo this.breadcrumbTransform = this.breadcrumbTransform ? this.breadcrumbTransform : null; this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation; + this.excludeSiteContent = this.excludeSiteContent ? this.excludeSiteContent : []; + this.rowFilter = this.getRowFilter(this.rowFilter); + } + + private getRowFilter(initialFilterFunction): RowFilter { + if (!initialFilterFunction) { + initialFilterFunction = () => true; + } + return (value: ShareDataRow, index: number, array: ShareDataRow[]) => { + return initialFilterFunction(value, index, array) && + !this.isExcludedSiteContent(value); + }; + } + + private isExcludedSiteContent(row: ShareDataRow): boolean { + const entry = row.node.entry; + if (this.excludeSiteContent.length && + entry && + entry.properties && + entry.properties['st:componentId']) { + const excludedItem = this.excludeSiteContent.find( + (id: string) => entry.properties['st:componentId'] === id + ); + return !!excludedItem; + } + return false; } /** diff --git a/lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts b/lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts index 045c72b89c..fb7d05d652 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts +++ b/lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts @@ -28,5 +28,6 @@ export interface ContentNodeSelectorComponentData { imageResolver?: any; isSelectionValid?: (entry: Node) => boolean; breadcrumbTransform?: (node) => any; + excludeSiteContent?: string[]; select: Subject; } diff --git a/lib/content-services/content-node-selector/content-node-selector.component.html b/lib/content-services/content-node-selector/content-node-selector.component.html index 29e80c8bf9..b6e045b4e3 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component.html +++ b/lib/content-services/content-node-selector/content-node-selector.component.html @@ -12,6 +12,7 @@ [imageResolver]="imageResolver || data?.imageResolver" [isSelectionValid]="data?.isSelectionValid" [breadcrumbTransform]="data?.breadcrumbTransform" + [excludeSiteContent]="data?.excludeSiteContent" (select)="onSelect($event)"> diff --git a/lib/content-services/content-node-selector/content-node-selector.component.spec.ts b/lib/content-services/content-node-selector/content-node-selector.component.spec.ts index a817558887..46a61157b8 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component.spec.ts +++ b/lib/content-services/content-node-selector/content-node-selector.component.spec.ts @@ -54,7 +54,7 @@ describe('ContentNodeSelectorDialogComponent', () => { const documentListService: DocumentListService = TestBed.get(DocumentListService); const sitesService: SitesService = TestBed.get(SitesService); spyOn(documentListService, 'getFolder').and.returnValue(of({ list: [] })); - spyOn(documentListService, 'getFolderNode').and.returnValue(of({})); + spyOn(documentListService, 'getFolderNode').and.returnValue(of({ entry: {} })); spyOn(sitesService, 'getSites').and.returnValue(of({ list: { entries: [] } })); fixture = TestBed.createComponent(ContentNodeSelectorComponent);