mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-02 17:53:30 +00:00
[MNT-25681] Content node selector panel filtering fixed (#12032)
* [MNT-25681] Content node selector panel filtering fixed * [MNT-25681] Small cleanup * [MNT-25681] CR fix
This commit is contained in:
@@ -206,5 +206,9 @@ describe('ContentNodeDialogService', () => {
|
||||
expect(testContentNodeSelectorComponentData.isSelectionValid(testData.node)).toBe(testData.expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('should scope the search to folders by disabling files in the result', () => {
|
||||
expect(testContentNodeSelectorComponentData.showFilesInResult).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,7 +154,8 @@ export class ContentNodeDialogService {
|
||||
where: '(isFolder=true)',
|
||||
isSelectionValid: this.isCopyMoveSelectionValid.bind(this),
|
||||
excludeSiteContent: excludeSiteContent || ContentNodeDialogService.nonDocumentSiteContent,
|
||||
select
|
||||
select,
|
||||
showFilesInResult: false
|
||||
};
|
||||
|
||||
const dialogRef = this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px');
|
||||
@@ -196,7 +197,8 @@ export class ContentNodeDialogService {
|
||||
imageResolver: this.imageResolver.bind(this),
|
||||
isSelectionValid: this.hasAllowableOperationsOnNodeFolder.bind(this),
|
||||
where: '(isFolder=true)',
|
||||
select
|
||||
select,
|
||||
showFilesInResult: false
|
||||
};
|
||||
|
||||
const dialogRef = this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px');
|
||||
|
||||
+51
-1
@@ -19,7 +19,7 @@ import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { Node, NodeEntry, NodePaging, RequestScope, ResultSetPaging, SiteEntry, SitePaging, SitePagingList } from '@alfresco/js-api';
|
||||
import { of } from 'rxjs';
|
||||
import { of, Subject } from 'rxjs';
|
||||
import { ContentNodeSelectorPanelComponent } from './content-node-selector-panel.component';
|
||||
import { DocumentListService } from '../../document-list/services/document-list.service';
|
||||
import { DocumentListComponent } from '../../document-list/components/document-list.component';
|
||||
@@ -294,6 +294,32 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
expect(searchQueryBuilderService.addFilterQuery).toHaveBeenCalledWith(expectedRequest);
|
||||
}));
|
||||
|
||||
it('should remove the previous site filter query when changing the selected site', fakeAsync(() => {
|
||||
spyOn(searchQueryBuilderService, 'addFilterQuery').and.callThrough();
|
||||
spyOn(searchQueryBuilderService, 'removeFilterQuery').and.callThrough();
|
||||
typeToSearchBox('search-term');
|
||||
tick(debounceSearch);
|
||||
|
||||
component.siteChanged({ entry: { guid: 'namek' } } as SiteEntry);
|
||||
component.siteChanged({ entry: { guid: 'vegeta' } } as SiteEntry);
|
||||
|
||||
expect(searchQueryBuilderService.removeFilterQuery).toHaveBeenCalledWith(`ANCESTOR:'workspace://SpacesStore/namek'`);
|
||||
expect(searchQueryBuilderService.addFilterQuery).toHaveBeenCalledWith(`ANCESTOR:'workspace://SpacesStore/vegeta'`);
|
||||
expect(searchQueryBuilderService.filterQueries).toEqual([{ query: `ANCESTOR:'workspace://SpacesStore/vegeta'` }]);
|
||||
}));
|
||||
|
||||
it('should browse the selected site folder without searching when no search term is present', fakeAsync(() => {
|
||||
expect(searchSpy.calls.count()).toBe(0);
|
||||
|
||||
component.siteChanged({ entry: { guid: 'namek' } } as SiteEntry);
|
||||
tick(debounceSearch);
|
||||
|
||||
expect(searchSpy).not.toHaveBeenCalled();
|
||||
expect(component.searchTerm).toBe('');
|
||||
expect(component.folderIdToShow).toBe('namek');
|
||||
expect(component.showingSearchResults).toBe(false);
|
||||
}));
|
||||
|
||||
it('should create the query with the right parameters on changing the site selectBox value from a custom dropdown menu', fakeAsync(() => {
|
||||
spyOn(searchQueryBuilderService, 'addFilterQuery').and.callThrough();
|
||||
component.dropdownSiteList = { list: { entries: [{ entry: { guid: '-sites-' } }, { entry: { guid: 'namek' } }] } } as SitePaging;
|
||||
@@ -343,6 +369,29 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
expect(getCorrespondingNodeIdsSpy.calls.mostRecent().args[0]).toEqual('-sites-');
|
||||
}));
|
||||
|
||||
it('should execute the search only after the corresponding node ids filter query is applied for aliases', fakeAsync(() => {
|
||||
component.documentList.folderNode = { id: 'fakeNodeId', isFolder: true, path: {} } as Node;
|
||||
spyOn(searchQueryBuilderService, 'addFilterQuery').and.callThrough();
|
||||
const nodeIds$ = new Subject<string[]>();
|
||||
getCorrespondingNodeIdsSpy.and.returnValue(nodeIds$.asObservable());
|
||||
|
||||
typeToSearchBox('vegeta');
|
||||
tick(debounceSearch);
|
||||
|
||||
searchSpy.calls.reset();
|
||||
|
||||
component.siteChanged({ entry: { guid: '-sites-' } } as SiteEntry);
|
||||
|
||||
expect(searchSpy).not.toHaveBeenCalled();
|
||||
|
||||
nodeIds$.next(['123456testId']);
|
||||
nodeIds$.complete();
|
||||
|
||||
const expectedRequest = `ANCESTOR:'workspace://SpacesStore/-sites-' OR ANCESTOR:'workspace://SpacesStore/123456testId'`;
|
||||
expect(searchQueryBuilderService.addFilterQuery).toHaveBeenCalledWith(expectedRequest);
|
||||
expect(searchSpy).toHaveBeenCalledWith(false);
|
||||
}));
|
||||
|
||||
it('should NOT get the corresponding node ids on search when NOTHING is selected from dropdown', fakeAsync(() => {
|
||||
component.dropdownSiteList = { list: { entries: [{ entry: { guid: '-sites-' } }, { entry: { guid: 'namek' } }] } } as SitePaging;
|
||||
fixture.detectChanges();
|
||||
@@ -508,6 +557,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
|
||||
it('should the query restrict the search to the site and not to the currentFolderId in case is changed', async () => {
|
||||
spyOn(searchQueryBuilderService, 'addFilterQuery').and.callThrough();
|
||||
component.searchTerm = 'search-term';
|
||||
searchQueryBuilderService.userQuery = 'search-term*';
|
||||
component.currentFolderId = 'my-root-id';
|
||||
component.restrictRootToCurrentFolderId = true;
|
||||
|
||||
+39
-21
@@ -40,7 +40,8 @@ import { ImageResolver } from '../../document-list/data/image-resolver.model';
|
||||
import { CustomResourcesService } from '../../document-list/services/custom-resources.service';
|
||||
import { ShareDataRow } from '../../document-list/data/share-data-row.model';
|
||||
import { NodeEntryEvent } from '../../document-list/components/node.event';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { debounceTime, map } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { ContentNodeSelectorPanelService } from './content-node-selector-panel.service';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
@@ -110,6 +111,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
private showSearchField = true;
|
||||
private showCounter = false;
|
||||
private _emptyList = true;
|
||||
private lastParentFilterQuery: string | null = null;
|
||||
|
||||
/** If true will restrict the search and breadcrumbs to the currentFolderId */
|
||||
@Input()
|
||||
@@ -440,7 +442,12 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
this.siteId = chosenSite.entry.guid;
|
||||
this.setTitleIfCustomSite(chosenSite);
|
||||
this.siteChange.emit(chosenSite.entry.title);
|
||||
this.executeSearch(this.searchTerm);
|
||||
if (this.searchTerm) {
|
||||
this.executeSearch(this.searchTerm);
|
||||
} else {
|
||||
this.resetFolderToShow();
|
||||
this.clearSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,7 +474,6 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
this.folderIdToShow = null;
|
||||
this.preselectedNodes = [];
|
||||
this.loadingSearchResults = true;
|
||||
this.addCorrespondingNodeIdsQuery();
|
||||
this.resetChosenNode();
|
||||
}
|
||||
|
||||
@@ -499,25 +505,35 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
this.showingSearch.emit(this.showingSearchResults);
|
||||
}
|
||||
|
||||
private addCorrespondingNodeIdsQuery() {
|
||||
let extraParentFiltering = '';
|
||||
|
||||
private addCorrespondingNodeIdsQuery(): Observable<void> {
|
||||
if (this.customResourcesService.hasCorrespondingNodeIds(this.siteId)) {
|
||||
this.customResourcesService.getCorrespondingNodeIds(this.siteId).subscribe((nodeIds) => {
|
||||
if (nodeIds?.length) {
|
||||
nodeIds
|
||||
.filter((id) => id !== this.siteId)
|
||||
.forEach((extraId) => {
|
||||
extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
|
||||
});
|
||||
}
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'${extraParentFiltering}` : '';
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
});
|
||||
} else {
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'` : '';
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
return this.customResourcesService.getCorrespondingNodeIds(this.siteId).pipe(
|
||||
map((nodeIds) => {
|
||||
let extraParentFiltering = '';
|
||||
if (nodeIds?.length) {
|
||||
nodeIds
|
||||
.filter((id) => id !== this.siteId)
|
||||
.forEach((extraId) => {
|
||||
extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
|
||||
});
|
||||
}
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'${extraParentFiltering}` : '';
|
||||
this.setParentFilterQuery(parentFiltering);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const siteFilter = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'` : '';
|
||||
this.setParentFilterQuery(siteFilter);
|
||||
return of(undefined);
|
||||
}
|
||||
|
||||
private setParentFilterQuery(parentFiltering: string) {
|
||||
if (this.lastParentFilterQuery) {
|
||||
this.queryBuilderService.removeFilterQuery(this.lastParentFilterQuery);
|
||||
}
|
||||
this.lastParentFilterQuery = parentFiltering || null;
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
}
|
||||
|
||||
private setSearchScopeToNodes() {
|
||||
@@ -685,6 +701,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
this.queryBuilderService.searchMode = 'formula';
|
||||
const wildcardSuffix = this.queryBuilderService.wildcardsEnabled ? '*' : '';
|
||||
this.queryBuilderService.userQuery = searchValue.length > 0 ? `(${searchValue}${wildcardSuffix})` : searchValue;
|
||||
this.queryBuilderService.execute(false);
|
||||
this.addCorrespondingNodeIdsQuery()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(() => this.queryBuilderService.execute(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,12 @@ export class InfiniteSelectScrollDirective implements AfterViewInit {
|
||||
ngAfterViewInit() {
|
||||
this.matSelect.openedChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((opened: boolean) => {
|
||||
if (opened) {
|
||||
this.itemHeightToWaitBeforeLoadNext = this.getItemHeight() * (InfiniteSelectScrollDirective.MAX_ITEMS / 2);
|
||||
this.matSelect.panel.nativeElement.addEventListener('scroll', (event: Event) => this.handleScrollEvent(event));
|
||||
setTimeout(() => {
|
||||
if (this.matSelect.panel?.nativeElement) {
|
||||
this.itemHeightToWaitBeforeLoadNext = this.getItemHeight() * (InfiniteSelectScrollDirective.MAX_ITEMS / 2);
|
||||
this.matSelect.panel.nativeElement.addEventListener('scroll', (event: Event) => this.handleScrollEvent(event));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -56,6 +60,7 @@ export class InfiniteSelectScrollDirective implements AfterViewInit {
|
||||
}
|
||||
|
||||
private getItemHeight(): number {
|
||||
return parseFloat(getComputedStyle(this.matSelect.panel.nativeElement).fontSize || '0') * SELECT_ITEM_HEIGHT_EM;
|
||||
const panelElement = this.matSelect.panel?.nativeElement;
|
||||
return panelElement ? parseFloat(getComputedStyle(panelElement).fontSize || '0') * SELECT_ITEM_HEIGHT_EM : 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user