mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACS-3259] Create / Update rule dialog - options section (#2651)
* first commit * intermediate commit * some progress * [ACS-3259] Create / Update rule dialog - options section
This commit is contained in:
parent
e6f1a1bd4a
commit
c2b9c6cc55
@ -14,7 +14,8 @@
|
||||
"LABEL": {
|
||||
"NAME": "Name",
|
||||
"DESCRIPTION": "Description",
|
||||
"WHEN": "When"
|
||||
"WHEN": "When",
|
||||
"OPTIONS": "Other options"
|
||||
},
|
||||
"PLACEHOLDER": {
|
||||
"NAME": "Enter rule name",
|
||||
@ -31,6 +32,13 @@
|
||||
"UPDATE": "Items are updated",
|
||||
"OUTBOUND": "Items are deleted or leave this folder"
|
||||
},
|
||||
"OPTIONS": {
|
||||
"CASCADE": "Rule applies to subfolders",
|
||||
"ASYNCHRONOUS": "Run rule in the background",
|
||||
"ENABLED": "Disable rule",
|
||||
"ERROR_SCRIPT": "If errors occur run script",
|
||||
"SELECT_ACTION": "Select action"
|
||||
},
|
||||
"COMPARATORS": {
|
||||
"EQUALS": "(=) Equals",
|
||||
"CONTAINS": "Contains",
|
||||
|
@ -39,6 +39,7 @@ import { BreadcrumbModule, DocumentListModule } from '@alfresco/adf-content-serv
|
||||
import { RuleListItemUiComponent } from './rules-list/rule/rule-list-item.ui-component';
|
||||
import { RulesListUiComponent } from './rules-list/rules-list.ui-component';
|
||||
import { RuleTriggersUiComponent } from './rule-details/triggers/rule-triggers.ui-component';
|
||||
import { RuleOptionsUiComponent } from './rule-details/options/rule-options.ui-component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -67,7 +68,8 @@ const routes: Routes = [
|
||||
RuleSimpleConditionUiComponent,
|
||||
RulesListUiComponent,
|
||||
RuleListItemUiComponent,
|
||||
RuleTriggersUiComponent
|
||||
RuleTriggersUiComponent,
|
||||
RuleOptionsUiComponent
|
||||
]
|
||||
})
|
||||
export class AcaFolderRulesModule {
|
||||
|
@ -0,0 +1,35 @@
|
||||
<div class="options-list" [formGroup]="form">
|
||||
<div class="options-list__asynchronous">
|
||||
<mat-checkbox
|
||||
formControlName="asynchronous"
|
||||
(change)="toggleScriptSelector()"
|
||||
[attr.data-automation-id]="'rule-option-checkbox-asynchronous'">
|
||||
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ASYNCHRONOUS' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="select-action" *ngIf="!preview">
|
||||
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ERROR_SCRIPT' | translate}}:</span>
|
||||
<mat-form-field>
|
||||
<mat-select [disabled]="disableSelector" formControlName="errorScript"
|
||||
placeholder="{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.SELECT_ACTION' | translate}}"
|
||||
[attr.data-automation-id]="'rule-option-select-errorScript'">
|
||||
<mat-option>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.SELECT_ACTION' | translate}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-list__rest">
|
||||
<mat-checkbox
|
||||
formControlName="cascade"
|
||||
[attr.data-automation-id]="'rule-option-checkbox-cascade'">
|
||||
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.CASCADE' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-checkbox
|
||||
[attr.data-automation-id]="'rule-option-checkbox-enabled'"
|
||||
[checked]="!form.value.enabled" *ngIf="!preview"
|
||||
(change)="form.get('enabled').setValue(!$event.checked)">
|
||||
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ENABLED' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
.options-list {
|
||||
display: flex;
|
||||
column-gap: 25px;
|
||||
padding: 0.75em 0;
|
||||
|
||||
&__rest {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-action {
|
||||
margin-left: 5px;
|
||||
margin-top: 12px;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*!
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, inject, waitForAsync } from '@angular/core/testing';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms';
|
||||
import { RuleOptionsUiComponent } from './rule-options.ui-component';
|
||||
import { CoreTestingModule } from '@alfresco/adf-core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('RuleOptionsUiComponent', () => {
|
||||
let component: RuleOptionsUiComponent;
|
||||
let fixture: ComponentFixture<RuleOptionsUiComponent>;
|
||||
|
||||
const getByDataAutomationId = (dataAutomationId: string): DebugElement =>
|
||||
fixture.debugElement.query(By.css(`[data-automation-id="${dataAutomationId}"]`));
|
||||
|
||||
const toggleMatCheckbox = (dataAutomationId: string) => {
|
||||
((getByDataAutomationId(dataAutomationId).nativeElement as HTMLElement).children[0] as HTMLElement).click();
|
||||
};
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
imports: [FormsModule, ReactiveFormsModule, CoreTestingModule],
|
||||
declarations: [RuleOptionsUiComponent]
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(inject([FormBuilder], (fb: FormBuilder) => {
|
||||
fixture = TestBed.createComponent(RuleOptionsUiComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
component.form = fb.group({
|
||||
asynchronous: [false],
|
||||
cascade: [false],
|
||||
enabled: [true],
|
||||
errorScript: ['']
|
||||
});
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('checkboxes should be falsy by default, selector is disabled', () => {
|
||||
expect(component).toBeTruthy();
|
||||
|
||||
expect(getByDataAutomationId('rule-option-checkbox-asynchronous').componentInstance.checked).toBeFalsy();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-cascade').componentInstance.checked).toBeFalsy();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-enabled').componentInstance.checked).toBeFalsy();
|
||||
expect(getByDataAutomationId('rule-option-select-errorScript').componentInstance.disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should enable selector when async checkbox is truthy', () => {
|
||||
toggleMatCheckbox('rule-option-checkbox-asynchronous');
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-asynchronous').componentInstance.checked).toBeTruthy();
|
||||
expect(getByDataAutomationId('rule-option-select-errorScript').componentInstance.disabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should hide some fields in preview mode', () => {
|
||||
component.preview = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getByDataAutomationId('rule-option-checkbox-asynchronous')).toBeTruthy();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-asynchronous')).toBeTruthy();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-cascade')).toBeTruthy();
|
||||
expect(getByDataAutomationId('rule-option-checkbox-enabled')).toBeFalsy();
|
||||
expect(getByDataAutomationId('rule-option-select-errorScript')).toBeFalsy();
|
||||
});
|
||||
});
|
@ -0,0 +1,42 @@
|
||||
/*!
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-rule-options',
|
||||
templateUrl: 'rule-options.ui-component.html',
|
||||
styleUrls: ['rule-options.ui-component.scss']
|
||||
})
|
||||
export class RuleOptionsUiComponent {
|
||||
@Input() form: FormGroup;
|
||||
@Input() preview: boolean;
|
||||
disableSelector = true;
|
||||
|
||||
toggleScriptSelector() {
|
||||
this.disableSelector = !this.disableSelector;
|
||||
}
|
||||
}
|
@ -42,4 +42,12 @@
|
||||
|
||||
<aca-rule-composite-condition formControlName="conditions"></aca-rule-composite-condition>
|
||||
<mat-error class="rule-details-error">{{ getErrorMessage(conditions) | translate }}</mat-error>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="aca-rule-details__form__row">
|
||||
<div class="label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.OPTIONS' | translate }}</div>
|
||||
<aca-rule-options [form]="form" [preview]="preview" data-automation-id="rule-details-options-component"></aca-rule-options>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -30,6 +30,8 @@ import { Rule } from '../model/rule.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RuleCompositeConditionUiComponent } from './conditions/rule-composite-condition.ui-component';
|
||||
import { RuleTriggersUiComponent } from './triggers/rule-triggers.ui-component';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { RuleOptionsUiComponent } from './options/rule-options.ui-component';
|
||||
|
||||
describe('RuleDetailsUiComponent', () => {
|
||||
let fixture: ComponentFixture<RuleDetailsUiComponent>;
|
||||
@ -39,7 +41,10 @@ describe('RuleDetailsUiComponent', () => {
|
||||
id: 'rule-id',
|
||||
name: 'Rule name',
|
||||
description: 'This is the description of the rule',
|
||||
triggers: ['update', 'outbound']
|
||||
triggers: ['update', 'outbound'],
|
||||
asynchronous: true,
|
||||
cascade: true,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
const getHtmlElement = <T>(dataAutomationId: string) =>
|
||||
@ -51,7 +56,7 @@ describe('RuleDetailsUiComponent', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreTestingModule],
|
||||
declarations: [RuleCompositeConditionUiComponent, RuleDetailsUiComponent, RuleTriggersUiComponent]
|
||||
declarations: [RuleCompositeConditionUiComponent, RuleDetailsUiComponent, RuleTriggersUiComponent, RuleOptionsUiComponent]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(RuleDetailsUiComponent);
|
||||
@ -65,10 +70,16 @@ describe('RuleDetailsUiComponent', () => {
|
||||
const nameInput = getHtmlElement<HTMLInputElement>('rule-details-name-input');
|
||||
const descriptionTextarea = getHtmlElement<HTMLTextAreaElement>('rule-details-description-textarea');
|
||||
const ruleTriggersComponent = getComponentInstance<RuleTriggersUiComponent>('rule-details-triggers-component');
|
||||
const ruleOptionAsynchronous = getComponentInstance<MatCheckbox>('rule-option-checkbox-asynchronous');
|
||||
const ruleOptionCascade = getComponentInstance<MatCheckbox>('rule-option-checkbox-cascade');
|
||||
const ruleOptionDisabled = getComponentInstance<MatCheckbox>('rule-option-checkbox-enabled');
|
||||
|
||||
expect(nameInput.value).toBe(testValue.name);
|
||||
expect(descriptionTextarea.value).toBe(testValue.description);
|
||||
expect(ruleTriggersComponent.value).toEqual(testValue.triggers);
|
||||
expect(ruleOptionAsynchronous.checked).toBe(testValue.asynchronous);
|
||||
expect(ruleOptionCascade.checked).toBe(testValue.cascade);
|
||||
expect(ruleOptionDisabled.checked).toBe(!testValue.enabled);
|
||||
});
|
||||
|
||||
it('should modify the form if the value input property is modified', () => {
|
||||
@ -95,10 +106,16 @@ describe('RuleDetailsUiComponent', () => {
|
||||
const nameInput = getHtmlElement<HTMLInputElement>('rule-details-name-input');
|
||||
const descriptionTextarea = getHtmlElement<HTMLTextAreaElement>('rule-details-description-textarea');
|
||||
const ruleTriggersComponent = getComponentInstance<RuleTriggersUiComponent>('rule-details-triggers-component');
|
||||
const ruleOptionAsynchronous = getComponentInstance<MatCheckbox>('rule-option-checkbox-asynchronous');
|
||||
const ruleOptionCascade = getComponentInstance<MatCheckbox>('rule-option-checkbox-cascade');
|
||||
const ruleOptionDisabled = getComponentInstance<MatCheckbox>('rule-option-checkbox-enabled');
|
||||
|
||||
expect(nameInput.disabled).toBeFalsy();
|
||||
expect(descriptionTextarea.disabled).toBeFalsy();
|
||||
expect(ruleTriggersComponent.readOnly).toBeFalsy();
|
||||
expect(ruleOptionAsynchronous.disabled).toBeFalsy();
|
||||
expect(ruleOptionCascade.disabled).toBeFalsy();
|
||||
expect(ruleOptionDisabled.disabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not be editable if read-only', () => {
|
||||
@ -108,9 +125,13 @@ describe('RuleDetailsUiComponent', () => {
|
||||
const nameInput = getHtmlElement<HTMLInputElement>('rule-details-name-input');
|
||||
const descriptionTextarea = getHtmlElement<HTMLTextAreaElement>('rule-details-description-textarea');
|
||||
const ruleTriggersComponent = getComponentInstance<RuleTriggersUiComponent>('rule-details-triggers-component');
|
||||
const ruleOptionAsynchronous = getComponentInstance<MatCheckbox>('rule-option-checkbox-asynchronous');
|
||||
const ruleOptionCascade = getComponentInstance<MatCheckbox>('rule-option-checkbox-cascade');
|
||||
|
||||
expect(nameInput.disabled).toBeTruthy();
|
||||
expect(descriptionTextarea.disabled).toBeTruthy();
|
||||
expect(ruleTriggersComponent.readOnly).toBeTruthy();
|
||||
expect(ruleOptionAsynchronous.disabled).toBeTruthy();
|
||||
expect(ruleOptionCascade.disabled).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +64,11 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
||||
name: newValue.name || FolderRulesService.emptyRule.name,
|
||||
description: newValue.description || FolderRulesService.emptyRule.description,
|
||||
triggers: newValue.triggers || FolderRulesService.emptyRule.triggers,
|
||||
conditions: newValue.conditions || FolderRulesService.emptyRule.conditions
|
||||
conditions: newValue.conditions || FolderRulesService.emptyRule.conditions,
|
||||
asynchronous: newValue.asynchronous || FolderRulesService.emptyRule.asynchronous,
|
||||
errorScript: newValue.errorScript || FolderRulesService.emptyRule.errorScript,
|
||||
cascade: newValue.cascade || FolderRulesService.emptyRule.cascade,
|
||||
enabled: newValue.enabled || FolderRulesService.emptyRule.enabled
|
||||
};
|
||||
if (this.form) {
|
||||
this.form.setValue(newValue);
|
||||
@ -95,6 +99,18 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
||||
get conditions(): UntypedFormControl {
|
||||
return this.form.get('conditions') as UntypedFormControl;
|
||||
}
|
||||
get asynchronous(): UntypedFormControl {
|
||||
return this.form.get('asynchronous') as UntypedFormControl;
|
||||
}
|
||||
get errorScript(): UntypedFormControl {
|
||||
return this.form.get('errorScript') as UntypedFormControl;
|
||||
}
|
||||
get cascade(): UntypedFormControl {
|
||||
return this.form.get('cascade') as UntypedFormControl;
|
||||
}
|
||||
get enabled(): UntypedFormControl {
|
||||
return this.form.get('enabled') as UntypedFormControl;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = new UntypedFormGroup({
|
||||
@ -109,7 +125,11 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
||||
simpleConditions: []
|
||||
},
|
||||
ruleCompositeConditionValidator()
|
||||
)
|
||||
),
|
||||
asynchronous: new UntypedFormControl(this.value.asynchronous),
|
||||
errorScript: new UntypedFormControl(this.value.errorScript),
|
||||
cascade: new UntypedFormControl(this.value.cascade),
|
||||
enabled: new UntypedFormControl(this.value.enabled)
|
||||
});
|
||||
this.readOnly = this._readOnly;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user