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 ?? []
+ };
+ }
+}