From e21b777a3ca28f8a9f0ce9c4741bb5a97d6e5fe0 Mon Sep 17 00:00:00 2001 From: Cilibiu Bogdan Date: Sat, 6 Mar 2021 11:37:42 +0200 Subject: [PATCH] [ADF-5354] Content node selector is not working properly for read-only folders (#6777) * disable button when no permission * test * breadcrumb fallback when selection is not valid * test --- ...tent-node-selector-panel.component.spec.ts | 15 +++++++++++ .../content-node-selector-panel.component.ts | 8 +++++- .../content-node-selector.component.spec.ts | 25 ++++++++++++++++--- .../content-node-selector.component.ts | 2 +- 4 files changed, 45 insertions(+), 5 deletions(-) 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 3c90d74ae9..7e52439897 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 @@ -328,6 +328,21 @@ describe('ContentNodeSelectorPanelComponent', () => { done(); }); }); + + it('should show the breadcrumb for the selected node event if selection is not valid', async () => { + const chosenNode = new Node({ path: { elements: [{ id: 'testId', name: 'testName' }] } }); + component.isSelectionValid = () => false; + searchQueryBuilderService.userQuery = 'mock-search-term'; + searchQueryBuilderService.update(); + triggerSearchResults(fakeResultSetPaging); + + component.onCurrentSelection([ { entry: chosenNode } ]); + fixture.detectChanges(); + const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent)); + + expect(breadcrumb.componentInstance.route[0].name).toBe('testName'); + expect(breadcrumb.componentInstance.route[0].id).toBe('testId'); + }); }); describe('Site selection', () => { 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 18e33ef8df..1ba9877c49 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 @@ -77,6 +77,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { private showSiteList = true; private showSearchField = true; + private breadcrumbFolderNodeFallback: Node ; /** If true will restrict the search and breadcrumbs to the currentFolderId */ @Input() @@ -445,7 +446,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { let folderNode: Node; if (this.showingSearchResults && this.chosenNode) { - folderNode = this.chosenNode[0]; + folderNode = this.chosenNode[0] || this.breadcrumbFolderNodeFallback; } else { folderNode = this.documentList.folderNode; } @@ -465,6 +466,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { this.loadingSearchResults = true; this.addCorrespondingNodeIdsQuery(); this.resetChosenNode(); + this.breadcrumbFolderNodeFallback = null ; } /** @@ -606,8 +608,12 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { * @param nodesEntries */ onCurrentSelection(nodesEntries: NodeEntry[]): void { + this.breadcrumbFolderNodeFallback = null; const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry)); this.chosenNode = validNodesEntity.map((node) => node.entry); + if (!this.chosenNode.length) { + this.breadcrumbFolderNodeFallback = nodesEntries[0].entry; + } } setTitleIfCustomSite(site: SiteEntry) { diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts index bf809d86eb..8427986f5e 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts @@ -21,7 +21,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ContentNodeSelectorComponent } from './content-node-selector.component'; import { Node, NodeEntry } from '@alfresco/js-api'; import { By } from '@angular/platform-browser'; -import { SitesService, ContentService } from '@alfresco/adf-core'; +import { SitesService, ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; import { of } from 'rxjs'; import { ContentTestingModule } from '../testing/content.testing.module'; import { DocumentListService } from '../document-list/services/document-list.service'; @@ -79,7 +79,6 @@ describe('ContentNodeSelectorComponent', () => { fixture = TestBed.createComponent(ContentNodeSelectorComponent); component = fixture.componentInstance; const contentService = TestBed.inject(ContentService); - spyOn(contentService, 'hasAllowableOperations').and.returnValue(true); const fakeFolderNodeWithPermission = new NodeEntry({ entry: { @@ -96,7 +95,6 @@ describe('ContentNodeSelectorComponent', () => { spyOn(contentService, 'getNode').and.returnValue(of(fakeFolderNodeWithPermission)); component.data.showLocalUploadButton = true; - component.hasAllowableOperations = true; component.showingSearch = false; fixture.detectChanges(); }); @@ -226,6 +224,27 @@ describe('ContentNodeSelectorComponent', () => { }); }); + describe('Action button for current folder', () => { + it('should be disabled when current folder does not allow upload', () => { + const node = new Node({ id: 'fake'}); + component.onCurrentFolder(node); + fixture.detectChanges(); + + const actionButtonWithoutNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); + expect(actionButtonWithoutNodeSelected.nativeElement.disabled).toBe(true); + }); + + it('should be enabled when current folder allows upload', () => { + const node = new Node({ id: 'fake', allowableOperations: [AllowableOperationsEnum.CREATE] }); + component.onCurrentFolder(node); + component.chosenNode = [node]; + fixture.detectChanges(); + + const actionButtonWithoutNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); + expect(actionButtonWithoutNodeSelected.nativeElement.disabled).toBe(false); + }); + }); + describe('Title', () => { it('should be updated when a site is chosen', () => { diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.ts index affd22312b..a952e4d8a8 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.ts @@ -109,7 +109,7 @@ export class ContentNodeSelectorComponent implements OnInit { } isChooseButtonDisabled(): boolean { - return this.uploadService.isUploading() || !this.hasNodeSelected(); + return this.uploadService.isUploading() || !this.hasNodeSelected() || this.hasNoPermissionToUpload(); } hasNodeSelected(): boolean {