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 ac68e6acc8..8968cb02b1 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 @@ -227,5 +227,24 @@ + + + +

shows files

+
+ + + +
+ +
+ + +
+
diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index 6906c0ce25..23d04a2499 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -22,8 +22,10 @@ Displays and edits metadata related to a node. - [Aspect oriented config](#aspect-oriented-config) - [Layout oriented config](#layout-oriented-config) - [Displaying all properties](#displaying-all-properties) + - [Making aspects and properties read only](#making-aspects-and-properties-read-only) - [What happens when there is a whitelisted aspect in the config but the given node doesn't relate to that aspect](#what-happens-when-there-is-a-whitelisted-aspect-in-the-config-but-the-given-node-doesnt-relate-to-that-aspect) - [Multi value card properties](#multi-value-card-properties) + - [Use chips for multi value properties](#use-chips-for-multi-value-properties) ## Basic Usage diff --git a/docs/content-services/components/content-node-selector-panel.component.md b/docs/content-services/components/content-node-selector-panel.component.md index fd39deaf7b..32c1d64e52 100644 --- a/docs/content-services/components/content-node-selector-panel.component.md +++ b/docs/content-services/components/content-node-selector-panel.component.md @@ -41,6 +41,7 @@ Opens a [Content Node Selector](content-node-selector.component.md) in its own | excludeSiteContent | `string[]` | | Custom list of site content componentIds. Used to filter out the corresponding items from the displayed nodes | | rowFilter | [`RowFilter`](../../../lib/content-services/src/lib/document-list/data/row-filter.model.ts) | | Custom row filter function. See the [Row Filter Model](row-filter.model.md) page for more information. | | showDropdownSiteList | `boolean` | | Toggle sites list dropdown rendering | +| showFilesInResult | `boolean` | | Shows the files and folders in the search result | | showSearch | `boolean` | | Toggle search input rendering | ### Events diff --git a/docs/content-services/services/content-node-dialog.service.md b/docs/content-services/services/content-node-dialog.service.md index 09b19b482e..d1b31a93fa 100644 --- a/docs/content-services/services/content-node-dialog.service.md +++ b/docs/content-services/services/content-node-dialog.service.md @@ -28,11 +28,11 @@ Displays and manages dialogs for selecting content to open, copy or upload. - _excludeSiteContent:_ `string[]` - (Optional) The site content that should be filtered out - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>` - Information about files that were copied/moved - **openFileBrowseDialogByFolderId**(folderNodeId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
- Opens a file browser at a chosen folder location. + Opens a file browser at a chosen folder location. shows files and folders in the dialog search result. - _folderNodeId:_ `string` - ID of the folder to use - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>` - Information about the selected file(s) - **openFileBrowseDialogBySite**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
- Opens a file browser at a chosen site location. + Opens a file browser at a chosen site location. shows files and folders in the dialog search result. - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>` - Information about the selected file(s) - **openFolderBrowseDialogByFolderId**(folderNodeId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
Opens a folder browser at a chosen folder location. @@ -45,10 +45,11 @@ Displays and manages dialogs for selecting content to open, copy or upload. Opens a lock node dialog. - _contentEntry:_ [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) - [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) to lock - **Returns** [`Subject`](http://reactivex.io/documentation/subject.html)`` - Error/status message (if any) -- **openUploadFileDialog**(action: `string`, contentEntry: [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
+- **openUploadFileDialog**(action: `string`, contentEntry: [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md), showFilesInResult: `boolean` = `false`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
Opens a dialog to choose a file to upload. - _action:_ `string` - Name of the action to show in the title - _contentEntry:_ [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) - Item to upload + - _showFilesInResult:_ `boolean` - Show files in dialog search result - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>` - Information about the chosen file(s) - **openUploadFolderDialog**(action: `string`, contentEntry: [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`[]>`
Opens a dialog to choose folders to upload. diff --git a/lib/content-services/src/lib/content-node-selector/content-node-dialog.service.ts b/lib/content-services/src/lib/content-node-selector/content-node-dialog.service.ts index 88bec54d67..920b488bab 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-dialog.service.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-dialog.service.ts @@ -54,12 +54,13 @@ export class ContentNodeDialogService { /** * Opens a file browser at a chosen folder location. + * shows files and folders in the dialog search result. * @param folderNodeId ID of the folder to use * @returns Information about the selected file(s) */ openFileBrowseDialogByFolderId(folderNodeId: string): Observable { return this.documentListService.getFolderNode(folderNodeId).pipe(switchMap((nodeEntry: NodeEntry) => { - return this.openUploadFileDialog('Choose', nodeEntry.entry); + return this.openUploadFileDialog('Choose', nodeEntry.entry, true); })); } @@ -91,6 +92,7 @@ export class ContentNodeDialogService { /** * Opens a file browser at a chosen site location. + * shows files and folders in the dialog search result. * @returns Information about the selected file(s) */ openFileBrowseDialogBySite(): Observable { @@ -196,9 +198,10 @@ export class ContentNodeDialogService { * Opens a dialog to choose a file to upload. * @param action Name of the action to show in the title * @param contentEntry Item to upload + * @param showFilesInResult Show files in dialog search result * @returns Information about the chosen file(s) */ - openUploadFileDialog(action: string, contentEntry: Node): Observable { + openUploadFileDialog(action: string, contentEntry: Node, showFilesInResult = false): Observable { const select = new Subject(); select.subscribe({ complete: this.close.bind(this) @@ -210,7 +213,8 @@ export class ContentNodeDialogService { currentFolderId: contentEntry.id, imageResolver: this.imageResolver.bind(this), isSelectionValid: this.isNodeFile.bind(this), - select: select + select: select, + showFilesInResult }; this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px'); diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts index dfb9a9cdf3..e40e0764ae 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts @@ -353,7 +353,7 @@ describe('ContentNodeSelectorComponent', () => { describe('Search functionality', () => { let getCorrespondingNodeIdsSpy; - const defaultSearchOptions = (searchTerm, rootNodeId = undefined, skipCount = 0) => { + const defaultSearchOptions = (searchTerm, rootNodeId = undefined, skipCount = 0, showFiles = false) => { const parentFiltering = rootNodeId ? [{ query: `ANCESTOR:'workspace://SpacesStore/${rootNodeId}'` }] : []; @@ -367,7 +367,7 @@ describe('ContentNodeSelectorComponent', () => { skipCount: skipCount }, filterQueries: [ - { query: "TYPE:'cm:folder'" }, + { query: `TYPE:'cm:folder'${ showFiles ? " OR TYPE:'cm:content'" : '' }` }, { query: 'NOT cm:creator:System' }, ...parentFiltering ], @@ -419,6 +419,16 @@ describe('ContentNodeSelectorComponent', () => { expect(searchSpy).toHaveBeenCalledWith(defaultSearchOptions('kakarot')); })); + it('should show files in results by calling the search api on search change', fakeAsync(() => { + component.showFilesInResult = true; + typeToSearchBox('kakarot'); + + tick(debounceSearch); + fixture.detectChanges(); + + expect(searchSpy).toHaveBeenCalledWith(defaultSearchOptions('kakarot', undefined, 0, true)); + })); + it('should reset the currently chosen node in case of starting a new search', fakeAsync(() => { component.chosenNode = {}; typeToSearchBox('kakarot'); @@ -452,8 +462,8 @@ describe('ContentNodeSelectorComponent', () => { expect(cnSearchSpy).toHaveBeenCalled(); expect(cnSearchSpy.calls.count()).toBe(2); - expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25); - expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId']); + expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25, [], false); + expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId'], false); })); it('should call the content node selector\'s search with the right parameters on changing the site selectBox value from a custom dropdown menu', fakeAsync(() => { @@ -470,8 +480,8 @@ describe('ContentNodeSelectorComponent', () => { expect(cnSearchSpy).toHaveBeenCalled(); expect(cnSearchSpy.calls.count()).toBe(2); - expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25); - expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId']); + expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25, [], false); + expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId'], false); })); it('should get the corresponding node ids on search when a known alias is selected from dropdown', fakeAsync(() => { diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts index fd6f0547fb..033f8ff51d 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts @@ -56,6 +56,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { private showSiteList = true; private showSearchField = true; + private showFiles = false; /** Node ID of the folder currently listed. */ @Input() @@ -163,6 +164,14 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { return this.showSiteList; } + /** Shows the files and folders in the search result */ + @Input() + set showFilesInResult(value: boolean) { + if (value !== undefined && value !== null) { + this.showFiles = value; + } + } + /** Emitted when the user has chosen an item. */ @Output() select: EventEmitter = new EventEmitter(); @@ -355,14 +364,14 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { if (this.customResourcesService.hasCorrespondingNodeIds(this.siteId)) { this.customResourcesService.getCorrespondingNodeIds(this.siteId) .subscribe((nodeIds) => { - this.contentNodeSelectorService.search(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems, nodeIds) + this.contentNodeSelectorService.search(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems, nodeIds, this.showFiles) .subscribe(this.showSearchResults.bind(this)); }, () => { this.showSearchResults({ list: { entries: [] } }); }); } else { - this.contentNodeSelectorService.search(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems) + this.contentNodeSelectorService.search(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems, [], this.showFiles) .subscribe(this.showSearchResults.bind(this)); } } diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component-data.interface.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.component-data.interface.ts index a3501f8610..c5c9a488f1 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component-data.interface.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component-data.interface.ts @@ -32,5 +32,6 @@ export interface ContentNodeSelectorComponentData { excludeSiteContent?: string[]; select: Subject; showSearch?: boolean; + showFilesInResult?: boolean; showDropdownSiteList?: boolean; } diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html index 9058be217c..4116ae40e4 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html @@ -17,6 +17,7 @@ [where]="data?.where" [showSearch]="data?.showSearch" [showDropdownSiteList]="data?.showDropdownSiteList" + [showFilesInResult]="data?.showFilesInResult" (select)="onSelect($event)"> diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.service.spec.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.service.spec.ts index e07d813773..bb5de09ed3 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.service.spec.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.service.spec.ts @@ -80,12 +80,18 @@ describe('ContentNodeSelectorService', () => { expect(search.query.paging.skipCount).toEqual(0); }); - it('should filter the search only for folders', () => { + it('should filter the search for folders', () => { service.search('nuka cola quantum'); expect(search.query.filterQueries).toContain({ query: "TYPE:'cm:folder'" }); }); + it('should filter the search for files', () => { + service.search('nuka cola quantum', null, 0, 25, [], true); + + expect(search.query.filterQueries).toContain({ query: "TYPE:'cm:folder' OR TYPE:'cm:content'" }); + }); + it('should filter out the "system-base" entries', () => { service.search('nuka cola quantum'); diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.service.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.service.ts index 4e8c0178f2..6b76831a0a 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.service.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.service.ts @@ -41,8 +41,9 @@ export class ContentNodeSelectorService { * @param [extraNodeIds] List of extra node ids to search from. This last parameter is necessary when * the rootNodeId is one of the supported aliases (e.g. '-my-', '-root-', '-mysites-', etc.) * and search is not supported for that alias, but can be performed on its corresponding nodes. + * @param [showFiles] shows the files in the dialog search result */ - public search(searchTerm: string, rootNodeId: string = null, skipCount: number = 0, maxItems: number = 25, extraNodeIds?: string[]): Observable { + public search(searchTerm: string, rootNodeId: string = null, skipCount: number = 0, maxItems: number = 25, extraNodeIds?: string[], showFiles?: boolean): Observable { let extraParentFiltering = ''; @@ -66,7 +67,7 @@ export class ContentNodeSelectorService { skipCount: skipCount }, filterQueries: [ - { query: "TYPE:'cm:folder'" }, + { query: `TYPE:'cm:folder'${ showFiles ? " OR TYPE:'cm:content'" : '' }` }, { query: 'NOT cm:creator:System' }, ...parentFiltering ], diff --git a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts index dd66cd7411..39e8fd08ee 100644 --- a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts @@ -46,7 +46,8 @@ export class ContentCloudNodeSelectorService { actionName: 'Choose', currentFolderId: '-my-', select, - isSelectionValid: this.isNodeFile.bind(this) + isSelectionValid: this.isNodeFile.bind(this), + showFilesInResult: true }; this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px'); diff --git a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog-component.interface.ts b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog-component.interface.ts index 5a6f3ab694..966174954e 100644 --- a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog-component.interface.ts +++ b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog-component.interface.ts @@ -25,4 +25,5 @@ export interface AttachFileWidgetDialogComponentData { ecmHost: string; context?: string; isSelectionValid?: (entry: Node) => boolean; + showFilesInResult?: boolean; } diff --git a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.component.html b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.component.html index 1418bb7620..4aeeaa3dc8 100644 --- a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.component.html +++ b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.component.html @@ -9,6 +9,7 @@ diff --git a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts index bbd00536e7..a4ecda3b3f 100644 --- a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts +++ b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts @@ -53,7 +53,8 @@ export class AttachFileWidgetDialogService { selected, ecmHost, context, - isSelectionValid: this.isNodeFile.bind(this) + isSelectionValid: this.isNodeFile.bind(this), + showFilesInResult: true }; this.openLoginDialog(data, 'adf-attach-file-widget-dialog', '630px');