mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-04-16 22:24:49 +00:00
[AAE-40028] Added group/section validation skipping to cloud forms for workspace (#11466)
This commit is contained in:
@@ -96,6 +96,7 @@ The template defined inside `empty-form` will be shown when no form definition i
|
||||
| showValidationIcon | `boolean` | true | Toggle rendering of the validation icon next to the form title. |
|
||||
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
||||
| displayModeConfigurations | [`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`[]` | | The available display configurations for the form |
|
||||
| enableParentVisibilityCheck | `boolean` | false | Toggle to enable parent visibility check for validation. When enabled, fields inside hidden groups/sections will skip validation. |
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ Starts a process.
|
||||
| processDefinitionName | `string` | | Name of the process definition. |
|
||||
| showSelectProcessDropdown | `boolean` | true | Show/hide the process dropdown list. |
|
||||
| showTitle | `boolean` | true | Show/hide title. |
|
||||
| showCancelButton | `boolean` | true | Show/hide cancel button. |
|
||||
| displayModeConfigurations | [`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`[]` | | The available display configurations for the form (start process event can have assigned form). |
|
||||
| enableParentVisibilityCheck | `boolean` | false | Toggle to enable parent visibility check for validation. When enabled, fields inside hidden groups/sections will skip validation. |
|
||||
| values | [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]` | | Parameter to pass form field values in the start form if one is associated. |
|
||||
| variables | `any` | | Variables to attach to the payload. |
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ Save and Complete buttons get disabled when at least one of the form's inputs ar
|
||||
| showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. |
|
||||
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
||||
| displayModeConfigurations | `FormCloudDisplayModeConfiguration[]` | | The available display configurations for the form |
|
||||
| enableParentVisibilityCheck | `boolean` | false | Toggle to enable parent visibility check for validation. When enabled, fields inside hidden groups/sections will skip validation. |
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ Based on property taskDetails: TaskDetailsCloudModel shows a form or a screen.
|
||||
| showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. |
|
||||
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
||||
| displayModeConfigurations | `FormCloudDisplayModeConfiguration[]` | | The available display configurations for the form |
|
||||
| enableParentVisibilityCheck | `boolean` | false | Toggle to enable parent visibility check for validation. When enabled, fields inside hidden groups/sections will skip validation. |
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
@@ -461,6 +461,138 @@ describe('FormCloudComponent', () => {
|
||||
expect(formComponent.getFormById).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('enableParentVisibilityCheck', () => {
|
||||
let formModel: FormModel;
|
||||
let field1: FormFieldModel;
|
||||
let field2: FormFieldModel;
|
||||
|
||||
beforeEach(() => {
|
||||
const formJson = {
|
||||
id: 'test-form',
|
||||
name: 'Test Form',
|
||||
fields: [
|
||||
{
|
||||
id: 'group1',
|
||||
type: FormFieldTypes.GROUP,
|
||||
numberOfColumns: 1,
|
||||
fields: {
|
||||
1: [
|
||||
{ id: 'field1', type: FormFieldTypes.TEXT, required: true },
|
||||
{ id: 'field2', type: FormFieldTypes.TEXT, required: true }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
formModel = new FormModel(formJson);
|
||||
formComponent.form = formModel;
|
||||
field1 = formModel.getFieldById('field1');
|
||||
field2 = formModel.getFieldById('field2');
|
||||
});
|
||||
|
||||
it('should set flags on form and fields when enableParentVisibilityCheck changes from false to true', () => {
|
||||
formComponent.enableParentVisibilityCheck = false;
|
||||
expect(formModel.enableParentVisibilityCheck).toBe(false);
|
||||
expect(field1.checkParentVisibilityForValidation).toBe(false);
|
||||
expect(field2.checkParentVisibilityForValidation).toBe(false);
|
||||
|
||||
const change = new SimpleChange(false, true, false);
|
||||
formComponent.enableParentVisibilityCheck = true;
|
||||
spyOn(formModel, 'validateForm').and.stub();
|
||||
|
||||
formComponent.ngOnChanges({ enableParentVisibilityCheck: change });
|
||||
|
||||
expect(formModel.enableParentVisibilityCheck).toBe(true);
|
||||
expect(field1.checkParentVisibilityForValidation).toBe(true);
|
||||
expect(field2.checkParentVisibilityForValidation).toBe(true);
|
||||
expect(formModel.validateForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not set flags when enableParentVisibilityCheck changes but form is null', () => {
|
||||
formComponent.form = null;
|
||||
formComponent.enableParentVisibilityCheck = false;
|
||||
|
||||
const change = new SimpleChange(false, true, false);
|
||||
formComponent.ngOnChanges({ enableParentVisibilityCheck: change });
|
||||
|
||||
expect(formComponent.form).toBeNull();
|
||||
});
|
||||
|
||||
it('should reset flags when enableParentVisibilityCheck changes from true to false', () => {
|
||||
formModel.enableParentVisibilityCheck = true;
|
||||
field1.checkParentVisibilityForValidation = true;
|
||||
field2.checkParentVisibilityForValidation = true;
|
||||
formComponent.enableParentVisibilityCheck = false;
|
||||
|
||||
const change = new SimpleChange(true, false, false);
|
||||
spyOn(formModel, 'validateForm').and.stub();
|
||||
|
||||
formComponent.ngOnChanges({ enableParentVisibilityCheck: change });
|
||||
|
||||
expect(formModel.enableParentVisibilityCheck).toBe(false);
|
||||
expect(field1.checkParentVisibilityForValidation).toBe(false);
|
||||
expect(field2.checkParentVisibilityForValidation).toBe(false);
|
||||
expect(formModel.validateForm).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set flags on all fields including nested fields', () => {
|
||||
const formJsonWithNestedFields = {
|
||||
id: 'test-form',
|
||||
name: 'Test Form',
|
||||
fields: [
|
||||
{
|
||||
id: 'group1',
|
||||
type: FormFieldTypes.GROUP,
|
||||
numberOfColumns: 1,
|
||||
fields: {
|
||||
1: [{ id: 'field1', type: FormFieldTypes.TEXT }]
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'section1',
|
||||
type: FormFieldTypes.SECTION,
|
||||
numberOfColumns: 1,
|
||||
fields: {
|
||||
1: [
|
||||
{
|
||||
id: 'group2',
|
||||
type: FormFieldTypes.GROUP,
|
||||
numberOfColumns: 1,
|
||||
fields: {
|
||||
1: [{ id: 'field2', type: FormFieldTypes.TEXT }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{ id: 'field3', type: FormFieldTypes.TEXT }
|
||||
]
|
||||
};
|
||||
const nestedFormModel = new FormModel(formJsonWithNestedFields);
|
||||
formComponent.form = nestedFormModel;
|
||||
formComponent.enableParentVisibilityCheck = true;
|
||||
|
||||
const change = new SimpleChange(false, true, false);
|
||||
formComponent.ngOnChanges({ enableParentVisibilityCheck: change });
|
||||
|
||||
const allFields = nestedFormModel.getFormFields();
|
||||
allFields.forEach((field) => {
|
||||
expect(field.checkParentVisibilityForValidation).toBe(true);
|
||||
});
|
||||
expect(nestedFormModel.enableParentVisibilityCheck).toBe(true);
|
||||
});
|
||||
|
||||
it('should re-validate form after setting flags', () => {
|
||||
formComponent.enableParentVisibilityCheck = true;
|
||||
spyOn(formModel, 'validateForm').and.stub();
|
||||
|
||||
const change = new SimpleChange(false, true, false);
|
||||
formComponent.ngOnChanges({ enableParentVisibilityCheck: change });
|
||||
|
||||
expect(formModel.validateForm).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should complete form on custom outcome click', () => {
|
||||
const formModel = new FormModel();
|
||||
const outcomeName = 'Custom Action';
|
||||
|
||||
@@ -135,6 +135,13 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
@Input()
|
||||
customCompleteButtonText: string = '';
|
||||
|
||||
/**
|
||||
* Toggle to enable parent visibility check for validation.
|
||||
* When enabled, fields inside hidden groups/sections will skip validation.
|
||||
*/
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
|
||||
@Output()
|
||||
formSaved = new EventEmitter<FormModel>();
|
||||
@@ -254,6 +261,12 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
this.onFormLoaded(this.form);
|
||||
return;
|
||||
}
|
||||
|
||||
const enableParentVisibilityCheckChange = changes['enableParentVisibilityCheck'];
|
||||
if (enableParentVisibilityCheckChange && this.form) {
|
||||
this.setCheckParentVisibilityForValidationOnFields();
|
||||
this.form.validateForm();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -338,8 +351,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
|
||||
const parsedForm = this.parseForm(this.formCloudRepresentationJSON);
|
||||
this.visibilityService.refreshVisibility(parsedForm, this.data);
|
||||
parsedForm.validateForm();
|
||||
this.form = parsedForm;
|
||||
this.setCheckParentVisibilityForValidationOnFields();
|
||||
parsedForm.validateForm();
|
||||
this.form.nodeId = '-my-';
|
||||
this.onFormLoaded(this.form);
|
||||
resolve(this.form);
|
||||
@@ -369,8 +383,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
this.formCloudRepresentationJSON.processVariables = this.data || [];
|
||||
const parsedForm = this.parseForm(form);
|
||||
this.visibilityService.refreshVisibility(parsedForm);
|
||||
parsedForm?.validateForm();
|
||||
this.form = parsedForm;
|
||||
this.setCheckParentVisibilityForValidationOnFields();
|
||||
parsedForm?.validateForm();
|
||||
this.form.nodeId = '-my-';
|
||||
this.onFormLoaded(this.form);
|
||||
},
|
||||
@@ -467,11 +482,29 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
private refreshFormData() {
|
||||
this.form = this.parseForm(this.formCloudRepresentationJSON);
|
||||
if (this.form) {
|
||||
this.setCheckParentVisibilityForValidationOnFields();
|
||||
this.onFormLoaded(this.form);
|
||||
this.onFormDataRefreshed(this.form);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent visibility check flag on all form fields.
|
||||
* When enabled, fields inside hidden groups/sections will skip validation.
|
||||
* When disabled, resets flags to false to revert to default behavior.
|
||||
*/
|
||||
private setCheckParentVisibilityForValidationOnFields(): void {
|
||||
if (!this.form) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.form.enableParentVisibilityCheck = this.enableParentVisibilityCheck;
|
||||
const allFields = this.form.getFormFields();
|
||||
allFields.forEach((field) => {
|
||||
field.checkParentVisibilityForValidation = this.enableParentVisibilityCheck;
|
||||
});
|
||||
}
|
||||
|
||||
protected onFormLoaded(form: FormModel) {
|
||||
if (form) {
|
||||
this.displayModeConfigurations = this.displayModeService.getDisplayModeConfigurations(this.displayModeConfigurations);
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
[data]="resolvedValues"
|
||||
[formId]="processDefinitionCurrent.formKey"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
[showSaveButton]="showSaveButton"
|
||||
[showCompleteButton]="showCompleteButton"
|
||||
[showRefreshButton]="false"
|
||||
|
||||
@@ -21,6 +21,7 @@ import { FormModel, FormOutcomeEvent, FormOutcomeModel } from '@alfresco/adf-cor
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { StartProcessCloudService } from '../services/start-process-cloud.service';
|
||||
import { FormCloudService } from '../../../form/services/form-cloud.service';
|
||||
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
|
||||
import { StartProcessCloudComponent } from './start-process-cloud.component';
|
||||
import {
|
||||
fakeProcessDefinitions,
|
||||
@@ -629,6 +630,51 @@ describe('StartProcessCloudComponent', () => {
|
||||
expect(processForm).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck to adf-cloud-form', async () => {
|
||||
getProcessDefinitionsSpy.and.returnValue(of([fakeProcessDefinitions[2]]));
|
||||
formDefinitionSpy.and.returnValue(of(fakeStartForm));
|
||||
component.enableParentVisibilityCheck = true;
|
||||
const change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
await selectOptionByName('processwithform');
|
||||
|
||||
component.processDefinitionName = fakeProcessDefinitions[2].name;
|
||||
component.setProcessDefinitionOnForm(fakeProcessDefinitions[2].name);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const cloudFormElement = fixture.debugElement.query(By.css('adf-cloud-form'));
|
||||
expect(cloudFormElement).toBeDefined();
|
||||
const cloudFormComponent = cloudFormElement.componentInstance as FormCloudComponent;
|
||||
expect(cloudFormComponent).toBeDefined();
|
||||
expect(cloudFormComponent.enableParentVisibilityCheck).toBe(true);
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck as false by default to adf-cloud-form', async () => {
|
||||
getProcessDefinitionsSpy.and.returnValue(of([fakeProcessDefinitions[2]]));
|
||||
formDefinitionSpy.and.returnValue(of(fakeStartForm));
|
||||
const change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
await selectOptionByName('processwithform');
|
||||
|
||||
component.processDefinitionName = fakeProcessDefinitions[2].name;
|
||||
component.setProcessDefinitionOnForm(fakeProcessDefinitions[2].name);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const cloudFormElement = fixture.debugElement.query(By.css('adf-cloud-form'));
|
||||
expect(cloudFormElement).toBeDefined();
|
||||
const cloudFormComponent = cloudFormElement.componentInstance as FormCloudComponent;
|
||||
expect(cloudFormComponent).toBeDefined();
|
||||
expect(cloudFormComponent.enableParentVisibilityCheck).toBe(false);
|
||||
});
|
||||
|
||||
it('should not select automatically any processDefinition if the app contain multiple process and does not have any processDefinition as input', async () => {
|
||||
getProcessDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.appName = 'myApp';
|
||||
|
||||
@@ -142,6 +142,13 @@ export class StartProcessCloudComponent implements OnChanges, OnInit {
|
||||
@Input()
|
||||
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||
|
||||
/**
|
||||
* Toggle to enable parent visibility check for validation.
|
||||
* When enabled, fields inside hidden groups/sections will skip validation.
|
||||
*/
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Emitted when the process is successfully started. */
|
||||
@Output()
|
||||
success = new EventEmitter<ProcessInstanceCloud>();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
[customSaveButtonText]="customSaveButtonText"
|
||||
[customCompleteButtonText]="customCompleteButtonText"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
(formLoaded)="onFormLoaded($event)"
|
||||
(formSaved)="onFormSaved($event)"
|
||||
(formCompleted)="onFormCompleted($event)"
|
||||
|
||||
@@ -276,6 +276,31 @@ describe('TaskFormCloudComponent', () => {
|
||||
expect(cloudFormComponent).toBeDefined();
|
||||
expect(cloudFormComponent.customCompleteButtonText).toBe(customText);
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck to adf-cloud-form', () => {
|
||||
component.appName = 'app1';
|
||||
component.taskId = 'task1';
|
||||
component.enableParentVisibilityCheck = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const cloudFormElement = fixture.debugElement.query(By.css('adf-cloud-form'));
|
||||
expect(cloudFormElement).toBeDefined();
|
||||
const cloudFormComponent = cloudFormElement.componentInstance as FormCloudComponent;
|
||||
expect(cloudFormComponent).toBeDefined();
|
||||
expect(cloudFormComponent.enableParentVisibilityCheck).toBe(true);
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck as false by default to adf-cloud-form', () => {
|
||||
component.appName = 'app1';
|
||||
component.taskId = 'task1';
|
||||
fixture.detectChanges();
|
||||
|
||||
const cloudFormElement = fixture.debugElement.query(By.css('adf-cloud-form'));
|
||||
expect(cloudFormElement).toBeDefined();
|
||||
const cloudFormComponent = cloudFormElement.componentInstance as FormCloudComponent;
|
||||
expect(cloudFormComponent).toBeDefined();
|
||||
expect(cloudFormComponent.enableParentVisibilityCheck).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Events', () => {
|
||||
|
||||
@@ -107,6 +107,13 @@ export class TaskFormCloudComponent {
|
||||
@Input()
|
||||
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||
|
||||
/**
|
||||
* Toggle to enable parent visibility check for validation.
|
||||
* When enabled, fields inside hidden groups/sections will skip validation.
|
||||
*/
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Task details. */
|
||||
@Input()
|
||||
taskDetails: TaskDetailsCloudModel;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[candidateUsers]="candidateUsers"
|
||||
[candidateGroups]="candidateGroups"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
[showValidationIcon]="showValidationIcon"
|
||||
[showTitle]="showTitle"
|
||||
[taskId]="taskId"
|
||||
|
||||
@@ -736,6 +736,25 @@ describe('UserTaskCloudComponent', () => {
|
||||
|
||||
expect(taskFormComponent.customCompleteButtonText).toBe(customText);
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck to task form when task type is Form', () => {
|
||||
fixture.componentRef.setInput('enableParentVisibilityCheck', true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const taskFormElement = fixture.debugElement.query(By.css('adf-cloud-task-form'));
|
||||
const taskFormComponent = taskFormElement?.componentInstance as TaskFormCloudComponent;
|
||||
|
||||
expect(taskFormComponent.enableParentVisibilityCheck).toBe(true);
|
||||
});
|
||||
|
||||
it('should pass enableParentVisibilityCheck as false by default to task form', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
const taskFormElement = fixture.debugElement.query(By.css('adf-cloud-task-form'));
|
||||
const taskFormComponent = taskFormElement?.componentInstance as TaskFormCloudComponent;
|
||||
|
||||
expect(taskFormComponent.enableParentVisibilityCheck).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -67,6 +67,13 @@ export class UserTaskCloudComponent implements OnInit, OnChanges {
|
||||
@Input()
|
||||
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||
|
||||
/**
|
||||
* Toggle to enable parent visibility check for validation.
|
||||
* When enabled, fields inside hidden groups/sections will skip validation.
|
||||
*/
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Toggle readonly state of the task. */
|
||||
@Input()
|
||||
readOnly = false;
|
||||
|
||||
Reference in New Issue
Block a user