diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json
index e49eb22dc3..6efbcea0b6 100644
--- a/lib/process-services-cloud/src/lib/i18n/en.json
+++ b/lib/process-services-cloud/src/lib/i18n/en.json
@@ -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"
}
}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.html
index 3a4ca575db..12d4b611d1 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.html
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.html
@@ -111,6 +111,12 @@
[mode]="taskFilterProperty.selectionMode"
(changedUsers)="onChangedUser($event, taskFilterProperty)">
+
+
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.ts
index cb1c29e358..e2e5c71585 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.ts
@@ -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;
}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-service-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-service-task-filter-cloud.component.spec.ts
index 1e4d79ffa8..cb4f447ab2 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-service-task-filter-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-service-task-filter-cloud.component.spec.ts
@@ -580,7 +580,6 @@ describe('EditServiceTaskFilterCloudComponent', () => {
expect(deleteButton).toBeFalsy();
});
}));
-
});
describe('edit filter actions', () => {
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.spec.ts
index 209993356b..ddb98eeda5 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.spec.ts
@@ -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();
});
});
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.ts
index 9e18618255..4a21db748f 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.ts
@@ -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 || []
+ }
})
];
}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.html b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.html
new file mode 100644
index 0000000000..4000dfa630
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.html
@@ -0,0 +1,20 @@
+
+
+
+ {{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.ASSIGNED_TO_ME' | translate }}
+ {{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.UNASSIGNED' | translate }}
+ {{ 'ADF_CLOUD_TASK_ASSIGNEMNT_FILTER.LIST_OF_CANDIDATE_USERS' | translate }}
+
+
+
+
+
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.scss b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.scss
new file mode 100644
index 0000000000..2a96127120
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.scss
@@ -0,0 +1,8 @@
+.adf-task-assignment-filter {
+ margin-right: 10px;
+}
+
+.adf-group-cloud-filter {
+ margin-left:15px;
+ flex: 1;
+}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.spec.ts
new file mode 100644
index 0000000000..bdf9005b9c
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.spec.ts
@@ -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;
+ 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();
+ });
+});
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.ts
new file mode 100644
index 0000000000..d1e30a5493
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-assignment-filter/task-assignment-filter.component.ts
@@ -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();
+
+ @Output() assignedGroupChange = new EventEmitter();
+
+ 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;
+ }
+}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts
index bc08213b1f..7c96d4aac7 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts
@@ -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;
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
index 9d189b2d8a..3875eda7f7 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
@@ -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,
diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts
index 84d40e6441..c740e43d8f 100644
--- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts
+++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts
@@ -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);
}
diff --git a/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts b/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts
index bfbdad6ae3..44c6b28961 100644
--- a/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts
+++ b/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts
@@ -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;
}
}
}