[ACS-10835] Add new param for recent filters in custom resources services (#11428)

* [ACS-10835] Add new param for recent filters in custom resources services

* [ACS-10835] CR fixes
This commit is contained in:
Michal Kinas
2025-12-08 15:51:31 +01:00
committed by GitHub
parent 3255bf675c
commit 58591c67dc
12 changed files with 616 additions and 26 deletions

View File

@@ -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. |

View File

@@ -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`<br/>
- **loadFolderByNodeId**(nodeId: `string`, pagination: [`PaginationModel`](../../../lib/core/src/lib/models/pagination.model.ts), includeFields: `string[]` = `[]`, where?: `string`, filters?: `string[]`): `any`<br/>
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)`>`<br/>
Gets sites that the current user is a member of.

View File

@@ -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<DocumentLoaderNode>`<br/>
- **loadFolderByNodeId**(nodeId: `string`, pagination: `PaginationModel`, includeFields: `string[]`, where?: `string`, orderBy?: `string[]`, filters?: `string[]`): `Observable<DocumentLoaderNode>`<br/>
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<DocumentLoaderNode>` - Details of the folder
- **moveNode**(nodeId: `string`, targetParentId: `string`): `Observable<NodeEntry>`<br/>
Moves a node to destination node.

View File

@@ -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
);
});

View File

@@ -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) => {

View File

@@ -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`);

View File

@@ -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) => {
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);
},
(err) => {
error: (err) => {
this.handleError(err);
}
);
});
}
resetSelection() {

View File

@@ -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 <DocumentLoaderNode>;
loadFolderByNodeId(
nodeId: string,
pagination: PaginationModel,
includeFields: string[],
where?: string,
filters?: string[]
): Observable<DocumentLoaderNode>;
}

View File

@@ -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> = 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<Site, { name: string }>).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<SiteMember, { name: string }>).name).toBe(fakeSite.entry.title);
expect((result.list.entries[0].entry as Extra<SiteMember, { allowableOperations: string[] }>).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();
}
});
});
});
});

View File

@@ -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);
}
}

View File

@@ -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();
});
});
});
});

View File

@@ -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<DocumentLoaderNode> {
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);