mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-6093] - fixed rest option for cloud widget (#7304)
* [AAE-6093] - fixed rest option for cloud widget * [AAE-6093] - reverted app config change * [AAE-6093] - fixed naming * [AAE-6093] - fixed radio button complete task and added support for rest url with the new feature * [AAE-6093] - removed test value * [AAE-6093] - fixed lint * [AAE-6093] - fixed lint * [AAE-6093] - merged fix for dropdown
This commit is contained in:
@@ -691,6 +691,98 @@ describe('FormFieldModel', () => {
|
|||||||
expect(form.values['dropdown_field'].name).toEqual('Option 1');
|
expect(form.values['dropdown_field'].name).toEqual('Option 1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('dropdown field type should be formatted on rest properties', () => {
|
||||||
|
const form = new FormModel();
|
||||||
|
const field = new FormFieldModel(form, {
|
||||||
|
fieldType: 'HeaderFieldtype',
|
||||||
|
id: 'dropdown_field',
|
||||||
|
name: 'header',
|
||||||
|
type: FormFieldTypes.DROPDOWN,
|
||||||
|
value: 'opt1',
|
||||||
|
required: false,
|
||||||
|
readOnly: true,
|
||||||
|
restUrl: 'fake-url-just-to-show',
|
||||||
|
optionType: 'rest',
|
||||||
|
restIdProperty: 'fake-id-property',
|
||||||
|
restLabelProperty: 'fake-label-property',
|
||||||
|
options: [
|
||||||
|
{id: 'opt1', name: 'Option 1'},
|
||||||
|
{id: 'opt2', name: 'Option 2'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
field.updateForm();
|
||||||
|
expect(form.values['dropdown_field']['fake-id-property']).toEqual('opt1');
|
||||||
|
expect(form.values['dropdown_field']['fake-label-property']).toEqual('Option 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dropdown field type should be formatted on id and name properties if rest properties are not set', () => {
|
||||||
|
const form = new FormModel();
|
||||||
|
const field = new FormFieldModel(form, {
|
||||||
|
fieldType: 'HeaderFieldtype',
|
||||||
|
id: 'dropdown_field',
|
||||||
|
name: 'header',
|
||||||
|
type: FormFieldTypes.DROPDOWN,
|
||||||
|
value: 'opt1',
|
||||||
|
required: false,
|
||||||
|
readOnly: true,
|
||||||
|
restUrl: 'fake-url-just-to-show',
|
||||||
|
optionType: 'rest',
|
||||||
|
options: [
|
||||||
|
{id: 'opt1', name: 'Option 1'},
|
||||||
|
{id: 'opt2', name: 'Option 2'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
field.updateForm();
|
||||||
|
expect(form.values['dropdown_field']['id']).toEqual('opt1');
|
||||||
|
expect(form.values['dropdown_field']['name']).toEqual('Option 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('radio button field rest type should appear with its configured label and id into the rest values', () => {
|
||||||
|
const form = new FormModel();
|
||||||
|
const field = new FormFieldModel(form, {
|
||||||
|
fieldType: 'HeaderFieldtype',
|
||||||
|
id: 'radio_bananan_field',
|
||||||
|
name: 'banana',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
value: 'opt1',
|
||||||
|
required: false,
|
||||||
|
readOnly: true,
|
||||||
|
restUrl: '<whatever-url-you-like-we-do-not-mind>',
|
||||||
|
restIdProperty: 'banana',
|
||||||
|
restLabelProperty: 'banLabel',
|
||||||
|
optionType: 'rest',
|
||||||
|
options: [
|
||||||
|
{id: 'opt1', name: 'Option 1'},
|
||||||
|
{id: 'opt2', name: 'Option 2'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
field.updateForm();
|
||||||
|
expect(form.values['radio_bananan_field']['banana']).toEqual('opt1');
|
||||||
|
expect(form.values['radio_bananan_field']['banLabel']).toEqual('Option 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('radio button field rest type should appear with id / name properties when rest properties are not configured', () => {
|
||||||
|
const form = new FormModel();
|
||||||
|
const field = new FormFieldModel(form, {
|
||||||
|
fieldType: 'HeaderFieldtype',
|
||||||
|
id: 'radio_bananan_field',
|
||||||
|
name: 'banana',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
value: 'opt1',
|
||||||
|
required: false,
|
||||||
|
readOnly: true,
|
||||||
|
restUrl: '<whatever-url-you-like-we-do-not-mind>',
|
||||||
|
optionType: 'rest',
|
||||||
|
options: [
|
||||||
|
{id: 'opt1', name: 'Option 1'},
|
||||||
|
{id: 'opt2', name: 'Option 2'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
field.updateForm();
|
||||||
|
expect(form.values['radio_bananan_field']['id']).toEqual('opt1');
|
||||||
|
expect(form.values['radio_bananan_field']['name']).toEqual('Option 1');
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse and resolve people null value as null', () => {
|
it('should parse and resolve people null value as null', () => {
|
||||||
const field = new FormFieldModel(new FormModel(), {
|
const field = new FormFieldModel(new FormModel(), {
|
||||||
type: FormFieldTypes.PEOPLE,
|
type: FormFieldTypes.PEOPLE,
|
||||||
|
@@ -62,7 +62,7 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
restLabelProperty: string;
|
restLabelProperty: string;
|
||||||
hasEmptyValue: boolean;
|
hasEmptyValue: boolean;
|
||||||
className: string;
|
className: string;
|
||||||
optionType: string;
|
optionType: 'rest' | 'manual' ;
|
||||||
params: FormFieldMetadata = {};
|
params: FormFieldMetadata = {};
|
||||||
hyperlinkUrl: string;
|
hyperlinkUrl: string;
|
||||||
displayText: string;
|
displayText: string;
|
||||||
@@ -372,18 +372,14 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
|
|
||||||
const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
|
const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
|
||||||
if (entry.length > 0) {
|
if (entry.length > 0) {
|
||||||
this.form.values[this.id] = entry[0];
|
this.setFormFieldValueOption(entry[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormFieldTypes.RADIO_BUTTONS:
|
case FormFieldTypes.RADIO_BUTTONS:
|
||||||
/*
|
|
||||||
This is needed due to Activiti issue related to reading radio button values as value string
|
|
||||||
but saving back as object: { id: <id>, name: <name> }
|
|
||||||
*/
|
|
||||||
const radioButton: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
|
const radioButton: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value);
|
||||||
if (radioButton.length > 0) {
|
if (radioButton.length > 0) {
|
||||||
this.form.values[this.id] = radioButton[0];
|
this.setFormFieldValueOption(radioButton[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormFieldTypes.UPLOAD:
|
case FormFieldTypes.UPLOAD:
|
||||||
@@ -491,4 +487,17 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
json.type === FormFieldTypes.BOOLEAN;
|
json.type === FormFieldTypes.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setFormFieldValueOption(option: FormFieldOption ) {
|
||||||
|
if (this.optionType === 'rest' && !!this.restUrl) {
|
||||||
|
const restEntry = {};
|
||||||
|
const restIdProperty = this.restIdProperty || 'id';
|
||||||
|
const restLabelProperty = this.restLabelProperty || 'name';
|
||||||
|
restEntry[restIdProperty] = option.id;
|
||||||
|
restEntry[restLabelProperty] = option.name;
|
||||||
|
this.form.values[this.id] = restEntry;
|
||||||
|
} else {
|
||||||
|
this.form.values[this.id] = option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import { DateCloudWidgetComponent } from './widgets/date/date-cloud.widget';
|
|||||||
import { PeopleCloudWidgetComponent } from './widgets/people/people-cloud.widget';
|
import { PeopleCloudWidgetComponent } from './widgets/people/people-cloud.widget';
|
||||||
import { GroupCloudWidgetComponent } from './widgets/group/group-cloud.widget';
|
import { GroupCloudWidgetComponent } from './widgets/group/group-cloud.widget';
|
||||||
import { PropertiesViewerWidgetComponent } from './widgets/properties-viewer/properties-viewer.widget';
|
import { PropertiesViewerWidgetComponent } from './widgets/properties-viewer/properties-viewer.widget';
|
||||||
|
import { RadioButtonsCloudWidgetComponent } from './widgets/radio-buttons/radio-buttons-cloud.widget';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -37,7 +38,8 @@ export class CloudFormRenderingService extends FormRenderingService {
|
|||||||
'date': () => DateCloudWidgetComponent,
|
'date': () => DateCloudWidgetComponent,
|
||||||
'people': () => PeopleCloudWidgetComponent,
|
'people': () => PeopleCloudWidgetComponent,
|
||||||
'functional-group': () => GroupCloudWidgetComponent,
|
'functional-group': () => GroupCloudWidgetComponent,
|
||||||
'properties-viewer': () => PropertiesViewerWidgetComponent
|
'properties-viewer': () => PropertiesViewerWidgetComponent,
|
||||||
|
'radio-buttons': () => RadioButtonsCloudWidgetComponent
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -146,7 +146,7 @@ describe('DropdownCloudWidgetComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should load data from restUrl and populate options', async () => {
|
it('should load data from restUrl and populate options', async () => {
|
||||||
const jsonDataSpy = spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of(fakeOptionList));
|
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of(fakeOptionList));
|
||||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||||
id: 'dropdown-id',
|
id: 'dropdown-id',
|
||||||
name: 'date-name',
|
name: 'date-name',
|
||||||
@@ -166,9 +166,9 @@ describe('DropdownCloudWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
const optOne = fixture.debugElement.queryAll(By.css('[id="option_1"]'));
|
const optOne = fixture.debugElement.queryAll(By.css('[id="opt_1"]'));
|
||||||
const optTwo = fixture.debugElement.queryAll(By.css('[id="option_2"]'));
|
const optTwo = fixture.debugElement.queryAll(By.css('[id="opt_2"]'));
|
||||||
const optThree = fixture.debugElement.queryAll(By.css('[id="option_3"]'));
|
const optThree = fixture.debugElement.queryAll(By.css('[id="opt_3"]'));
|
||||||
const allOptions = fixture.debugElement.queryAll(By.css('mat-option'));
|
const allOptions = fixture.debugElement.queryAll(By.css('mat-option'));
|
||||||
|
|
||||||
expect(jsonDataSpy).toHaveBeenCalled();
|
expect(jsonDataSpy).toHaveBeenCalled();
|
||||||
@@ -195,7 +195,7 @@ describe('DropdownCloudWidgetComponent', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of([
|
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
|
||||||
{
|
{
|
||||||
id: 'opt1',
|
id: 'opt1',
|
||||||
name: 'default1_value'
|
name: 'default1_value'
|
||||||
@@ -230,7 +230,7 @@ describe('DropdownCloudWidgetComponent', () => {
|
|||||||
value: 'opt1'
|
value: 'opt1'
|
||||||
});
|
});
|
||||||
|
|
||||||
spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of([
|
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
|
||||||
{
|
{
|
||||||
id: 'opt1',
|
id: 'opt1',
|
||||||
name: 'default1_value'
|
name: 'default1_value'
|
||||||
@@ -265,98 +265,11 @@ describe('DropdownCloudWidgetComponent', () => {
|
|||||||
restResponsePath: 'path'
|
restResponsePath: 'path'
|
||||||
});
|
});
|
||||||
|
|
||||||
const dropdownSpy = spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of({
|
const dropdownSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of( [
|
||||||
id: 1,
|
|
||||||
path: [
|
|
||||||
{ id: 'opt_1', name: 'option_1' },
|
{ id: 'opt_1', name: 'option_1' },
|
||||||
{ id: 'opt_2', name: 'option_2' },
|
{ id: 'opt_2', name: 'option_2' },
|
||||||
{ id: 'opt_3', name: 'option_3' }],
|
{ id: 'opt_3', name: 'option_3' }]
|
||||||
name: ''
|
));
|
||||||
}));
|
|
||||||
|
|
||||||
widget.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
openSelect('#dropdown-id');
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
expect(dropdownSpy).toHaveBeenCalled();
|
|
||||||
|
|
||||||
const optOne: any = fixture.debugElement.queryAll(By.css('[id="opt_1"]'));
|
|
||||||
expect(optOne[0].context.value).toBe('opt_1');
|
|
||||||
expect(optOne[0].context.viewValue).toBe('option_1');
|
|
||||||
const optTwo: any = fixture.debugElement.queryAll(By.css('[id="opt_2"]'));
|
|
||||||
expect(optTwo[0].context.value).toBe('opt_2');
|
|
||||||
expect(optTwo[0].context.viewValue).toBe('option_2');
|
|
||||||
const optThree: any = fixture.debugElement.queryAll(By.css('[id="opt_3"]'));
|
|
||||||
expect(optThree[0].context.value).toBe('opt_3');
|
|
||||||
expect(optThree[0].context.viewValue).toBe('option_3');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should map correct label if restLabelProperty is set', (done) => {
|
|
||||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
|
||||||
id: 'dropdown-id',
|
|
||||||
name: 'date-name',
|
|
||||||
type: 'dropdown-cloud',
|
|
||||||
readOnly: 'false',
|
|
||||||
restUrl: 'fake-rest-url',
|
|
||||||
optionType: 'rest',
|
|
||||||
restResponsePath: 'path',
|
|
||||||
restLabelProperty: 'first_name'
|
|
||||||
});
|
|
||||||
|
|
||||||
const dropdownSpy = spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of({
|
|
||||||
id: 1,
|
|
||||||
path: [
|
|
||||||
{ id: 'opt_1', first_name: 'option_1' },
|
|
||||||
{ id: 'opt_2', first_name: 'option_2' },
|
|
||||||
{ id: 'opt_3', first_name: 'option_3' }],
|
|
||||||
name: ''
|
|
||||||
}));
|
|
||||||
|
|
||||||
widget.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
openSelect('#dropdown-id');
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
expect(dropdownSpy).toHaveBeenCalled();
|
|
||||||
|
|
||||||
const optOne: any = fixture.debugElement.queryAll(By.css('[id="opt_1"]'));
|
|
||||||
expect(optOne[0].context.value).toBe('opt_1');
|
|
||||||
expect(optOne[0].context.viewValue).toBe('option_1');
|
|
||||||
const optTwo: any = fixture.debugElement.queryAll(By.css('[id="opt_2"]'));
|
|
||||||
expect(optTwo[0].context.value).toBe('opt_2');
|
|
||||||
expect(optTwo[0].context.viewValue).toBe('option_2');
|
|
||||||
const optThree: any = fixture.debugElement.queryAll(By.css('[id="opt_3"]'));
|
|
||||||
expect(optThree[0].context.value).toBe('opt_3');
|
|
||||||
expect(optThree[0].context.viewValue).toBe('option_3');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should map correct id if restIdProperty is set', (done) => {
|
|
||||||
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
|
||||||
id: 'dropdown-id',
|
|
||||||
name: 'date-name',
|
|
||||||
type: 'dropdown-cloud',
|
|
||||||
readOnly: 'false',
|
|
||||||
restUrl: 'fake-rest-url',
|
|
||||||
optionType: 'rest',
|
|
||||||
restResponsePath: 'path',
|
|
||||||
restIdProperty: 'my_id'
|
|
||||||
});
|
|
||||||
|
|
||||||
const dropdownSpy = spyOn(formCloudService, 'getDropDownJsonData').and.returnValue(of({
|
|
||||||
id: 1,
|
|
||||||
path: [
|
|
||||||
{ my_id: 'opt_1', name: 'option_1' },
|
|
||||||
{ my_id: 'opt_2', name: 'option_2' },
|
|
||||||
{ my_id: 'opt_3', name: 'option_3' }],
|
|
||||||
name: ''
|
|
||||||
}));
|
|
||||||
|
|
||||||
widget.ngOnInit();
|
widget.ngOnInit();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@@ -59,27 +59,14 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
|
|||||||
|
|
||||||
getValuesFromRestApi() {
|
getValuesFromRestApi() {
|
||||||
if (this.isValidRestType()) {
|
if (this.isValidRestType()) {
|
||||||
this.formCloudService.getDropDownJsonData(this.field.restUrl)
|
this.formCloudService.getRestWidgetData(this.field.form.id, this.field.id)
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
.subscribe((result: FormFieldOption[]) => {
|
.subscribe((result: FormFieldOption[]) => {
|
||||||
this.field.options = this.mapJsonData(result);
|
this.field.options = result;
|
||||||
}, (err) => this.handleError(err));
|
}, (err) => this.handleError(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapJsonData(data: any[]): FormFieldOption[] {
|
|
||||||
const dataToMap: any[] = this.field.restResponsePath ? data[this.field.restResponsePath] : data;
|
|
||||||
const idProperty = this.field.restIdProperty || 'id';
|
|
||||||
const restLabelProperty = this.field.restLabelProperty || 'name';
|
|
||||||
|
|
||||||
return dataToMap.map((value: any) => {
|
|
||||||
return {
|
|
||||||
name: value[restLabelProperty],
|
|
||||||
id: value[idProperty]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
|
compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
|
||||||
if (!opt1 || !opt2) {
|
if (!opt1 || !opt2) {
|
||||||
return false;
|
return false;
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
<div class="adf-radio-buttons-widget-cloud {{field.className}}"
|
||||||
|
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" [id]="field.id">
|
||||||
|
<div class="adf-radio-button-container">
|
||||||
|
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span *ngIf="isRequired()">*</span></label>
|
||||||
|
<mat-radio-group class="adf-radio-group" [(ngModel)]="field.value" [disabled]="field.readOnly">
|
||||||
|
<mat-radio-button
|
||||||
|
[matTooltip]="field.tooltip"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
matTooltipShowDelay="1000"
|
||||||
|
[id]="field.id + '-' + opt.id"
|
||||||
|
[name]="field.id"
|
||||||
|
[value]="opt.id"
|
||||||
|
[checked]="field.value === opt.id"
|
||||||
|
(change)="onOptionClick(opt.id)"
|
||||||
|
color="primary"
|
||||||
|
class="adf-radio-button" *ngFor="let opt of field.options" >
|
||||||
|
{{opt.name}}
|
||||||
|
</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
</div>
|
||||||
|
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||||
|
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||||
|
</div>
|
@@ -0,0 +1,20 @@
|
|||||||
|
.adf {
|
||||||
|
|
||||||
|
&-radio-button-container {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-radio-group {
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-left: 5px;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-radio-button {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,177 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AlfrescoApiService, CoreTestingModule, FormFieldModel, FormFieldOption, FormFieldTypes, FormModel, FormService, setupTestBed } from 'core';
|
||||||
|
import { FormCloudService } from 'process-services-cloud';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { RadioButtonsCloudWidgetComponent } from './radio-buttons-cloud.widget';
|
||||||
|
|
||||||
|
describe('RadioButtonsCloudWidgetComponent', () => {
|
||||||
|
|
||||||
|
let formService: FormService;
|
||||||
|
let formCloudService: FormCloudService;
|
||||||
|
let widget: RadioButtonsCloudWidgetComponent;
|
||||||
|
let alfrescoApiService: AlfrescoApiService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
CoreTestingModule,
|
||||||
|
MatRadioModule,
|
||||||
|
FormsModule,
|
||||||
|
MatIconModule
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||||
|
|
||||||
|
formService = new FormService(null, alfrescoApiService, null);
|
||||||
|
formCloudService = new FormCloudService(alfrescoApiService, null);
|
||||||
|
widget = new RadioButtonsCloudWidgetComponent(formService, formCloudService, null);
|
||||||
|
widget.field = new FormFieldModel(new FormModel(), { restUrl: '<url>' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update form on values fetched', () => {
|
||||||
|
const taskId = '<form-id>';
|
||||||
|
const fieldId = '<field-id>';
|
||||||
|
|
||||||
|
const form = new FormModel({
|
||||||
|
taskId: taskId
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.field = new FormFieldModel(form, {
|
||||||
|
id: fieldId,
|
||||||
|
restUrl: '<url>'
|
||||||
|
});
|
||||||
|
const field = widget.field;
|
||||||
|
spyOn(field, 'updateForm').and.stub();
|
||||||
|
|
||||||
|
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(new Observable((observer) => {
|
||||||
|
observer.next(null);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
widget.ngOnInit();
|
||||||
|
expect(field.updateForm).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the field value when an option is selected', () => {
|
||||||
|
spyOn(widget, 'onFieldChanged').and.stub();
|
||||||
|
widget.onOptionClick('fake-opt');
|
||||||
|
|
||||||
|
expect(widget.field.value).toEqual('fake-opt');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when template is ready', () => {
|
||||||
|
let radioButtonWidget: RadioButtonsCloudWidgetComponent;
|
||||||
|
let fixture: ComponentFixture<RadioButtonsCloudWidgetComponent>;
|
||||||
|
let element: HTMLElement;
|
||||||
|
const restOption: FormFieldOption[] = [
|
||||||
|
{
|
||||||
|
id: 'opt-1',
|
||||||
|
name: 'opt-name-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'opt-2',
|
||||||
|
name: 'opt-name-2'
|
||||||
|
}];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RadioButtonsCloudWidgetComponent);
|
||||||
|
radioButtonWidget = fixture.componentInstance;
|
||||||
|
element = fixture.nativeElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show radio buttons as text when is readonly', async () => {
|
||||||
|
radioButtonWidget.field = new FormFieldModel(new FormModel({}), {
|
||||||
|
id: 'radio-id',
|
||||||
|
name: 'radio-name',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
readOnly: true
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(element.querySelector('display-text-widget')).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to set label property for Radio Button widget', () => {
|
||||||
|
radioButtonWidget.field = new FormFieldModel(new FormModel({}), {
|
||||||
|
id: 'radio-id',
|
||||||
|
name: 'radio-name-label',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
readOnly: true
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(element.querySelector('label').innerText).toBe('radio-name-label');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to set a Radio Button widget as required', async () => {
|
||||||
|
radioButtonWidget.field = new FormFieldModel(new FormModel({}), {
|
||||||
|
id: 'radio-id',
|
||||||
|
name: 'radio-name-label',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
readOnly: false,
|
||||||
|
required: true,
|
||||||
|
optionType: 'manual',
|
||||||
|
options: restOption,
|
||||||
|
restUrl: null
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const widgetLabel = element.querySelector('label');
|
||||||
|
expect(widgetLabel.innerText).toBe('radio-name-label*');
|
||||||
|
expect(radioButtonWidget.field.isValid).toBe(false);
|
||||||
|
|
||||||
|
const option: HTMLElement = <HTMLElement> element.querySelector('#radio-id-opt-1 label');
|
||||||
|
option.click();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const selectedOption: HTMLElement = <HTMLElement> element.querySelector('[class*="mat-radio-checked"]');
|
||||||
|
expect(selectedOption.innerText).toBe('opt-name-1');
|
||||||
|
expect(radioButtonWidget.field.isValid).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to set a Radio Button widget as required', () => {
|
||||||
|
radioButtonWidget.field = new FormFieldModel(new FormModel({}), {
|
||||||
|
id: 'radio-id',
|
||||||
|
name: 'radio-name-label',
|
||||||
|
type: FormFieldTypes.RADIO_BUTTONS,
|
||||||
|
readOnly: false,
|
||||||
|
required: true,
|
||||||
|
optionType: 'manual',
|
||||||
|
options: restOption,
|
||||||
|
restUrl: null,
|
||||||
|
value: 'opt-name-2'
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
const selectedOption: HTMLElement = <HTMLElement> element.querySelector('[class*="mat-radio-checked"]');
|
||||||
|
expect(selectedOption.innerText).toBe('opt-name-2');
|
||||||
|
expect(radioButtonWidget.field.isValid).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,78 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable:component-selector */
|
||||||
|
|
||||||
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { WidgetComponent, FormService, LogService, FormFieldOption } from '@alfresco/adf-core';
|
||||||
|
import { FormCloudService } from '../../../services/form-cloud.service';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'radio-buttons-cloud-widget',
|
||||||
|
templateUrl: './radio-buttons-cloud.widget.html',
|
||||||
|
styleUrls: ['./radio-buttons-cloud.widget.scss'],
|
||||||
|
host: {
|
||||||
|
'(click)': 'event($event)',
|
||||||
|
'(blur)': 'event($event)',
|
||||||
|
'(change)': 'event($event)',
|
||||||
|
'(focus)': 'event($event)',
|
||||||
|
'(focusin)': 'event($event)',
|
||||||
|
'(focusout)': 'event($event)',
|
||||||
|
'(input)': 'event($event)',
|
||||||
|
'(invalid)': 'event($event)',
|
||||||
|
'(select)': 'event($event)'
|
||||||
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class RadioButtonsCloudWidgetComponent extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
|
typeId = 'RadioButtonsCloudWidgetComponent';
|
||||||
|
protected onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
constructor(public formService: FormService,
|
||||||
|
private formCloudService: FormCloudService,
|
||||||
|
private logService: LogService) {
|
||||||
|
super(formService);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.field && this.field.restUrl) {
|
||||||
|
this.getValuesFromRestApi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getValuesFromRestApi() {
|
||||||
|
this.formCloudService.getRestWidgetData(this.field.form.id, this.field.id)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe((result: FormFieldOption[]) => {
|
||||||
|
this.field.options = result;
|
||||||
|
this.field.updateForm();
|
||||||
|
}, (err) => this.handleError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
onOptionClick(optionSelected: any) {
|
||||||
|
this.field.value = optionSelected;
|
||||||
|
this.fieldChanged.emit(this.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(error: any) {
|
||||||
|
this.logService.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -37,6 +37,7 @@ import { PeopleCloudModule } from '../people/people-cloud.module';
|
|||||||
import { GroupCloudModule } from '../group/group-cloud.module';
|
import { GroupCloudModule } from '../group/group-cloud.module';
|
||||||
import { PropertiesViewerWidgetComponent } from './components/widgets/properties-viewer/properties-viewer.widget';
|
import { PropertiesViewerWidgetComponent } from './components/widgets/properties-viewer/properties-viewer.widget';
|
||||||
import { PropertiesViewerWrapperComponent } from './components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer-wrapper.component';
|
import { PropertiesViewerWrapperComponent } from './components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer-wrapper.component';
|
||||||
|
import { RadioButtonsCloudWidgetComponent } from './components/widgets/radio-buttons/radio-buttons-cloud.widget';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -57,6 +58,7 @@ import { PropertiesViewerWrapperComponent } from './components/widgets/propertie
|
|||||||
FormDefinitionSelectorCloudComponent,
|
FormDefinitionSelectorCloudComponent,
|
||||||
FormCustomOutcomesComponent,
|
FormCustomOutcomesComponent,
|
||||||
DropdownCloudWidgetComponent,
|
DropdownCloudWidgetComponent,
|
||||||
|
RadioButtonsCloudWidgetComponent,
|
||||||
AttachFileCloudWidgetComponent,
|
AttachFileCloudWidgetComponent,
|
||||||
DateCloudWidgetComponent,
|
DateCloudWidgetComponent,
|
||||||
PeopleCloudWidgetComponent,
|
PeopleCloudWidgetComponent,
|
||||||
@@ -70,6 +72,7 @@ import { PropertiesViewerWrapperComponent } from './components/widgets/propertie
|
|||||||
FormDefinitionSelectorCloudComponent,
|
FormDefinitionSelectorCloudComponent,
|
||||||
FormCustomOutcomesComponent,
|
FormCustomOutcomesComponent,
|
||||||
DropdownCloudWidgetComponent,
|
DropdownCloudWidgetComponent,
|
||||||
|
RadioButtonsCloudWidgetComponent,
|
||||||
AttachFileCloudWidgetComponent,
|
AttachFileCloudWidgetComponent,
|
||||||
DateCloudWidgetComponent,
|
DateCloudWidgetComponent,
|
||||||
PeopleCloudWidgetComponent,
|
PeopleCloudWidgetComponent,
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { UploadApi } from '@alfresco/js-api';
|
import { UploadApi } from '@alfresco/js-api';
|
||||||
import { FormModel, FormValues } from '@alfresco/adf-core';
|
import { FormFieldOption, FormModel, FormValues } from '@alfresco/adf-core';
|
||||||
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
|
||||||
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
|
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
|
||||||
import { FormContent } from '../../services/form-fields.interfaces';
|
import { FormContent } from '../../services/form-fields.interfaces';
|
||||||
@@ -33,6 +33,6 @@ export interface FormCloudServiceInterface {
|
|||||||
getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel>;
|
getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel>;
|
||||||
getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]>;
|
getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]>;
|
||||||
getForm(appName: string, formKey: string, version?: number): Observable<FormContent>;
|
getForm(appName: string, formKey: string, version?: number): Observable<FormContent>;
|
||||||
getDropDownJsonData(url: string): Observable<any>;
|
|
||||||
parseForm(json: any, data?: TaskVariableCloud[], readOnly?: boolean): FormModel;
|
parseForm(json: any, data?: TaskVariableCloud[], readOnly?: boolean): FormModel;
|
||||||
|
getRestWidgetData(formName: string, widgetId: string, body: Map<String, String>): Observable<FormFieldOption[]>;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,8 @@ import {
|
|||||||
FormValues,
|
FormValues,
|
||||||
AppConfigService,
|
AppConfigService,
|
||||||
FormOutcomeModel,
|
FormOutcomeModel,
|
||||||
FormModel
|
FormModel,
|
||||||
|
FormFieldOption
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { Observable, from } from 'rxjs';
|
import { Observable, from } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
@@ -191,13 +192,10 @@ export class FormCloudService extends BaseCloudService implements FormCloudServi
|
|||||||
return this.get(url);
|
return this.get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getRestWidgetData(formName: string, widgetId: string, body: any = {}): Observable<FormFieldOption[]> {
|
||||||
* Parses JSON data to create a corresponding form.
|
const appName = this.appConfigService.get('alfresco-deployed-apps')[0]?.name;
|
||||||
* @param url String data to make the request
|
const apiUrl = `${this.getBasePath(appName)}/form/v1/forms/${formName}/values/${widgetId}`;
|
||||||
* @returns Array of FormFieldOption object
|
return this.post(apiUrl, body);
|
||||||
*/
|
|
||||||
getDropDownJsonData(url: string): Observable<any> {
|
|
||||||
return this.get<any>(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user