diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json
index dca6df9a7e..fbb4554716 100644
--- a/demo-shell/resources/i18n/en.json
+++ b/demo-shell/resources/i18n/en.json
@@ -296,7 +296,8 @@
"ROLE": "Roles: ",
"APP_NAME": "Aplication Name",
"APP_FILTER_MODE": "Filter by application name",
- "ROLE_FILTER_MODE": "Filter by role"
+ "ROLE_FILTER_MODE": "Filter by role",
+ "PRESELECT_VALIDATION": "Preselect validation"
},
"ABOUT": {
"TITLE": "Plugins",
diff --git a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html
index 319c52387d..87917d2c49 100644
--- a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html
+++ b/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html
@@ -30,9 +30,17 @@
{{ 'PEOPLE_GROUPS_CLOUD.PRESELECTED_VALUE' | translate }}: {{ DEFAULT_PEOPLE_PLACEHOLDER }}
+ {{
+ 'PEOPLE_GROUPS_CLOUD.PRESELECT_VALIDATION' | translate }}
diff --git a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts
index be5e208751..60bf38f6d9 100644
--- a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts
+++ b/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts
@@ -17,7 +17,7 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { PeopleCloudComponent, GroupCloudComponent, GroupModel } from '@alfresco/adf-process-services-cloud';
-import { MatRadioChange } from '@angular/material';
+import { MatRadioChange, MatCheckboxChange } from '@angular/material';
@Component({
selector: 'app-people-groups-cloud',
@@ -29,13 +29,14 @@ export class PeopleGroupCloudDemoComponent {
DEFAULT_FILTER_MODE: string = 'appName';
DEFAULT_GROUP_PLACEHOLDER: string = `[{"id": "1", "name":"activitiUserGroup"}]`;
- DEFAULT_PEOPLE_PLACEHOLDER: string = `[{"email": "example@alfresco.com", "firstName":"Administrator", "lastName": "ADF"}]`;
+ DEFAULT_PEOPLE_PLACEHOLDER: string = `[{"id": "1", email": "user@user.com", "firstName":"user", "lastName": "lastName", "username": "user"}]`;
peopleMode: string = PeopleCloudComponent.MODE_SINGLE;
preSelectUsers: string[] = [];
peopleRoles: string[] = [];
peopleAppName: string;
peopleFilterMode: string = this.DEFAULT_FILTER_MODE;
+ peoplePreselectValidation: Boolean = false;
groupMode: string = GroupCloudComponent.MODE_SINGLE;
preSelectGroup: GroupModel[] = [];
@@ -112,6 +113,11 @@ export class PeopleGroupCloudDemoComponent {
}
}
+ onChangePeopleValidation(event: MatCheckboxChange) {
+ this.peoplePreselectValidation = event.checked;
+ this.preSelectUsers = [...this.preSelectUsers];
+ }
+
isStringArray(str: string) {
try {
const result = JSON.parse(str);
diff --git a/docs/core/identity-user.service.md b/docs/core/identity-user.service.md
index a8b3b5d161..1d3fcec045 100644
--- a/docs/core/identity-user.service.md
+++ b/docs/core/identity-user.service.md
@@ -5,9 +5,9 @@ Status: Active
Last reviewed: 2019-02-08
---
-# [Identity user service](../../lib/core/userinfo/services/identity-user.service.ts "Defined in identity-user.service.ts")
+# [Identity user service](../../lib/lib/core/userinfo/services/identity-user.service.ts "Defined in identity-user.service.ts")
-Gets OAuth2 personal details and roles for users.
+Gets OAuth2 personal details and roles for users.
## Class members
@@ -40,9 +40,21 @@ Gets OAuth2 personal details and roles for users.
- _userId:_ `string` - ID of the target user
- _roleNames:_ `string[]` - Array of roles to check for
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`
` - True if the user has one of the roles, false otherwise
+- **findUserByEmail**(email: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on email input.
+ - _email:_ `string` - [Search](../../lib/node_modules/@alfresco/js-api/src/api-legacy/legacy.ts) query string
+ - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users
+- **findUserById**(id: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on id input.
+ - _id:_ `string` - [Search](../../lib/node_modules/@alfresco/js-api/src/api-legacy/legacy.ts) query string
+ - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - users object
+- **findUserByUsername**(username: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
+ Find users based on username input.
+ - _username:_ `string` - [Search](../../lib/node_modules/@alfresco/js-api/src/api-legacy/legacy.ts) query string
+ - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users
- **findUsersByName**(search: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
Find users based on search input.
- - _search:_ `string` - Search query string
+ - _search:_ `string` - [Search](../../lib/node_modules/@alfresco/js-api/src/api-legacy/legacy.ts) query string
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`` - List of users
- **getClientIdByApplicationName**(applicationName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)``
Gets the client ID for an application.
@@ -59,8 +71,8 @@ Gets OAuth2 personal details and roles for users.
- **getUserRoles**(userId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../lib/core/userinfo/models/identity-role.model.ts)`[]>`
Gets a list of roles for a user.
- _userId:_ `string` - ID of the user
- - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of role info objects
-- **getUsers**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`[]>`
+ - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityRoleModel`](../../lib/lib/core/userinfo/models/identity-role.model.ts)`[]>` - Array of role info objects
+- **getUsers**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserModel`](../../lib/lib/core/userinfo/models/identity-user.model.ts)`[]>`
Gets details for all users.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`[]>` - Array of user info objects
- **getUsersByRolesWithCurrentUser**(roleNames: `string[]`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`[]>`
diff --git a/docs/process-services-cloud/people-cloud.component.md b/docs/process-services-cloud/people-cloud.component.md
index 04f2009ed1..8351ef51e0 100644
--- a/docs/process-services-cloud/people-cloud.component.md
+++ b/docs/process-services-cloud/people-cloud.component.md
@@ -26,13 +26,14 @@ Allows one or more users to be selected (with auto-suggestion) based on the inpu
| ---- | ---- | ------------- | ----------- |
| appName | `string` | | Name of the application. If specified, this shows the users who have access to the app. |
| mode | `string` | | User selection mode (single/multiple). |
-| preSelectUsers | [`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`[]` | | Array of users to be pre-selected. All users in the array are pre-selected in multi selection mode, but only the first user is pre-selected in single selection mode. |
+| preSelectUsers | [`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`[]` | | Array of users to be pre-selected. All users in the array are pre-selected in multi selection mode, but only the first user is pre-selected in single selection mode. Mandatory properties are: id, email, username |
| roles | `string[]` | | Role names of the users to be listed. |
+| validate | `Boolean` | false | This flag enables the validation on the preSelectUsers passed as input. In case the flag is true the components call the identity service to verify the validity of the information passed as input. Otherwise, no check will be done. |
### Events
| Name | Type | Description |
| ---- | ---- | ----------- |
-| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when an error occurs. |
| removeUser | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`>` | Emitted when a selected user is removed in multi selection mode. |
| selectUser | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityUserModel`](../../lib/core/userinfo/models/identity-user.model.ts)`>` | Emitted when a user is selected. |
+| warning | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when an warning occurs. |
diff --git a/lib/core/userinfo/services/identity-user.service.ts b/lib/core/userinfo/services/identity-user.service.ts
index db56a23e8e..21b02437db 100644
--- a/lib/core/userinfo/services/identity-user.service.ts
+++ b/lib/core/userinfo/services/identity-user.service.ts
@@ -40,7 +40,7 @@ export class IdentityUserService {
constructor(
private helper: JwtHelperService,
private apiService: AlfrescoApiService,
- private appConfigService: AppConfigService) {}
+ private appConfigService: AppConfigService) { }
/**
* Gets the name and other basic details of the current user.
@@ -80,14 +80,74 @@ export class IdentityUserService {
return of([]);
}
const url = this.buildUserUrl();
- 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'];
return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
- url, httpMethod, pathParams, queryParams,
- headerParams, formParams, bodyParam,
- contentTypes, accepts, Object, null, null)
- ));
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ ));
+ }
+
+ /**
+ * Find users based on username input.
+ * @param username Search query string
+ * @returns List of users
+ */
+ findUserByUsername(username: string): Observable {
+ if (username === '') {
+ return of([]);
+ }
+ const url = this.buildUserUrl();
+ const httpMethod = 'GET', pathParams = {}, queryParams = { username: username }, bodyParam = {}, headerParams = {},
+ formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
+
+ return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ ));
+ }
+
+ /**
+ * Find users based on email input.
+ * @param email Search query string
+ * @returns List of users
+ */
+ findUserByEmail(email: string): Observable {
+ if (email === '') {
+ return of([]);
+ }
+ const url = this.buildUserUrl();
+ const httpMethod = 'GET', pathParams = {}, queryParams = { email: email }, bodyParam = {}, headerParams = {},
+ formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
+
+ return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ ));
+ }
+
+ /**
+ * Find users based on id input.
+ * @param id Search query string
+ * @returns users object
+ */
+ findUserById(id: string): Observable {
+ if (id === '') {
+ return of([]);
+ }
+ const url = this.buildUserUrl() + '/' + id;
+ const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
+ formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
+
+ return (from(this.apiService.getInstance().oauth2Auth.callCustomApi(
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ ));
}
/**
@@ -102,10 +162,10 @@ export class IdentityUserService {
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
- url, httpMethod, pathParams, queryParams,
- headerParams, formParams, bodyParam,
- contentTypes, accepts, Object, null, null)
- );
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ );
}
/**
@@ -160,18 +220,18 @@ export class IdentityUserService {
*/
getClientIdByApplicationName(applicationName: string): Observable {
const url = this.buildGetClientsUrl();
- const httpMethod = 'GET', pathParams = {}, queryParams = {clientId: applicationName}, bodyParam = {}, headerParams = {}, formParams = {},
- contentTypes = ['application/json'], accepts = ['application/json'];
+ const httpMethod = 'GET', pathParams = {}, queryParams = { clientId: applicationName }, bodyParam = {}, headerParams = {}, formParams = {},
+ contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance()
- .oauth2Auth.callCustomApi(url, httpMethod, pathParams, queryParams, headerParams,
- formParams, bodyParam, contentTypes,
- accepts, Object, null, null)
- ).pipe(
- map((response: any[]) => {
- const clientId = response && response.length > 0 ? response[0].id : '';
- return clientId;
- })
- );
+ .oauth2Auth.callCustomApi(url, httpMethod, pathParams, queryParams, headerParams,
+ formParams, bodyParam, contentTypes,
+ accepts, Object, null, null)
+ ).pipe(
+ map((response: any[]) => {
+ const clientId = response && response.length > 0 ? response[0].id : '';
+ return clientId;
+ })
+ );
}
/**
@@ -213,14 +273,14 @@ export class IdentityUserService {
formParams = {}, authNames = [], contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
- url, httpMethod, pathParams, queryParams,
- headerParams, formParams, bodyParam, authNames,
- contentTypes, accepts, null, null)
- ).pipe(
- map((response: IdentityUserModel[]) => {
- return response;
- })
- );
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam, authNames,
+ contentTypes, accepts, null, null)
+ ).pipe(
+ map((response: IdentityUserModel[]) => {
+ return response;
+ })
+ );
}
/**
@@ -234,14 +294,14 @@ export class IdentityUserService {
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
- url, httpMethod, pathParams, queryParams,
- headerParams, formParams, bodyParam,
- contentTypes, accepts, Object, null, null)
- ).pipe(
- map((response: IdentityRoleModel[]) => {
- return response;
- })
- );
+ url, httpMethod, pathParams, queryParams,
+ headerParams, formParams, bodyParam,
+ contentTypes, accepts, Object, null, null)
+ ).pipe(
+ map((response: IdentityRoleModel[]) => {
+ return response;
+ })
+ );
}
/**
@@ -308,7 +368,7 @@ export class IdentityUserService {
* @param roleNames Array of roles to check for
* @returns True if the user has one of the roles, false otherwise
*/
- checkUserHasRole(userId: string, roleNames: string[]): Observable {
+ checkUserHasRole(userId: string, roleNames: string[]): Observable {
return this.getUserRoles(userId).pipe(map((userRoles: IdentityRoleModel[]) => {
let hasRole = false;
if (userRoles && userRoles.length > 0) {
diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts
index 0487ffbb35..74e646b589 100644
--- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts
@@ -85,7 +85,7 @@ describe('PeopleCloudComponent', () => {
it('should emit selectedUser if option is valid', async(() => {
fixture.detectChanges();
let selectEmitSpy = spyOn(component.selectUser, 'emit');
- component.onSelect(new IdentityUserModel({ username: 'username'}));
+ component.onSelect(new IdentityUserModel({ username: 'username' }));
fixture.whenStable().then(() => {
expect(selectEmitSpy).toHaveBeenCalled();
});
@@ -130,7 +130,7 @@ describe('PeopleCloudComponent', () => {
it('should pre-select all preSelectUsers when mode=multiple', async(() => {
spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers));
component.mode = 'multiple';
- component.preSelectUsers = [{id: mockUsers[1].id}, {id: mockUsers[2].id}];
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -153,7 +153,7 @@ describe('PeopleCloudComponent', () => {
it('should pre-select preSelectUsers[0] when mode=single', async(() => {
spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers));
component.mode = 'single';
- component.preSelectUsers = [{id: mockUsers[1].id}, {id: mockUsers[2].id}];
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
fixture.detectChanges();
fixture.whenStable().then(() => {
const selectedUser = component.searchUserCtrl.value;
@@ -176,7 +176,7 @@ describe('PeopleCloudComponent', () => {
let removeUserSpy = spyOn(component.removeUser, 'emit');
component.mode = 'multiple';
- component.preSelectUsers = [{id: mockUsers[1].id}, {id: mockUsers[2].id}];
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -296,10 +296,10 @@ describe('PeopleCloudComponent', () => {
});
}));
- it('should load the clients if appName change', async( () => {
+ it('should load the clients if appName change', async(() => {
component.appName = 'ADF';
fixture.detectChanges();
- fixture.whenStable().then( () => {
+ fixture.whenStable().then(() => {
fixture.detectChanges();
expect(loadClientsByApplicationNameSpy).toHaveBeenCalled();
});
@@ -310,9 +310,91 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
component.appName = 'ADF';
fixture.detectChanges();
- fixture.whenStable().then( () => {
+ fixture.whenStable().then(() => {
fixture.detectChanges();
expect(checkUserHasAccessSpy).toHaveBeenCalled();
});
}));
+
+ it('should not validate preselect values if preselectValidation flag is set to false', () => {
+ component.mode = 'multiple';
+ component.validate = false;
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(component.validatePreselectUsers).not.toHaveBeenCalled();
+ });
+ });
+
+ it('should filter users when validation flag is true', async(() => {
+ component.mode = 'multiple';
+ component.validate = true;
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ component.filterPreselectUsers().then((result) => {
+ expect(component.userExists(result)).toEqual(false);
+ });
+ });
+ }));
+
+ it('should emit warning if are invalid users', async((done) => {
+ const warningSpy = spyOn(component.warning, 'emit').and.returnValue(of(false));
+ component.mode = 'single';
+ component.validate = true;
+ component.preSelectUsers = [{ username: 'invalidUsername' }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ component.loadSinglePreselectUser().then((result) => {
+ fixture.detectChanges();
+ expect(warningSpy).toHaveBeenCalled();
+ });
+ });
+ }));
+
+ it('should filter user by id if validate true', async((done) => {
+ const findByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(Promise.resolve(mockUsers));
+ component.mode = 'multiple';
+ component.validate = true;
+ component.preSelectUsers = [{ id: mockUsers[1].id }, { id: mockUsers[2].id }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ component.filterPreselectUsers().then((result) => {
+ expect(findByIdSpy).toHaveBeenCalled();
+ expect(component.userExists(result)).toEqual(true);
+ done();
+ });
+ });
+ }));
+
+ it('should filter user by username if validate true', async((done) => {
+ const findUserByUsernameSpy = spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve(mockUsers));
+ component.mode = 'multiple';
+ component.validate = true;
+ component.preSelectUsers = [{ username: mockUsers[1].username }, { username: mockUsers[2].username }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ component.filterPreselectUsers().then((result) => {
+ expect(findUserByUsernameSpy).toHaveBeenCalled();
+ expect(component.userExists(result)).toEqual(true);
+ done();
+ });
+ });
+ }));
+
+ it('should filter user by email if validate true', async((done) => {
+ const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(Promise.resolve(mockUsers));
+ component.mode = 'multiple';
+ component.validate = true;
+ component.preSelectUsers = [{ email: mockUsers[1].email }, { email: mockUsers[2].email }];
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ component.filterPreselectUsers().then((result) => {
+ expect(findUserByEmailSpy).toHaveBeenCalled();
+ expect(component.userExists(result)).toEqual(true);
+ done();
+ });
+ });
+ }));
});
diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts
index 4fef317370..c6e9b148d3 100644
--- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts
+++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts
@@ -19,7 +19,7 @@ import { FormControl } from '@angular/forms';
import { Component, OnInit, Output, EventEmitter, ViewEncapsulation, Input, ViewChild, ElementRef, SimpleChanges, OnChanges } from '@angular/core';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter } from 'rxjs/operators';
-import { FullNamePipe, IdentityUserModel, IdentityUserService } from '@alfresco/adf-core';
+import { FullNamePipe, IdentityUserModel, IdentityUserService, LogService } from '@alfresco/adf-core';
import { trigger, state, style, transition, animate } from '@angular/animations';
@Component({
@@ -28,9 +28,9 @@ import { trigger, state, style, transition, animate } from '@angular/animations'
styleUrls: ['./people-cloud.component.scss'],
animations: [
trigger('transitionMessages', [
- state('enter', style({opacity: 1, transform: 'translateY(0%)'})),
+ state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
transition('void => enter', [
- style({opacity: 0, transform: 'translateY(-100%)'}),
+ style({ opacity: 0, transform: 'translateY(-100%)' }),
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')
])
])
@@ -56,10 +56,17 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
@Input()
roles: string[];
- /**
- * Array of users to be pre-selected. All users in the
+ /** This flag enables the validation on the preSelectUsers passed as input.
+ * In case the flag is true the components call the identity service to verify the validity of the information passed as input.
+ * Otherwise, no check will be done.
+ */
+ @Input()
+ validate: Boolean = false;
+
+ /** Array of users to be pre-selected. All users in the
* array are pre-selected in multi selection mode, but only the first user
* is pre-selected in single selection mode.
+ * Mandatory properties are: id, email, username
*/
@Input()
preSelectUsers: IdentityUserModel[];
@@ -72,9 +79,9 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
@Output()
removeUser: EventEmitter = new EventEmitter();
- /** Emitted when an error occurs. */
+ /** Emitted when an warning occurs. */
@Output()
- error: EventEmitter = new EventEmitter();
+ warning: EventEmitter = new EventEmitter();
@ViewChild('userInput')
private userInput: ElementRef;
@@ -93,7 +100,9 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
isFocused: boolean;
- constructor(private identityUserService: IdentityUserService) {
+ invalidUsers: IdentityUserModel[];
+
+ constructor(private identityUserService: IdentityUserService, private logService: LogService) {
this.searchUsersSubject = new BehaviorSubject(this._searchUsers);
this.searchUsers$ = this.searchUsersSubject.asObservable();
}
@@ -102,11 +111,18 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
this.selectedUsersSubject = new BehaviorSubject(this.preSelectUsers);
this.selectedUsers$ = this.selectedUsersSubject.asObservable();
this.initSearch();
+
+ if (this.appName) {
+ this.disableSearch();
+ this.loadClientId();
+ }
}
ngOnChanges(changes: SimpleChanges) {
- if (changes.preSelectUsers && this.hasPreSelectUsers()) {
+ if (this.isPreselectedUserChanged(changes) && this.isValidationEnabled()) {
this.loadPreSelectUsers();
+ } else {
+ this.loadNoValidationPreselctUsers();
}
if (changes.appName && this.isAppNameChanged(changes.appName)) {
@@ -121,6 +137,70 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
return change.previousValue !== change.currentValue && this.appName && this.appName.length > 0;
}
+ isPreselectedUserChanged(changes: SimpleChanges) {
+ return changes.preSelectUsers
+ && changes.preSelectUsers.previousValue !== changes.preSelectUsers.currentValue
+ && this.hasPreSelectUsers();
+ }
+
+ isValidationEnabled() {
+ return this.validate === true;
+ }
+
+ async validatePreselectUsers(): Promise {
+ this.invalidUsers = [];
+ let filteredPreSelectUsers: IdentityUserModel[];
+
+ try {
+ filteredPreSelectUsers = await this.filterPreselectUsers();
+ } catch (error) {
+ filteredPreSelectUsers = [];
+ this.logService.error(error);
+ }
+
+ return filteredPreSelectUsers.reduce((validUsers, user: IdentityUserModel) => {
+ if (this.userExists(user)) {
+ validUsers.push(user);
+ } else {
+ this.invalidUsers.push(user);
+ }
+ return validUsers;
+ }, []);
+ }
+
+ async filterPreselectUsers() {
+ const promiseBatch = this.preSelectUsers.map(async (user: IdentityUserModel) => {
+ let result: any;
+
+ try {
+ result = await this.searchUser(user);
+ } catch (error) {
+ result = [];
+ this.logService.error(error);
+ }
+ const isUserValid: Boolean = this.userExists(result);
+ return isUserValid ? new IdentityUserModel(result[0]) : user;
+ });
+ return await Promise.all(promiseBatch);
+ }
+
+ async searchUser(user: IdentityUserModel) {
+ const key: string = Object.keys(user)[0];
+ switch (key) {
+ case 'id': return this.identityUserService.findUserById(user[key]).toPromise();
+ case 'username': return this.identityUserService.findUserByUsername(user[key]).toPromise();
+ case 'email': return this.identityUserService.findUserByEmail(user[key]).toPromise();
+ default: return of([]);
+ }
+ }
+
+ public userExists(result: any) {
+ return result.length > 0 ||
+ result.id !== undefined ||
+ result.username !== undefined ||
+ result.amil !== undefined;
+ }
+
private initSearch() {
this.searchUserCtrl.valueChanges.pipe(
filter((value) => {
@@ -135,7 +215,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
}
this.clearError();
}
- }),
+ }),
debounceTime(500),
distinctUntilChanged(),
tap(() => {
@@ -190,7 +270,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
private isUserAlreadySelected(user: IdentityUserModel): boolean {
if (this.preSelectUsers && this.preSelectUsers.length > 0) {
const result = this.preSelectUsers.find((selectedUser) => {
- return selectedUser.id === user.id || selectedUser.email === user.email;
+ return selectedUser.id === user.id || selectedUser.email === user.email || selectedUser.username === user.username;
});
return !!result;
@@ -200,15 +280,46 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
private loadPreSelectUsers() {
if (!this.isMultipleMode()) {
- this.searchUserCtrl.setValue(this.preSelectUsers[0]);
- this.preSelectUsers = [];
+ this.loadSinglePreselectUser();
} else {
+ this.loadMultiplePreselectUsers();
+ }
+ if (this.userInput) {
+ this.userInput.nativeElement.click();
+ }
+ }
+
+ loadNoValidationPreselctUsers() {
+ if (this.isMultipleMode()) {
this.selectedUsersSubject.next(this.preSelectUsers);
+ } else {
+ this.searchUserCtrl.setValue(this.preSelectUsers[0]);
+ }
+ }
+
+ public async loadSinglePreselectUser() {
+ const users = await this.validatePreselectUsers();
+ this.checkPreselectValidationErrors();
+ this.searchUserCtrl.setValue(users[0]);
+ }
+
+ public async loadMultiplePreselectUsers() {
+ let users = await this.validatePreselectUsers();
+ this.checkPreselectValidationErrors();
+ this.preSelectUsers = [...users];
+ this.selectedUsersSubject.next(users);
+ }
+
+ public checkPreselectValidationErrors() {
+ if (this.invalidUsers.length > 0) {
+ this.warning.emit({
+ message: 'INVALID_PRESELECTED_USERS',
+ users: this.invalidUsers
+ });
}
}
private async loadClientId() {
-
this.clientId = await this.identityUserService.getClientIdByApplicationName(this.appName).toPromise();
if (this.clientId) {
@@ -260,7 +371,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
}
private setError() {
- this.searchUserCtrl.setErrors({invalid: true});
+ this.searchUserCtrl.setErrors({ invalid: true });
}
private clearError() {