mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACS-3895] ACA - Folder Rules: inherit rule sets toggle (#2808)
* ACS-3895 - initial layout * ACS-3895 - finished functionality * ACS-3895 - unit tests * ACS-3895 - deleted comments * ACS-3895 - small fixes * ACS-3895 - renamed ruleSettings to ruleSettingsMock * ACS-3895 - rebase
This commit is contained in:
parent
654aebe964
commit
60ba8eb6ce
projects/aca-folder-rules
@ -95,7 +95,8 @@
|
|||||||
"CREATE_RULE": "Create rule",
|
"CREATE_RULE": "Create rule",
|
||||||
"LINK_RULES": "Link rules",
|
"LINK_RULES": "Link rules",
|
||||||
"EDIT_RULE": "Edit",
|
"EDIT_RULE": "Edit",
|
||||||
"SEE_IN_FOLDER": "See in folder"
|
"SEE_IN_FOLDER": "See in folder",
|
||||||
|
"INHERIT_RULES": "Inherit rules"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"EMPTY_RULES_LIST": {
|
"EMPTY_RULES_LIST": {
|
||||||
|
@ -26,6 +26,17 @@
|
|||||||
class="aca-manage-rules__actions-bar__title__breadcrumb"></adf-breadcrumb>
|
class="aca-manage-rules__actions-bar__title__breadcrumb"></adf-breadcrumb>
|
||||||
</adf-toolbar-title>
|
</adf-toolbar-title>
|
||||||
|
|
||||||
|
<mat-slide-toggle
|
||||||
|
data-automation-id="manage-rules-inheritance-toggle-button"
|
||||||
|
[checked]="isInheritanceEnabled"
|
||||||
|
(change)="onInheritanceToggleChange($event)"
|
||||||
|
[disabled]="isInheritanceToggleDisabled"
|
||||||
|
[labelPosition]="'before'">
|
||||||
|
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.INHERIT_RULES' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
|
||||||
|
<mat-divider vertical class="vertical-divider"></mat-divider>
|
||||||
|
|
||||||
<div class="aca-manage-rules__actions-bar__buttons">
|
<div class="aca-manage-rules__actions-bar__buttons">
|
||||||
<button
|
<button
|
||||||
*ngIf="!(mainRuleSet$ | async)"
|
*ngIf="!(mainRuleSet$ | async)"
|
||||||
|
@ -17,7 +17,18 @@
|
|||||||
&__buttons {
|
&__buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: 4px;
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-slide-toggle-label {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--adf-breadcrumb-item-active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical-divider {
|
||||||
|
height: 50%;
|
||||||
|
margin: 0 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ import { owningFolderIdMock, owningFolderMock } from '../mock/node.mock';
|
|||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ActionsService } from '../services/actions.service';
|
import { ActionsService } from '../services/actions.service';
|
||||||
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
||||||
import { ruleMock } from '../mock/rules.mock';
|
import { ruleMock, ruleSettingsMock } from '../mock/rules.mock';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
describe('ManageRulesSmartComponent', () => {
|
describe('ManageRulesSmartComponent', () => {
|
||||||
@ -229,4 +229,43 @@ describe('ManageRulesSmartComponent', () => {
|
|||||||
expect(createButton).toBeFalsy();
|
expect(createButton).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Rule inheritance toggle button', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
folderRuleSetsService.folderInfo$ = of(owningFolderMock);
|
||||||
|
folderRuleSetsService.inheritedRuleSets$ = of([]);
|
||||||
|
folderRuleSetsService.isLoading$ = of(false);
|
||||||
|
actionsService.loading$ = of(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show inherit rules toggle button, and disable it when isInheritanceToggleDisabled = true', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const createButton = debugElement.query(By.css(`[data-automation-id="manage-rules-inheritance-toggle-button"]`));
|
||||||
|
expect(createButton).toBeTruthy();
|
||||||
|
|
||||||
|
component.isInheritanceToggleDisabled = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(createButton.nativeNode.classList).toContain('mat-disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call onInheritanceToggleChange() on change', () => {
|
||||||
|
const onInheritanceToggleChangeSpy = spyOn(component, 'onInheritanceToggleChange').and.callThrough();
|
||||||
|
const updateRuleSettingsSpy = spyOn(folderRulesService, 'updateRuleSettings').and.returnValue(Promise.resolve(ruleSettingsMock));
|
||||||
|
const loadRuleSetsSpy = spyOn(folderRuleSetsService, 'loadRuleSets').and.callThrough();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const inheritanceToggleBtn = fixture.debugElement.query(By.css(`[data-automation-id="manage-rules-inheritance-toggle-button"]`));
|
||||||
|
|
||||||
|
inheritanceToggleBtn.nativeElement.dispatchEvent(new Event('change'));
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(onInheritanceToggleChangeSpy).toHaveBeenCalled();
|
||||||
|
expect(updateRuleSettingsSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(loadRuleSetsSpy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,6 +40,7 @@ import { ActionsService } from '../services/actions.service';
|
|||||||
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
||||||
import { RuleSet } from '../model/rule-set.model';
|
import { RuleSet } from '../model/rule-set.model';
|
||||||
import { RuleSetPickerSmartComponent } from '../rule-set-picker/rule-set-picker.smart-component';
|
import { RuleSetPickerSmartComponent } from '../rule-set-picker/rule-set-picker.smart-component';
|
||||||
|
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'aca-manage-rules',
|
selector: 'aca-manage-rules',
|
||||||
@ -50,6 +51,8 @@ import { RuleSetPickerSmartComponent } from '../rule-set-picker/rule-set-picker.
|
|||||||
})
|
})
|
||||||
export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
||||||
nodeId = '';
|
nodeId = '';
|
||||||
|
isInheritanceEnabled = true;
|
||||||
|
isInheritanceToggleDisabled = false;
|
||||||
|
|
||||||
mainRuleSet$: Observable<RuleSet>;
|
mainRuleSet$: Observable<RuleSet>;
|
||||||
inheritedRuleSets$: Observable<RuleSet[]>;
|
inheritedRuleSets$: Observable<RuleSet[]>;
|
||||||
@ -93,6 +96,10 @@ export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
|||||||
this.route.params.subscribe((params) => {
|
this.route.params.subscribe((params) => {
|
||||||
this.nodeId = params.nodeId;
|
this.nodeId = params.nodeId;
|
||||||
if (this.nodeId) {
|
if (this.nodeId) {
|
||||||
|
this.folderRulesService.getRuleSettings(this.nodeId).then((ruleSettings) => {
|
||||||
|
this.isInheritanceEnabled = ruleSettings.value;
|
||||||
|
});
|
||||||
|
|
||||||
this.folderRuleSetsService.loadRuleSets(this.nodeId);
|
this.folderRuleSetsService.loadRuleSets(this.nodeId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -153,6 +160,14 @@ export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
|||||||
await this.folderRulesService.updateRule(this.nodeId, rule.id, { ...rule, isEnabled });
|
await this.folderRulesService.updateRule(this.nodeId, rule.id, { ...rule, isEnabled });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onInheritanceToggleChange(event: MatSlideToggleChange) {
|
||||||
|
this.isInheritanceToggleDisabled = true;
|
||||||
|
const ruleSettings = await this.folderRulesService.updateRuleSettings(this.nodeId, '-isInheritanceEnabled-', { value: event.checked });
|
||||||
|
this.isInheritanceEnabled = ruleSettings.value;
|
||||||
|
this.folderRuleSetsService.loadRuleSets(this.nodeId);
|
||||||
|
this.isInheritanceToggleDisabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
onRuleDeleteButtonClicked(rule: Rule) {
|
onRuleDeleteButtonClicked(rule: Rule) {
|
||||||
this.matDialogService
|
this.matDialogService
|
||||||
.open(ConfirmDialogComponent, {
|
.open(ConfirmDialogComponent, {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Rule } from '../model/rule.model';
|
import { Rule, RuleSettings } from '../model/rule.model';
|
||||||
import { RuleGroupingItem } from '../model/rule-grouping-item.model';
|
import { RuleGroupingItem } from '../model/rule-grouping-item.model';
|
||||||
|
|
||||||
export const getRulesResponseMock = {
|
export const getRulesResponseMock = {
|
||||||
@ -170,3 +170,8 @@ export const ruleListGroupingItemsMock: RuleGroupingItem[] = [
|
|||||||
rule: ruleMock('rule2')
|
rule: ruleMock('rule2')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ruleSettingsMock: RuleSettings = {
|
||||||
|
value: false,
|
||||||
|
key: '-parameter-'
|
||||||
|
};
|
||||||
|
@ -58,3 +58,8 @@ export interface RuleForForm {
|
|||||||
actions: RuleAction[];
|
actions: RuleAction[];
|
||||||
options: RuleOptions;
|
options: RuleOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RuleSettings {
|
||||||
|
value: boolean;
|
||||||
|
key?: string;
|
||||||
|
}
|
||||||
|
@ -68,7 +68,7 @@ export class FolderRuleSetsService {
|
|||||||
inheritedRuleSets$: Observable<RuleSet[]> = this.inheritedRuleSetsSource.asObservable();
|
inheritedRuleSets$: Observable<RuleSet[]> = this.inheritedRuleSetsSource.asObservable();
|
||||||
hasMoreRuleSets$: Observable<boolean> = this.hasMoreRuleSetsSource.asObservable();
|
hasMoreRuleSets$: Observable<boolean> = this.hasMoreRuleSetsSource.asObservable();
|
||||||
folderInfo$: Observable<NodeInfo> = this.folderInfoSource.asObservable();
|
folderInfo$: Observable<NodeInfo> = this.folderInfoSource.asObservable();
|
||||||
isLoading$ = this.isLoadingSource.asObservable();
|
isLoading$: Observable<boolean> = this.isLoadingSource.asObservable();
|
||||||
|
|
||||||
selectedRuleSet$ = this.folderRulesService.selectedRule$.pipe(
|
selectedRuleSet$ = this.folderRulesService.selectedRule$.pipe(
|
||||||
map((rule: Rule) => {
|
map((rule: Rule) => {
|
||||||
|
@ -27,7 +27,15 @@ import { TestBed } from '@angular/core/testing';
|
|||||||
import { CoreTestingModule } from '@alfresco/adf-core';
|
import { CoreTestingModule } from '@alfresco/adf-core';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { FolderRulesService } from './folder-rules.service';
|
import { FolderRulesService } from './folder-rules.service';
|
||||||
import { getMoreRulesResponseMock, getRulesResponseMock, manyRulesMock, moreRulesMock, ruleMock, rulesMock } from '../mock/rules.mock';
|
import {
|
||||||
|
getMoreRulesResponseMock,
|
||||||
|
getRulesResponseMock,
|
||||||
|
manyRulesMock,
|
||||||
|
moreRulesMock,
|
||||||
|
ruleMock,
|
||||||
|
ruleSettingsMock,
|
||||||
|
rulesMock
|
||||||
|
} from '../mock/rules.mock';
|
||||||
import { ruleSetMock } from '../mock/rule-sets.mock';
|
import { ruleSetMock } from '../mock/rule-sets.mock';
|
||||||
import { expect } from '@angular/flex-layout/_private-utils/testing';
|
import { expect } from '@angular/flex-layout/_private-utils/testing';
|
||||||
import { owningFolderIdMock } from '../mock/node.mock';
|
import { owningFolderIdMock } from '../mock/node.mock';
|
||||||
@ -44,6 +52,8 @@ describe('FolderRulesService', () => {
|
|||||||
const { id, ...mockedRuleWithoutId } = mockedRule;
|
const { id, ...mockedRuleWithoutId } = mockedRule;
|
||||||
const mockedRuleEntry = { entry: mockedRule };
|
const mockedRuleEntry = { entry: mockedRule };
|
||||||
const ruleId = mockedRule.id;
|
const ruleId = mockedRule.id;
|
||||||
|
const mockedRuleSettingsEntry = { entry: ruleSettingsMock };
|
||||||
|
const key = ruleSettingsMock.key;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -138,4 +148,18 @@ describe('FolderRulesService', () => {
|
|||||||
const result = await folderRulesService.updateRule(nodeId, ruleId, mockedRule, ruleSetId);
|
const result = await folderRulesService.updateRule(nodeId, ruleId, mockedRule, ruleSetId);
|
||||||
expect(result).toEqual(mockedRule);
|
expect(result).toEqual(mockedRule);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send correct GET request and return rule settings', async () => {
|
||||||
|
callApiSpy.withArgs(`/nodes/${nodeId}/rule-settings/${key}`, 'GET').and.returnValue(Promise.resolve(mockedRuleSettingsEntry));
|
||||||
|
|
||||||
|
const result = await folderRulesService.getRuleSettings(nodeId, key);
|
||||||
|
expect(result).toEqual(ruleSettingsMock);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send correct PUT request to update rule settings and return them', async () => {
|
||||||
|
callApiSpy.withArgs(`/nodes/${nodeId}/rule-settings/${key}`, 'PUT', ruleSettingsMock).and.returnValue(Promise.resolve(mockedRuleSettingsEntry));
|
||||||
|
|
||||||
|
const result = await folderRulesService.updateRuleSettings(nodeId, key, ruleSettingsMock);
|
||||||
|
expect(result).toEqual(ruleSettingsMock);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||||
import { BehaviorSubject, from, Observable } from 'rxjs';
|
import { BehaviorSubject, from, Observable } from 'rxjs';
|
||||||
import { finalize, map } from 'rxjs/operators';
|
import { finalize, map } from 'rxjs/operators';
|
||||||
import { Rule, RuleForForm, RuleOptions } from '../model/rule.model';
|
import { Rule, RuleForForm, RuleOptions, RuleSettings } from '../model/rule.model';
|
||||||
import { RuleCompositeCondition } from '../model/rule-composite-condition.model';
|
import { RuleCompositeCondition } from '../model/rule-composite-condition.model';
|
||||||
import { RuleSimpleCondition } from '../model/rule-simple-condition.model';
|
import { RuleSimpleCondition } from '../model/rule-simple-condition.model';
|
||||||
import { RuleSet } from '../model/rule-set.model';
|
import { RuleSet } from '../model/rule-set.model';
|
||||||
@ -152,6 +152,16 @@ export class FolderRulesService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getRuleSettings(nodeId: string, key: string = '-isInheritanceEnabled-'): Promise<RuleSettings> {
|
||||||
|
const response = await this.callApi(`/nodes/${nodeId}/rule-settings/${key}`, 'GET');
|
||||||
|
return response.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateRuleSettings(nodeId: string, key: string, body: RuleSettings): Promise<RuleSettings> {
|
||||||
|
const response = await this.callApi(`/nodes/${nodeId}/rule-settings/${key}`, 'PUT', { ...body });
|
||||||
|
return response.entry;
|
||||||
|
}
|
||||||
|
|
||||||
private formatRules(res): Rule[] {
|
private formatRules(res): Rule[] {
|
||||||
return res.list.entries.map((entry) => this.formatRule(entry.entry));
|
return res.list.entries.map((entry) => this.formatRule(entry.entry));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user