mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACA-3619] - add task assignment filter (#5907)
* [ACA-3619] - add task assignment filter * rework task assignment filter * fix unit test Co-authored-by: Silviu Popa <p3701014@L3700101120.ness.com>
This commit is contained in:
@@ -162,7 +162,8 @@
|
||||
"START_DATE": "StartDate",
|
||||
"COMPLETED_BY": "Completed By",
|
||||
"COMPLETED_DATE": "CompletedDate",
|
||||
"CREATED_DATE": "CreatedDate"
|
||||
"CREATED_DATE": "CreatedDate",
|
||||
"CANDIDATE_GROUPS": "CandidateGroups"
|
||||
},
|
||||
"DIALOG": {
|
||||
"TITLE": "Save filter as",
|
||||
@@ -333,5 +334,12 @@
|
||||
},
|
||||
"ADF_CLOUD_FORM_COMPONENT": {
|
||||
"RETRIEVE_METADATA": "Fill form fields with this file's metadata"
|
||||
},
|
||||
"ADF_CLOUD_TASK_ASSIGNEMNT_FILTER": {
|
||||
"ASSIGNED_TO_ME": "Assigned to me",
|
||||
"UNASSIGNED": "Unassigned",
|
||||
"LIST_OF_CANDIDATE_USERS": "List of candidate users",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"ASSIGNMENT_TYPE": "Assignment type"
|
||||
}
|
||||
}
|
||||
|
@@ -111,6 +111,12 @@
|
||||
[mode]="taskFilterProperty.selectionMode"
|
||||
(changedUsers)="onChangedUser($event, taskFilterProperty)"></adf-cloud-people>
|
||||
</div>
|
||||
|
||||
<adf-cloud-task-assignment-filter
|
||||
*ngIf="isAssignmentType(taskFilterProperty)"
|
||||
[taskFilterProperty]="taskFilterProperty"
|
||||
(assignedChange)="onAssignedChange($event)"
|
||||
(assignedGroupChange)="onAssignedGroupsChange($event)"></adf-cloud-task-assignment-filter>
|
||||
</ng-container>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -27,7 +27,7 @@ import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { debounceTime, filter, takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { DateAdapter } from '@angular/material/core';
|
||||
import { IdentityUserModel, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
|
||||
import { IdentityGroupModel, IdentityUserModel, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
|
||||
|
||||
@Directive()
|
||||
// tslint:disable-next-line: directive-class-suffix
|
||||
@@ -202,6 +202,10 @@ export abstract class BaseEditTaskFilterCloudComponent implements OnInit, OnChan
|
||||
return this.isDisabledForDefaultFilters(action) ? true : this.hasFormChanged(action);
|
||||
}
|
||||
|
||||
isAssignmentType(property: TaskFilterProperties): boolean {
|
||||
return property.type === 'assignment';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return filter name
|
||||
* @param filterName
|
||||
@@ -300,6 +304,16 @@ export abstract class BaseEditTaskFilterCloudComponent implements OnInit, OnChan
|
||||
this.getPropertyController(userProperty).setValue(users[0]);
|
||||
}
|
||||
|
||||
onAssignedChange(assignedValue: IdentityUserModel) {
|
||||
this.editTaskFilterForm.get('candidateGroups').setValue([]);
|
||||
this.editTaskFilterForm.get('assignee').setValue(assignedValue?.username);
|
||||
}
|
||||
|
||||
onAssignedGroupsChange(groups: IdentityGroupModel[]) {
|
||||
this.editTaskFilterForm.get('assignee').setValue(null);
|
||||
this.editTaskFilterForm.get('candidateGroups').setValue(groups);
|
||||
}
|
||||
|
||||
hasError(property: TaskFilterProperties): boolean {
|
||||
return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid;
|
||||
}
|
||||
|
@@ -580,7 +580,6 @@ describe('EditServiceTaskFilterCloudComponent', () => {
|
||||
expect(deleteButton).toBeFalsy();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('edit filter actions', () => {
|
||||
|
@@ -694,6 +694,32 @@ describe('EditTaskFilterCloudComponent', () => {
|
||||
expect(component.changedTaskFilter.createdTo).toEqual(dateFilter.endDate);
|
||||
done();
|
||||
});
|
||||
|
||||
component.onFilterChange();
|
||||
});
|
||||
|
||||
it('should show the task assignment filter', () => {
|
||||
component.appName = 'fake';
|
||||
component.filterProperties = ['assignment'];
|
||||
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||
fixture.detectChanges();
|
||||
const assignmentComponent = fixture.debugElement.nativeElement.querySelector('adf-cloud-task-assignment-filter');
|
||||
expect(assignmentComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should filter by user assignment', (done) => {
|
||||
const identityUserMock = { firstName: 'fake-identity-first-name', username: 'username', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' };
|
||||
component.appName = 'fake';
|
||||
component.filterProperties = ['assignment'];
|
||||
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||
component.onAssignedChange(identityUserMock);
|
||||
|
||||
component.filterChange.subscribe(() => {
|
||||
expect(component.changedTaskFilter.assignee).toEqual(identityUserMock.username);
|
||||
done();
|
||||
});
|
||||
component.onFilterChange();
|
||||
});
|
||||
|
||||
@@ -730,6 +756,26 @@ describe('EditTaskFilterCloudComponent', () => {
|
||||
expect(component.changedTaskFilter.createdTo).toEqual(dateFilter.endDate);
|
||||
done();
|
||||
});
|
||||
|
||||
component.onFilterChange();
|
||||
});
|
||||
|
||||
it('should filter by candidateGroups assignment', (done) => {
|
||||
const identityGroupsMock = [
|
||||
{ name: 'group1'},
|
||||
{ name: 'group2'}
|
||||
];
|
||||
component.appName = 'fake';
|
||||
component.filterProperties = ['assignment'];
|
||||
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||
fixture.detectChanges();
|
||||
component.onAssignedGroupsChange(identityGroupsMock);
|
||||
|
||||
component.filterChange.subscribe(() => {
|
||||
expect(component.changedTaskFilter.candidateGroups).toEqual(identityGroupsMock);
|
||||
done();
|
||||
});
|
||||
component.onFilterChange();
|
||||
});
|
||||
});
|
||||
|
@@ -358,6 +358,16 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
|
||||
key: 'completedBy',
|
||||
value: this.taskFilter.completedBy ? [this.taskFilter.completedBy] : null,
|
||||
selectionMode: 'single'
|
||||
}),
|
||||
new TaskFilterProperties({
|
||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT',
|
||||
type: 'assignment',
|
||||
key: 'assignment',
|
||||
attributes: { assignee: 'assignee', candidateGroups: 'candidateGroups'},
|
||||
value: {
|
||||
assignee: this.taskFilter.assignee || null,
|
||||
candidateGroups: this.taskFilter.candidateGroups || []
|
||||
}
|
||||
})
|
||||
];
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
<div fxLayout="row">
|
||||
<mat-form-field>
|
||||
<mat-select class="adf-task-assignment-filter"
|
||||
placeholder="{{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.ASSIGNMENT_TYPE' | translate }}"
|
||||
[(ngModel)]="assignmentType"
|
||||
(ngModelChange)="onAssignmentTypeChange(assignmentType)">
|
||||
<mat-option [value]="assignmentTypeList.currentUser">{{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.ASSIGNED_TO_ME' | translate }} </mat-option>
|
||||
<mat-option [value]="assignmentTypeList.unassigned">{{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.UNASSIGNED' | translate }} </mat-option>
|
||||
<mat-option [value]="assignmentTypeList.candidateGroups">{{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.LIST_OF_CANDIDATE_USERS' | translate }} </mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<adf-cloud-group class="adf-group-cloud-filter" *ngIf="isCandidateGroupsType()"
|
||||
[mode]="'multiple'"
|
||||
[appName]="appName"
|
||||
[preSelectGroups]="candidateGroups"
|
||||
[searchGroupsControl]="groupForm"
|
||||
(changedGroups)="onChangedGroups($event)"
|
||||
[title]="'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.CANDIDATE_GROUP'"></adf-cloud-group>
|
||||
</div>
|
@@ -0,0 +1,8 @@
|
||||
.adf-task-assignment-filter {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.adf-group-cloud-filter {
|
||||
margin-left:15px;
|
||||
flex: 1;
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed, IdentityUserService, TranslationService, TranslationMock } from '@alfresco/adf-core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TaskAssignmentFilterCloudComponent } from './task-assignment-filter.component';
|
||||
import { GroupCloudModule } from 'process-services-cloud/src/lib/group/public-api';
|
||||
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
|
||||
import { AssignmentType } from '../../models/filter-cloud.model';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('EditTaskFilterCloudComponent', () => {
|
||||
let component: TaskAssignmentFilterCloudComponent;
|
||||
let fixture: ComponentFixture<TaskAssignmentFilterCloudComponent>;
|
||||
let identityUserService: IdentityUserService;
|
||||
const identityUserMock = { firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' };
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
GroupCloudModule,
|
||||
TaskFiltersCloudModule,
|
||||
NoopAnimationsModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: TranslationService, useClass: TranslationMock }
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TaskAssignmentFilterCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
identityUserService = TestBed.inject(IdentityUserService);
|
||||
component.taskFilterProperty = {
|
||||
key: 'assignment',
|
||||
label: 'mock-filter',
|
||||
value: null,
|
||||
type: 'dateRange',
|
||||
attributes: null,
|
||||
options: null
|
||||
};
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => fixture.destroy());
|
||||
|
||||
it('should emit the current user info when assignment is the current user', () => {
|
||||
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
|
||||
spyOn(component.assignedChange, 'emit');
|
||||
component.onAssignmentTypeChange(AssignmentType.CURRENT_USER);
|
||||
fixture.detectChanges();
|
||||
expect(component.assignedChange.emit).toHaveBeenCalledWith(identityUserMock);
|
||||
});
|
||||
|
||||
it('should show the candidate groups', () => {
|
||||
component.assignmentType = AssignmentType.CANDIDATE_GROUPS;
|
||||
fixture.detectChanges();
|
||||
const candidateGroups = fixture.debugElement.nativeElement.querySelector('.adf-group-cloud-filter');
|
||||
expect(candidateGroups).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,94 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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, Input, Output, EventEmitter, OnInit } from '@angular/core';
|
||||
import { AbstractControl, FormControl } from '@angular/forms';
|
||||
import { IdentityGroupModel, IdentityUserModel, IdentityUserService } from '@alfresco/adf-core';
|
||||
import { AssignmentType, TaskFilterProperties } from '../../models/filter-cloud.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-task-assignment-filter',
|
||||
templateUrl: './task-assignment-filter.component.html',
|
||||
styleUrls: ['./task-assignment-filter.component.scss']
|
||||
})
|
||||
export class TaskAssignmentFilterCloudComponent implements OnInit {
|
||||
|
||||
@Input() appName: string;
|
||||
|
||||
@Input() taskFilterProperty: TaskFilterProperties;
|
||||
|
||||
@Output() assignedChange = new EventEmitter<IdentityUserModel>();
|
||||
|
||||
@Output() assignedGroupChange = new EventEmitter<IdentityGroupModel[]>();
|
||||
|
||||
assignmentType: AssignmentType;
|
||||
candidateGroups: IdentityGroupModel[] = [];
|
||||
groupForm: AbstractControl = new FormControl('');
|
||||
assignmentTypeList = {
|
||||
unassigned: AssignmentType.UNASSIGNED,
|
||||
currentUser: AssignmentType.CURRENT_USER,
|
||||
candidateGroups: AssignmentType.CANDIDATE_GROUPS
|
||||
};
|
||||
|
||||
constructor(private identityUserService: IdentityUserService) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.isFilterPropertyDefined()) {
|
||||
this.setDefaultAssignedGroups();
|
||||
this.setDefaultAssignmentType();
|
||||
}
|
||||
}
|
||||
|
||||
isCandidateGroupsType(): boolean {
|
||||
return this.assignmentType === AssignmentType.CANDIDATE_GROUPS;
|
||||
}
|
||||
|
||||
onAssignmentTypeChange(type: any) {
|
||||
this.candidateGroups = [];
|
||||
if (type === AssignmentType.CURRENT_USER) {
|
||||
this.assignedChange.emit(this.identityUserService.getCurrentUserInfo());
|
||||
} else if (type === AssignmentType.UNASSIGNED) {
|
||||
this.assignedChange.emit(null);
|
||||
}
|
||||
}
|
||||
|
||||
onChangedGroups(groups: IdentityGroupModel[]) {
|
||||
this.assignedGroupChange.emit(groups);
|
||||
}
|
||||
|
||||
private setDefaultAssignmentType() {
|
||||
const assignmentAttr = this.taskFilterProperty.attributes['assignee'];
|
||||
const assignee = this.taskFilterProperty.value[assignmentAttr];
|
||||
|
||||
if (this.candidateGroups.length > 0) {
|
||||
this.assignmentType = AssignmentType.CANDIDATE_GROUPS;
|
||||
} else if (assignee) {
|
||||
this.assignmentType = AssignmentType.CURRENT_USER;
|
||||
} else {
|
||||
this.assignmentType = AssignmentType.UNASSIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
private setDefaultAssignedGroups() {
|
||||
const assignmentGroupsAttr = this.taskFilterProperty.attributes['candidateGroups'];
|
||||
this.candidateGroups = this.taskFilterProperty.value[assignmentGroupsAttr];
|
||||
}
|
||||
|
||||
private isFilterPropertyDefined(): boolean {
|
||||
return !!this.taskFilterProperty.attributes && !!this.taskFilterProperty.value;
|
||||
}
|
||||
}
|
@@ -18,9 +18,9 @@
|
||||
import { DateCloudFilterType } from '../../../models/date-cloud-filter.model';
|
||||
import { DateRangeFilterService } from '../../../common/date-range-filter/date-range-filter.service';
|
||||
import { ComponentSelectionMode } from '../../../types';
|
||||
import { IdentityUserModel } from '@alfresco/adf-core';
|
||||
import { IdentityUserModel, IdentityGroupModel } from '@alfresco/adf-core';
|
||||
|
||||
export class TaskFilterCloudModel {
|
||||
export class TaskFilterCloudModel {
|
||||
id: string;
|
||||
name: string;
|
||||
key: string;
|
||||
@@ -30,6 +30,7 @@ export class TaskFilterCloudModel {
|
||||
status: string;
|
||||
sort: string;
|
||||
assignee: string;
|
||||
candidateGroups: IdentityGroupModel[];
|
||||
order: string;
|
||||
owner: string;
|
||||
processDefinitionName?: string;
|
||||
@@ -47,6 +48,7 @@ export class TaskFilterCloudModel {
|
||||
lastModifiedTo: string;
|
||||
completedDateType: DateCloudFilterType;
|
||||
createdDateType: DateCloudFilterType;
|
||||
assignmentType: AssignmentType;
|
||||
completedDate: Date;
|
||||
completedBy: IdentityUserModel;
|
||||
|
||||
@@ -94,6 +96,7 @@ export class TaskFilterCloudModel {
|
||||
this.createdDateType = obj.createdDateType || null;
|
||||
this.createdFrom = obj._createdFrom || null;
|
||||
this.createdTo = obj._createdTo || null;
|
||||
this.candidateGroups = obj.candidateGroups || null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +248,12 @@ export interface FilterOptions {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export enum AssignmentType {
|
||||
CURRENT_USER = 'CURRENT_USER',
|
||||
UNASSIGNED = 'UNASSIGNED',
|
||||
CANDIDATE_GROUPS = 'CANDIDATE_GROUPS'
|
||||
}
|
||||
|
||||
export class TaskFilterProperties {
|
||||
label: string;
|
||||
type: string;
|
||||
|
@@ -31,6 +31,8 @@ import { EditServiceTaskFilterCloudComponent } from './components/edit-task-filt
|
||||
import { EditTaskFilterCloudComponent } from './components/edit-task-filters/edit-task-filter-cloud.component';
|
||||
import { TaskFilterDialogCloudComponent } from './components/task-filter-dialog/task-filter-dialog-cloud.component';
|
||||
import { ServiceTaskFiltersCloudComponent } from './components/service-task-filters-cloud.component';
|
||||
import { TaskAssignmentFilterCloudComponent } from './components/task-assignment-filter/task-assignment-filter.component';
|
||||
import { GroupCloudModule } from '../../group/group-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -42,6 +44,7 @@ import { ServiceTaskFiltersCloudComponent } from './components/service-task-filt
|
||||
MaterialModule,
|
||||
AppListCloudModule,
|
||||
CoreModule,
|
||||
GroupCloudModule,
|
||||
ProcessCommonModule,
|
||||
PeopleCloudModule
|
||||
],
|
||||
@@ -50,7 +53,8 @@ import { ServiceTaskFiltersCloudComponent } from './components/service-task-filt
|
||||
ServiceTaskFiltersCloudComponent,
|
||||
EditTaskFilterCloudComponent,
|
||||
EditServiceTaskFilterCloudComponent,
|
||||
TaskFilterDialogCloudComponent
|
||||
TaskFilterDialogCloudComponent,
|
||||
TaskAssignmentFilterCloudComponent
|
||||
],
|
||||
exports: [
|
||||
TaskFiltersCloudComponent,
|
||||
|
@@ -127,6 +127,10 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent {
|
||||
@Input()
|
||||
completedTo: string = '';
|
||||
|
||||
/** Filter the tasks. Display only tasks with candidateGroups equal to the supplied value. */
|
||||
@Input()
|
||||
candidateGroupId: string = '';
|
||||
|
||||
constructor(private taskListCloudService: TaskListCloudService,
|
||||
appConfigService: AppConfigService,
|
||||
userPreferences: UserPreferencesService) {
|
||||
@@ -175,7 +179,8 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent {
|
||||
completedBy: this.completedBy,
|
||||
completedFrom: this.completedFrom,
|
||||
completedTo: this.completedTo,
|
||||
completedDate: this.completedDate
|
||||
completedDate: this.completedDate,
|
||||
candidateGroupId: this.candidateGroupId
|
||||
};
|
||||
return new TaskQueryCloudRequestModel(requestNode);
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ export class TaskQueryCloudRequestModel {
|
||||
completedDate?: Date;
|
||||
completedFrom?: string;
|
||||
completedTo?: string;
|
||||
candidateGroupId?: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
@@ -81,6 +82,7 @@ export class TaskQueryCloudRequestModel {
|
||||
this.completedFrom = obj.completedFrom;
|
||||
this.completedTo = obj.completedTo;
|
||||
this.completedDate = obj.completedDate;
|
||||
this.candidateGroupId = obj.candidateGroupId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user