From 0577f35e296991d5d954bd4ecab65a9fa73d07dc Mon Sep 17 00:00:00 2001 From: Nikita Maliarchuk <84377976+nikita-web-ua@users.noreply.github.com> Date: Fri, 12 Aug 2022 10:31:51 +0200 Subject: [PATCH] [ACS-3338] Manage Rules screen / listing - Folder rules service (#2577) * created service for rules * progress on folder-rule service * some progress with folder-rules service unit testing * [ACS-3339] Manage Rules screen / listing - Folder rules service * Review comments * Review comments --- .../src/lib/mock/rules.mock.ts | 102 ++++++++++++++++++ .../src/lib/model/rule-action.model.ts | 35 ++++++ .../src/lib/model/rule.model.ts | 5 +- .../lib/services/folder-rules.service.spec.ts | 68 ++++++++++++ .../src/lib/services/folder-rules.service.ts | 79 ++++++++++++++ 5 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 projects/aca-folder-rules/src/lib/mock/rules.mock.ts create mode 100644 projects/aca-folder-rules/src/lib/model/rule-action.model.ts create mode 100644 projects/aca-folder-rules/src/lib/services/folder-rules.service.spec.ts create mode 100644 projects/aca-folder-rules/src/lib/services/folder-rules.service.ts diff --git a/projects/aca-folder-rules/src/lib/mock/rules.mock.ts b/projects/aca-folder-rules/src/lib/mock/rules.mock.ts new file mode 100644 index 000000000..ded2e9168 --- /dev/null +++ b/projects/aca-folder-rules/src/lib/mock/rules.mock.ts @@ -0,0 +1,102 @@ +import { Rule } from '../model/rule.model'; + +export const dummyResponse = { + list: { + pagination: { + count: 2, + hasMoreItems: false, + totalItems: 2, + skipCount: 0, + maxItems: 100 + }, + entries: [ + { + entry: { + shared: false, + cascade: false, + asynchronous: false, + name: 'rule1', + id: 'd388ed54-a522-410f-a158-6dbf5a833731', + triggers: ['INBOUND'], + actions: [ + { + actionDefinitionId: 'copy', + params: { + 'deep-copy': false, + 'destination-folder': '279c65f0-912b-4563-affb-ed9dab8338e0', + actionContext: 'rule' + } + } + ], + enabled: true + } + }, + { + entry: { + shared: false, + cascade: false, + asynchronous: false, + name: 'rule2', + id: 'e0e645ca-e6c0-47d4-9936-1a8872a6c30b', + triggers: ['INBOUND'], + actions: [ + { + actionDefinitionId: 'move', + params: { + 'destination-folder': '279c65f0-912b-4563-affb-ed9dab8338e0', + actionContext: 'rule' + } + } + ], + enabled: true + } + } + ] + } +}; + +export const dummyRules: Rule[] = [ + { + id: 'd388ed54-a522-410f-a158-6dbf5a833731', + name: 'rule1', + description: '', + enabled: true, + cascade: false, + asynchronous: false, + errorScript: '', + shared: false, + triggers: ['INBOUND'], + conditions: null, + actions: [ + { + actionDefinitionId: 'copy', + params: { + 'deep-copy': false, + 'destination-folder': '279c65f0-912b-4563-affb-ed9dab8338e0', + actionContext: 'rule' + } + } + ] + }, + { + id: 'e0e645ca-e6c0-47d4-9936-1a8872a6c30b', + name: 'rule2', + description: '', + enabled: true, + cascade: false, + asynchronous: false, + errorScript: '', + shared: false, + triggers: ['INBOUND'], + conditions: null, + actions: [ + { + actionDefinitionId: 'move', + params: { + 'destination-folder': '279c65f0-912b-4563-affb-ed9dab8338e0', + actionContext: 'rule' + } + } + ] + } +]; diff --git a/projects/aca-folder-rules/src/lib/model/rule-action.model.ts b/projects/aca-folder-rules/src/lib/model/rule-action.model.ts new file mode 100644 index 000000000..1ba35ee4c --- /dev/null +++ b/projects/aca-folder-rules/src/lib/model/rule-action.model.ts @@ -0,0 +1,35 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +export interface RuleAction { + actionDefinitionId: string; + params: RuleActionParams; +} + +export interface RuleActionParams { + 'deep-copy'?: boolean; + 'destination-folder'?: string; + actionContext?: string; +} diff --git a/projects/aca-folder-rules/src/lib/model/rule.model.ts b/projects/aca-folder-rules/src/lib/model/rule.model.ts index 8463cc8f3..58b9e4ff7 100644 --- a/projects/aca-folder-rules/src/lib/model/rule.model.ts +++ b/projects/aca-folder-rules/src/lib/model/rule.model.ts @@ -24,6 +24,7 @@ */ import { RuleCompositeCondition } from './rule-composite-condition.model'; +import { RuleAction } from './rule-action.model'; export interface Rule { id: string; @@ -34,7 +35,7 @@ export interface Rule { asynchronous: boolean; errorScript: string; shared: boolean; - triggers: ('inbound' | 'update' | 'outbound')[]; + triggers: ('INBOUND' | 'UPDATE' | 'OUTBOUND')[]; conditions: RuleCompositeCondition; - actions: string[]; + actions: RuleAction[]; } diff --git a/projects/aca-folder-rules/src/lib/services/folder-rules.service.spec.ts b/projects/aca-folder-rules/src/lib/services/folder-rules.service.spec.ts new file mode 100644 index 000000000..4165ade0f --- /dev/null +++ b/projects/aca-folder-rules/src/lib/services/folder-rules.service.spec.ts @@ -0,0 +1,68 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { TestBed } from '@angular/core/testing'; +import { CoreTestingModule } from '@alfresco/adf-core'; +import { take } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { FolderRulesService } from './folder-rules.service'; +import { Rule } from '../model/rule.model'; +import { dummyResponse, dummyRules } from '../mock/rules.mock'; + +describe('FolderRulesService', () => { + let folderRulesService: FolderRulesService; + let rulesPromise: Promise[]>; + let rules: Partial[]; + let apiCallSpy; + + const nodeId = ''; + const ruleSetId = '-default-'; + + describe('loadRules', () => { + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [CoreTestingModule], + providers: [FolderRulesService] + }); + + folderRulesService = TestBed.inject(FolderRulesService); + + apiCallSpy = spyOn(folderRulesService, 'apiCall').and.returnValue(of(dummyResponse) as any); + + rulesPromise = folderRulesService.rulesListing$.pipe(take(2)).toPromise(); + + folderRulesService.loadRules(nodeId, ruleSetId); + + rules = await rulesPromise; + }); + + it('should format and set the data', async () => { + expect(rules).toBeTruthy('rulesListing$ is empty'); + expect(rules.length).toBe(2, 'rulesListing$ size is wrong'); + expect(rules).toEqual(dummyRules, 'The list of rules is incorrectly formatted'); + expect(apiCallSpy).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/projects/aca-folder-rules/src/lib/services/folder-rules.service.ts b/projects/aca-folder-rules/src/lib/services/folder-rules.service.ts new file mode 100644 index 000000000..ce652af31 --- /dev/null +++ b/projects/aca-folder-rules/src/lib/services/folder-rules.service.ts @@ -0,0 +1,79 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Injectable } from '@angular/core'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { BehaviorSubject, from, Observable } from 'rxjs'; +import { finalize, map } from 'rxjs/operators'; +import { Rule } from '../model/rule.model'; + +@Injectable({ + providedIn: 'root' +}) +export class FolderRulesService { + private rulesListingSource = new BehaviorSubject([]); + rulesListing$: Observable = this.rulesListingSource.asObservable(); + private loadingSource = new BehaviorSubject(false); + loading$ = this.loadingSource.asObservable(); + constructor(private apiService: AlfrescoApiService) {} + + loadRules(nodeId: string, ruleSetId: string = '-default-'): void { + from(this.apiCall(`/nodes/${nodeId}/rule-sets/${ruleSetId}/rules`, 'GET', [{}, {}, {}, {}, {}, ['application/json'], ['application/json']])) + .pipe( + map((res) => this.formatRules(res)), + finalize(() => this.loadingSource.next(false)) + ) + .subscribe( + (res) => this.rulesListingSource.next(res), + (err) => this.rulesListingSource.error(err) + ); + + this.loadingSource.next(true); + } + + private apiCall(path: string, httpMethod: string, params?: any[]): Promise { + return this.apiService.getInstance().contentClient.callApi(path, httpMethod, ...params); + } + + private formatRules(res): Rule[] { + return res.list.entries.map((entry) => this.formatRule(entry.entry)); + } + + private formatRule(obj): Rule { + return { + id: obj.id, + name: obj.name ?? '', + description: obj.description ?? '', + enabled: obj.enabled ?? true, + cascade: obj.cascade ?? false, + asynchronous: obj.asynchronous ?? false, + errorScript: obj.errorScript ?? '', + shared: obj.shared ?? false, + triggers: obj.triggers ?? ['INBOUND'], + conditions: obj.conditions ?? null, + actions: obj.actions ?? [] + }; + } +}