mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[ADF-1532] Assignee typeahead in start task form (#2839)
* people module directory restructuring * Extract PeopleSearchFieldComponent to reuse most part of it * Transform PeopleSearchFieldComponent to the form we want to reuse * People selector component, first try * Remove material grid from start-task.component, first part * Styling and i18n * clear button for deleting the selected assignee * Remove people preloading, remove combobox and update assigneeId * Fix existing tests * Add new tests * Final css fixes
This commit is contained in:
parent
74cd0fab33
commit
9bd18c9770
@ -141,6 +141,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"PEOPLE": {
|
"PEOPLE": {
|
||||||
|
"ASSIGNEE": "Assignee",
|
||||||
"DIALOG_CLOSE": "CLOSE",
|
"DIALOG_CLOSE": "CLOSE",
|
||||||
"ADD_USER": "ADD",
|
"ADD_USER": "ADD",
|
||||||
"ADD_ASSIGNEE": "ASSIGN",
|
"ADD_ASSIGNEE": "ASSIGN",
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { UserProcessModel } from '@alfresco/adf-core';
|
import { UserProcessModel } from '@alfresco/adf-core';
|
||||||
import { DataRowActionEvent, DataRowEvent, ObjectDataRow } from '@alfresco/adf-core';
|
import { DataRowActionEvent, DataRowEvent, ObjectDataRow } from '@alfresco/adf-core';
|
||||||
import { UserEventModel } from '../task-list/models/user-event.model';
|
import { UserEventModel } from '../../../task-list/models/user-event.model';
|
||||||
import { PeopleListComponent } from './people-list.component';
|
import { PeopleListComponent } from './people-list.component';
|
||||||
|
|
||||||
const fakeUser: UserProcessModel = new UserProcessModel({
|
const fakeUser: UserProcessModel = new UserProcessModel({
|
@ -18,7 +18,7 @@
|
|||||||
import { DataTableComponent } from '@alfresco/adf-core';
|
import { DataTableComponent } from '@alfresco/adf-core';
|
||||||
import { DataColumnListComponent, UserProcessModel } from '@alfresco/adf-core';
|
import { DataColumnListComponent, UserProcessModel } from '@alfresco/adf-core';
|
||||||
import { AfterContentInit, AfterViewInit, Component, ContentChild, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
import { AfterContentInit, AfterViewInit, Component, ContentChild, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||||
import { UserEventModel } from '../task-list/models/user-event.model';
|
import { UserEventModel } from '../../../task-list/models/user-event.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-people-list',
|
selector: 'adf-people-list',
|
@ -0,0 +1,33 @@
|
|||||||
|
<mat-form-field class="search-text-container">
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
placeholder="{{ searchPlaceholder }}"
|
||||||
|
type="text"
|
||||||
|
id="userSearchText"
|
||||||
|
[value]=""
|
||||||
|
[formControl]="searchUser"
|
||||||
|
data-automation-id="adf-people-search-input">
|
||||||
|
</mat-form-field>
|
||||||
|
<ng-container *ngIf="users$ | async; let users">
|
||||||
|
<div class="search-list-container" id="search-people-list" *ngIf="users.length > 0">
|
||||||
|
<adf-people-list [users]="users" (clickRow)="onRowClick($event)">
|
||||||
|
<data-columns>
|
||||||
|
<data-column key="firstName">
|
||||||
|
<ng-template let-entry="$implicit">
|
||||||
|
<div *ngIf="!entry.row.obj.pictureId" class="people-pic">
|
||||||
|
{{getInitialUserName(entry.row.obj.firstName, entry.row.obj.lastName)}}</div>
|
||||||
|
<div>
|
||||||
|
<img *ngIf="entry.row.obj.pictureId" class="people-img"
|
||||||
|
[src]="peopleProcessService.getUserImage(entry.row.obj)"/>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</data-column>
|
||||||
|
<data-column key="email" class="full-width">
|
||||||
|
<ng-template let-entry="$implicit">
|
||||||
|
<div class="people-full-name">{{ getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ') }}</div>
|
||||||
|
</ng-template>
|
||||||
|
</data-column>
|
||||||
|
</data-columns>
|
||||||
|
</adf-people-list>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
@ -1,27 +1,11 @@
|
|||||||
@mixin adf-task-list-people-search-theme($theme) {
|
@mixin adf-task-list-people-search-field-theme($theme) {
|
||||||
$primary: map-get($theme, primary);
|
$primary: map-get($theme, primary);
|
||||||
$accent: map-get($theme, accent);
|
$accent: map-get($theme, accent);
|
||||||
$warn: map-get($theme, warn);
|
$warn: map-get($theme, warn);
|
||||||
|
|
||||||
.adf-people-search {
|
.adf-people-search-field {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.activiti-label {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fix-element-user-list {
|
|
||||||
padding-top: 0px;
|
|
||||||
padding-right: 0px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
padding-left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-text-header {
|
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0.54;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-text-container {
|
.search-text-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@ -40,20 +24,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-list-action-container {
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
text-align: right;
|
|
||||||
padding: 5px 0px;
|
|
||||||
margin-top: 5px;
|
|
||||||
> button {
|
|
||||||
opacity: 0.54;
|
|
||||||
font-weight: bolder;
|
|
||||||
&:hover {
|
|
||||||
color: mat-color($primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.people-pic {
|
.people-pic {
|
||||||
background: mat-color($primary);
|
background: mat-color($primary);
|
||||||
width: 30px;
|
width: 30px;
|
@ -0,0 +1,79 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
import { MatButtonModule, MatInputModule } from '@angular/material';
|
||||||
|
import { TranslationService, TranslationMock } from '@alfresco/adf-core';
|
||||||
|
import { PeopleSearchFieldComponent } from './people-search-field.component';
|
||||||
|
import { PeopleListComponent } from '../people-list/people-list.component';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
describe('PeopleSearchFieldComponent', () => {
|
||||||
|
|
||||||
|
let component: PeopleSearchFieldComponent;
|
||||||
|
let fixture: ComponentFixture<PeopleSearchFieldComponent>;
|
||||||
|
let debug: DebugElement;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
MatButtonModule,
|
||||||
|
MatInputModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
PeopleListComponent,
|
||||||
|
PeopleSearchFieldComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: TranslationService, useClass: TranslationMock }
|
||||||
|
]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PeopleSearchFieldComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
debug = fixture.debugElement;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the proper placeholder by default', () => {
|
||||||
|
let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
|
||||||
|
expect(searchField.placeholder).toBe('ADF_TASK_LIST.PEOPLE.SEARCH_USER');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the overridden placeholder if set as input parameter', () => {
|
||||||
|
component.placeholder = 'Arcadia Bay';
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
|
||||||
|
expect(searchField.placeholder).toBe('Arcadia Bay');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset the user on reset method invocation', () => {
|
||||||
|
let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
|
||||||
|
searchField.value = 'User to be searched';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.reset();
|
||||||
|
|
||||||
|
searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
|
||||||
|
expect(searchField.value).toBe('');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,85 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { UserProcessModel, TranslationService } from '@alfresco/adf-core';
|
||||||
|
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { debounceTime } from 'rxjs/operators';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { PerformSearchCallback } from '../../interfaces/perform-search-callback.interface';
|
||||||
|
import { getDisplayUser } from '../../helpers/getDisplayUser';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-people-search-field',
|
||||||
|
templateUrl: './people-search-field.component.html',
|
||||||
|
styleUrls: ['./people-search-field.component.scss'],
|
||||||
|
host: { 'class': 'adf-people-search-field' },
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PeopleSearchFieldComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
performSearch: PerformSearchCallback;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
placeholder: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
rowClick: EventEmitter<UserProcessModel> = new EventEmitter<UserProcessModel>();
|
||||||
|
|
||||||
|
users$: Observable<UserProcessModel[]>;
|
||||||
|
searchUser: FormControl = new FormControl();
|
||||||
|
|
||||||
|
defaultPlaceholder = 'ADF_TASK_LIST.PEOPLE.SEARCH_USER';
|
||||||
|
|
||||||
|
constructor(private translationService: TranslationService) {
|
||||||
|
this.users$ = this.searchUser.valueChanges
|
||||||
|
.pipe(debounceTime(200))
|
||||||
|
.switchMap((searchWord: string) => {
|
||||||
|
if (searchWord && searchWord.trim()) {
|
||||||
|
return this.performSearch(searchWord);
|
||||||
|
} else {
|
||||||
|
return Observable.of([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.defaultPlaceholder = this.translationService.instant(this.defaultPlaceholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public reset() {
|
||||||
|
this.searchUser.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
get searchPlaceholder() {
|
||||||
|
return this.placeholder || this.defaultPlaceholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(event) {
|
||||||
|
this.rowClick.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string {
|
||||||
|
return getDisplayUser(firstName, lastName, delimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialUserName(firstName: string, lastName: string) {
|
||||||
|
firstName = (firstName !== null && firstName !== '' ? firstName[0] : '');
|
||||||
|
lastName = (lastName !== null && lastName !== '' ? lastName[0] : '');
|
||||||
|
return this.getDisplayUser(firstName, lastName, '');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<div class="search-text-header">
|
||||||
|
<ng-content select="[people-search-title]"></ng-content>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<adf-people-search-field [performSearch]="performSearch" (rowClick)="onRowClick($event)"></adf-people-search-field>
|
||||||
|
|
||||||
|
<div class="search-list-action-container">
|
||||||
|
<button mat-button type="button" id="close-people-search" (click)="closeSearchList()">
|
||||||
|
{{'ADF_TASK_LIST.PEOPLE.DIALOG_CLOSE' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-button type="button" id="add-people" (click)="involveUserAndClose()">
|
||||||
|
<ng-content select="[people-search-action-label]"></ng-content>
|
||||||
|
</button>
|
||||||
|
</div>
|
@ -0,0 +1,39 @@
|
|||||||
|
@mixin adf-task-list-people-search-theme($theme) {
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$accent: map-get($theme, accent);
|
||||||
|
$warn: map-get($theme, warn);
|
||||||
|
|
||||||
|
.adf-people-search {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fix-element-user-list {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-text-header {
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: 0.54;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-list-action-container {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
text-align: right;
|
||||||
|
padding: 5px 0px;
|
||||||
|
margin-top: 5px;
|
||||||
|
> button {
|
||||||
|
opacity: 0.54;
|
||||||
|
font-weight: bolder;
|
||||||
|
&:hover {
|
||||||
|
color: mat-color($primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,10 +17,11 @@
|
|||||||
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatButtonModule, MatInputModule } from '@angular/material';
|
import { MatButtonModule, MatInputModule } from '@angular/material';
|
||||||
import { UserProcessModel } from '@alfresco/adf-core';
|
import { UserProcessModel, TranslationService, TranslationMock } from '@alfresco/adf-core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { PeopleListComponent } from './people-list.component';
|
import { PeopleListComponent } from '../people-list/people-list.component';
|
||||||
import { PeopleSearchComponent } from './people-search.component';
|
import { PeopleSearchComponent } from './people-search.component';
|
||||||
|
import { PeopleSearchFieldComponent } from '../people-search-field/people-search-field.component';
|
||||||
|
|
||||||
const fakeUser: UserProcessModel = new UserProcessModel({
|
const fakeUser: UserProcessModel = new UserProcessModel({
|
||||||
id: '1',
|
id: '1',
|
||||||
@ -52,9 +53,11 @@ describe('PeopleSearchComponent', () => {
|
|||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
PeopleSearchComponent,
|
PeopleSearchComponent,
|
||||||
|
PeopleSearchFieldComponent,
|
||||||
PeopleListComponent
|
PeopleListComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
{ provide: TranslationService, useClass: TranslationMock }
|
||||||
]
|
]
|
||||||
}).compileComponents().then(() => {
|
}).compileComponents().then(() => {
|
||||||
|
|
||||||
@ -81,22 +84,21 @@ describe('PeopleSearchComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should show user which can be involved ', (done) => {
|
it('should show user which can be involved ', (done) => {
|
||||||
peopleSearchComponent.searchPeople.subscribe(() => {
|
peopleSearchComponent.results = Observable.of(userArray);
|
||||||
peopleSearchComponent.results = Observable.of(userArray);
|
peopleSearchComponent.ngOnInit();
|
||||||
peopleSearchComponent.ngOnInit();
|
fixture.detectChanges();
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.whenStable()
|
|
||||||
.then(() => {
|
|
||||||
let gatewayElement: any = element.querySelector('#search-people-list tbody');
|
|
||||||
expect(gatewayElement).not.toBeNull();
|
|
||||||
expect(gatewayElement.children.length).toBe(2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
searchInput = element.querySelector('#userSearchText');
|
searchInput = element.querySelector('#userSearchText');
|
||||||
searchInput.value = 'fake-search';
|
searchInput.value = 'fake-search';
|
||||||
peopleSearchComponent.searchUser.markAsDirty();
|
|
||||||
searchInput.dispatchEvent(new Event('input'));
|
searchInput.dispatchEvent(new Event('input'));
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let gatewayElement: any = element.querySelector('#search-people-list tbody');
|
||||||
|
expect(gatewayElement).not.toBeNull();
|
||||||
|
expect(gatewayElement.children.length).toBe(2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send an event when an user is clicked', (done) => {
|
it('should send an event when an user is clicked', (done) => {
|
||||||
@ -120,13 +122,20 @@ describe('PeopleSearchComponent', () => {
|
|||||||
peopleSearchComponent.results = Observable.of(userArray);
|
peopleSearchComponent.results = Observable.of(userArray);
|
||||||
peopleSearchComponent.ngOnInit();
|
peopleSearchComponent.ngOnInit();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
searchInput = element.querySelector('#userSearchText');
|
||||||
|
searchInput.value = 'fake-search';
|
||||||
|
searchInput.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
peopleSearchComponent.onRowClick(fakeUser);
|
peopleSearchComponent.onRowClick(fakeUser);
|
||||||
let addUserButton = <HTMLElement> element.querySelector('#add-people');
|
let addUserButton = <HTMLElement> element.querySelector('#add-people');
|
||||||
addUserButton.click();
|
addUserButton.click();
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable()
|
fixture.whenStable()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
let gatewayElement: any = element.querySelector('#search-people-list tbody');
|
let gatewayElement: any = element.querySelector('#search-people-list tbody');
|
||||||
expect(gatewayElement).not.toBeNull();
|
expect(gatewayElement).not.toBeNull();
|
||||||
expect(gatewayElement.children.length).toBe(1);
|
expect(gatewayElement.children.length).toBe(1);
|
@ -0,0 +1,84 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { UserProcessModel } from '@alfresco/adf-core';
|
||||||
|
import { Component, EventEmitter, OnInit, Input, Output, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { PerformSearchCallback } from '../../interfaces/perform-search-callback.interface';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-people-search',
|
||||||
|
templateUrl: './people-search.component.html',
|
||||||
|
styleUrls: ['./people-search.component.scss'],
|
||||||
|
host: {
|
||||||
|
'class': 'adf-people-search'
|
||||||
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PeopleSearchComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
results: Observable<UserProcessModel[]>;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
searchPeople: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
success: EventEmitter<UserProcessModel> = new EventEmitter<UserProcessModel>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
closeSearch = new EventEmitter();
|
||||||
|
|
||||||
|
filteredResults$: Observable<UserProcessModel[]>;
|
||||||
|
selectedUser: UserProcessModel = {};
|
||||||
|
performSearch: PerformSearchCallback;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.filteredResults$ = this.results.map((users) => {
|
||||||
|
return users.filter(user => user.id !== this.selectedUser.id);
|
||||||
|
});
|
||||||
|
this.performSearch = this.performSearchCallback.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private performSearchCallback(event): Observable<UserProcessModel[]> {
|
||||||
|
this.searchPeople.emit(event);
|
||||||
|
return this.filteredResults$;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(user: UserProcessModel) {
|
||||||
|
this.selectedUser = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeSearchList() {
|
||||||
|
this.closeSearch.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
involveUserAndClose() {
|
||||||
|
this.involveUser();
|
||||||
|
this.closeSearchList();
|
||||||
|
}
|
||||||
|
|
||||||
|
involveUser() {
|
||||||
|
if (this.selectedUser === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.success.emit(this.selectedUser);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<adf-people-search-field
|
||||||
|
class="adf-people-selector-field"
|
||||||
|
[performSearch]="performSearch"
|
||||||
|
[placeholder]="placeholder"
|
||||||
|
(rowClick)="userSelected($event)">
|
||||||
|
</adf-people-search-field>
|
||||||
|
<button
|
||||||
|
*ngIf="selectedUser"
|
||||||
|
mat-icon-button
|
||||||
|
class="adf-people-selector-deselect"
|
||||||
|
data-automation-id="adf-people-selector-deselect"
|
||||||
|
(click)="userDeselected()">
|
||||||
|
<mat-icon>cancel</mat-icon>
|
||||||
|
</button>
|
@ -0,0 +1,21 @@
|
|||||||
|
@mixin adf-task-list-people-selector-theme($theme) {
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$accent: map-get($theme, accent);
|
||||||
|
$warn: map-get($theme, warn);
|
||||||
|
|
||||||
|
.adf-people-selector {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&-field {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-deselect {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { MatButtonModule, MatInputModule } from '@angular/material';
|
||||||
|
import { LogService, TranslationService, TranslationMock, PeopleProcessService } from '@alfresco/adf-core';
|
||||||
|
import { PeopleSearchFieldComponent } from '../people-search-field/people-search-field.component';
|
||||||
|
import { PeopleListComponent } from '../people-list/people-list.component';
|
||||||
|
import { PeopleSelectorComponent } from './people-selector.component';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
describe('PeopleSelectorComponent', () => {
|
||||||
|
|
||||||
|
let component: PeopleSelectorComponent;
|
||||||
|
let fixture: ComponentFixture<PeopleSelectorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
MatButtonModule,
|
||||||
|
MatInputModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
PeopleListComponent,
|
||||||
|
PeopleSearchFieldComponent,
|
||||||
|
PeopleSelectorComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: TranslationService, useClass: TranslationMock },
|
||||||
|
{ provide: LogService, useValue: {error: () => {} }},
|
||||||
|
PeopleProcessService
|
||||||
|
]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PeopleSelectorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the proper placeholder by default', () => {
|
||||||
|
expect(component.placeholder).toBe('ADF_TASK_LIST.PEOPLE.ASSIGNEE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the selected user\'s details as placeholder if one is set', () => {
|
||||||
|
component.selectedUser = {
|
||||||
|
firstName: 'Max',
|
||||||
|
lastName: 'CaulField'
|
||||||
|
};
|
||||||
|
expect(component.placeholder).toBe('Max CaulField');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the PeopleProcessService\'s getWorkflowUsers method on search', () => {
|
||||||
|
const peopleProcessService = TestBed.get(PeopleProcessService);
|
||||||
|
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(Observable.of([]));
|
||||||
|
|
||||||
|
component.performSearch('Chloe Price');
|
||||||
|
|
||||||
|
expect(peopleProcessService.getWorkflowUsers).toHaveBeenCalledWith(undefined, 'Chloe Price');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log error on getWorkflowUsers\'s error', () => {
|
||||||
|
const peopleProcessService = TestBed.get(PeopleProcessService);
|
||||||
|
const logService = TestBed.get(LogService);
|
||||||
|
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(Observable.throw(new Error()));
|
||||||
|
spyOn(logService, 'error');
|
||||||
|
|
||||||
|
component.performSearch('Chloe Price')
|
||||||
|
.subscribe((people) => {
|
||||||
|
expect(people).toEqual([]);
|
||||||
|
expect(logService.error).toHaveBeenCalledWith('getWorkflowUsers threw error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit an event with the selected users\'s id when userSelected method is invoked', (done) => {
|
||||||
|
|
||||||
|
component.peopleIdChange.subscribe((userId) => {
|
||||||
|
expect(userId).toBe(789);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
component.userSelected({id: 789});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit an event with undefined when reset button is clicked', (done) => {
|
||||||
|
component.selectedUser = { id: 746 };
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.peopleIdChange.subscribe((userId) => {
|
||||||
|
expect(userId).toBe(undefined);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
const resetButton = fixture.debugElement.query(By.css('[data-automation-id="adf-people-selector-deselect"]'));
|
||||||
|
resetButton.triggerEventHandler('click', {});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,92 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { Component, ViewChild, ViewEncapsulation, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { PerformSearchCallback } from '../../interfaces/perform-search-callback.interface';
|
||||||
|
import { PeopleProcessService, UserProcessModel, LogService, TranslationService } from '@alfresco/adf-core';
|
||||||
|
import { PeopleSearchFieldComponent } from '../people-search-field/people-search-field.component';
|
||||||
|
import { getDisplayUser } from '../../helpers/getDisplayUser';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
const DEFAULT_ASSIGNEE_PLACEHOLDER = 'ADF_TASK_LIST.PEOPLE.ASSIGNEE';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-people-selector',
|
||||||
|
templateUrl: './people-selector.component.html',
|
||||||
|
styleUrls: ['./people-selector.component.scss'],
|
||||||
|
host: { 'class': 'adf-people-selector' },
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PeopleSelectorComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
peopleId: UserProcessModel;
|
||||||
|
|
||||||
|
// Poorly documented Angular magic for [(peopleId)]
|
||||||
|
@Output()
|
||||||
|
peopleIdChange: EventEmitter<number>;
|
||||||
|
|
||||||
|
@ViewChild(PeopleSearchFieldComponent)
|
||||||
|
searchFieldComponent: PeopleSearchFieldComponent;
|
||||||
|
|
||||||
|
performSearch: PerformSearchCallback;
|
||||||
|
selectedUser: UserProcessModel;
|
||||||
|
defaultPlaceholder: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private peopleProcessService: PeopleProcessService,
|
||||||
|
private logService: LogService,
|
||||||
|
private translationService: TranslationService) {
|
||||||
|
|
||||||
|
this.peopleIdChange = new EventEmitter();
|
||||||
|
this.performSearch = this.searchUser.bind(this);
|
||||||
|
this.defaultPlaceholder = this.translationService.instant(DEFAULT_ASSIGNEE_PLACEHOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchUser(searchWord: string): Observable<{} | UserProcessModel[]> {
|
||||||
|
return this.peopleProcessService.getWorkflowUsers(undefined, searchWord)
|
||||||
|
.catch(this.onSearchUserError.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private onSearchUserError(): Observable<UserProcessModel[]> {
|
||||||
|
this.logService.error('getWorkflowUsers threw error');
|
||||||
|
return Observable.of([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
userSelected(user: UserProcessModel): void {
|
||||||
|
this.updateUserSelection(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
userDeselected(): void {
|
||||||
|
this.updateUserSelection(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateUserSelection(user: UserProcessModel): void {
|
||||||
|
this.selectedUser = user;
|
||||||
|
this.peopleIdChange.emit(user && user.id || undefined);
|
||||||
|
this.searchFieldComponent.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
get placeholder() {
|
||||||
|
if (!this.selectedUser) {
|
||||||
|
return this.defaultPlaceholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDisplayUser(this.selectedUser.firstName, this.selectedUser.lastName, ' ');
|
||||||
|
}
|
||||||
|
}
|
@ -51,13 +51,13 @@
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
adf-people-list adf-datatable {
|
adf-people-list adf-datatable {
|
||||||
thead {
|
thead {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-data-table .adf-data-table-cell .cell-container {
|
.adf-data-table .adf-data-table-cell .cell-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: left;
|
align-items: left;
|
@ -20,8 +20,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { MatButtonModule, MatInputModule } from '@angular/material';
|
import { MatButtonModule, MatInputModule } from '@angular/material';
|
||||||
import { LogService } from '@alfresco/adf-core';
|
import { LogService } from '@alfresco/adf-core';
|
||||||
import { PeopleProcessService, UserProcessModel } from '@alfresco/adf-core';
|
import { PeopleProcessService, UserProcessModel } from '@alfresco/adf-core';
|
||||||
import { PeopleListComponent } from './people-list.component';
|
import { PeopleListComponent } from '../people-list/people-list.component';
|
||||||
import { PeopleSearchComponent } from './people-search.component';
|
import { PeopleSearchComponent } from '../people-search/people-search.component';
|
||||||
import { PeopleComponent } from './people.component';
|
import { PeopleComponent } from './people.component';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
@ -20,8 +20,8 @@ import { PeopleProcessService } from '@alfresco/adf-core';
|
|||||||
import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Observer } from 'rxjs/Observer';
|
import { Observer } from 'rxjs/Observer';
|
||||||
import { UserEventModel } from '../task-list/models/user-event.model';
|
import { UserEventModel } from '../../../task-list/models/user-event.model';
|
||||||
import { PeopleSearchComponent } from './people-search.component';
|
import { PeopleSearchComponent } from '../people-search/people-search.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-people',
|
selector: 'adf-people',
|
@ -0,0 +1,21 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { Directive } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({ selector: 'people-search-action-label' })
|
||||||
|
export class PeopleSearchActionLabelDirective { }
|
@ -0,0 +1,21 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { Directive } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({ selector: 'people-search-title' })
|
||||||
|
export class PeopleSearchTitleDirective { }
|
22
lib/process-services/people/helpers/getDisplayUser.ts
Normal file
22
lib/process-services/people/helpers/getDisplayUser.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string {
|
||||||
|
firstName = (firstName !== null ? firstName : '');
|
||||||
|
lastName = (lastName !== null ? lastName : '');
|
||||||
|
return firstName + delimiter + lastName;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 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 { Observable } from 'rxjs/Observable';
|
||||||
|
import { UserProcessModel } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
export type PerformSearchCallback = (searchWord: string) => Observable<UserProcessModel[]>;
|
@ -1,37 +0,0 @@
|
|||||||
<div class="search-text-header">
|
|
||||||
<ng-content select="[people-search-title]"></ng-content>
|
|
||||||
</div>
|
|
||||||
<mat-form-field class="search-text-container">
|
|
||||||
<input matInput placeholder="{{'ADF_TASK_LIST.PEOPLE.SEARCH_USER'|translate}}" type="text" id="userSearchText" [value]="" [formControl]="searchUser">
|
|
||||||
</mat-form-field>
|
|
||||||
<div class="search-list-container" id="search-people-list" *ngIf="hasUsers()">
|
|
||||||
<adf-people-list
|
|
||||||
[users]="users"
|
|
||||||
(clickRow)="onRowClick($event)">
|
|
||||||
<data-columns>
|
|
||||||
<data-column key="firstName">
|
|
||||||
<ng-template let-entry="$implicit">
|
|
||||||
<div *ngIf="!entry.row.obj.pictureId" class="people-pic">
|
|
||||||
{{getInitialUserName(entry.row.obj.firstName, entry.row.obj.lastName)}}</div>
|
|
||||||
<div>
|
|
||||||
<img *ngIf="entry.row.obj.pictureId" class="people-img"
|
|
||||||
[src]="peopleProcessService.getUserImage(entry.row.obj)"/>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
</data-column>
|
|
||||||
<data-column key="email" class="full-width">
|
|
||||||
<ng-template let-entry="$implicit">
|
|
||||||
<div class="people-full-name">{{ getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ') }}</div>
|
|
||||||
</ng-template>
|
|
||||||
</data-column>
|
|
||||||
</data-columns>
|
|
||||||
</adf-people-list>
|
|
||||||
</div>
|
|
||||||
<div class="search-list-action-container">
|
|
||||||
<button mat-button type="button" id="close-people-search" (click)="closeSearchList()">
|
|
||||||
{{'ADF_TASK_LIST.PEOPLE.DIALOG_CLOSE' | translate }}
|
|
||||||
</button>
|
|
||||||
<button mat-button type="button" id="add-people" (click)="involveUserAndClose()">
|
|
||||||
<ng-content select="[people-search-action-label]"></ng-content>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
@ -1,116 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright 2016 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 { PeopleProcessService, UserProcessModel } from '@alfresco/adf-core';
|
|
||||||
import { Component, Directive, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
|
||||||
import { FormControl } from '@angular/forms';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { debounceTime } from 'rxjs/operators';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'adf-people-search',
|
|
||||||
templateUrl: './people-search.component.html',
|
|
||||||
styleUrls: ['./people-search.component.scss'],
|
|
||||||
host: {
|
|
||||||
'class': 'adf-people-search'
|
|
||||||
},
|
|
||||||
encapsulation: ViewEncapsulation.None
|
|
||||||
})
|
|
||||||
|
|
||||||
export class PeopleSearchComponent implements OnInit {
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
results: Observable<UserProcessModel[]>;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
searchPeople: EventEmitter<any> = new EventEmitter();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
success: EventEmitter<UserProcessModel> = new EventEmitter<UserProcessModel>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closeSearch = new EventEmitter();
|
|
||||||
|
|
||||||
searchUser: FormControl = new FormControl();
|
|
||||||
|
|
||||||
users: UserProcessModel[] = [];
|
|
||||||
|
|
||||||
selectedUser: UserProcessModel;
|
|
||||||
|
|
||||||
constructor(public peopleProcessService: PeopleProcessService) {
|
|
||||||
this.searchUser.valueChanges
|
|
||||||
.pipe(
|
|
||||||
debounceTime(200)
|
|
||||||
)
|
|
||||||
.subscribe((event: string) => {
|
|
||||||
if (event && event.trim()) {
|
|
||||||
this.searchPeople.emit(event);
|
|
||||||
} else {
|
|
||||||
this.users = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.results.subscribe((list) => {
|
|
||||||
this.users = list;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowClick(user: UserProcessModel) {
|
|
||||||
this.selectedUser = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
closeSearchList() {
|
|
||||||
this.closeSearch.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
involveUserAndClose() {
|
|
||||||
this.involveUser();
|
|
||||||
this.closeSearchList();
|
|
||||||
}
|
|
||||||
|
|
||||||
involveUser() {
|
|
||||||
if (this.selectedUser === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.success.emit(this.selectedUser);
|
|
||||||
this.users = this.users.filter((user) => {
|
|
||||||
this.searchUser.reset();
|
|
||||||
return user.id !== this.selectedUser.id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string {
|
|
||||||
firstName = (firstName !== null ? firstName : '');
|
|
||||||
lastName = (lastName !== null ? lastName : '');
|
|
||||||
return firstName + delimiter + lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
getInitialUserName(firstName: string, lastName: string) {
|
|
||||||
firstName = (firstName !== null && firstName !== '' ? firstName[0] : '');
|
|
||||||
lastName = (lastName !== null && lastName !== '' ? lastName[0] : '');
|
|
||||||
return this.getDisplayUser(firstName, lastName, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
hasUsers() {
|
|
||||||
return (this.users && this.users.length > 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Directive({ selector: 'people-search-title' }) export class PeopleSearchTitleDirective { }
|
|
||||||
@Directive({ selector: 'people-search-action-label' }) export class PeopleSearchActionLabelDirective { }
|
|
11
lib/process-services/people/people.module.scss
Normal file
11
lib/process-services/people/people.module.scss
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@import './components/people-search/people-search.component';
|
||||||
|
@import './components/people-search-field/people-search-field.component';
|
||||||
|
@import './components/people/people.component';
|
||||||
|
@import './components/people-selector/people-selector.component';
|
||||||
|
|
||||||
|
@mixin adf-people-module-theme($theme) {
|
||||||
|
@include adf-task-list-people-selector-theme($theme);
|
||||||
|
@include adf-task-list-people-search-theme($theme);
|
||||||
|
@include adf-task-list-people-search-field-theme($theme);
|
||||||
|
@include adf-task-list-people-theme($theme);
|
||||||
|
}
|
@ -22,9 +22,14 @@ import { MaterialModule } from '../material.module';
|
|||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { DataColumnModule, DataTableModule } from '@alfresco/adf-core';
|
import { DataColumnModule, DataTableModule } from '@alfresco/adf-core';
|
||||||
import { PeopleComponent } from './people.component';
|
import { PeopleComponent } from './components/people/people.component';
|
||||||
import { PeopleListComponent } from './people-list.component';
|
import { PeopleListComponent } from './components/people-list/people-list.component';
|
||||||
import { PeopleSearchActionLabelDirective, PeopleSearchComponent, PeopleSearchTitleDirective } from './people-search.component';
|
import { PeopleSearchComponent } from './components/people-search/people-search.component';
|
||||||
|
import { PeopleSearchFieldComponent } from './components/people-search-field/people-search-field.component';
|
||||||
|
import { PeopleSelectorComponent } from './components/people-selector/people-selector.component';
|
||||||
|
|
||||||
|
import { PeopleSearchActionLabelDirective } from './directives/people-search-action-label.directive';
|
||||||
|
import { PeopleSearchTitleDirective } from './directives/people-search-title.directive';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -39,6 +44,8 @@ import { PeopleSearchActionLabelDirective, PeopleSearchComponent, PeopleSearchTi
|
|||||||
declarations: [
|
declarations: [
|
||||||
PeopleComponent,
|
PeopleComponent,
|
||||||
PeopleSearchComponent,
|
PeopleSearchComponent,
|
||||||
|
PeopleSearchFieldComponent,
|
||||||
|
PeopleSelectorComponent,
|
||||||
PeopleSearchTitleDirective,
|
PeopleSearchTitleDirective,
|
||||||
PeopleSearchActionLabelDirective,
|
PeopleSearchActionLabelDirective,
|
||||||
PeopleListComponent
|
PeopleListComponent
|
||||||
@ -46,6 +53,8 @@ import { PeopleSearchActionLabelDirective, PeopleSearchComponent, PeopleSearchTi
|
|||||||
exports: [
|
exports: [
|
||||||
PeopleComponent,
|
PeopleComponent,
|
||||||
PeopleSearchComponent,
|
PeopleSearchComponent,
|
||||||
|
PeopleSearchFieldComponent,
|
||||||
|
PeopleSelectorComponent,
|
||||||
PeopleSearchTitleDirective,
|
PeopleSearchTitleDirective,
|
||||||
PeopleSearchActionLabelDirective,
|
PeopleSearchActionLabelDirective,
|
||||||
PeopleListComponent
|
PeopleListComponent
|
||||||
|
@ -15,6 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './people.component';
|
export * from './components/people/people.component';
|
||||||
export * from './people-list.component';
|
export * from './components/people-list/people-list.component';
|
||||||
export * from './people-search.component';
|
export * from './components/people-search/people-search.component';
|
||||||
|
export * from './components/people-search-field/people-search-field.component';
|
||||||
|
export * from './components/people-selector/people-selector.component';
|
||||||
|
|
||||||
|
export * from './interfaces/perform-search-callback.interface';
|
||||||
|
|
||||||
|
export * from './directives/people-search-action-label.directive';
|
||||||
|
export * from './directives/people-search-title.directive';
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
@import '../attachment/process-attachment-list.component';
|
@import '../attachment/process-attachment-list.component';
|
||||||
@import '../attachment/task-attachment-list.component';
|
@import '../attachment/task-attachment-list.component';
|
||||||
@import '../comments/comment-list.component';
|
@import '../comments/comment-list.component';
|
||||||
@import '../people/people-search.component';
|
@import '../people/people.module';
|
||||||
@import '../people/people.component';
|
|
||||||
@import '../task-list/components/start-task.component';
|
@import '../task-list/components/start-task.component';
|
||||||
@import '../task-list/components/task-filters.component';
|
@import '../task-list/components/task-filters.component';
|
||||||
@import '../task-list/components/task-header.component';
|
@import '../task-list/components/task-header.component';
|
||||||
@ -12,8 +11,7 @@
|
|||||||
@include adf-process-filters-theme($theme);
|
@include adf-process-filters-theme($theme);
|
||||||
@include adf-task-list-comment-list-theme($theme);
|
@include adf-task-list-comment-list-theme($theme);
|
||||||
@include adf-task-list-start-task-theme($theme);
|
@include adf-task-list-start-task-theme($theme);
|
||||||
@include adf-task-list-people-search-theme($theme);
|
@include adf-people-module-theme($theme);
|
||||||
@include adf-task-list-people-theme($theme);
|
|
||||||
@include adf-task-list-filters-task-theme($theme);
|
@include adf-task-list-filters-task-theme($theme);
|
||||||
@include adf-task-list-header-theme($theme);
|
@include adf-task-list-header-theme($theme);
|
||||||
@include adf-process-attachment-list-theme($theme);
|
@include adf-process-attachment-list-theme($theme);
|
||||||
|
@ -5,67 +5,70 @@
|
|||||||
</mat-grid-tile>
|
</mat-grid-tile>
|
||||||
</mat-grid-list>
|
</mat-grid-list>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-grid-list cols="1" rowHeight="80px">
|
<div class="adf-new-task-layout-card-content">
|
||||||
<mat-grid-tile>
|
<div class="adf-grid-full-width adf-grid-row">
|
||||||
<mat-form-field class="adf-new-task-text-width">
|
<mat-form-field class="adf-grid-full-width adf-grid-column">
|
||||||
<input matInput placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NAME'|translate}}"
|
|
||||||
[(ngModel)]="startTaskmodel.name" required id="name_id">
|
|
||||||
</mat-form-field>
|
|
||||||
</mat-grid-tile>
|
|
||||||
</mat-grid-list>
|
|
||||||
<mat-grid-list cols="1" rowHeight="80px">
|
|
||||||
<mat-grid-tile>
|
|
||||||
<mat-form-field class="adf-new-task-text-width">
|
|
||||||
<textarea matInput placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DESCRIPTION'|translate}}"
|
|
||||||
[(ngModel)]="startTaskmodel.description" id="description_id"></textarea>
|
|
||||||
</mat-form-field>
|
|
||||||
</mat-grid-tile>
|
|
||||||
</mat-grid-list>
|
|
||||||
<mat-grid-list cols="2" rowHeight="80px">
|
|
||||||
<mat-grid-tile>
|
|
||||||
<mat-form-field class="adf-start-task-input-container">
|
|
||||||
<input matInput
|
<input matInput
|
||||||
[matDatepicker]="taskDatePicker"
|
class="adf-grid-full-width"
|
||||||
(keydown)="true"
|
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NAME'|translate}}"
|
||||||
(focusout)="onDateChanged($event.srcElement.value)"
|
[(ngModel)]="startTaskmodel.name"
|
||||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}"
|
required
|
||||||
[(ngModel)]="startTaskmodel.dueDate" id="date_id">
|
id="name_id">
|
||||||
<mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle>
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-datepicker #taskDatePicker [touchUi]="true"
|
</div>
|
||||||
(dateChanged)="onDateChanged($event)"></mat-datepicker>
|
|
||||||
<div class="adf-error-text-container">
|
<div class="adf-grid-full-width adf-grid-row">
|
||||||
<div *ngIf="dateError">
|
<mat-form-field class="adf-grid-full-width adf-grid-column">
|
||||||
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.DATE.ERROR'|translate}}</div>
|
<textarea
|
||||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
matInput
|
||||||
|
class="adf-grid-full-width"
|
||||||
|
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DESCRIPTION'|translate}}"
|
||||||
|
[(ngModel)]="startTaskmodel.description"
|
||||||
|
rows="1"
|
||||||
|
id="description_id">
|
||||||
|
</textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adf-grid-full-width adf-grid-row">
|
||||||
|
<div class="adf-grid-column adf-grid-half-width">
|
||||||
|
<div class="adf-grid-full-width adf-grid-row">
|
||||||
|
<mat-form-field class="adf-grid-full-width">
|
||||||
|
<input matInput
|
||||||
|
[matDatepicker]="taskDatePicker"
|
||||||
|
(keydown)="true"
|
||||||
|
(focusout)="onDateChanged($event.srcElement.value)"
|
||||||
|
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}"
|
||||||
|
[(ngModel)]="startTaskmodel.dueDate"
|
||||||
|
id="date_id">
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #taskDatePicker
|
||||||
|
[touchUi]="true"
|
||||||
|
(dateChanged)="onDateChanged($event)">
|
||||||
|
</mat-datepicker>
|
||||||
|
<div class="adf-error-text-container">
|
||||||
|
<div *ngIf="dateError">
|
||||||
|
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.DATE.ERROR'|translate}}</div>
|
||||||
|
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="adf-grid-full-width adf-grid-row">
|
||||||
|
<mat-form-field class="adf-grid-full-width">
|
||||||
|
<mat-select placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM'|translate}}" id="form_id" [(ngModel)]="formKey">
|
||||||
|
<mat-option>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option>
|
||||||
|
<mat-option *ngFor="let form of forms" [value]="form.id">{{ form.name }}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-grid-tile>
|
|
||||||
<mat-grid-tile>
|
<div class="adf-grid-column adf-grid-half-width">
|
||||||
<mat-form-field class="adf-start-task-input-container">
|
<adf-people-selector [(peopleId)]="assigneeId" id="assignee_id"></adf-people-selector>
|
||||||
<mat-select placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'|translate}}" id="assignee_id"
|
</div>
|
||||||
class="adf-mat-select" [(ngModel)]="assigneeId">
|
</div>
|
||||||
<mat-option>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option>
|
</div>
|
||||||
<span *ngFor="let user of people">
|
|
||||||
<mat-option [value]="user.id" *ngIf="!isUserNameEmpty(user)">{{ getDisplayUser(user.firstName,
|
|
||||||
user.lastName, ' ')}}
|
|
||||||
</mat-option>
|
|
||||||
</span>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</mat-grid-tile>
|
|
||||||
</mat-grid-list>
|
|
||||||
<mat-grid-list cols="2" rowHeight="80px">
|
|
||||||
<mat-grid-tile>
|
|
||||||
<mat-form-field class="adf-start-task-input-container">
|
|
||||||
<mat-select placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM'|translate}}" id="form_id" [(ngModel)]="formKey">
|
|
||||||
<mat-option>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option>
|
|
||||||
<mat-option *ngFor="let form of forms" [value]="form.id">{{ form.name }}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</mat-grid-tile>
|
|
||||||
<mat-grid-tile></mat-grid-tile>
|
|
||||||
</mat-grid-list>
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<mat-grid-list cols="1" rowHeight="60px">
|
<mat-grid-list cols="1" rowHeight="60px">
|
||||||
|
@ -20,6 +20,34 @@
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.adf-grid-row {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-grid-column {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-grid-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-grid-half-width {
|
||||||
|
width: 49%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-new-task-footer {
|
.adf-new-task-footer {
|
||||||
@ -31,14 +59,6 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-start-task-input-container {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-new-task-text-width {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-mat-select {
|
.adf-mat-select {
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
}
|
}
|
||||||
@ -58,22 +78,27 @@
|
|||||||
|
|
||||||
&-error-text-container {
|
&-error-text-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 81%;
|
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-top: 30px;
|
margin-top: 12px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-error-text {
|
&-error-text {
|
||||||
padding: 1px;
|
padding-right: 8px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.33;
|
line-height: 1.33;
|
||||||
float: left;
|
|
||||||
color: mat-color($warn);
|
color: mat-color($warn);
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-error-icon {
|
&-error-icon {
|
||||||
float: right;
|
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
color: mat-color($warn);
|
color: mat-color($warn);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../material.module';
|
||||||
import { PeopleProcessService } from '@alfresco/adf-core';
|
import { TranslationService, TranslationMock } from '@alfresco/adf-core';
|
||||||
|
import { PeopleSelectorComponent, PeopleSearchFieldComponent, PeopleListComponent } from '../../people';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { startTaskMock } from '../../mock';
|
import { startTaskMock } from '../../mock';
|
||||||
import { StartTaskModel } from '../models/start-task.model';
|
import { StartTaskModel } from '../models/start-task.model';
|
||||||
@ -30,10 +31,8 @@ describe('StartTaskComponent', () => {
|
|||||||
let component: StartTaskComponent;
|
let component: StartTaskComponent;
|
||||||
let fixture: ComponentFixture<StartTaskComponent>;
|
let fixture: ComponentFixture<StartTaskComponent>;
|
||||||
let service: TaskListService;
|
let service: TaskListService;
|
||||||
let peopleService: PeopleProcessService;
|
|
||||||
let element: HTMLElement;
|
let element: HTMLElement;
|
||||||
let getFormlistSpy: jasmine.Spy;
|
let getFormlistSpy: jasmine.Spy;
|
||||||
let getWorkflowUsersSpy: jasmine.Spy;
|
|
||||||
let createNewTaskSpy: jasmine.Spy;
|
let createNewTaskSpy: jasmine.Spy;
|
||||||
let fakeForms = [
|
let fakeForms = [
|
||||||
{
|
{
|
||||||
@ -52,11 +51,14 @@ describe('StartTaskComponent', () => {
|
|||||||
MaterialModule
|
MaterialModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
StartTaskComponent
|
StartTaskComponent,
|
||||||
|
PeopleSearchFieldComponent,
|
||||||
|
PeopleListComponent,
|
||||||
|
PeopleSelectorComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
TaskListService,
|
TaskListService,
|
||||||
PeopleProcessService
|
{ provide: TranslationService, useClass: TranslationMock }
|
||||||
]
|
]
|
||||||
}).compileComponents().then(() => {
|
}).compileComponents().then(() => {
|
||||||
|
|
||||||
@ -65,25 +67,7 @@ describe('StartTaskComponent', () => {
|
|||||||
element = fixture.nativeElement;
|
element = fixture.nativeElement;
|
||||||
|
|
||||||
service = fixture.debugElement.injector.get(TaskListService);
|
service = fixture.debugElement.injector.get(TaskListService);
|
||||||
peopleService = fixture.debugElement.injector.get(PeopleProcessService);
|
|
||||||
getFormlistSpy = spyOn(service, 'getFormList').and.returnValue(Observable.of(fakeForms));
|
getFormlistSpy = spyOn(service, 'getFormList').and.returnValue(Observable.of(fakeForms));
|
||||||
getWorkflowUsersSpy = spyOn(peopleService, 'getWorkflowUsers').and.returnValue(Observable.of([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
firstName: 'fakeName',
|
|
||||||
lastName: 'fakeName',
|
|
||||||
email: 'fake@app.activiti.com',
|
|
||||||
company: 'Alfresco.com',
|
|
||||||
pictureId: 3003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1001,
|
|
||||||
firstName: 'fake-name',
|
|
||||||
lastName: 'fake-name',
|
|
||||||
email: 'fake-@app.com',
|
|
||||||
company: 'app'
|
|
||||||
}
|
|
||||||
]));
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
@ -299,16 +283,6 @@ describe('StartTaskComponent', () => {
|
|||||||
expect(element.querySelector('#button-start').textContent).toContain('ADF_TASK_LIST.START_TASK.FORM.ACTION.START');
|
expect(element.querySelector('#button-start').textContent).toContain('ADF_TASK_LIST.START_TASK.FORM.ACTION.START');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch all users on ngonint', () => {
|
|
||||||
component.ngOnInit();
|
|
||||||
expect(component.people).toBeDefined();
|
|
||||||
expect(component.people[0].firstName).toEqual('fakeName');
|
|
||||||
expect(component.people[1].firstName).toEqual('fake-name');
|
|
||||||
expect(component.people[0].id).toEqual(1);
|
|
||||||
expect(component.people[1].id).toEqual(1001);
|
|
||||||
expect(getWorkflowUsersSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not emit TaskDetails OnCancel', () => {
|
it('should not emit TaskDetails OnCancel', () => {
|
||||||
let emitSpy = spyOn(component.cancel, 'emit');
|
let emitSpy = spyOn(component.cancel, 'emit');
|
||||||
component.onCancel();
|
component.onCancel();
|
||||||
@ -340,15 +314,6 @@ describe('StartTaskComponent', () => {
|
|||||||
expect(createTaskButton.disabled).toBeFalsy();
|
expect(createTaskButton.disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should define the select option for Assignee', async(() => {
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
let selectElement = fixture.nativeElement.querySelector('#assignee_id');
|
|
||||||
expect(selectElement).not.toBeNull();
|
|
||||||
expect(selectElement).toBeDefined();
|
|
||||||
expect(selectElement.attributes['aria-label'].value).toContain('ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should define the select option for Forms', () => {
|
it('should define the select option for Forms', () => {
|
||||||
component.forms = fakeForms;
|
component.forms = fakeForms;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { LogService, PeopleProcessService, UserPreferencesService, UserProcessModel } from '@alfresco/adf-core';
|
import { LogService, UserPreferencesService, UserProcessModel } from '@alfresco/adf-core';
|
||||||
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
||||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||||
import { MOMENT_DATE_FORMATS, MomentDateAdapter } from '@alfresco/adf-core';
|
import { MOMENT_DATE_FORMATS, MomentDateAdapter } from '@alfresco/adf-core';
|
||||||
@ -52,8 +52,6 @@ export class StartTaskComponent implements OnInit {
|
|||||||
@Output()
|
@Output()
|
||||||
error: EventEmitter<any> = new EventEmitter<any>();
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
people: UserProcessModel[] = [];
|
|
||||||
|
|
||||||
startTaskmodel: StartTaskModel = new StartTaskModel();
|
startTaskmodel: StartTaskModel = new StartTaskModel();
|
||||||
|
|
||||||
forms: Form[];
|
forms: Form[];
|
||||||
@ -73,7 +71,6 @@ export class StartTaskComponent implements OnInit {
|
|||||||
* @param taskService
|
* @param taskService
|
||||||
*/
|
*/
|
||||||
constructor(private taskService: TaskListService,
|
constructor(private taskService: TaskListService,
|
||||||
private peopleService: PeopleProcessService,
|
|
||||||
private dateAdapter: DateAdapter<Moment>,
|
private dateAdapter: DateAdapter<Moment>,
|
||||||
private preferences: UserPreferencesService,
|
private preferences: UserPreferencesService,
|
||||||
private logService: LogService) {
|
private logService: LogService) {
|
||||||
@ -84,7 +81,6 @@ export class StartTaskComponent implements OnInit {
|
|||||||
this.dateAdapter.setLocale(locale);
|
this.dateAdapter.setLocale(locale);
|
||||||
});
|
});
|
||||||
this.loadFormsTask();
|
this.loadFormsTask();
|
||||||
this.getUsers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(): void {
|
public start(): void {
|
||||||
@ -140,15 +136,6 @@ export class StartTaskComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUsers(): void {
|
|
||||||
this.peopleService.getWorkflowUsers().subscribe((users) => {
|
|
||||||
this.people = users;
|
|
||||||
}, (err) => {
|
|
||||||
this.error.emit(err);
|
|
||||||
this.logService.error('Could not load users');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public isUserNameEmpty(user: UserProcessModel): boolean {
|
public isUserNameEmpty(user: UserProcessModel): boolean {
|
||||||
return !user || (this.isEmpty(user.firstName) && this.isEmpty(user.lastName));
|
return !user || (this.isEmpty(user.firstName) && this.isEmpty(user.lastName));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user