mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[MNT-24657] Add multiple selection support for people widget (#10458)
* [MNT-24657] Add multiple selection support for people widget [ci:force] * [MNT-24657] cr fixes
This commit is contained in:
parent
60a9565c71
commit
2b0100466a
@ -4,22 +4,37 @@
|
|||||||
id="people-widget-content">
|
id="people-widget-content">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
||||||
<input #inputValue
|
<mat-chip-grid #chipGrid [attr.aria-label]="'ADF_PROCESS_LIST.START_PROCESS.FORM.LABEL.SELECTED_PEOPLE' | translate">
|
||||||
matInput
|
<mat-chip-row
|
||||||
class="adf-input"
|
*ngFor="let user of selectedUsers"
|
||||||
data-automation-id="adf-people-search-input"
|
(removed)="onRemove(user)"
|
||||||
type="text"
|
[disabled]="field.readOnly"
|
||||||
[id]="field.id"
|
[attr.data-automation-id]="'adf-people-widget-chip-' + user.id">
|
||||||
[formControl]="searchTerm"
|
{{ getDisplayName(user) }}
|
||||||
[placeholder]="field.placeholder"
|
<button matChipRemove [attr.aria-label]="'remove ' + user.firstName">
|
||||||
[matAutocomplete]="auto"
|
<mat-icon>cancel</mat-icon>
|
||||||
(blur)="markAsTouched()"
|
</button>
|
||||||
[title]="field.tooltip">
|
</mat-chip-row>
|
||||||
|
<input #inputValue
|
||||||
|
matInput
|
||||||
|
class="adf-input"
|
||||||
|
[matChipInputFor]="chipGrid"
|
||||||
|
data-automation-id="adf-people-search-input"
|
||||||
|
type="text"
|
||||||
|
[disabled]="!multiSelect && selectedUsers.length > 0 || field.readOnly"
|
||||||
|
[id]="field.id"
|
||||||
|
[formControl]="searchTerm"
|
||||||
|
[placeholder]="selectedUsers.length > 0 ? '' : field.placeholder"
|
||||||
|
[matAutocomplete]="auto"
|
||||||
|
(blur)="markAsTouched()"
|
||||||
|
[title]="field.tooltip">
|
||||||
|
</mat-chip-grid>
|
||||||
|
|
||||||
<mat-autocomplete class="adf-people-widget-list"
|
<mat-autocomplete class="adf-people-widget-list"
|
||||||
#auto="matAutocomplete"
|
#auto="matAutocomplete"
|
||||||
(optionSelected)="onItemSelect($event.option.value)"
|
(optionSelected)="onItemSelect($event.option.value)"
|
||||||
[displayWith]="getDisplayName">
|
[displayWith]="getDisplayName">
|
||||||
<mat-option *ngFor="let user of users$ | async; let i = index" [value]="user">
|
<mat-option *ngFor="let user of users$ | async; let i = index" [value]="user" [disabled]="isUserAlreadySelected(user)">
|
||||||
<div class="adf-people-widget-row" id="adf-people-widget-user-{{i}}">
|
<div class="adf-people-widget-row" id="adf-people-widget-user-{{i}}">
|
||||||
<div [outerHTML]="user | usernameInitials:'adf-people-widget-pic'"></div>
|
<div [outerHTML]="user | usernameInitials:'adf-people-widget-pic'"></div>
|
||||||
<div *ngIf="user.pictureId" class="adf-people-widget-image-row">
|
<div *ngIf="user.pictureId" class="adf-people-widget-image-row">
|
||||||
|
@ -23,20 +23,28 @@ import { PeopleWidgetComponent } from './people.widget';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { PeopleProcessService } from '../../../services/people-process.service';
|
import { PeopleProcessService } from '../../../services/people-process.service';
|
||||||
import { LightUserRepresentation } from '@alfresco/js-api';
|
import { LightUserRepresentation } from '@alfresco/js-api';
|
||||||
|
import { MatChipHarness } from '@angular/material/chips/testing';
|
||||||
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||||
|
import { HarnessLoader } from '@angular/cdk/testing';
|
||||||
|
|
||||||
describe('PeopleWidgetComponent', () => {
|
describe('PeopleWidgetComponent', () => {
|
||||||
let widget: PeopleWidgetComponent;
|
let widget: PeopleWidgetComponent;
|
||||||
let fixture: ComponentFixture<PeopleWidgetComponent>;
|
let fixture: ComponentFixture<PeopleWidgetComponent>;
|
||||||
let element: HTMLElement;
|
let element: HTMLElement;
|
||||||
|
let loader: HarnessLoader;
|
||||||
let translationService: TranslateService;
|
let translationService: TranslateService;
|
||||||
let peopleProcessService: PeopleProcessService;
|
let peopleProcessService: PeopleProcessService;
|
||||||
|
|
||||||
|
const getChipById = async (id: string) =>
|
||||||
|
loader.getHarness(MatChipHarness.with({ selector: `[data-automation-id="adf-people-widget-chip-${id}"]` }));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreTestingModule]
|
imports: [CoreTestingModule]
|
||||||
});
|
});
|
||||||
fixture = TestBed.createComponent(PeopleWidgetComponent);
|
fixture = TestBed.createComponent(PeopleWidgetComponent);
|
||||||
peopleProcessService = TestBed.inject(PeopleProcessService);
|
peopleProcessService = TestBed.inject(PeopleProcessService);
|
||||||
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||||
|
|
||||||
translationService = TestBed.inject(TranslateService);
|
translationService = TestBed.inject(TranslateService);
|
||||||
spyOn(translationService, 'instant').and.callFake((key) => key);
|
spyOn(translationService, 'instant').and.callFake((key) => key);
|
||||||
@ -48,26 +56,28 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return empty display name for missing model', () => {
|
describe('display name', () => {
|
||||||
expect(widget.getDisplayName(null)).toBe('');
|
it('should return empty display name for missing model', () => {
|
||||||
});
|
expect(widget.getDisplayName(null)).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
it('should return full name for a given model', () => {
|
it('should return full name for a given model', () => {
|
||||||
const model = {
|
const model = {
|
||||||
firstName: 'John',
|
firstName: 'John',
|
||||||
lastName: 'Doe'
|
lastName: 'Doe'
|
||||||
};
|
};
|
||||||
expect(widget.getDisplayName(model)).toBe('John Doe');
|
expect(widget.getDisplayName(model)).toBe('John Doe');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip first name for display name', () => {
|
it('should skip first name for display name', () => {
|
||||||
const model = { firstName: null, lastName: 'Doe' };
|
const model = { firstName: null, lastName: 'Doe' };
|
||||||
expect(widget.getDisplayName(model)).toBe('Doe');
|
expect(widget.getDisplayName(model)).toBe('Doe');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip last name for display name', () => {
|
it('should skip last name for display name', () => {
|
||||||
const model = { firstName: 'John', lastName: null };
|
const model = { firstName: 'John', lastName: null };
|
||||||
expect(widget.getDisplayName(model)).toBe('John');
|
expect(widget.getDisplayName(model)).toBe('John');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should init value from the field', async () => {
|
it('should init value from the field', async () => {
|
||||||
@ -83,7 +93,33 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect((element.querySelector('input') as HTMLInputElement).value).toBe('John Doe');
|
const chip = await getChipById('people-id');
|
||||||
|
expect(await chip.getText()).toBe('John Doe');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show correct number of chips if multiple users provided', async () => {
|
||||||
|
widget.field.readOnly = false;
|
||||||
|
widget.field.params.multiple = true;
|
||||||
|
widget.field.value = [
|
||||||
|
{
|
||||||
|
id: 'people-id-1',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'people-id-2',
|
||||||
|
firstName: 'Rick',
|
||||||
|
lastName: 'Grimes'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
widget.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
const chips = await loader.getAllHarnesses(MatChipHarness);
|
||||||
|
expect(chips.length).toBe(2);
|
||||||
|
expect(await chips[0].getText()).toBe('John Doe');
|
||||||
|
expect(await chips[1].getText()).toBe('Rick Grimes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the readonly value when the form is readonly', async () => {
|
it('should show the readonly value when the form is readonly', async () => {
|
||||||
@ -101,10 +137,30 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect((element.querySelector('input') as HTMLInputElement).value).toBe('John Doe');
|
const chip = await getChipById('people-id');
|
||||||
|
expect(await chip.getText()).toBe('John Doe');
|
||||||
|
expect(await chip.isDisabled()).toBe(true);
|
||||||
expect((element.querySelector('input') as HTMLInputElement).disabled).toBeTruthy();
|
expect((element.querySelector('input') as HTMLInputElement).disabled).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should display the cancel button in the chip', async () => {
|
||||||
|
widget.field.value = {
|
||||||
|
id: 'people-id',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe'
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(of(null));
|
||||||
|
|
||||||
|
widget.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
const chip = await getChipById('people-id');
|
||||||
|
const cancelIcon = await chip.getRemoveButton();
|
||||||
|
expect(cancelIcon).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('should require form field to setup values on init', () => {
|
it('should require form field to setup values on init', () => {
|
||||||
widget.field.value = null;
|
widget.field.value = null;
|
||||||
widget.ngOnInit();
|
widget.ngOnInit();
|
||||||
@ -138,13 +194,63 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
email: 'john@test.com'
|
email: 'john@test.com'
|
||||||
};
|
};
|
||||||
widget.ngOnInit();
|
widget.ngOnInit();
|
||||||
|
|
||||||
const involvedUser = fixture.debugElement.nativeElement.querySelector('input[data-automation-id="adf-people-search-input"]');
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(involvedUser.value).toBe('John Doe');
|
const chip = await getChipById('people-id');
|
||||||
|
expect(await chip.getText()).toBe('John Doe');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add user to selectedUsers when multiSelect is false and user is not already selected', () => {
|
||||||
|
const user: LightUserRepresentation = { id: 1, firstName: 'John', lastName: 'Doe' };
|
||||||
|
widget.multiSelect = false;
|
||||||
|
widget.onItemSelect(user);
|
||||||
|
expect(widget.selectedUsers).toContain(user);
|
||||||
|
expect(widget.field.value).toEqual(widget.selectedUsers[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add user to selectedUsers when multiSelect is true and user is already selected', () => {
|
||||||
|
const user: LightUserRepresentation = { id: 1, firstName: 'John', lastName: 'Doe' };
|
||||||
|
widget.multiSelect = true;
|
||||||
|
widget.selectedUsers = [user];
|
||||||
|
widget.onItemSelect(user);
|
||||||
|
expect(widget.selectedUsers.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear the input value after selection', () => {
|
||||||
|
const user: LightUserRepresentation = { id: 1, firstName: 'John', lastName: 'Doe' };
|
||||||
|
widget.input.nativeElement.value = 'test';
|
||||||
|
widget.onItemSelect(user);
|
||||||
|
expect(widget.input.nativeElement.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset the search term after selection', () => {
|
||||||
|
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(of(null));
|
||||||
|
const user: LightUserRepresentation = { id: 1, firstName: 'John', lastName: 'Doe' };
|
||||||
|
widget.searchTerm.setValue('test');
|
||||||
|
widget.onItemSelect(user);
|
||||||
|
expect(widget.searchTerm.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove user from selectedUsers if user exists', () => {
|
||||||
|
const users: LightUserRepresentation[] = [
|
||||||
|
{ id: 1, firstName: 'John', lastName: 'Doe' },
|
||||||
|
{ id: 2, firstName: 'Jane', lastName: 'Doe' }
|
||||||
|
];
|
||||||
|
|
||||||
|
widget.selectedUsers = [...users];
|
||||||
|
widget.onRemove(users[0]);
|
||||||
|
|
||||||
|
expect(widget.selectedUsers).not.toContain(users[0]);
|
||||||
|
expect(widget.field.value).toEqual([users[1]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change selectedUsers if user does not exist', () => {
|
||||||
|
const selectedUser: LightUserRepresentation = { id: 1, firstName: 'John', lastName: 'Doe' };
|
||||||
|
const anotherUser: LightUserRepresentation = { id: 2, firstName: 'Jane', lastName: 'Doe' };
|
||||||
|
widget.selectedUsers = [selectedUser];
|
||||||
|
widget.onRemove(anotherUser);
|
||||||
|
expect(widget.selectedUsers).toEqual([selectedUser]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when is required', () => {
|
describe('when is required', () => {
|
||||||
@ -274,16 +380,12 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
|
|
||||||
it('should emit peopleSelected if option is valid', async () => {
|
it('should emit peopleSelected if option is valid', async () => {
|
||||||
const selectEmitSpy = spyOn(widget.peopleSelected, 'emit');
|
const selectEmitSpy = spyOn(widget.peopleSelected, 'emit');
|
||||||
const peopleHTMLElement = element.querySelector<HTMLInputElement>('input');
|
widget.onItemSelect(fakeUserResult[0]);
|
||||||
peopleHTMLElement.focus();
|
|
||||||
peopleHTMLElement.value = 'Test01 Test01';
|
|
||||||
peopleHTMLElement.dispatchEvent(new Event('keyup'));
|
|
||||||
peopleHTMLElement.dispatchEvent(new Event('input'));
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(selectEmitSpy).toHaveBeenCalledWith(1001);
|
expect(selectEmitSpy).toHaveBeenCalledWith(fakeUserResult[0].id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display tooltip when tooltip is set', async () => {
|
it('should display tooltip when tooltip is set', async () => {
|
||||||
|
@ -20,8 +20,10 @@
|
|||||||
import { ErrorWidgetComponent, FormService, InitialUsernamePipe, WidgetComponent } from '@alfresco/adf-core';
|
import { ErrorWidgetComponent, FormService, InitialUsernamePipe, WidgetComponent } from '@alfresco/adf-core';
|
||||||
import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
||||||
|
import { MatChipsModule } from '@angular/material/chips';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
|
import { catchError, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
||||||
import { PeopleProcessService } from '../../../services/people-process.service';
|
import { PeopleProcessService } from '../../../services/people-process.service';
|
||||||
import { LightUserRepresentation } from '@alfresco/js-api';
|
import { LightUserRepresentation } from '@alfresco/js-api';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
@ -38,6 +40,8 @@ import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|||||||
TranslateModule,
|
TranslateModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatIconModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
InitialUsernamePipe,
|
InitialUsernamePipe,
|
||||||
@ -66,20 +70,19 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
@Output()
|
@Output()
|
||||||
peopleSelected: EventEmitter<number> = new EventEmitter();
|
peopleSelected: EventEmitter<number> = new EventEmitter();
|
||||||
|
|
||||||
|
selectedUsers: LightUserRepresentation[] = [];
|
||||||
|
multiSelect = false;
|
||||||
groupId: number;
|
groupId: number;
|
||||||
value: any;
|
|
||||||
|
|
||||||
searchTerm = new UntypedFormControl();
|
searchTerm = new UntypedFormControl();
|
||||||
searchTerms$: Observable<any> = this.searchTerm.valueChanges;
|
searchTerms$: Observable<any> = this.searchTerm.valueChanges;
|
||||||
|
|
||||||
users$ = this.searchTerms$.pipe(
|
users$: Observable<LightUserRepresentation[]> = this.searchTerms$.pipe(
|
||||||
tap((searchInput) => {
|
|
||||||
if (typeof searchInput === 'string') {
|
|
||||||
this.onItemSelect();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
switchMap((searchTerm) => {
|
switchMap((searchTerm) => {
|
||||||
|
if (!searchTerm) {
|
||||||
|
return of([]);
|
||||||
|
}
|
||||||
const value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm;
|
const value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm;
|
||||||
return this.peopleProcessService.getWorkflowUsers(undefined, value, this.groupId).pipe(catchError(() => of([])));
|
return this.peopleProcessService.getWorkflowUsers(undefined, value, this.groupId).pipe(catchError(() => of([])));
|
||||||
}),
|
}),
|
||||||
@ -97,16 +100,16 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.field) {
|
if (this.field) {
|
||||||
if (this.field.value) {
|
if (this.field.value) {
|
||||||
this.searchTerm.setValue(this.field.value);
|
Array.isArray(this.field.value) ? this.selectedUsers.push(...this.field.value) : this.selectedUsers.push(this.field.value);
|
||||||
}
|
|
||||||
if (this.field.readOnly) {
|
|
||||||
this.searchTerm.disable();
|
|
||||||
}
|
}
|
||||||
const params = this.field.params;
|
const params = this.field.params;
|
||||||
if (params?.restrictWithGroup) {
|
if (params?.restrictWithGroup) {
|
||||||
const restrictWithGroup = params.restrictWithGroup;
|
const restrictWithGroup = params.restrictWithGroup;
|
||||||
this.groupId = restrictWithGroup.id;
|
this.groupId = restrictWithGroup.id;
|
||||||
}
|
}
|
||||||
|
if (params?.multiple) {
|
||||||
|
this.multiSelect = params.multiple;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +129,7 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
isValidUser(users: LightUserRepresentation[], name: string): boolean {
|
isValidUser(users: LightUserRepresentation[], name: string): boolean {
|
||||||
if (users) {
|
if (users) {
|
||||||
return !!users.find((user) => {
|
return !!users.find((user) => {
|
||||||
const selectedUser = this.getDisplayName(user).toLocaleLowerCase() === name.toLocaleLowerCase();
|
return this.getDisplayName(user).toLocaleLowerCase() === name.toLocaleLowerCase();
|
||||||
if (selectedUser) {
|
|
||||||
this.peopleSelected.emit(user?.id || undefined);
|
|
||||||
}
|
|
||||||
return selectedUser;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -144,11 +143,36 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemSelect(item?: LightUserRepresentation) {
|
onRemove(user: LightUserRepresentation) {
|
||||||
if (item) {
|
const index = this.selectedUsers.indexOf(user);
|
||||||
this.field.value = item;
|
if (index >= 0) {
|
||||||
} else {
|
this.selectedUsers.splice(index, 1);
|
||||||
this.field.value = null;
|
this.field.value = this.selectedUsers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onItemSelect(user: LightUserRepresentation) {
|
||||||
|
if (this.multiSelect) {
|
||||||
|
if (!this.isUserAlreadySelected(user)) {
|
||||||
|
this.selectedUsers.push(user);
|
||||||
|
}
|
||||||
|
this.field.value = this.selectedUsers;
|
||||||
|
} else {
|
||||||
|
this.selectedUsers = [user];
|
||||||
|
this.field.value = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.peopleSelected.emit(user?.id || undefined);
|
||||||
|
this.input.nativeElement.value = '';
|
||||||
|
this.searchTerm.setValue('');
|
||||||
|
}
|
||||||
|
|
||||||
|
isUserAlreadySelected(user: LightUserRepresentation): boolean {
|
||||||
|
if (this.selectedUsers?.length > 0) {
|
||||||
|
const result = this.selectedUsers.find((selectedUser) => selectedUser.id === user.id);
|
||||||
|
|
||||||
|
return !!result;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,8 @@
|
|||||||
"LABEL": {
|
"LABEL": {
|
||||||
"SELECT_APPLICATION": "Select Application",
|
"SELECT_APPLICATION": "Select Application",
|
||||||
"TYPE": "Select Process",
|
"TYPE": "Select Process",
|
||||||
"NAME": "Process Name"
|
"NAME": "Process Name",
|
||||||
|
"SELECTED_PEOPLE": "Selected people"
|
||||||
},
|
},
|
||||||
"TYPE_PLACEHOLDER": "Choose one...",
|
"TYPE_PLACEHOLDER": "Choose one...",
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user