diff --git a/docs/content-services/components/document-list.component.md b/docs/content-services/components/document-list.component.md
index c15407bb24..90012990cb 100644
--- a/docs/content-services/components/document-list.component.md
+++ b/docs/content-services/components/document-list.component.md
@@ -69,6 +69,7 @@ Displays the documents from a repository.
| displayCheckboxesOnHover | `boolean` | false | Enables checkboxes in datatable rows being displayed on hover only. |
| displayDragAndDropHint | `boolean` | true | Display drag and drop hint. |
| emptyFolderImageUrl | `string` | | Custom image for empty folder. Default value: './assets/images/empty_doc_lib.svg' |
+| filters | `string[]` | | Specifies additional filters to apply (joined with **AND**). Applied for recent files only |
| filterValue | `any` | | Initial value for filter. |
| headerFilters | `boolean` | false | Toggles the header filters mode. |
| imageResolver | `any \| null` | null | Custom function to choose image file paths to show. See the [Image Resolver Model](image-resolver.model.md) page for more information. |
diff --git a/docs/content-services/services/custom-resources.service.md b/docs/content-services/services/custom-resources.service.md
index b50894cac2..fdb9955fdc 100644
--- a/docs/content-services/services/custom-resources.service.md
+++ b/docs/content-services/services/custom-resources.service.md
@@ -47,12 +47,13 @@ Manages Document List information that is specific to a user.
- _includeFields:_ `string[]` - List of data field names to include in the results
- _where:_ `string` - (Optional) A string to restrict the returned objects by using a predicate
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/content-rest-api/docs/NodePaging.md)`>` - List of favorite files
-- **loadFolderByNodeId**(nodeId: `string`, pagination: [`PaginationModel`](../../../lib/core/src/lib/models/pagination.model.ts), includeFields: `string[]` = `[]`, where?: `string`): `any`
+- **loadFolderByNodeId**(nodeId: `string`, pagination: [`PaginationModel`](../../../lib/core/src/lib/models/pagination.model.ts), includeFields: `string[]` = `[]`, where?: `string`, filters?: `string[]`): `any`
Gets a folder's contents.
- _nodeId:_ `string` - ID of the target folder node
- _pagination:_ [`PaginationModel`](../../../lib/core/src/lib/models/pagination.model.ts) - Specifies how to paginate the results
- _includeFields:_ `string[]` - List of data field names to include in the results
- _where:_ `string` - (Optional) Filters the Node list using the _where_ condition of the REST API (for example, isFolder=true). See the REST API documentation for more information.
+ - _filters:_ `string[]` - Specifies additional filters to apply (joined with **AND**). Applied for '-recent-' only.
- **Returns** `any` - List of items contained in the folder
- **loadMemberSites**(pagination: [`PaginationModel`](../../../lib/core/src/lib/models/pagination.model.ts), where?: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`SiteMemberPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/content-rest-api/docs/SiteMemberPaging.md)`>`
Gets sites that the current user is a member of.
diff --git a/docs/content-services/services/document-list.service.md b/docs/content-services/services/document-list.service.md
index 75ec50f9f7..5539991b69 100644
--- a/docs/content-services/services/document-list.service.md
+++ b/docs/content-services/services/document-list.service.md
@@ -62,13 +62,14 @@ import { DocumentListService } from '@alfresco/adf-core';
- _nodeId:_ `any` -
- **Returns** `boolean` -
-- **loadFolderByNodeId**(nodeId: `string`, pagination: `PaginationModel`, includeFields: `string[]`, where?: `string`, orderBy?: `string[]`): `Observable`
+- **loadFolderByNodeId**(nodeId: `string`, pagination: `PaginationModel`, includeFields: `string[]`, where?: `string`, orderBy?: `string[]`, filters?: `string[]`): `Observable`
Load a folder by Node Id.
- _nodeId:_ `string` - ID of the folder node
- _pagination:_ `PaginationModel` - pagination model
- _includeFields:_ `string[]` - List of data field names to include in the results
- _where:_ `string` - (Optional) Optionally filter the list
- _orderBy:_ `string[]` - (Optional) order by node property
+ - _filters:_ `string[]` - (Optional) Specifies additional filters to apply (joined with **AND**). Applied for recent files only
- **Returns** `Observable` - Details of the folder
- **moveNode**(nodeId: `string`, targetParentId: `string`): `Observable`
Moves a node to destination node.
diff --git a/lib/content-services/src/lib/breadcrumb/breadcrumb.component.spec.ts b/lib/content-services/src/lib/breadcrumb/breadcrumb.component.spec.ts
index 90e54d801d..e98ccf45bb 100644
--- a/lib/content-services/src/lib/breadcrumb/breadcrumb.component.spec.ts
+++ b/lib/content-services/src/lib/breadcrumb/breadcrumb.component.spec.ts
@@ -116,7 +116,25 @@ describe('Breadcrumb', () => {
documentListComponent.DEFAULT_PAGINATION,
documentListComponent.includeFields,
documentListComponent.where,
- documentListComponent.orderBy
+ documentListComponent.orderBy,
+ undefined
+ );
+ });
+
+ it('should update document list with filters param for recent files when filters are provided', () => {
+ const node = { id: '-id-', name: 'name' };
+ component.target = documentListComponent;
+ documentListComponent.filters = ['filter1', 'filter2'];
+
+ component.onRoutePathClick(node, null);
+
+ expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith(
+ node.id,
+ documentListComponent.DEFAULT_PAGINATION,
+ documentListComponent.includeFields,
+ documentListComponent.where,
+ documentListComponent.orderBy,
+ documentListComponent.filters
);
});
diff --git a/lib/content-services/src/lib/breadcrumb/dropdown-breadcrumb.component.spec.ts b/lib/content-services/src/lib/breadcrumb/dropdown-breadcrumb.component.spec.ts
index 59162f1f9b..886b707c65 100644
--- a/lib/content-services/src/lib/breadcrumb/dropdown-breadcrumb.component.spec.ts
+++ b/lib/content-services/src/lib/breadcrumb/dropdown-breadcrumb.component.spec.ts
@@ -113,7 +113,14 @@ describe('DropdownBreadcrumb', () => {
await fixture.whenStable();
clickOnTheFirstOption();
- expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith('1', documentList.DEFAULT_PAGINATION, undefined, undefined, null);
+ expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith(
+ '1',
+ documentList.DEFAULT_PAGINATION,
+ undefined,
+ undefined,
+ null,
+ undefined
+ );
});
it('should open the selectBox when clicking on the folder icon', (done) => {
diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts
index 859a4d68ea..3ebc174333 100644
--- a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts
+++ b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts
@@ -1732,6 +1732,23 @@ describe('DocumentList', () => {
expect(getEmptyFolderDragDropSubtitle()).toBeUndefined();
});
+ it('should call loadFolderByNodeId with filters when they are provided', () => {
+ spyOn(documentListService, 'loadFolderByNodeId').and.callFake(() => of(new DocumentLoaderNode(null, { list: { pagination: {} } })));
+ documentList.filters = ['filter1', 'filter2'];
+ documentList.currentFolderId = '-recent-';
+ documentList.loadFolder();
+
+ fixture.detectChanges();
+ expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith(
+ documentList.currentFolderId,
+ documentList.DEFAULT_PAGINATION,
+ documentList.includeFields,
+ documentList.where,
+ documentList.orderBy,
+ documentList.filters
+ );
+ });
+
describe('Preselect nodes', () => {
beforeEach(() => {
spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_created.svg`);
diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.ts b/lib/content-services/src/lib/document-list/components/document-list.component.ts
index 8901fb6d23..f2d867d4e4 100644
--- a/lib/content-services/src/lib/document-list/components/document-list.component.ts
+++ b/lib/content-services/src/lib/document-list/components/document-list.component.ts
@@ -154,6 +154,12 @@ export class DocumentListComponent extends DataTableSchema implements OnInit, On
@Input()
where: string;
+ /**
+ * Specifies additional filters to apply (joined with **AND**). Applied for recent files only.
+ */
+ @Input()
+ filters: string[];
+
/**
* Define a set of CSS styles to apply depending on the permission
* of the user on that node. See the Permission Style model
@@ -789,18 +795,20 @@ export class DocumentListComponent extends DataTableSchema implements OnInit, On
this.updateCustomSourceData(this.currentFolderId);
}
- this.documentListService.loadFolderByNodeId(this.currentFolderId, this._pagination, this.includeFields, this.where, this.orderBy).subscribe(
- (documentNode: DocumentLoaderNode) => {
- if (documentNode.currentNode) {
- this.folderNode = documentNode.currentNode.entry;
- this.$folderNode.next(documentNode.currentNode.entry);
+ this.documentListService
+ .loadFolderByNodeId(this.currentFolderId, this._pagination, this.includeFields, this.where, this.orderBy, this.filters)
+ .subscribe({
+ next: (documentNode: DocumentLoaderNode) => {
+ if (documentNode.currentNode) {
+ this.folderNode = documentNode.currentNode.entry;
+ this.$folderNode.next(documentNode.currentNode.entry);
+ }
+ this.onPageLoaded(documentNode.children);
+ },
+ error: (err) => {
+ this.handleError(err);
}
- this.onPageLoaded(documentNode.children);
- },
- (err) => {
- this.handleError(err);
- }
- );
+ });
}
resetSelection() {
diff --git a/lib/content-services/src/lib/document-list/interfaces/document-list-loader.interface.ts b/lib/content-services/src/lib/document-list/interfaces/document-list-loader.interface.ts
index 7e9cf23e96..9440c6ece9 100644
--- a/lib/content-services/src/lib/document-list/interfaces/document-list-loader.interface.ts
+++ b/lib/content-services/src/lib/document-list/interfaces/document-list-loader.interface.ts
@@ -20,6 +20,11 @@ import { Observable } from 'rxjs';
import { DocumentLoaderNode } from '../models/document-folder.model';
export interface DocumentListLoader {
-
- loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable ;
+ loadFolderByNodeId(
+ nodeId: string,
+ pagination: PaginationModel,
+ includeFields: string[],
+ where?: string,
+ filters?: string[]
+ ): Observable;
}
diff --git a/lib/content-services/src/lib/document-list/services/custom-resources.service.spec.ts b/lib/content-services/src/lib/document-list/services/custom-resources.service.spec.ts
index 0738f746d5..f4e75311f9 100644
--- a/lib/content-services/src/lib/document-list/services/custom-resources.service.spec.ts
+++ b/lib/content-services/src/lib/document-list/services/custom-resources.service.spec.ts
@@ -19,7 +19,22 @@ import { CustomResourcesService } from './custom-resources.service';
import { PaginationModel } from '@alfresco/adf-core';
import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
-import { Favorite, FavoritePaging, FavoritePagingList } from '@alfresco/js-api';
+import {
+ Favorite,
+ FavoritePaging,
+ FavoritePagingList,
+ NodeEntry,
+ NodePaging,
+ Site,
+ SiteEntry,
+ SiteMember,
+ SitePaging,
+ SiteRoleEntry,
+ SiteRolePaging
+} from '@alfresco/js-api';
+import { of } from 'rxjs';
+
+type Extra = T & K;
describe('CustomResourcesService', () => {
let customResourcesService: CustomResourcesService;
@@ -131,4 +146,376 @@ describe('CustomResourcesService', () => {
});
});
});
+
+ describe('loadFolderByNodeId', () => {
+ const pagination: PaginationModel = {
+ maxItems: 100,
+ skipCount: 0
+ };
+
+ it('should return null observable when nodeId is not from custom source', (done) => {
+ customResourcesService.loadFolderByNodeId('unsupported', pagination).subscribe((result) => {
+ expect(result).toBeNull();
+ done();
+ });
+ });
+
+ it('should call loadTrashcan when nodeId is -trashcan-', () => {
+ spyOn(customResourcesService, 'loadTrashcan').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-trashcan-', pagination);
+ expect(customResourcesService.loadTrashcan).toHaveBeenCalledWith(pagination, []);
+ });
+
+ it('should call loadSharedLinks when nodeId is -sharedlinks-', () => {
+ spyOn(customResourcesService, 'loadSharedLinks').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-sharedlinks-', pagination, ['include'], 'where');
+ expect(customResourcesService.loadSharedLinks).toHaveBeenCalledWith(pagination, ['include'], 'where');
+ });
+
+ it('should call loadSites when nodeId is -sites-', () => {
+ spyOn(customResourcesService, 'loadSites').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-sites-', pagination, ['include'], 'where');
+ expect(customResourcesService.loadSites).toHaveBeenCalledWith(pagination, 'where');
+ });
+
+ it('should call loadMemberSites when nodeId is -mysites-', () => {
+ spyOn(customResourcesService, 'loadMemberSites').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-mysites-', pagination, ['include'], 'where');
+ expect(customResourcesService.loadMemberSites).toHaveBeenCalledWith(pagination, 'where');
+ });
+
+ it('should call loadFavorites when nodeId is -favorites-', () => {
+ spyOn(customResourcesService, 'loadFavorites').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-favorites-', pagination, ['include'], 'where');
+ expect(customResourcesService.loadFavorites).toHaveBeenCalledWith(pagination, ['include'], 'where');
+ });
+
+ it('should call getRecentFiles when nodeId is -recent-', () => {
+ spyOn(customResourcesService, 'getRecentFiles').and.stub();
+
+ customResourcesService.loadFolderByNodeId('-recent-', pagination, ['include'], 'where', ['filters']);
+ expect(customResourcesService.getRecentFiles).toHaveBeenCalledWith('-me-', pagination, ['filters']);
+ });
+ });
+
+ describe('hasCorrespondingNodeIds', () => {
+ it('should return true when nodeId comes from custom source', () => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(true);
+
+ const result = customResourcesService.hasCorrespondingNodeIds('-trashcan-');
+ expect(result).toBeTrue();
+ });
+
+ it('should return true when nodeId comes from supported source', () => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(false);
+ spyOn(customResourcesService, 'isSupportedSource').and.returnValue(true);
+
+ const result = customResourcesService.hasCorrespondingNodeIds('-trashcan-');
+ expect(result).toBeTrue();
+ });
+
+ it('should return false when nodeId comes from neither custom nor supported source', () => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(false);
+ spyOn(customResourcesService, 'isSupportedSource').and.returnValue(false);
+
+ const result = customResourcesService.hasCorrespondingNodeIds('-trashcan-');
+ expect(result).toBeFalse();
+ });
+ });
+
+ describe('getIdFromEntry', () => {
+ const fakeNode: any = {
+ entry: {
+ id: 'some-id',
+ nodeId: 'some-node-id',
+ guid: 'guid',
+ targetGuid: 'target-guid'
+ }
+ };
+
+ it('should return nodeId for shared links', () => {
+ expect(customResourcesService.getIdFromEntry(fakeNode, '-sharedlinks-')).toBe('some-node-id');
+ });
+
+ it('should return guid for sites and my sites', () => {
+ expect(customResourcesService.getIdFromEntry(fakeNode, '-sites-')).toBe('guid');
+ expect(customResourcesService.getIdFromEntry(fakeNode, '-mysites-')).toBe('guid');
+ });
+
+ it('should return targetGuid for favorites', () => {
+ expect(customResourcesService.getIdFromEntry(fakeNode, '-favorites-')).toBe('target-guid');
+ });
+
+ it('should return id for other custom sources', () => {
+ expect(customResourcesService.getIdFromEntry(fakeNode, '-trashcan-')).toBe('some-id');
+ });
+ });
+
+ describe('getCorrespondingNodeIds', () => {
+ const fakeNode: NodeEntry = {
+ entry: {
+ id: 'fake-id',
+ name: 'fake-name',
+ nodeType: 'cm:folder',
+ isFolder: true,
+ isFile: false,
+ modifiedAt: new Date(),
+ createdAt: new Date(),
+ createdByUser: { id: 'fake-user', displayName: 'Fake User' },
+ modifiedByUser: { id: 'fake-user', displayName: 'Fake User' },
+ parentId: 'fake-parent-id'
+ }
+ };
+
+ const fakePaging: NodePaging = {
+ list: {
+ pagination: { count: 1, hasMoreItems: false, totalItems: 1, skipCount: 0, maxItems: 20 },
+ entries: [fakeNode]
+ }
+ };
+
+ it('should return empty array when source is not custom and nodeId is not defined', (done) => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(false);
+
+ customResourcesService.getCorrespondingNodeIds(undefined).subscribe((result) => {
+ expect(result).toEqual([]);
+ done();
+ });
+ });
+
+ it('should return node id when source is not custom and nodeId is defined', (done) => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(false);
+ spyOn(customResourcesService['nodesApi'], 'getNode').and.returnValue(Promise.resolve(fakeNode));
+
+ customResourcesService.getCorrespondingNodeIds('nodeId').subscribe((result) => {
+ expect(result).toEqual(['fake-id']);
+ done();
+ });
+ });
+
+ it('should return node id when source is custom', (done) => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(true);
+ spyOn(customResourcesService, 'loadFolderByNodeId').and.returnValue(of(fakePaging));
+ spyOn(customResourcesService, 'getIdFromEntry').and.callThrough();
+
+ customResourcesService.getCorrespondingNodeIds('nodeId').subscribe((result) => {
+ expect(result).toEqual(['fake-id']);
+ expect(customResourcesService.getIdFromEntry).toHaveBeenCalledWith(fakeNode, 'nodeId');
+ done();
+ });
+ });
+ });
+
+ describe('isSupportedSource', () => {
+ it('should return true for supported sources', () => {
+ expect(customResourcesService.isSupportedSource('-my-')).toBeTrue();
+ expect(customResourcesService.isSupportedSource('-root-')).toBeTrue();
+ expect(customResourcesService.isSupportedSource('-shared-')).toBeTrue();
+ });
+
+ it('should return false for unsupported sources', () => {
+ expect(customResourcesService.isSupportedSource('-unsupported-')).toBeFalse();
+ expect(customResourcesService.isSupportedSource('regular-node-id')).toBeFalse();
+ });
+ });
+
+ describe('isCustomSource', () => {
+ it('should return true for custom sources', () => {
+ expect(customResourcesService.isCustomSource('-trashcan-')).toBeTrue();
+ expect(customResourcesService.isCustomSource('-sharedlinks-')).toBeTrue();
+ expect(customResourcesService.isCustomSource('-sites-')).toBeTrue();
+ expect(customResourcesService.isCustomSource('-mysites-')).toBeTrue();
+ expect(customResourcesService.isCustomSource('-favorites-')).toBeTrue();
+ expect(customResourcesService.isCustomSource('-recent-')).toBeTrue();
+ });
+
+ it('should return false for other sources', () => {
+ expect(customResourcesService.isCustomSource('-unsupported-')).toBeFalse();
+ expect(customResourcesService.isCustomSource('regular-node-id')).toBeFalse();
+ });
+ });
+
+ describe('loadSharedLinks', () => {
+ it('should call sharedLinksApi.listSharedLinks', (done) => {
+ spyOn(customResourcesService.sharedLinksApi, 'listSharedLinks').and.callFake(() => Promise.resolve(null));
+
+ customResourcesService.loadSharedLinks({ maxItems: 10, skipCount: 0 }).subscribe(() => {
+ expect(customResourcesService.sharedLinksApi.listSharedLinks).toHaveBeenCalledWith({
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames'],
+ maxItems: 10,
+ skipCount: 0,
+ where: undefined
+ });
+ done();
+ });
+ });
+
+ it('should call sharedLinksApi.listSharedLinks with custom params when provided', (done) => {
+ spyOn(customResourcesService.sharedLinksApi, 'listSharedLinks').and.callFake(() => Promise.resolve(null));
+
+ customResourcesService.loadSharedLinks({ maxItems: 10, skipCount: 0 }, ['custom'], 'customWhere').subscribe(() => {
+ expect(customResourcesService.sharedLinksApi.listSharedLinks).toHaveBeenCalledWith({
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', 'custom'],
+ maxItems: 10,
+ skipCount: 0,
+ where: 'customWhere'
+ });
+ done();
+ });
+ });
+ });
+
+ describe('loadTrashcan', () => {
+ it('should call trashcanApi.listDeletedNodes', (done) => {
+ spyOn(customResourcesService.trashcanApi, 'listDeletedNodes').and.callFake(() => Promise.resolve(null));
+
+ customResourcesService.loadTrashcan({ maxItems: 10, skipCount: 0 }).subscribe(() => {
+ expect(customResourcesService.trashcanApi.listDeletedNodes).toHaveBeenCalledWith({
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames'],
+ maxItems: 10,
+ skipCount: 0
+ });
+ done();
+ });
+ });
+
+ it('should call trashcanApi.listDeletedNodes with custom params when provided', (done) => {
+ spyOn(customResourcesService.trashcanApi, 'listDeletedNodes').and.callFake(() => Promise.resolve(null));
+
+ customResourcesService.loadTrashcan({ maxItems: 10, skipCount: 0 }, ['custom']).subscribe(() => {
+ expect(customResourcesService.trashcanApi.listDeletedNodes).toHaveBeenCalledWith({
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', 'custom'],
+ maxItems: 10,
+ skipCount: 0
+ });
+ done();
+ });
+ });
+ });
+
+ describe('loadSites', () => {
+ const fakeSite: SiteEntry = {
+ entry: {
+ id: 'fake-site-id',
+ guid: 'fake-site-guid',
+ title: 'Fake Site',
+ description: 'This is a fake site for testing purposes',
+ visibility: 'PUBLIC'
+ }
+ };
+
+ const fakeSitePaging: SitePaging = {
+ list: {
+ entries: [fakeSite],
+ pagination: {
+ count: 1,
+ hasMoreItems: false,
+ totalItems: 1,
+ skipCount: 0,
+ maxItems: 25
+ }
+ }
+ };
+
+ it('should call sitesApi.listSites', (done) => {
+ spyOn(customResourcesService.sitesApi, 'listSites').and.callFake(() => Promise.resolve(fakeSitePaging));
+
+ customResourcesService.loadSites({ maxItems: 10, skipCount: 0 }, 'where').subscribe((result) => {
+ expect(customResourcesService.sitesApi.listSites).toHaveBeenCalledWith({
+ include: ['properties', 'aspectNames'],
+ maxItems: 10,
+ skipCount: 0,
+ where: 'where'
+ });
+ expect(result).toEqual(fakeSitePaging);
+ expect((result.list.entries[0].entry as Extra).name).toBe(fakeSite.entry.title);
+ done();
+ });
+ });
+
+ it('should return error when sitesApi.listSites fails', (done) => {
+ spyOn(customResourcesService.sitesApi, 'listSites').and.rejectWith(new Error('Error'));
+ customResourcesService.loadSites({ maxItems: 10, skipCount: 0 }, 'where').subscribe({
+ next: () => {
+ fail('Expected to throw an error');
+ done();
+ },
+ error: (error) => {
+ expect(error).toEqual(new Error('Error'));
+ done();
+ }
+ });
+ });
+ });
+
+ describe('loadMemberSites', () => {
+ const fakeSite: SiteEntry = {
+ entry: {
+ id: 'fake-site-id',
+ guid: 'fake-site-guid',
+ title: 'Fake Site',
+ description: 'This is a fake site for testing purposes',
+ visibility: 'PUBLIC'
+ }
+ };
+
+ const fakeRole: SiteRoleEntry = {
+ entry: {
+ id: 'fake-site-id',
+ guid: 'fake-site-guid',
+ role: 'Fake Role',
+ site: fakeSite.entry
+ }
+ };
+
+ const fakeRolePaging: SiteRolePaging = {
+ list: {
+ entries: [fakeRole],
+ pagination: {
+ count: 1,
+ hasMoreItems: false,
+ totalItems: 1,
+ skipCount: 0,
+ maxItems: 25
+ }
+ }
+ };
+
+ it('should call sitesApi.listSiteMembershipsForPerson', (done) => {
+ spyOn(customResourcesService.sitesApi, 'listSiteMembershipsForPerson').and.callFake(() => Promise.resolve(fakeRolePaging));
+
+ customResourcesService.loadMemberSites({ maxItems: 10, skipCount: 0 }, 'where').subscribe((result) => {
+ expect(customResourcesService.sitesApi.listSiteMembershipsForPerson).toHaveBeenCalledWith('-me-', {
+ include: ['properties'],
+ maxItems: 10,
+ skipCount: 0,
+ where: 'where'
+ });
+ expect((result.list.entries[0].entry as Extra).name).toBe(fakeSite.entry.title);
+ expect((result.list.entries[0].entry as Extra).allowableOperations).toEqual([
+ 'create'
+ ]);
+ done();
+ });
+ });
+
+ it('should return error when sitesApi.listSiteMembershipsForPerson fails', (done) => {
+ spyOn(customResourcesService.sitesApi, 'listSiteMembershipsForPerson').and.rejectWith(new Error('Error'));
+ customResourcesService.loadMemberSites({ maxItems: 10, skipCount: 0 }, 'where').subscribe({
+ next: () => {
+ fail('Expected to throw an error');
+ done();
+ },
+ error: (error) => {
+ expect(error).toEqual(new Error('Error'));
+ done();
+ }
+ });
+ });
+ });
});
diff --git a/lib/content-services/src/lib/document-list/services/custom-resources.service.ts b/lib/content-services/src/lib/document-list/services/custom-resources.service.ts
index eba75b71f0..2869f3cece 100644
--- a/lib/content-services/src/lib/document-list/services/custom-resources.service.ts
+++ b/lib/content-services/src/lib/document-list/services/custom-resources.service.ts
@@ -385,9 +385,10 @@ export class CustomResourcesService {
* @param pagination Specifies how to paginate the results
* @param includeFields List of data field names to include in the results
* @param where Filters the Node list using the *where* condition of the REST API (for example, isFolder=true). See the REST API documentation for more information.
+ * @param filters Specifies additional filters to apply (joined with **AND**). Applied for '-recent-' only.
* @returns List of items contained in the folder
*/
- loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[] = [], where?: string): any {
+ loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[] = [], where?: string, filters?: string[]): any {
if (nodeId === '-trashcan-') {
return this.loadTrashcan(pagination, includeFields);
} else if (nodeId === '-sharedlinks-') {
@@ -399,7 +400,9 @@ export class CustomResourcesService {
} else if (nodeId === '-favorites-') {
return this.loadFavorites(pagination, includeFields, where);
} else if (nodeId === '-recent-') {
- return this.getRecentFiles('-me-', pagination);
+ return this.getRecentFiles('-me-', pagination, filters);
+ } else {
+ return of(null);
}
}
diff --git a/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts b/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts
index 977152330e..da0b41644a 100644
--- a/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts
+++ b/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts
@@ -18,11 +18,17 @@
import { DocumentListService } from './document-list.service';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
+import { of } from 'rxjs';
+import { NodeEntry, NodePaging } from '@alfresco/js-api';
+import { CustomResourcesService } from './custom-resources.service';
+import { NodesApiService } from '../../common';
declare let jasmine: any;
describe('DocumentListService', () => {
let service: DocumentListService;
+ let customResourcesService: CustomResourcesService;
+ let nodesApiService: NodesApiService;
const fakeFolder = {
list: {
@@ -71,6 +77,8 @@ describe('DocumentListService', () => {
imports: [ContentTestingModule]
});
service = TestBed.inject(DocumentListService);
+ customResourcesService = TestBed.inject(CustomResourcesService);
+ nodesApiService = TestBed.inject(NodesApiService);
jasmine.Ajax.install();
});
@@ -109,8 +117,38 @@ describe('DocumentListService', () => {
});
}));
+ it('should use rootFolderId provided in options', () => {
+ const spyGetNodeInfo = spyOn(service.nodes, 'listNodeChildren').and.callThrough();
+
+ service.getFolder('/fake-root/fake-name', { rootFolderId: 'testRoot' }, ['isLocked']);
+
+ expect(spyGetNodeInfo).toHaveBeenCalledWith('testRoot', {
+ includeSource: true,
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', 'isLocked'],
+ relativePath: '/fake-root/fake-name'
+ });
+ });
+
+ it('should use provided other values passed in options', () => {
+ const spyGetNodeInfo = spyOn(service.nodes, 'listNodeChildren').and.callThrough();
+
+ service.getFolder('/fake-root/fake-name', { rootFolderId: 'testRoot', maxItems: 10, skipCount: 5, where: 'where', orderBy: ['order'] }, [
+ 'isLocked'
+ ]);
+
+ expect(spyGetNodeInfo).toHaveBeenCalledWith('testRoot', {
+ includeSource: true,
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', 'isLocked'],
+ relativePath: '/fake-root/fake-name',
+ maxItems: 10,
+ skipCount: 5,
+ where: 'where',
+ orderBy: ['order']
+ });
+ });
+
it('should add the includeTypes in the request Node Children if required', () => {
- const spyGetNodeInfo = spyOn(service['nodes'], 'listNodeChildren').and.callThrough();
+ const spyGetNodeInfo = spyOn(service.nodes, 'listNodeChildren').and.callThrough();
service.getFolder('/fake-root/fake-name', {}, ['isLocked']);
@@ -122,7 +160,7 @@ describe('DocumentListService', () => {
});
it('should not add the includeTypes in the request Node Children if is duplicated', () => {
- const spyGetNodeInfo = spyOn(service['nodes'], 'listNodeChildren').and.callThrough();
+ const spyGetNodeInfo = spyOn(service.nodes, 'listNodeChildren').and.callThrough();
service.getFolder('/fake-root/fake-name', {}, ['allowableOperations']);
@@ -134,7 +172,7 @@ describe('DocumentListService', () => {
});
it('should add the includeTypes in the request getFolderNode if required', () => {
- const spyGetNodeInfo = spyOn(service['nodes'], 'getNode').and.callThrough();
+ const spyGetNodeInfo = spyOn(service.nodes, 'getNode').and.callThrough();
service.getFolderNode('test-id', ['isLocked']);
@@ -145,7 +183,7 @@ describe('DocumentListService', () => {
});
it('should not add the includeTypes in the request getFolderNode if is duplicated', () => {
- const spyGetNodeInfo = spyOn(service['nodes'], 'getNode').and.callThrough();
+ const spyGetNodeInfo = spyOn(service.nodes, 'getNode').and.callThrough();
service.getFolderNode('test-id', ['allowableOperations']);
@@ -155,6 +193,17 @@ describe('DocumentListService', () => {
});
});
+ it('should add default includeTypes in the request getFolderNode if none is provided', () => {
+ const spyGetNodeInfo = spyOn(service.nodes, 'getNode').and.callThrough();
+
+ service.getFolderNode('test-id');
+
+ expect(spyGetNodeInfo).toHaveBeenCalledWith('test-id', {
+ includeSource: true,
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames']
+ });
+ });
+
it('should delete the folder', fakeAsync(() => {
service.deleteNode('fake-id').subscribe((res) => {
expect(res).toBe('');
@@ -185,4 +234,95 @@ describe('DocumentListService', () => {
jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json' });
});
+
+ it('should call isCustomSource from customResourcesService when isCustomSourceService is called', () => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(true);
+
+ const isCustom = service.isCustomSourceService('fake-source-id');
+ expect(isCustom).toBeTrue();
+ expect(customResourcesService.isCustomSource).toHaveBeenCalledWith('fake-source-id');
+ });
+
+ it('should call getNode from nodes service with proper params when getNode is called', () => {
+ spyOn(nodesApiService, 'getNode').and.returnValue(of(null));
+
+ service.getNode('fake-node-id');
+
+ expect(nodesApiService.getNode).toHaveBeenCalledWith('fake-node-id', {
+ includeSource: true,
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'definition']
+ });
+ });
+
+ it('should removed duplicated include values for getNode', () => {
+ spyOn(nodesApiService, 'getNode').and.returnValue(of(null));
+
+ service.getNode('fake-node-id', ['aspectNames', 'path', 'properties', 'custom1', 'custom2']);
+
+ expect(nodesApiService.getNode).toHaveBeenCalledWith('fake-node-id', {
+ includeSource: true,
+ include: ['path', 'properties', 'allowableOperations', 'permissions', 'definition', 'aspectNames', 'custom1', 'custom2']
+ });
+ });
+
+ describe('loadFolderByNodeId', () => {
+ const fakeFolderLocal: NodeEntry = {
+ entry: {
+ id: 'fake-id',
+ name: 'fake-name',
+ nodeType: 'cm:folder',
+ isFolder: true,
+ isFile: false,
+ modifiedAt: new Date(),
+ createdAt: new Date(),
+ createdByUser: { id: 'fake-user', displayName: 'Fake User' },
+ modifiedByUser: { id: 'fake-user', displayName: 'Fake User' },
+ parentId: 'fake-parent-id'
+ }
+ };
+
+ const fakeFolderPaging: NodePaging = {
+ list: {
+ pagination: { count: 1, hasMoreItems: false, totalItems: 1, skipCount: 0, maxItems: 20 },
+ entries: [fakeFolderLocal]
+ }
+ };
+ it('should call getFolder and getFolderNode when source is not custom', (done) => {
+ spyOn(service, 'getFolder').and.returnValue(of(fakeFolderPaging));
+ spyOn(service, 'getFolderNode').and.returnValue(of(fakeFolderLocal));
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(false);
+
+ service.loadFolderByNodeId('fake-id', { maxItems: 10, skipCount: 0 }, ['includeMe'], 'where', ['order']).subscribe((result) => {
+ expect(service.getFolder).toHaveBeenCalledWith(
+ null,
+ { maxItems: 10, skipCount: 0, orderBy: ['order'], rootFolderId: 'fake-id', where: 'where' },
+ ['includeMe']
+ );
+ expect(service.getFolderNode).toHaveBeenCalledWith('fake-id', ['includeMe']);
+ expect(result.currentNode).toEqual(fakeFolderLocal);
+ expect(result.children).toEqual(fakeFolderPaging);
+ done();
+ });
+ });
+
+ it('should call customResourcesService.loadFolderByNodeId when source is custom', (done) => {
+ spyOn(customResourcesService, 'isCustomSource').and.returnValue(true);
+ spyOn(customResourcesService, 'loadFolderByNodeId').and.returnValue(of(fakeFolderPaging));
+
+ service
+ .loadFolderByNodeId('fake-id', { maxItems: 10, skipCount: 0 }, ['includeMe'], 'where', ['order'], ['filter'])
+ .subscribe((result) => {
+ expect(customResourcesService.loadFolderByNodeId).toHaveBeenCalledWith(
+ 'fake-id',
+ { maxItems: 10, skipCount: 0 },
+ ['includeMe'],
+ 'where',
+ ['filter']
+ );
+ expect(result.currentNode).toBeNull();
+ expect(result.children).toEqual(fakeFolderPaging);
+ done();
+ });
+ });
+ });
});
diff --git a/lib/content-services/src/lib/document-list/services/document-list.service.ts b/lib/content-services/src/lib/document-list/services/document-list.service.ts
index 97e542129c..8f6c98e314 100644
--- a/lib/content-services/src/lib/document-list/services/document-list.service.ts
+++ b/lib/content-services/src/lib/document-list/services/document-list.service.ts
@@ -190,6 +190,7 @@ export class DocumentListService implements DocumentListLoader {
* @param includeFields List of data field names to include in the results
* @param where Optionally filter the list
* @param orderBy order by node property
+ * @param filters Specifies additional filters to apply (joined with **AND**). Applied for recent files only.
* @returns Details of the folder
*/
loadFolderByNodeId(
@@ -197,11 +198,12 @@ export class DocumentListService implements DocumentListLoader {
pagination: PaginationModel,
includeFields: string[],
where?: string,
- orderBy?: string[]
+ orderBy?: string[],
+ filters?: string[]
): Observable {
if (this.customResourcesService.isCustomSource(nodeId)) {
return this.customResourcesService
- .loadFolderByNodeId(nodeId, pagination, includeFields, where)
+ .loadFolderByNodeId(nodeId, pagination, includeFields, where, filters)
.pipe(map((result: any) => new DocumentLoaderNode(null, result)));
} else {
return this.retrieveDocumentNode(nodeId, pagination, includeFields, where, orderBy);