[AAE-3719][AAE-3720] - Fix content node selector search should align with the filtering (#6214)

* Fix content node selector search should align with the filtering

* Add a flag to disable optionally the search execution in the filters

* Add unit tests

* refactoring - Remove content node selector service and use the main search service instead

* Fix existing unit tests to align with the new changes

* Fix bug when copying a file

* add include properties in demo shell search config

* revert attach-file-cloud widget

* Remove unused import

* More unit tests
This commit is contained in:
arditdomi
2020-10-20 15:48:23 +01:00
committed by GitHub
parent 7dec482d91
commit 072f910452
11 changed files with 317 additions and 376 deletions

View File

@@ -119,7 +119,8 @@
], ],
"include": [ "include": [
"path", "path",
"allowableOperations" "allowableOperations",
"properties"
], ],
"sorting": { "sorting": {
"options": [ "options": [

View File

@@ -18,7 +18,7 @@
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { tick, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing'; import { tick, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { NodeEntry, Node, SiteEntry, SitePaging, NodePaging, ResultSetPaging } from '@alfresco/js-api'; import { NodeEntry, Node, SiteEntry, SitePaging, NodePaging, ResultSetPaging, RequestScope } from '@alfresco/js-api';
import { SitesService, setupTestBed, NodesApiService } from '@alfresco/adf-core'; import { SitesService, setupTestBed, NodesApiService } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { DropdownBreadcrumbComponent } from '../breadcrumb'; import { DropdownBreadcrumbComponent } from '../breadcrumb';
@@ -31,7 +31,7 @@ import { CustomResourcesService } from '../document-list/services/custom-resourc
import { NodeEntryEvent, ShareDataRow } from '../document-list'; import { NodeEntryEvent, ShareDataRow } from '../document-list';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { SearchQueryBuilderService } from '../search'; import { SearchQueryBuilderService } from '../search';
import { ContentNodeSelectorService } from './content-node-selector.service'; import { mockQueryBody } from '../mock/search-query.mock';
const fakeResultSetPaging: ResultSetPaging = { const fakeResultSetPaging: ResultSetPaging = {
list: { list: {
@@ -59,11 +59,9 @@ describe('ContentNodeSelectorPanelComponent', () => {
let nodeService: NodesApiService; let nodeService: NodesApiService;
let sitesService: SitesService; let sitesService: SitesService;
let searchSpy: jasmine.Spy; let searchSpy: jasmine.Spy;
let cnSearchSpy: jasmine.Spy;
const fakeNodeEntry = new Node({ id: 'fakeId' }); const fakeNodeEntry = new Node({ id: 'fakeId' });
const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry); const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry);
let searchQueryBuilderService: SearchQueryBuilderService; let searchQueryBuilderService: SearchQueryBuilderService;
let contentNodeSelectorService: ContentNodeSelectorService;
function typeToSearchBox(searchTerm = 'string-to-search') { function typeToSearchBox(searchTerm = 'string-to-search') {
const searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]')); const searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]'));
@@ -93,11 +91,9 @@ describe('ContentNodeSelectorPanelComponent', () => {
nodeService = TestBed.inject(NodesApiService); nodeService = TestBed.inject(NodesApiService);
sitesService = TestBed.inject(SitesService); sitesService = TestBed.inject(SitesService);
contentNodeSelectorService = TestBed.inject(ContentNodeSelectorService);
searchQueryBuilderService = component.queryBuilderService; searchQueryBuilderService = component.queryBuilderService;
spyOn(nodeService, 'getNode').and.returnValue(of({ id: 'fake-node', path: { elements: [{ nodeType: 'st:site', name: 'fake-site'}] } })); spyOn(nodeService, 'getNode').and.returnValue(of({ id: 'fake-node', path: { elements: [{ nodeType: 'st:site', name: 'fake-site'}] } }));
cnSearchSpy = spyOn(contentNodeSelectorService, 'createQuery').and.callThrough();
searchSpy = spyOn(searchQueryBuilderService, 'execute'); searchSpy = spyOn(searchQueryBuilderService, 'execute');
const fakeSite = new SiteEntry({ entry: { id: 'fake-site', guid: 'fake-site', title: 'fake-site', visibility: 'visible' } }); const fakeSite = new SiteEntry({ entry: { id: 'fake-site', guid: 'fake-site', title: 'fake-site', visibility: 'visible' } });
spyOn(sitesService, 'getSite').and.returnValue(of(fakeSite)); spyOn(sitesService, 'getSite').and.returnValue(of(fakeSite));
@@ -362,32 +358,6 @@ describe('ContentNodeSelectorPanelComponent', () => {
let customResourcesService: CustomResourcesService; let customResourcesService: CustomResourcesService;
const entry: Node = <Node> { id: 'fakeid'}; const entry: Node = <Node> { id: 'fakeid'};
const defaultSearchOptions = (searchTerm, rootNodeId = undefined, skipCount = 0, showFiles = false) => {
const parentFiltering = rootNodeId ? [{ query: `ANCESTOR:'workspace://SpacesStore/${rootNodeId}'` }] : [];
const defaultSearchNode: any = {
query: {
query: searchTerm ? `${searchTerm}*` : searchTerm
},
include: ['path', 'allowableOperations', 'properties'],
paging: {
maxItems: 25,
skipCount: skipCount
},
filterQueries: [
{ query: `TYPE:'cm:folder'${ showFiles ? " OR TYPE:'cm:content'" : '' }` },
{ query: 'NOT cm:creator:System' },
...parentFiltering
],
scope: {
locations: 'nodes'
}
};
return defaultSearchNode;
};
beforeEach(() => { beforeEach(() => {
const documentListService = TestBed.inject(DocumentListService); const documentListService = TestBed.inject(DocumentListService);
const expectedDefaultFolderNode = <NodeEntry> { entry: { path: { elements: [] } } }; const expectedDefaultFolderNode = <NodeEntry> { entry: { path: { elements: [] } } };
@@ -418,23 +388,79 @@ describe('ContentNodeSelectorPanelComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should load the results by calling the search api on search change', fakeAsync(() => { it('should the user query get updated when the user types in the search input', fakeAsync(() => {
typeToSearchBox('kakarot'); const updateSpy = spyOn(searchQueryBuilderService, 'update');
typeToSearchBox('search-term');
tick(debounceSearch); tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
expect(searchSpy).toHaveBeenCalledWith(defaultSearchOptions('kakarot')); expect(updateSpy).toHaveBeenCalled();
expect(searchQueryBuilderService.userQuery).toEqual('(search-term)');
expect(component.searchTerm).toEqual('search-term');
})); }));
it('should show files in results by calling the search api on search change', fakeAsync(() => { it('should perform a search when the queryBody gets updated and it is defined', async () => {
component.showFilesInResult = true; searchQueryBuilderService.userQuery = 'search-term';
typeToSearchBox('kakarot'); searchQueryBuilderService.update();
fixture.detectChanges();
await fixture.whenStable();
expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
});
it('should NOT perform a search and clear the results when the queryBody gets updated and it is NOT defined', async () => {
spyOn(component, 'clearSearch');
searchQueryBuilderService.userQuery = '';
searchQueryBuilderService.update();
fixture.detectChanges();
await fixture.whenStable();
expect(searchSpy).not.toHaveBeenCalled();
expect(component.clearSearch).toHaveBeenCalled();
});
it('should reset the search term when clicking the clear icon', () => {
component.searchTerm = 'search-term';
searchQueryBuilderService.userQuery = 'search-term';
spyOn(component, 'clearSearch');
fixture.detectChanges();
const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]'));
clearIcon.nativeElement.click();
fixture.detectChanges();
expect(searchQueryBuilderService.userQuery).toEqual('');
expect(component.searchTerm).toEqual('');
expect(component.clearSearch).toHaveBeenCalled();
});
it('should load the results by calling the search api on search change', fakeAsync(() => {
typeToSearchBox('search-term');
tick(debounceSearch); tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
expect(searchSpy).toHaveBeenCalledWith(defaultSearchOptions('kakarot', undefined, 0, true)); expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
}));
it('should the query include the show files filterQuery', fakeAsync(() => {
component.showFilesInResult = true;
typeToSearchBox('search-term');
const expectedQueryBody = mockQueryBody;
expectedQueryBody.filterQueries.push({
query: `TYPE:'cm:folder' OR TYPE:'cm:content'`
});
tick(debounceSearch);
fixture.detectChanges();
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
})); }));
it('should reset the currently chosen node in case of starting a new search', fakeAsync(() => { it('should reset the currently chosen node in case of starting a new search', fakeAsync(() => {
@@ -453,8 +479,8 @@ describe('ContentNodeSelectorPanelComponent', () => {
expect(component.breadcrumbFolderTitle).toBe('My Sites'); expect(component.breadcrumbFolderTitle).toBe('My Sites');
}); });
it('should call the search api on changing the site selectBox value', fakeAsync(() => { it('should perform a search when selecting a site with the correct query', fakeAsync(() => {
typeToSearchBox('vegeta'); typeToSearchBox('search-term');
tick(debounceSearch); tick(debounceSearch);
@@ -462,40 +488,34 @@ describe('ContentNodeSelectorPanelComponent', () => {
component.siteChanged(<SiteEntry> { entry: { guid: 'namek' } }); component.siteChanged(<SiteEntry> { entry: { guid: 'namek' } });
const expectedQueryBody = mockQueryBody;
expectedQueryBody.filterQueries = [ { query: `ANCESTOR:'workspace://SpacesStore/namek'`} ];
expect(searchSpy.calls.count()).toBe(2, 'Search count should be two after the site change'); expect(searchSpy.calls.count()).toBe(2, 'Search count should be two after the site change');
expect(searchSpy.calls.argsFor(1)).toEqual([defaultSearchOptions('vegeta', 'namek')]); expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
}));
it('should create the query with the right parameters on changing the site selectbox\'s value', fakeAsync(() => {
typeToSearchBox('vegeta');
tick(debounceSearch);
expect(cnSearchSpy.calls.count()).toBe(1);
component.siteChanged(<SiteEntry> { entry: { guid: '-sites-' } });
expect(cnSearchSpy).toHaveBeenCalled();
expect(cnSearchSpy.calls.count()).toBe(2);
expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25, [], false);
expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId'], false);
})); }));
it('should create the query with the right parameters on changing the site selectBox value from a custom dropdown menu', fakeAsync(() => { it('should create the query with the right parameters on changing the site selectBox value from a custom dropdown menu', fakeAsync(() => {
component.dropdownSiteList = <SitePaging> { list: { entries: [<SiteEntry> { entry: { guid: '-sites-' } }, <SiteEntry> { entry: { guid: 'namek' } }] } }; component.dropdownSiteList = <SitePaging> { list: { entries: [<SiteEntry> { entry: { guid: '-sites-' } }, <SiteEntry> { entry: { guid: 'namek' } }] } };
fixture.detectChanges(); fixture.detectChanges();
typeToSearchBox('vegeta'); typeToSearchBox('search-term');
tick(debounceSearch); tick(debounceSearch);
expect(cnSearchSpy.calls.count()).toBe(1); expect(searchSpy.calls.count()).toBe(1);
component.siteChanged(<SiteEntry> { entry: { guid: '-sites-' } }); component.siteChanged(<SiteEntry> { entry: { guid: '-sites-' } });
expect(cnSearchSpy).toHaveBeenCalled(); const expectedQueryBodyWithSiteChange = mockQueryBody;
expect(cnSearchSpy.calls.count()).toBe(2); expectedQueryBodyWithSiteChange.filterQueries = [
expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', undefined, 0, 25, [], false); { query: `ANCESTOR:'workspace://SpacesStore/-sites-' OR ANCESTOR:'workspace://SpacesStore/123456testId' OR ANCESTOR:'workspace://SpacesStore/09876543testId'` }
expect(cnSearchSpy).toHaveBeenCalledWith('vegeta', '-sites-', 0, 25, ['123456testId', '09876543testId'], false); ];
expect(searchSpy).toHaveBeenCalled();
expect(searchSpy.calls.count()).toBe(2);
expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBodyWithSiteChange);
})); }));
it('should get the corresponding node ids on search when a known alias is selected from dropdown', fakeAsync(() => { it('should get the corresponding node ids on search when a known alias is selected from dropdown', fakeAsync(() => {
@@ -601,19 +621,24 @@ describe('ContentNodeSelectorPanelComponent', () => {
expect(component.showingSearchResults).toBeFalsy(); expect(component.showingSearchResults).toBeFalsy();
}); });
it('should the query restrict the search to the currentFolderId in case is defined', () => { it('should the query restrict the search to the currentFolderId in case is defined', fakeAsync(() => {
component.currentFolderId = 'my-root-id'; component.currentFolderId = 'my-root-id';
component.restrictRootToCurrentFolderId = true; component.restrictRootToCurrentFolderId = true;
component.ngOnInit(); component.ngOnInit();
component.search('search'); typeToSearchBox('search-term');
tick(debounceSearch);
expect(cnSearchSpy).toHaveBeenCalledWith('search', 'my-root-id', 0, 25, [], false); const expectedQueryBody = mockQueryBody;
}); expectedQueryBody.filterQueries = [ { query: `ANCESTOR:'workspace://SpacesStore/my-root-id'`} ];
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
}));
it('should emit showingSearch event with true while searching', async () => { it('should emit showingSearch event with true while searching', async () => {
spyOn(customResourcesService, 'hasCorrespondingNodeIds').and.returnValue(true); spyOn(customResourcesService, 'hasCorrespondingNodeIds').and.returnValue(true);
const showingSearchSpy = spyOn(component.showingSearch, 'emit'); const showingSearchSpy = spyOn(component.showingSearch, 'emit');
component.search('search');
component.queryBuilderService.execute({ query: { query: 'search' } });
triggerSearchResults(fakeResultSetPaging); triggerSearchResults(fakeResultSetPaging);
fixture.detectChanges(); fixture.detectChanges();
@@ -623,15 +648,16 @@ describe('ContentNodeSelectorPanelComponent', () => {
expect(showingSearchSpy).toHaveBeenCalledWith(true); expect(showingSearchSpy).toHaveBeenCalledWith(true);
}); });
it('should emit showingSearch event with false if you remove search term without clicking on X (icon) icon', async () => { it('should emit showingSearch event with false if you remove search term without clicking on X (icon) icon', fakeAsync(() => {
const showingSearchSpy = spyOn(component.showingSearch, 'emit'); const showingSearchSpy = spyOn(component.showingSearch, 'emit');
component.search(''); typeToSearchBox('');
tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.showingSearchResults).toBe(false); expect(component.showingSearchResults).toBe(false);
expect(showingSearchSpy).toHaveBeenCalledWith(false); expect(showingSearchSpy).toHaveBeenCalledWith(false);
}); }));
it('should emit showingResults event with false when clicking on the X (clear) icon', () => { it('should emit showingResults event with false when clicking on the X (clear) icon', () => {
const showingSearchSpy = spyOn(component.showingSearch, 'emit'); const showingSearchSpy = spyOn(component.showingSearch, 'emit');
@@ -654,7 +680,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
it('should emit showingResults event with false if search api fails', async () => { it('should emit showingResults event with false if search api fails', async () => {
getCorrespondingNodeIdsSpy.and.throwError('Failed'); getCorrespondingNodeIdsSpy.and.throwError('Failed');
const showingSearchSpy = spyOn(component.showingSearch, 'emit'); const showingSearchSpy = spyOn(component.showingSearch, 'emit');
component.search('search'); component.queryBuilderService.execute({ query: { query: 'search' } });
triggerSearchResults(fakeResultSetPaging); triggerSearchResults(fakeResultSetPaging);
fixture.detectChanges(); fixture.detectChanges();
@@ -665,13 +691,17 @@ describe('ContentNodeSelectorPanelComponent', () => {
}); });
it('should the query restrict the search to the site and not to the currentFolderId in case is changed', () => { it('should the query restrict the search to the site and not to the currentFolderId in case is changed', () => {
component.queryBuilderService.userQuery = 'search-term';
component.currentFolderId = 'my-root-id'; component.currentFolderId = 'my-root-id';
component.restrictRootToCurrentFolderId = true; component.restrictRootToCurrentFolderId = true;
component.ngOnInit();
component.siteChanged(<SiteEntry> { entry: { guid: 'my-site-id' } }); component.siteChanged(<SiteEntry> { entry: { guid: 'my-site-id' } });
component.search('search');
expect(cnSearchSpy).toHaveBeenCalledWith('search', 'my-site-id', 0, 25, [], false); const expectedQueryBodyWithSiteChange = mockQueryBody;
expectedQueryBodyWithSiteChange.filterQueries = [
{ query: `ANCESTOR:'workspace://SpacesStore/my-site-id'` }
];
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBodyWithSiteChange);
}); });
it('should restrict the breadcrumb to the currentFolderId in case restrictedRoot is true', () => { it('should restrict the breadcrumb to the currentFolderId in case restrictedRoot is true', () => {
@@ -689,7 +719,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
}); });
it('should clear the search field, nodes and chosenNode when deleting the search input', fakeAsync (() => { it('should clear the search field, nodes and chosenNode when deleting the search input', fakeAsync (() => {
spyOn(component, 'clear').and.callThrough(); spyOn(component, 'clearSearch').and.callThrough();
typeToSearchBox('a'); typeToSearchBox('a');
tick(debounceSearch); tick(debounceSearch);
@@ -703,7 +733,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(searchSpy.calls.count()).toBe(1, 'no other search has been performed'); expect(searchSpy.calls.count()).toBe(1, 'no other search has been performed');
expect(component.clear).toHaveBeenCalled(); expect(component.clearSearch).toHaveBeenCalled();
expect(component.folderIdToShow).toBe('cat-girl-nuku-nuku', 'back to the folder in which the search was performed'); expect(component.folderIdToShow).toBe('cat-girl-nuku-nuku', 'back to the folder in which the search was performed');
})); }));
@@ -728,7 +758,6 @@ describe('ContentNodeSelectorPanelComponent', () => {
component.siteChanged(<SiteEntry> { entry: { guid: 'namek' } }); component.siteChanged(<SiteEntry> { entry: { guid: 'namek' } });
expect(searchSpy.calls.count()).toBe(2); expect(searchSpy.calls.count()).toBe(2);
expect(searchSpy.calls.argsFor(1)).toEqual([defaultSearchOptions('piccolo', 'namek')]);
component.clear(); component.clear();
@@ -845,21 +874,19 @@ describe('ContentNodeSelectorPanelComponent', () => {
}, 300); }, 300);
}); });
it('should reload the original folderId when clearing the search input', async() => { it('should reload the original folderId when clearing the search input', fakeAsync(() => {
component.search('mock-type-search'); typeToSearchBox('search-term');
tick(debounceSearch);
triggerSearchResults(fakeResultSetPaging);
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.folderIdToShow).toBe(null); expect(component.folderIdToShow).toBe(null);
component.clear(); typeToSearchBox('');
tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.folderIdToShow).toBe('cat-girl-nuku-nuku'); expect(component.folderIdToShow).toBe('cat-girl-nuku-nuku');
}); }));
it('should set the folderIdToShow to the default "currentFolderId" if siteId is undefined', (done) => { it('should set the folderIdToShow to the default "currentFolderId" if siteId is undefined', (done) => {
component.siteChanged(<SiteEntry> { entry: { guid: 'Kame-Sennin Muten Roshi' } }); component.siteChanged(<SiteEntry> { entry: { guid: 'Kame-Sennin Muten Roshi' } });
@@ -900,63 +927,50 @@ describe('ContentNodeSelectorPanelComponent', () => {
expect(component.searchTerm).toBe(''); expect(component.searchTerm).toBe('');
expect(component.infiniteScroll).toBeTruthy(); expect(component.infiniteScroll).toBeTruthy();
expect(component.pagination.maxItems).toBe(45); expect(component.queryBuilderService.paging.maxItems).toBe(45);
expect(searchSpy).not.toHaveBeenCalled(); expect(searchSpy).not.toHaveBeenCalled();
}); });
it('should set its loading state to true after search was started', fakeAsync (() => { it('should set its loading state to true to perform a new search', async() => {
component.showingSearchResults = true; component.prepareDialogForNewSearch(mockQueryBody);
typeToSearchBox('shenron');
tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
tick(debounceSearch);
const spinnerSelector = By.css('[data-automation-id="content-node-selector-search-pagination"] [data-automation-id="adf-infinite-pagination-spinner"]'); const spinnerSelector = By.css('[data-automation-id="content-node-selector-search-pagination"] [data-automation-id="adf-infinite-pagination-spinner"]');
const paginationLoading = fixture.debugElement.query(spinnerSelector); const paginationLoading = fixture.debugElement.query(spinnerSelector);
expect(paginationLoading).not.toBeNull(); expect(paginationLoading).not.toBeNull();
})); });
it('Should infinite pagination target be null when we use it for search ', fakeAsync (() => { it('Should infinite pagination target be null when we use it for search ', fakeAsync (() => {
component.showingSearchResults = true; component.showingSearchResults = true;
typeToSearchBox('shenron'); typeToSearchBox('shenron');
tick(debounceSearch); tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
tick(debounceSearch);
expect(component.target).toBeNull(); expect(component.target).toBeNull();
})); }));
it('Should infinite pagination target be present when search finish', fakeAsync (() => { it('Should infinite pagination target be present when search finish', () => {
component.showingSearchResults = true; triggerSearchResults(fakeResultSetPaging);
typeToSearchBox('shenron');
tick(debounceSearch);
fixture.detectChanges();
typeToSearchBox('');
tick(debounceSearch);
fixture.detectChanges(); fixture.detectChanges();
expect(component.target).not.toBeNull(); expect(component.target).not.toBeNull();
})); });
it('Should infinite pagination target on init be the document list', fakeAsync(() => { it('Should infinite pagination target on init be the document list', fakeAsync(() => {
component.showingSearchResults = true; component.showingSearchResults = true;
expect(component.target).toEqual(component.documentList); expect(component.target).toEqual(component.documentList);
})); }));
it('Should set the scope to nodes when the component inits', () => {
const expectedScope: RequestScope = { locations: 'nodes' };
const setScopeSpy = spyOn(component.queryBuilderService, 'setScope');
component.ngOnInit();
expect(setScopeSpy).toHaveBeenCalledWith(expectedScope);
});
}); });
}); });

View File

@@ -29,7 +29,6 @@ import {
import { import {
HighlightDirective, HighlightDirective,
UserPreferencesService, UserPreferencesService,
PaginationModel,
UserPreferenceValues, UserPreferenceValues,
InfinitePaginationComponent, PaginatedComponent, InfinitePaginationComponent, PaginatedComponent,
NodesApiService, NodesApiService,
@@ -38,11 +37,10 @@ import {
FileUploadCompleteEvent FileUploadCompleteEvent
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry } from '@alfresco/js-api'; import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry, QueryBody, RequestScope } from '@alfresco/js-api';
import { DocumentListComponent } from '../document-list/components/document-list.component'; import { DocumentListComponent } from '../document-list/components/document-list.component';
import { RowFilter } from '../document-list/data/row-filter.model'; import { RowFilter } from '../document-list/data/row-filter.model';
import { ImageResolver } from '../document-list/data/image-resolver.model'; import { ImageResolver } from '../document-list/data/image-resolver.model';
import { ContentNodeSelectorService } from './content-node-selector.service';
import { debounceTime, takeUntil, scan } from 'rxjs/operators'; import { debounceTime, takeUntil, scan } from 'rxjs/operators';
import { CustomResourcesService } from '../document-list/services/custom-resources.service'; import { CustomResourcesService } from '../document-list/services/custom-resources.service';
import { NodeEntryEvent, ShareDataRow } from '../document-list'; import { NodeEntryEvent, ShareDataRow } from '../document-list';
@@ -69,14 +67,11 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
DEFAULT_PAGINATION: Pagination = new Pagination({ DEFAULT_PAGINATION: Pagination = new Pagination({
maxItems: 25, maxItems: 25,
skipCount: 0, skipCount: 0
totalItems: 0,
hasMoreItems: false
}); });
private showSiteList = true; private showSiteList = true;
private showSearchField = true; private showSearchField = true;
private showFiles = false;
/** If true will restrict the search and breadcrumbs to the currentFolderId */ /** If true will restrict the search and breadcrumbs to the currentFolderId */
@Input() @Input()
@@ -196,7 +191,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
@Input() @Input()
set showFilesInResult(value: boolean) { set showFilesInResult(value: boolean) {
if (value !== undefined && value !== null) { if (value !== undefined && value !== null) {
this.showFiles = value; const showFilesQuery = `TYPE:'cm:folder'${value ? " OR TYPE:'cm:content'" : ''}`;
this.queryBuilderService.addFilterQuery(showFilesQuery);
} }
} }
@@ -234,8 +230,6 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
breadcrumbFolderTitle: string | null = null; breadcrumbFolderTitle: string | null = null;
startSiteGuid: string | null = null; startSiteGuid: string | null = null;
pagination: PaginationModel = this.DEFAULT_PAGINATION;
@ViewChild(InfinitePaginationComponent, { static: true }) @ViewChild(InfinitePaginationComponent, { static: true })
infinitePaginationComponent: InfinitePaginationComponent; infinitePaginationComponent: InfinitePaginationComponent;
@@ -248,8 +242,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();
constructor(private contentNodeSelectorService: ContentNodeSelectorService, constructor(private customResourcesService: CustomResourcesService,
private customResourcesService: CustomResourcesService,
@Inject(SEARCH_QUERY_SERVICE_TOKEN) public queryBuilderService: SearchQueryBuilderService, @Inject(SEARCH_QUERY_SERVICE_TOKEN) public queryBuilderService: SearchQueryBuilderService,
private userPreferencesService: UserPreferencesService, private userPreferencesService: UserPreferencesService,
private nodesApiService: NodesApiService, private nodesApiService: NodesApiService,
@@ -272,7 +265,23 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
debounceTime(this.debounceSearch), debounceTime(this.debounceSearch),
takeUntil(this.onDestroy$) takeUntil(this.onDestroy$)
) )
.subscribe(searchValue => this.search(searchValue)); .subscribe(searchValue => {
this.searchTerm = searchValue;
this.queryBuilderService.userQuery = searchValue;
this.queryBuilderService.update();
});
this.queryBuilderService.updated
.pipe(takeUntil(this.onDestroy$))
.subscribe((queryBody: QueryBody) => {
if (queryBody) {
this.prepareDialogForNewSearch(queryBody);
this.queryBuilderService.execute(queryBody);
} else {
this.resetFolderToShow();
this.clearSearch();
}
});
this.queryBuilderService.executed this.queryBuilderService.executed
.pipe(takeUntil(this.onDestroy$)) .pipe(takeUntil(this.onDestroy$))
@@ -299,6 +308,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.breadcrumbTransform = this.breadcrumbTransform ? this.breadcrumbTransform : null; this.breadcrumbTransform = this.breadcrumbTransform ? this.breadcrumbTransform : null;
this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation; this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation;
this.onFileUploadEvent(); this.onFileUploadEvent();
this.resetPagination();
this.setSearchScopeToNodes();
} }
ngOnDestroy() { ngOnDestroy() {
@@ -365,17 +376,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.siteId = chosenSite.entry.guid; this.siteId = chosenSite.entry.guid;
this.setTitleIfCustomSite(chosenSite); this.setTitleIfCustomSite(chosenSite);
this.siteChange.emit(chosenSite.entry.title); this.siteChange.emit(chosenSite.entry.title);
this.updateResults(); this.queryBuilderService.update();
}
/**
* Updates the searchTerm attribute and starts a new search
*
* @param searchTerm string value to search against
*/
search(searchTerm: string): void {
this.searchTerm = searchTerm;
this.updateResults();
} }
/** /**
@@ -393,11 +394,33 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
return folderNode; return folderNode;
} }
/**
* Prepares the dialog for a new search
*/
prepareDialogForNewSearch(queryBody: QueryBody): void {
this.target = queryBody ? null : this.documentList;
if (this.target) {
this.infinitePaginationComponent.reset();
}
this.folderIdToShow = null;
this.loadingSearchResults = true;
this.addCorrespondingNodeIdsQuery();
this.resetChosenNode();
}
/** /**
* Clear the search input and reset to last folder node in which search was performed * Clear the search input and reset to last folder node in which search was performed
*/ */
clear(): void { clear(): void {
this.clearSearch(); this.searchTerm = '';
this.queryBuilderService.userQuery = '';
this.queryBuilderService.update();
}
/**
* Resets the folder to be shown with the site selection or the initial landing folder
*/
resetFolderToShow(): void {
this.folderIdToShow = this.siteId || this.currentFolderId; this.folderIdToShow = this.siteId || this.currentFolderId;
} }
@@ -407,71 +430,52 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
clearSearch() { clearSearch() {
this.searchTerm = ''; this.searchTerm = '';
this.nodePaging = null; this.nodePaging = null;
this.pagination.maxItems = this.pageSize; this.resetPagination();
this.resetChosenNode(); this.resetChosenNode();
this.showingSearchResults = false; this.showingSearchResults = false;
this.showingSearch.emit(this.showingSearchResults); this.showingSearch.emit(this.showingSearchResults);
} }
/** private addCorrespondingNodeIdsQuery() {
* Update the result list depending on the criteria let extraParentFiltering = '';
*/
private updateResults(): void {
this.target = this.searchTerm.length > 0 ? null : this.documentList;
if (this.searchTerm.length === 0) {
this.clear();
} else {
this.startNewSearch();
}
}
/**
* Load the first page of a new search result
*/
private startNewSearch(): void {
this.nodePaging = null;
this.pagination.maxItems = this.pageSize;
if (this.target) {
this.infinitePaginationComponent.reset();
}
this.chosenNode = null;
this.folderIdToShow = null;
this.querySearch();
}
/**
* Perform the call to searchService with the proper parameters
*/
private querySearch(): void {
this.loadingSearchResults = true;
if (this.customResourcesService.hasCorrespondingNodeIds(this.siteId)) { if (this.customResourcesService.hasCorrespondingNodeIds(this.siteId)) {
this.customResourcesService.getCorrespondingNodeIds(this.siteId) this.customResourcesService.getCorrespondingNodeIds(this.siteId)
.subscribe((nodeIds) => { .subscribe((nodeIds) => {
const query = this.contentNodeSelectorService.createQuery(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems, nodeIds, this.showFiles); if (nodeIds && nodeIds.length) {
this.queryBuilderService.execute(query); nodeIds
}, .filter((id) => id !== this.siteId)
() => { .forEach((extraId) => {
this.showSearchResults({ list: { entries: [] } }); extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
});
}
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'${extraParentFiltering}` : '';
this.queryBuilderService.addFilterQuery(parentFiltering);
}); });
} else { } else {
const query = this.contentNodeSelectorService.createQuery(this.searchTerm, this.siteId, this.pagination.skipCount, this.pagination.maxItems, [], this.showFiles); const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'` : '';
this.queryBuilderService.execute(query); this.queryBuilderService.addFilterQuery(parentFiltering);
} }
} }
private setSearchScopeToNodes() {
const scope: RequestScope = {
locations: 'nodes'
};
this.queryBuilderService.setScope(scope);
}
/** /**
* Show the results of the search * Show the results of the search
* *
* @param results Search results * @param results Search results
*/ */
private showSearchResults(nodePaging: NodePaging): void { private showSearchResults(results: NodePaging): void {
this.showingSearchResults = true; this.showingSearchResults = true;
this.loadingSearchResults = false; this.loadingSearchResults = false;
this.showingSearch.emit(this.showingSearchResults); this.showingSearch.emit(this.showingSearchResults);
this.nodePaging = nodePaging; this.nodePaging = results;
} }
/** /**
@@ -505,14 +509,15 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Loads the next batch of search results * Loads the next batch of search results
* *
* @param event Pagination object * @param pagination Pagination object
*/ */
getNextPageOfSearch(pagination: Pagination): void { getNextPageOfSearch(pagination: Pagination): void {
this.infiniteScroll = true; this.infiniteScroll = true;
this.pagination = pagination; this.queryBuilderService.paging.maxItems = pagination.maxItems;
this.queryBuilderService.paging.skipCount = pagination.skipCount;
if (this.searchTerm.length > 0) { if (this.searchTerm.length > 0) {
this.querySearch(); this.queryBuilderService.update();
} }
} }
@@ -541,8 +546,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
*/ */
onCurrentSelection(nodesEntries: NodeEntry[]): void { onCurrentSelection(nodesEntries: NodeEntry[]): void {
const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry)); const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry));
const nodes: Node[] = validNodesEntity.map((node) => node.entry ); this.chosenNode = validNodesEntity.map((node) => node.entry );
this.chosenNode = nodes;
} }
setTitleIfCustomSite(site: SiteEntry) { setTitleIfCustomSite(site: SiteEntry) {
@@ -578,4 +582,11 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
return selectedNodes; return selectedNodes;
} }
private resetPagination(): void {
this.queryBuilderService.paging = {
maxItems: this.pageSize,
skipCount: this.DEFAULT_PAGINATION.skipCount
};
}
} }

View File

@@ -1,120 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { setupTestBed } from '@alfresco/adf-core';
import { ContentNodeSelectorService } from './content-node-selector.service';
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('ContentNodeSelectorService', () => {
let service: ContentNodeSelectorService;
setupTestBed({
imports: [
TranslateModule.forRoot(),
ContentTestingModule
]
});
beforeEach(() => {
service = TestBed.inject(ContentNodeSelectorService);
});
it('should have the proper main query for search string', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.query).toEqual({
query: 'nuka cola quantum*'
});
});
it('should make it including the path and allowableOperations', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.include).toEqual(['path', 'allowableOperations', 'properties']);
});
it('should make the search restricted to nodes only', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.scope.locations).toEqual('nodes');
});
it('should set the maxItems and paging properly by parameters', () => {
const queryBody = service.createQuery('nuka cola quantum', null, 10, 100);
expect(queryBody.paging.maxItems).toEqual(100);
expect(queryBody.paging.skipCount).toEqual(10);
});
it('should set the maxItems and paging properly by default', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.paging.maxItems).toEqual(25);
expect(queryBody.paging.skipCount).toEqual(0);
});
it('should filter the search for folders', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.filterQueries).toContain({ query: "TYPE:'cm:folder'" });
});
it('should filter the search for files', () => {
const queryBody = service.createQuery('nuka cola quantum', null, 0, 25, [], true);
expect(queryBody.filterQueries).toContain({ query: "TYPE:'cm:folder' OR TYPE:'cm:content'" });
});
it('should filter out the "system-base" entries', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.filterQueries).toContain({ query: 'NOT cm:creator:System' });
});
it('should filter for the provided ancestor if defined', () => {
const queryBody = service.createQuery('nuka cola quantum', 'diamond-city');
expect(queryBody.filterQueries).toContain({ query: 'ANCESTOR:\'workspace://SpacesStore/diamond-city\'' });
});
it('should NOT filter for the ancestor if NOT defined', () => {
const queryBody = service.createQuery('nuka cola quantum');
expect(queryBody.filterQueries).not.toContain({ query: 'ANCESTOR:\'workspace://SpacesStore/null\'' });
});
it('should filter for the extra provided ancestors if defined', () => {
const queryBody = service.createQuery('nuka cola quantum', 'diamond-city', 0, 25, ['extra-diamond-city']);
expect(queryBody.filterQueries).toContain({ query: 'ANCESTOR:\'workspace://SpacesStore/diamond-city\' OR ANCESTOR:\'workspace://SpacesStore/extra-diamond-city\'' });
});
it('should NOT filter for extra ancestors if an empty list of ids is provided', () => {
const queryBody = service.createQuery('nuka cola quantum', 'diamond-city', 0, 25, []);
expect(queryBody.filterQueries).toContain({ query: 'ANCESTOR:\'workspace://SpacesStore/diamond-city\'' });
});
it('should NOT filter for the extra provided ancestor if it\'s the same as the rootNodeId', () => {
const queryBody = service.createQuery('nuka cola quantum', 'diamond-city', 0, 25, ['diamond-city']);
expect(queryBody.filterQueries).toContain({ query: 'ANCESTOR:\'workspace://SpacesStore/diamond-city\'' });
});
});

View File

@@ -1,62 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Injectable } from '@angular/core';
import { QueryBody } from '@alfresco/js-api';
/**
* Internal service used by ContentNodeSelector component.
*/
@Injectable({
providedIn: 'root'
})
export class ContentNodeSelectorService {
createQuery(searchTerm: string, rootNodeId: string = null, skipCount: number = 0, maxItems: number = 25, extraNodeIds?: string[], showFiles?: boolean): QueryBody {
let extraParentFiltering = '';
if (extraNodeIds && extraNodeIds.length) {
extraNodeIds
.filter((id) => id !== rootNodeId)
.forEach((extraId) => {
extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
});
}
const parentFiltering = rootNodeId ? [{ query: `ANCESTOR:'workspace://SpacesStore/${rootNodeId}'${extraParentFiltering}` }] : [];
return {
query: {
query: `${searchTerm}*`
},
include: ['path', 'allowableOperations', 'properties'],
paging: {
maxItems: maxItems,
skipCount: skipCount
},
filterQueries: [
{ query: `TYPE:'cm:folder'${showFiles ? " OR TYPE:'cm:content'" : ''}` },
{ query: 'NOT cm:creator:System' },
...parentFiltering
],
scope: {
locations: 'nodes'
}
};
}
}

View File

@@ -19,7 +19,6 @@ export * from './name-location-cell/name-location-cell.component';
export * from './content-node-selector.component-data.interface'; export * from './content-node-selector.component-data.interface';
export * from './content-node-selector-panel.component'; export * from './content-node-selector-panel.component';
export * from './content-node-selector.component'; export * from './content-node-selector.component';
export * from './content-node-selector.service';
export * from './content-node-dialog.service'; export * from './content-node-dialog.service';
export * from './content-node-selector-panel.service'; export * from './content-node-selector-panel.service';

View File

@@ -21,3 +21,4 @@ export * from './search.component.mock';
export * from './search.service.mock'; export * from './search.service.mock';
export * from './search-filter-mock'; export * from './search-filter-mock';
export * from './sites-dropdown.component.mock'; export * from './sites-dropdown.component.mock';
export * from './search-query.mock';

View File

@@ -0,0 +1,41 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { QueryBody } from '@alfresco/js-api';
export const mockQueryBody: QueryBody = <QueryBody> {
query: {
query: '(search-term)',
language: 'afts'
},
include: ['path', 'allowableOperations'],
paging: {
maxItems: 25,
skipCount: 0
},
fields: undefined,
filterQueries: [],
facetQueries: null,
facetIntervals: null,
facetFields: null,
sort: [],
scope: {
locations: 'nodes'
},
highlight: null,
facetFormat: 'V2'
};

View File

@@ -24,7 +24,8 @@ import {
RequestFacetField, RequestFacetField,
RequestSortDefinitionInner, RequestSortDefinitionInner,
ResultSetPaging, ResultSetPaging,
RequestHighlight RequestHighlight,
RequestScope
} from '@alfresco/js-api'; } from '@alfresco/js-api';
import { SearchCategory } from './search-category.interface'; import { SearchCategory } from './search-category.interface';
import { FilterQuery } from './filter-query.interface'; import { FilterQuery } from './filter-query.interface';
@@ -52,6 +53,7 @@ export abstract class BaseQueryBuilderService {
paging: { maxItems?: number; skipCount?: number } = null; paging: { maxItems?: number; skipCount?: number } = null;
sorting: SearchSortingDefinition[] = []; sorting: SearchSortingDefinition[] = [];
sortingOptions: SearchSortingDefinition[] = []; sortingOptions: SearchSortingDefinition[] = [];
private scope: RequestScope;
protected userFacetBuckets: { [key: string]: FacetFieldBucket[] } = {}; protected userFacetBuckets: { [key: string]: FacetFieldBucket[] } = {};
@@ -193,6 +195,14 @@ export abstract class BaseQueryBuilderService {
return null; return null;
} }
setScope(scope: RequestScope) {
this.scope = scope;
}
getScope(): RequestScope {
return this.scope;
}
/** /**
* Builds the current query and triggers the `updated` event. * Builds the current query and triggers the `updated` event.
*/ */
@@ -265,6 +275,10 @@ export abstract class BaseQueryBuilderService {
highlight: this.highlight highlight: this.highlight
}; };
if (this.scope) {
result['scope'] = this.scope;
}
result['facetFormat'] = 'V2'; result['facetFormat'] = 'V2';
return result; return result;
} }

View File

@@ -618,4 +618,47 @@ describe('SearchQueryBuilder', () => {
builder.execute(); builder.execute();
}); });
it('should include contain the path and allowableOperations by default', () => {
const builder = new SearchQueryBuilderService(buildConfig({}), null);
builder.userQuery = 'nuka cola quantum';
const queryBody = builder.buildQuery();
expect(queryBody.include).toEqual(['path', 'allowableOperations']);
});
it('should fetch the include config from the app config', () => {
const includeConfig = ['path', 'allowableOperations', 'properties'];
const config: SearchConfiguration = {
include: includeConfig
};
const builder = new SearchQueryBuilderService(buildConfig(config), null);
builder.userQuery = 'nuka cola quantum';
const queryBody = builder.buildQuery();
expect(queryBody.include).toEqual(includeConfig);
});
it('should the query contain the pagination', () => {
const builder = new SearchQueryBuilderService(buildConfig({}), null);
builder.userQuery = 'nuka cola quantum';
const mockPagination = {
maxItems: 10,
skipCount: 0
};
builder.paging = mockPagination;
const queryBody = builder.buildQuery();
expect(queryBody.paging).toEqual(mockPagination);
});
it('should the query contain the scope in case it is defined', () => {
const builder = new SearchQueryBuilderService(buildConfig({}), null);
const mockScope = { locations: 'mock-location' };
builder.userQuery = 'nuka cola quantum';
builder.setScope(mockScope);
const queryBody = builder.buildQuery();
expect(queryBody.scope).toEqual(mockScope);
});
}); });

View File

@@ -19,7 +19,7 @@ import { Component, Inject, ViewEncapsulation, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ExternalAlfrescoApiService, AlfrescoApiService, LoginDialogPanelComponent, SearchService, TranslationService, AuthenticationService, SitesService } from '@alfresco/adf-core'; import { ExternalAlfrescoApiService, AlfrescoApiService, LoginDialogPanelComponent, SearchService, TranslationService, AuthenticationService, SitesService } from '@alfresco/adf-core';
import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface'; import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface';
import { DocumentListService, ContentNodeSelectorService } from '@alfresco/adf-content-services'; import { DocumentListService } from '@alfresco/adf-content-services';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
@Component({ @Component({
@@ -31,7 +31,6 @@ import { Node } from '@alfresco/js-api';
AuthenticationService, AuthenticationService,
DocumentListService, DocumentListService,
SitesService, SitesService,
ContentNodeSelectorService,
SearchService, SearchService,
{ provide: AlfrescoApiService, useClass: ExternalAlfrescoApiService} ] { provide: AlfrescoApiService, useClass: ExternalAlfrescoApiService} ]
}) })