[AAE-1152] Making sure the people and group widget is working fine as part of form (#5322)

* Making sure the people and group widget is working fine as part of the form

* Be able to save a form with people and group

* Fix tslint

* Fix html error

* Fix unit test
This commit is contained in:
Maurizio Vitale
2019-12-11 11:22:50 +00:00
committed by Eugenio Romano
parent d8b703b6ef
commit 88d89b4ca8
10 changed files with 98 additions and 55 deletions

View File

@@ -55,6 +55,7 @@ export class FormFieldModel extends FormWidgetModel {
regexPattern: string; regexPattern: string;
options: FormFieldOption[] = []; options: FormFieldOption[] = [];
restUrl: string; restUrl: string;
roles: string[];
restResponsePath: string; restResponsePath: string;
restIdProperty: string; restIdProperty: string;
restLabelProperty: string; restLabelProperty: string;
@@ -79,11 +80,6 @@ export class FormFieldModel extends FormWidgetModel {
emptyOption: FormFieldOption; emptyOption: FormFieldOption;
validationSummary: ErrorMessageModel; validationSummary: ErrorMessageModel;
// People and Group Options
appName: string;
roles: string[];
mode: string;
get value(): any { get value(): any {
return this._value; return this._value;
} }
@@ -145,6 +141,8 @@ export class FormFieldModel extends FormWidgetModel {
this.id = json.id; this.id = json.id;
this.name = json.name; this.name = json.name;
this.type = json.type; this.type = json.type;
this.roles = json.roles;
this.optionType = json.optionType;
this._required = <boolean> json.required; this._required = <boolean> json.required;
this._readOnly = <boolean> json.readOnly || json.type === 'readonly'; this._readOnly = <boolean> json.readOnly || json.type === 'readonly';
this.overrideId = <boolean> json.overrideId; this.overrideId = <boolean> json.overrideId;
@@ -173,11 +171,6 @@ export class FormFieldModel extends FormWidgetModel {
this._value = this.parseValue(json); this._value = this.parseValue(json);
this.validationSummary = new ErrorMessageModel(); this.validationSummary = new ErrorMessageModel();
// People and Group Options
this.appName = json.appName;
this.roles = json.roles;
this.mode = json.mode;
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') { if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
this.placeholder = json.placeholder; this.placeholder = json.placeholder;
} }
@@ -403,6 +396,12 @@ export class FormFieldModel extends FormWidgetModel {
case FormFieldTypes.BOOLEAN: case FormFieldTypes.BOOLEAN:
this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : false; this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : false;
break; break;
case FormFieldTypes.PEOPLE:
this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : [];
break;
case FormFieldTypes.FUNCTIONAL_GROUP:
this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : [];
break;
default: default:
if (!FormFieldTypes.isReadOnlyType(this.type) && !this.isInvalidFieldType(this.type)) { if (!FormFieldTypes.isReadOnlyType(this.type) && !this.isInvalidFieldType(this.type)) {
this.form.values[this.id] = this.value; this.form.values[this.id] = this.value;

View File

@@ -34,8 +34,6 @@ import {
groupsMockApi, groupsMockApi,
roleMappingApi, roleMappingApi,
clientRoles, clientRoles,
returnCallQueryParameters,
returnCallUrl,
applicationDetailsMockApi, applicationDetailsMockApi,
mockApiError, mockApiError,
mockIdentityGroup1, mockIdentityGroup1,
@@ -233,22 +231,14 @@ describe('IdentityGroupService', () => {
); );
}); });
it('should append to the call all the parameters', (done) => { it('should return only the properties of IdentityGroupSearchParam', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(returnCallQueryParameters); spyOn(apiService, 'getInstance').and.returnValue(groupsMockApi);
service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((res) => { service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((groups) => {
expect(res).toBeDefined(); expect(groups).toBeDefined();
expect(res).not.toBeNull(); expect(groups).toBeDefined();
expect(res.search).toBe('mock'); expect(groups[0].id).toEqual('mock-group-id-1');
done(); expect(groups[0].name).toEqual('Mock Group 1');
}); expect(groups[0]['subGroups']).not.toBeDefined();
});
it('should request groups api url', (done) => {
spyOn(apiService, 'getInstance').and.returnValue(returnCallUrl);
service.findGroupsByName(<IdentityGroupSearchParam> {name: 'mock'}).subscribe((requestUrl) => {
expect(requestUrl).toBeDefined();
expect(requestUrl).not.toBeNull();
expect(requestUrl).toContain('/groups');
done(); done();
}); });
}); });

View File

@@ -173,7 +173,7 @@ export class IdentityGroupService {
* @param searchParams Object containing the name filter string * @param searchParams Object containing the name filter string
* @returns List of group information * @returns List of group information
*/ */
findGroupsByName(searchParams: IdentityGroupSearchParam): Observable<any> { findGroupsByName(searchParams: IdentityGroupSearchParam): Observable<IdentityGroupModel[]> {
if (searchParams.name === '') { if (searchParams.name === '') {
return of([]); return of([]);
} }
@@ -181,12 +181,17 @@ export class IdentityGroupService {
const httpMethod = 'GET', pathParams = {}, queryParams = {search: searchParams.name}, bodyParam = {}, headerParams = {}, const httpMethod = 'GET', pathParams = {}, queryParams = {search: searchParams.name}, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams, url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null) contentTypes, accepts, Object, null, null)
)).pipe( ).pipe(
catchError((error) => this.handleError(error)) map((response: []) => {
return response.map( (group: IdentityGroupModel) => {
return {id: group.id, name: group.name};
});
}),
catchError((err) => this.handleError(err))
); );
} }

View File

@@ -78,7 +78,7 @@ export class IdentityUserService {
* @param search Search query string * @param search Search query string
* @returns List of users * @returns List of users
*/ */
findUsersByName(search: string): Observable<any> { findUsersByName(search: string): Observable<IdentityUserModel[]> {
if (search === '') { if (search === '') {
return of([]); return of([]);
} }
@@ -86,11 +86,18 @@ export class IdentityUserService {
const httpMethod = 'GET', pathParams = {}, queryParams = { search: search }, bodyParam = {}, headerParams = {}, const httpMethod = 'GET', pathParams = {}, queryParams = { search: search }, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams, url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null) contentTypes, accepts, Object, null, null)
)); ).pipe(
map((response: []) => {
return response.map( (user: IdentityUserModel) => {
return {id: user.id, firstName: user.firstName, lastName: user.lastName, email: user.email, username: user.username};
});
}),
catchError((err) => this.handleError(err))
);
} }
/** /**
@@ -98,7 +105,7 @@ export class IdentityUserService {
* @param username Search query string * @param username Search query string
* @returns List of users * @returns List of users
*/ */
findUserByUsername(username: string): Observable<any> { findUserByUsername(username: string): Observable<IdentityUserModel[]> {
if (username === '') { if (username === '') {
return of([]); return of([]);
} }
@@ -106,11 +113,18 @@ export class IdentityUserService {
const httpMethod = 'GET', pathParams = {}, queryParams = { username: username }, bodyParam = {}, headerParams = {}, const httpMethod = 'GET', pathParams = {}, queryParams = { username: username }, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams, url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null) contentTypes, accepts, Object, null, null)
)); ).pipe(
map((response: []) => {
return response.map( (user: IdentityUserModel) => {
return {id: user.id, firstName: user.firstName, lastName: user.lastName, email: user.email, username: user.username};
});
}),
catchError((err) => this.handleError(err))
);
} }
/** /**
@@ -118,7 +132,7 @@ export class IdentityUserService {
* @param email Search query string * @param email Search query string
* @returns List of users * @returns List of users
*/ */
findUserByEmail(email: string): Observable<any> { findUserByEmail(email: string): Observable<IdentityUserModel[]> {
if (email === '') { if (email === '') {
return of([]); return of([]);
} }
@@ -126,11 +140,18 @@ export class IdentityUserService {
const httpMethod = 'GET', pathParams = {}, queryParams = { email: email }, bodyParam = {}, headerParams = {}, const httpMethod = 'GET', pathParams = {}, queryParams = { email: email }, bodyParam = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi(
url, httpMethod, pathParams, queryParams, url, httpMethod, pathParams, queryParams,
headerParams, formParams, bodyParam, headerParams, formParams, bodyParam,
contentTypes, accepts, Object, null, null) contentTypes, accepts, Object, null, null)
)); ).pipe(
map((response: []) => {
return response.map( (user: IdentityUserModel) => {
return {id: user.id, firstName: user.firstName, lastName: user.lastName, email: user.email, username: user.username};
});
}),
catchError((err) => this.handleError(err))
);
} }
/** /**

View File

@@ -202,6 +202,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
.subscribe( .subscribe(
(data) => { (data) => {
this.formCloudRepresentationJSON = data[0]; this.formCloudRepresentationJSON = data[0];
this.formCloudRepresentationJSON.processVariables = data[1]; this.formCloudRepresentationJSON.processVariables = data[1];
this.data = data[1]; this.data = data[1];

View File

@@ -3,12 +3,11 @@
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span <label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span
*ngIf="isRequired()">*</span></label> *ngIf="isRequired()">*</span></label>
<adf-cloud-group [mode]="mode" <adf-cloud-group [mode]="mode"
[title]="title"
[roles]="roles" [roles]="roles"
[appName]="appName" (selectGroup)="onSelectGroup($event)"
(removeGroup)="onRemoveGroup($event)"
[preSelectGroups]="preSelectGroup"> [preSelectGroups]="preSelectGroup">
</adf-cloud-group> </adf-cloud-group>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div> </div>

View File

@@ -16,7 +16,7 @@
*/ */
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { baseHost, WidgetComponent, IdentityGroupCountModel } from '@alfresco/adf-core'; import { baseHost, WidgetComponent, IdentityGroupModel } from '@alfresco/adf-core';
/* tslint:disable:component-selector */ /* tslint:disable:component-selector */
@@ -28,17 +28,29 @@ import { baseHost, WidgetComponent, IdentityGroupCountModel } from '@alfresco/ad
}) })
export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit { export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit {
appName: string;
roles: string[]; roles: string[];
mode: string; mode: string;
preSelectGroup: IdentityGroupCountModel[]; title: string;
preSelectGroup: IdentityGroupModel[];
ngOnInit() { ngOnInit() {
if (this.field) { if (this.field) {
this.appName = this.field.appName;
this.roles = this.field.roles; this.roles = this.field.roles;
this.mode = this.field.mode; this.mode = this.field.optionType;
this.preSelectGroup = this.field.value; this.title = this.field.placeholder;
this.preSelectGroup = this.field.value ? this.field.value : [];
} }
} }
onSelectGroup(group: IdentityGroupModel) {
this.field.value = [...this.field.value, group];
this.onFieldChanged(this.field);
}
onRemoveGroup(group: IdentityGroupModel) {
const indexToRemove = this.field.value.findIndex((selected) => { return selected.id === group.id; });
this.field.value.splice(indexToRemove, 1);
this.field.value = [...this.field.value];
this.onFieldChanged(this.field);
}
} }

View File

@@ -5,6 +5,9 @@
[preSelectUsers]="preSelectUsers" [preSelectUsers]="preSelectUsers"
[validate]="true" [validate]="true"
[appName]="appName" [appName]="appName"
[title]="title"
(selectUser)="onSelectUser($event)"
(removeUser)="onRemoveUser($event)"
[roles]="roles" [roles]="roles"
[mode]="mode"> [mode]="mode">
</adf-cloud-people> </adf-cloud-people>

View File

@@ -31,14 +31,27 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
appName: string; appName: string;
roles: string[]; roles: string[];
mode: string; mode: string;
title: string;
preSelectUsers: IdentityUserModel[]; preSelectUsers: IdentityUserModel[];
ngOnInit() { ngOnInit() {
if (this.field) { if (this.field) {
this.appName = this.field.appName;
this.roles = this.field.roles; this.roles = this.field.roles;
this.mode = this.field.mode; this.mode = this.field.optionType;
this.preSelectUsers = this.field.value; this.title = this.field.placeholder;
this.preSelectUsers = this.field.value ? this.field.value : [];
} }
} }
onSelectUser(user: IdentityUserModel) {
this.field.value = [...this.field.value, user];
this.onFieldChanged(this.field);
}
onRemoveUser(user: IdentityUserModel) {
const indexToRemove = this.field.value.findIndex((selectedUser) => { return selectedUser.id === user.id; });
this.field.value.splice(indexToRemove, 1);
this.field.value = [...this.field.value];
this.onFieldChanged(this.field);
}
} }

View File

@@ -69,7 +69,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
* Mandatory properties are: id, email, username * Mandatory properties are: id, email, username
*/ */
@Input() @Input()
preSelectUsers: IdentityUserModel[]; preSelectUsers: IdentityUserModel[] = [];
/** FormControl to search the user */ /** FormControl to search the user */
@Input() @Input()