[ADF-5031][PeopleCloudComponent] [PeopleCloudComponent] Provide a way to make selected items read-only (not remove) (#5289)

* [DW-1618] Admin App -Application Instances - Able to delete all the admin users in Manage app permissions.

* [ADF-5031] [PeopleCloudComponent] Do not delete selected users completely.

* Added flag for not to remove last chip
* Added unit tests to the changes.

* * Added doc

* * Changed removeLastChip to remove

* * Added readonly strategy
* Removed remove input
* Updated unit tests

* * Added  tooltip
* Hiding remove icon.

* * Fixed unit tests
This commit is contained in:
siva kumar
2019-12-09 16:10:33 +05:30
committed by Maurizio Vitale
parent 57df944bbf
commit 84dac48d9b
7 changed files with 90 additions and 6 deletions

View File

@@ -39,3 +39,25 @@ Allows one or more users to be selected (with auto-suggestion) based on the inpu
| removeUser | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityUserModel`](../../../lib/core/models/identity-user.model.ts)`>` | Emitted when a selected user is removed in multi selection mode. | | removeUser | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityUserModel`](../../../lib/core/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/models/identity-user.model.ts)`>` | Emitted when a user is selected. | | selectUser | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`IdentityUserModel`](../../../lib/core/models/identity-user.model.ts)`>` | Emitted when a user is selected. |
| warning | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when an warning occurs. | | warning | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when an warning occurs. |
## Details
### Read-only
You can use `readonly` property to make preselected users read-only in `multiple` mode.
```ts
const preSelectUsers = [
{ "id": "1", "username": "username1", "firstName": "user 1", "readonly": true },
{ "id": "2", "username": "username2", "firstName": "user 2", "readonly": false },
{ "id": "3", "username": "username3", "firstName": "user 3", "readonly": true }
];
```
```html
<adf-cloud-people
[mode]="'multiple'",
[preSelectUsers]="preSelectUsers">
</adf-cloud-people>
```
from above `preSelectUsers`, `username2` is removable from the `preSelectUsers` whereas `username1`, `username3` are readonly you can not remove them.

View File

@@ -24,4 +24,5 @@ export interface IdentityUserModel {
createdTimestamp?: any; createdTimestamp?: any;
emailVerified?: boolean; emailVerified?: boolean;
enabled?: boolean; enabled?: boolean;
readonly?: boolean;
} }

View File

@@ -6,9 +6,11 @@
*ngFor="let group of selectedGroups$ | async" *ngFor="let group of selectedGroups$ | async"
[removable]="!(group.readonly)" [removable]="!(group.readonly)"
(removed)="onRemove(group)" (removed)="onRemove(group)"
matTooltip="{{ (group.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}"
[attr.data-automation-id]="'adf-cloud-group-chip-' + group.name"> [attr.data-automation-id]="'adf-cloud-group-chip-' + group.name">
{{group.name}} {{group.name}}
<mat-icon <mat-icon
*ngIf=!(group.readonly)
matChipRemove [attr.data-automation-id]="'adf-cloud-group-chip-remove-icon-' + group.name"> matChipRemove [attr.data-automation-id]="'adf-cloud-group-chip-remove-icon-' + group.name">
cancel cancel
</mat-icon> </mat-icon>

View File

@@ -442,7 +442,7 @@ describe('GroupCloudComponent', () => {
describe('Multiple Mode with read-only', () => { describe('Multiple Mode with read-only', () => {
it('Should not be able to remove pre-selected groups if readonly property set to true', (done) => { it('Should not show remove icon for pre-selected groups if readonly property set to true', (done) => {
fixture.detectChanges(); fixture.detectChanges();
const preselectedGroups = [ const preselectedGroups = [
{ id: mockIdentityGroups[0].id, name: mockIdentityGroups[0].name, readonly: true }, { id: mockIdentityGroups[0].id, name: mockIdentityGroups[0].name, readonly: true },
@@ -451,7 +451,6 @@ describe('GroupCloudComponent', () => {
component.preSelectGroups = preselectedGroups; component.preSelectGroups = preselectedGroups;
const change = new SimpleChange(null, preselectedGroups, false); const change = new SimpleChange(null, preselectedGroups, false);
component.mode = 'multiple'; component.mode = 'multiple';
const removeGroupSpy = spyOn(component.removeGroup, 'emit');
component.ngOnChanges({ 'preSelectGroups': change }); component.ngOnChanges({ 'preSelectGroups': change });
fixture.detectChanges(); fixture.detectChanges();
const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip'); const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip');
@@ -462,9 +461,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
removeIcon.click(); expect(removeIcon).toBeNull();
fixture.detectChanges();
expect(removeGroupSpy).not.toHaveBeenCalled();
expect(component.preSelectGroups.length).toBe(2); expect(component.preSelectGroups.length).toBe(2);
expect(component.preSelectGroups[0].readonly).toBe(true, 'Not removable'); expect(component.preSelectGroups[0].readonly).toBe(true, 'Not removable');
expect(component.preSelectGroups[1].readonly).toBe(true, 'Not removable'); expect(component.preSelectGroups[1].readonly).toBe(true, 'Not removable');

View File

@@ -176,6 +176,7 @@
}, },
"ADF_CLOUD_GROUPS": { "ADF_CLOUD_GROUPS": {
"SEARCH-GROUP": "Groups", "SEARCH-GROUP": "Groups",
"MANDATORY": "Mandatory",
"ERROR": { "ERROR": {
"NOT_FOUND": "No group found with the name {{groupName}}" "NOT_FOUND": "No group found with the name {{groupName}}"
} }

View File

@@ -4,9 +4,17 @@
<mat-chip-list #userChipList *ngIf="isMultipleMode(); else singleSelection"> <mat-chip-list #userChipList *ngIf="isMultipleMode(); else singleSelection">
<mat-chip <mat-chip
*ngFor="let user of selectedUsers$ | async" *ngFor="let user of selectedUsers$ | async"
[removable]="!(user.readonly)"
[attr.data-automation-id]="'adf-people-cloud-chip-' + user.username"
matTooltip="{{ (user.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}"
(removed)="onRemove(user)"> (removed)="onRemove(user)">
{{user | fullName}} {{user | fullName}}
<mat-icon matChipRemove>cancel</mat-icon> <mat-icon
matChipRemove
*ngIf=!(user.readonly)
[attr.data-automation-id]="'adf-people-cloud-chip-remove-icon-' + user.username">
cancel
</mat-icon>
</mat-chip> </mat-chip>
<input <input
#userInput #userInput

View File

@@ -461,6 +461,59 @@ describe('PeopleCloudComponent', () => {
}); });
}); });
describe('Multiple Mode with read-only mode', () => {
it('Should not show remove icon for pre-selected users if readonly property set to true', (done) => {
component.mode = 'multiple';
const removeUserSpy = spyOn(component.removeUser, 'emit');
component.preSelectUsers = [
{ id: mockUsers[0].id, username: mockUsers[0].username, readonly: true },
{ id: mockUsers[1].id, username: mockUsers[1].username, readonly: true }
];
fixture.detectChanges();
const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip');
const removeIcon = <HTMLElement> fixture.nativeElement.querySelector('[data-automation-id="adf-people-cloud-chip-remove-icon-first-name-1 last-name-1"]');
expect(chipList.length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBeTruthy();
expect(component.preSelectUsers[1].readonly).toBeTruthy();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(removeIcon).toBeNull();
fixture.detectChanges();
expect(removeUserSpy).not.toHaveBeenCalled();
expect(component.preSelectUsers.length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBe(true, 'Not removable');
expect(component.preSelectUsers[1].readonly).toBe(true, 'not removable');
done();
});
});
it('Should be able to remove preselected users if readonly property set to false', (done) => {
component.mode = 'multiple';
const removeUserSpy = spyOn(component.removeUser, 'emit');
component.preSelectUsers = [
{ id: mockUsers[0].id, username: mockUsers[0].username, readonly: false },
{ id: mockUsers[1].id, username: mockUsers[1].username, readonly: false }
];
fixture.detectChanges();
const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip');
const removeIcon = <HTMLElement> fixture.nativeElement.querySelector('[data-automation-id="adf-people-cloud-chip-remove-icon-first-name-1 last-name-1"]');
expect(chipList.length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBe(false, 'Removable');
expect(component.preSelectUsers[1].readonly).toBe(false, 'Removable');
removeIcon.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(removeUserSpy).toHaveBeenCalled();
expect(component.preSelectUsers.length).toBe(1);
expect(component.preSelectUsers[0].readonly).toBeFalsy();
done();
});
});
});
describe('Multiple Mode and Pre-selected users with validate flag', () => { describe('Multiple Mode and Pre-selected users with validate flag', () => {
const change = new SimpleChange(null, mockPreselectedUsers, false); const change = new SimpleChange(null, mockPreselectedUsers, false);