diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html index cfebffe344..3ed80ff5f4 100644 --- a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html @@ -4,3 +4,9 @@

Simple page to show the taskId: {{ taskId }} of the app: {{ applicationName }}

+ + + diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts index a3746998c6..96a328e79a 100644 --- a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts @@ -26,6 +26,7 @@ export class TaskDetailsCloudDemoComponent { taskId: string; applicationName: string; + readOnly = false; constructor(private route: ActivatedRoute, private router: Router) { this.route.params.subscribe((params) => { diff --git a/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.html b/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.html index b2740609f8..f06de51bcf 100644 --- a/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.html +++ b/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.html @@ -74,13 +74,6 @@ - - Select First Row - diff --git a/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.ts b/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.ts index 33b3809777..c5c3ee02d7 100644 --- a/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.ts +++ b/demo-shell/src/app/components/task-list-cloud/task-list-cloud-demo.component.ts @@ -43,7 +43,6 @@ export class TaskListCloudDemoComponent implements OnInit { createdDate: string; dueDate: string; selectionMode: string; - selectFirstRow: boolean = false; multiSelection: boolean = false; statusOptions = [ @@ -153,10 +152,6 @@ export class TaskListCloudDemoComponent implements OnInit { this.multiSelection = !this.multiSelection; } - toggleSelectFirstRow() { - this.selectFirstRow = !this.selectFirstRow; - } - showSelectedRows(rows: any) { const selectedRows = rows.map((row) => { diff --git a/docs/process-services-cloud/task-header-cloud.component.md b/docs/process-services-cloud/task-header-cloud.component.md new file mode 100644 index 0000000000..43b1768fb2 --- /dev/null +++ b/docs/process-services-cloud/task-header-cloud.component.md @@ -0,0 +1,52 @@ +# [Task Header component](../../lib/process-services-cloud/task-header/components/task-header-cloud.component.ts "Defined in task-header.component.ts") + +Shows all the information related to a task. + +![adf-task-header](../docassets/images/adf-task-header.png) + +## Basic Usage + +```html + + +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | | (required) The name of the application. | +| taskId | `string` | | (required) The id of the Task. | +| readOnly | `boolean` | false | Flag to set the component in Read Only Mode. This mode makes all the cells not clickable and not editable. | + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| claim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is claimed. | +| unclaim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is unclaimed (ie, requeued). | + +## Details + +The component populates an internal array of +[CardViewModel](../core/card-view.component.md) with the information that we want to display. + +By default all properties are displayed: + +**_assignee_**, **_status_**, **_priority_**, **_dueDate_**, **_category_**, **_parentName_**, **_created_**, **_id_**, **_description_**, **_formName_**. + +However, you can also choose which properties to show using a configuration in `app.config.json`: + +```json + "adf-cloud-task-header": { + "presets": { + "properties" : [ "assignee", "status", "priority", "parentName"] + } + } +``` + +With this configuration, only the four listed properties will be shown. diff --git a/docs/process-services-cloud/task-list-cloud.component.md b/docs/process-services-cloud/task-list-cloud.component.md index fac2cdf087..7772851452 100644 --- a/docs/process-services-cloud/task-list-cloud.component.md +++ b/docs/process-services-cloud/task-list-cloud.component.md @@ -62,7 +62,6 @@ when the task list is empty: | parentTaskId | `string` | "" | Filter the tasks. Display only tasks with parentTaskId equal to the supplied value. | | processDefinitionId | `string` | "" | Filter the tasks. Display only tasks with processDefinitionId equal to the supplied value. | | processInstanceId | `string` | "" | Filter the tasks. Display only tasks with processInstanceId equal to the supplied value. | -| selectFirstRow | `boolean` | true | Toggles default selection of the first row. | | selectionMode | `string` | "single" | Row selection mode. Can be none, `single` or `multiple`. For `multiple` mode, you can use the Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows. | | sorting | [`TaskListCloudSortingModel`](../../lib/process-services-cloud/src/lib/task/task-list/models/task-list-sorting.model.ts)`[]` | | Specifies how the table should be sorted. The parameters are for BE sorting. | | status | `string` | "" | Filter the tasks. Display only tasks with status equal to the supplied value. | diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index ce16e8c87c..eb0e3a9d9f 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -151,5 +151,36 @@ "ERROR": { "NOT_FOUND": "No group found with the name {{groupName}}" } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Claim", + "UNCLAIM": "Requeue" + }, + "PROPERTIES": { + "TASK_NAME": "Task", + "THUMBNAIL": "Thumbnail", + "DURATION": "Duration", + "PARENT_TASK_ID": "Parent task id", + "NAME": "Name", + "ASSIGNEE": "Assignee", + "ASSIGNEE_DEFAULT": "No assignee", + "PRIORITY": "Priority", + "DUE_DATE": "Due Date", + "DUE_DATE_DEFAULT": "No date", + "STATUS": "Status", + "CATEGORY": "Category", + "CATEGORY_DEFAULT": "No category", + "PARENT_NAME": "Parent name", + "PARENT_NAME_DEFAULT": "No parent", + "CREATED_BY": "Created By", + "CREATED": "Created", + "END_DATE": "End date", + "ID": "ID", + "DESCRIPTION": "Description", + "DESCRIPTION_DEFAULT": "No description", + "FORM_NAME": "Form Name", + "FORM_NAME_DEFAULT": "No form" + } } } diff --git a/lib/process-services-cloud/src/lib/task/public-api.ts b/lib/process-services-cloud/src/lib/task/public-api.ts index c15ea586a2..008d567778 100644 --- a/lib/process-services-cloud/src/lib/task/public-api.ts +++ b/lib/process-services-cloud/src/lib/task/public-api.ts @@ -18,4 +18,6 @@ export * from './task-list/public-api'; export * from './task-filters/public-api'; export * from './start-task/public-api'; +export * from './task-header/public-api'; + export * from './task-cloud.module'; diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts index 6fdc98bd63..bd56601794 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts @@ -42,37 +42,43 @@ export class TaskDetailsCloudModel { serviceName: string; serviceFullName: string; serviceVersion: string; + managerOfCandidateGroup: boolean; + memberOfCandidateGroup: boolean; + memberOfCandidateUsers: boolean; - constructor(obj?: any) { - if (obj) { - this.id = obj.id || null; - this.name = obj.name || null; - this.appName = obj.appName || null; - this.assignee = obj.assignee || null; - this.appVersion = obj.appVersion || null; - this.createdDate = obj.createdDate || null; - this.claimedDate = obj.claimedDate || null; - this.formKey = obj.formKey || null; - this.description = obj.description || null; - this.dueDate = obj.dueDate || null; - this.lastModified = obj.lastModified || null; - this.lastModifiedTo = obj.lastModifiedTo || null; - this.lastModifiedFrom = obj.lastModifiedFrom || null; - this.owner = obj.owner || null; - this.parentTaskId = obj.parentTaskId || null; - this.priority = obj.priority || null; - this.processDefinitionId = obj.processDefinitionId || null; - this.processInstanceId = obj.processInstanceId || null; - this.serviceType = obj.serviceType || null; - this.status = obj.status || null; - this.standAlone = obj.standAlone || null; - this.serviceName = obj.serviceName || null; - this.serviceName = obj.serviceName || null; - this.serviceFullName = obj.serviceFullName || null; - this.serviceVersion = obj.serviceVersion || null; - } + constructor(obj?: any) { + if (obj) { + this.id = obj.id || null; + this.name = obj.name || null; + this.appName = obj.appName || null; + this.assignee = obj.assignee || null; + this.appVersion = obj.appVersion || null; + this.createdDate = obj.createdDate || null; + this.claimedDate = obj.claimedDate || null; + this.formKey = obj.formKey || null; + this.description = obj.description || null; + this.dueDate = obj.dueDate || null; + this.lastModified = obj.lastModified || null; + this.lastModifiedTo = obj.lastModifiedTo || null; + this.lastModifiedFrom = obj.lastModifiedFrom || null; + this.owner = obj.owner || null; + this.parentTaskId = obj.parentTaskId || null; + this.priority = obj.priority || null; + this.processDefinitionId = obj.processDefinitionId || null; + this.processInstanceId = obj.processInstanceId || null; + this.serviceType = obj.serviceType || null; + this.status = obj.status || null; + this.standAlone = obj.standAlone || null; + this.serviceName = obj.serviceName || null; + this.serviceName = obj.serviceName || null; + this.serviceFullName = obj.serviceFullName || null; + this.serviceVersion = obj.serviceVersion || null; + this.managerOfCandidateGroup = obj.managerOfCandidateGroup || null; + this.memberOfCandidateGroup = obj.memberOfCandidateGroup || null; + this.memberOfCandidateUsers = obj.memberOfCandidateUsers || null; } - } + } +} export interface StartTaskCloudResponseModel { entry: TaskDetailsCloudModel; diff --git a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts index ccab6a2b0b..f378f5e36d 100644 --- a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts @@ -19,17 +19,20 @@ import { NgModule } from '@angular/core'; import { TaskListCloudModule } from './task-list/task-list-cloud.module'; import { TaskFiltersCloudModule } from './task-filters/task-filters-cloud.module'; import { StartTaskCloudModule } from './start-task/start-task-cloud.module'; +import { TaskHeaderCloudModule } from './task-header/task-header-cloud.module'; @NgModule({ imports: [ TaskListCloudModule, TaskFiltersCloudModule, - StartTaskCloudModule + StartTaskCloudModule, + TaskHeaderCloudModule ], exports: [ TaskListCloudModule, TaskFiltersCloudModule, - StartTaskCloudModule + StartTaskCloudModule, + TaskHeaderCloudModule ] }) export class TaskCloudModule { } diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.html new file mode 100644 index 0000000000..0bd14053ad --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.scss b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.scss new file mode 100644 index 0000000000..c59023f992 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.scss @@ -0,0 +1,40 @@ +@mixin adf-task-list-header-theme($theme) { + $primary: map-get($theme, primary); + + .adf { + &-controls { + display: flex; + justify-content: space-between; + } + + &-edit-controls { + display: flex; + justify-content: flex-end; + margin-left: auto; + } + + &-switch-to-edit-mode, + &-save-edit-mode { + color: mat-color($primary); + } + + &-cancel-edit-mode, + &-claim-controls { + color: rgb(131, 131, 131); + } + + &-card-container { + font-family: inherit; + } + + } + + @media screen and ($mat-small) { + adf-card-view .adf-property-value { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + +} diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts new file mode 100644 index 0000000000..f3445840dd --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts @@ -0,0 +1,155 @@ +/*! + * @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 { setupTestBed, AppConfigService } from '@alfresco/adf-core'; +import { TaskHeaderCloudComponent } from './task-header-cloud.component'; +import { taskDetailsCloudMock } from '../mocks/task-details-cloud.mock'; +import { TaskHeaderCloudModule } from '../task-header-cloud.module'; +import { By } from '@angular/platform-browser'; +import { TaskHeaderCloudService } from '../services/task-header-cloud.service'; +import { of } from 'rxjs'; +import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; + +describe('TaskHeaderComponent', () => { + let component: TaskHeaderCloudComponent; + let fixture: ComponentFixture; + let service: TaskHeaderCloudService; + let appConfigService: AppConfigService; + + setupTestBed({ + imports: [ + ProcessServiceCloudTestingModule, + TaskHeaderCloudModule + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskHeaderCloudComponent); + component = fixture.componentInstance; + component.appName = 'myApp'; + component.taskId = taskDetailsCloudMock.id; + service = TestBed.get(TaskHeaderCloudService); + appConfigService = TestBed.get(AppConfigService); + spyOn(service, 'getTaskById').and.returnValue(of(taskDetailsCloudMock)); + }); + + it('should render empty component if no task details provided', async(() => { + component.appName = undefined; + component.taskId = undefined; + fixture.detectChanges(); + expect(fixture.debugElement.children.length).toBe(0); + })); + + it('should display assignee', async(() => { + component.ngOnInit(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); + expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); + }); + })); + + it('should display placeholder if no assignee', async(() => { + component.ngOnInit(); + component.taskDetails.assignee = null; + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); + expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT'); + }); + + })); + + it('should display priority', async(() => { + component.ngOnInit(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]')); + expect(formNameEl.nativeElement.innerText).toBe('5'); + }); + })); + + it('should display due date', async(() => { + component.ngOnInit(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + expect(valueEl.nativeElement.innerText.trim()).toBe('Dec 18 2018'); + }); + })); + + it('should display placeholder if no due date', async(() => { + component.ngOnInit(); + component.taskDetails.dueDate = null; + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + expect(valueEl.nativeElement.innerText.trim()).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'); + }); + })); + + it('should display the default parent value if is undefined', async(() => { + component.ngOnInit(); + component.taskDetails.processInstanceId = null; + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); + expect(valueEl.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT'); + }); + })); + + describe('Config Filtering', () => { + + it('should show only the properties from the configuration file', async(() => { + spyOn(appConfigService, 'get').and.returnValue(['assignee', 'status']); + component.ngOnInit(); + fixture.detectChanges(); + let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + + fixture.whenStable().then(() => { + expect(propertyList).toBeDefined(); + expect(propertyList).not.toBeNull(); + expect(propertyList.length).toBe(2); + expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE'); + expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS'); + }); + })); + + it('should show all the default properties if there is no configuration', async(() => { + spyOn(appConfigService, 'get').and.returnValue(null); + component.ngOnInit(); + fixture.detectChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + expect(propertyList).toBeDefined(); + expect(propertyList).not.toBeNull(); + expect(propertyList.length).toBe(component.properties.length); + expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE'); + expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS'); + }); + })); + }); +}); diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts new file mode 100644 index 0000000000..33fa3ba60a --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -0,0 +1,273 @@ +/*! + * @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, Input, OnInit, EventEmitter, Output } from '@angular/core'; +import { + CardViewDateItemModel, + CardViewItem, + CardViewTextItemModel, + CardViewBaseItemModel, + TranslationService, + AppConfigService, + CardViewMapItemModel, + UpdateNotification, + CardViewUpdateService, + StorageService +} from '@alfresco/adf-core'; +import { TaskHeaderCloudService } from '../services/task-header-cloud.service'; +import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; + +@Component({ + selector: 'adf-cloud-task-header', + templateUrl: './task-header-cloud.component.html', + styleUrls: ['./task-header-cloud.component.scss'] +}) +export class TaskHeaderCloudComponent implements OnInit { + + /** (Required) The appName */ + @Input() + appName: string; + + /** (Required) The id of the task. */ + @Input() + taskId: string; + + /** The id of the task. */ + @Input() + readOnly: boolean = false; + + /** Emitted when the task is claimed. */ + @Output() + claim: EventEmitter = new EventEmitter(); + + /** Emitted when the task is unclaimed (ie, requeued). */ + @Output() + unclaim: EventEmitter = new EventEmitter(); + + taskDetails: TaskDetailsCloudModel = new TaskDetailsCloudModel(); + properties: CardViewItem []; + inEdit: boolean = false; + private currentUser: string; + + constructor(private taskHeaderCloudService: TaskHeaderCloudService, + private translationService: TranslationService, + private appConfig: AppConfigService, + private cardViewUpdateService: CardViewUpdateService, + private storage: StorageService) { + } + + ngOnInit() { + this.loadCurrentBpmUserId(); + if (this.appName && this.taskId) { + this.loadTaskDetailsById(this.appName, this.taskId); + } + + this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this)); + } + loadCurrentBpmUserId(): any { + this.currentUser = this.storage.getItem('USERNAME'); + } + + loadTaskDetailsById(appName: string, taskId: string): any { + this.taskHeaderCloudService.getTaskById(appName, taskId).subscribe( + (taskDetails) => { + this.taskDetails = taskDetails; + this.refreshData(); + }); + } + + private initDefaultProperties(parentInfoMap) { + return [ + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE', + value: this.taskDetails.assignee, + key: 'assignee', + default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT'), + icon: 'create' + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS', + value: this.taskDetails.status, + key: 'status' + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PRIORITY', + value: this.taskDetails.priority, + key: 'priority', + editable: this.isReadOnlyMode() + } + ), + new CardViewDateItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE', + value: this.taskDetails.dueDate, + key: 'dueDate', + default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'), + editable: this.isReadOnlyMode() + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CATEGORY', + value: this.taskDetails.category, + key: 'category', + default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CATEGORY_DEFAULT') + } + ), + new CardViewDateItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CREATED', + value: this.taskDetails.createdDate, + key: 'created' + } + ), + new CardViewMapItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME', + value: parentInfoMap, + key: 'parentName', + default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT'), + clickable: this.isReadOnlyMode() + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_TASK_ID', + value: this.taskDetails.parentTaskId, + key: 'parentTaskId' + } + ), + new CardViewDateItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.END_DATE', + value: this.taskDetails.claimedDate, + key: 'endDate' + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.ID', + value: this.taskDetails.id, + key: 'id' + } + ), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.DESCRIPTION', + value: this.taskDetails.description, + key: 'description', + default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DESCRIPTION_DEFAULT'), + multiline: true, + editable: this.isReadOnlyMode() + } + ) + ]; + } + + /** + * Refresh the card data + */ + refreshData() { + if (this.taskDetails) { + const defaultProperties = this.initDefaultProperties(this.getParentInfo()); + const filteredProperties: string[] = this.appConfig.get('adf-cloud-task-header.presets.properties'); + this.properties = defaultProperties.filter((cardItem) => this.isValidSelection(filteredProperties, cardItem)); + } + } + + /** + * Save a task detail and update it after a successful response + * + * @param updateNotification + */ + private updateTaskDetails(updateNotification: UpdateNotification) { + this.taskHeaderCloudService.updateTask(this.appName, this.taskId, updateNotification.changed) + .subscribe( + (taskDetails) => { + this.taskDetails = taskDetails; + this.refreshData(); + } + ); + } + + getParentInfo() { + if (this.taskDetails.processInstanceId && this.taskDetails.processDefinitionId) { + return new Map([[this.taskDetails.processInstanceId, this.taskDetails.processDefinitionId]]); + } + } + + isCompleted() { + return this.taskDetails && this.taskDetails.status === 'completed'; + } + + isTaskClaimable(): boolean { + return !this.hasAssignee() && this.isCandidateMember(); + } + + hasAssignee(): boolean { + return !!this.taskDetails.assignee ? true : false; + } + + isCandidateMember() { + return this.taskDetails.managerOfCandidateGroup || this.taskDetails.memberOfCandidateGroup || this.taskDetails.memberOfCandidateUsers; + } + + isTaskClaimedByCandidateMember(): boolean { + return this.isCandidateMember() && this.isAssignedToCurrentUser() && !this.isCompleted(); + } + + isAssignedToCurrentUser(): boolean { + return this.hasAssignee() && this.isAssignedTo(this.currentUser); + } + + isAssignedTo(userName): boolean { + return this.hasAssignee() ? this.taskDetails.assignee === userName : false; + } + + isTaskValid() { + return this.appName && this.taskId; + } + + isReadOnlyMode() { + return !this.readOnly; + } + + claimTask() { + this.taskHeaderCloudService.claimTask(this.appName, this.taskId, this.currentUser).subscribe( + (res: any) => { + this.loadTaskDetailsById(this.appName, this.taskId); + this.claim.emit(this.taskId); + }); + } + + unclaimTask() { + this.taskHeaderCloudService.unclaimTask(this.appName, this.taskId).subscribe( + () => { + this.loadTaskDetailsById(this.appName, this.taskId); + this.unclaim.emit(this.taskId); + }); + } + + private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean { + return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true; + } +} diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-task-details-response.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-task-details-response.mock.ts new file mode 100644 index 0000000000..38c84b7280 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-task-details-response.mock.ts @@ -0,0 +1,46 @@ +/*! + * @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 const fakeTaskDetailsCloud = { + 'entry': { + 'serviceName': 'task-app-rb', + 'serviceFullName': 'task-app-rb', + 'serviceVersion': '', + 'appName': 'task-app', + 'appVersion': '', + 'serviceType': null, + 'id': '68d54a8f', + 'assignee': 'Phil Woods', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': 1545048055900, + 'dueDate': 1545091200000, + 'claimedDate': 1545140162601, + 'priority': 0, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'ASSIGNED', + 'owner': 'Phil Woods', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': 1545140162601, + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standAlone': true + } +}; diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts new file mode 100644 index 0000000000..4ed01973db --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts @@ -0,0 +1,48 @@ +/*! + * @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 { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; + +export const taskDetailsCloudMock = new TaskDetailsCloudModel( + { + 'serviceName': 'task-app-rb', + 'serviceFullName': 'task-app-rb', + 'serviceVersion': '', + 'appName': 'task-app', + 'appVersion': '', + 'serviceType': null, + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'Wilbur Adams', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': 1545048055900, + 'dueDate': 1545091200000, + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'ASSIGNED', + 'owner': 'superadminuser', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': 1545048055900, + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standAlone': true + } +); diff --git a/lib/process-services-cloud/src/lib/task/task-header/public-api.ts b/lib/process-services-cloud/src/lib/task/task-header/public-api.ts new file mode 100644 index 0000000000..cdb2a35f47 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/public-api.ts @@ -0,0 +1,20 @@ +/*! + * @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 * from './components/task-header-cloud.component'; + +export * from './task-header-cloud.module'; diff --git a/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.spec.ts new file mode 100644 index 0000000000..ec7bd20829 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.spec.ts @@ -0,0 +1,245 @@ +/*! + * @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 } from '@angular/core/testing'; +import { setupTestBed } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core'; +import { fakeTaskDetailsCloud } from '../mocks/fake-task-details-response.mock'; +import { TaskHeaderCloudService } from './task-header-cloud.service'; + +describe('Task Header Cloud Service', () => { + + let service: TaskHeaderCloudService; + let alfrescoApiMock: AlfrescoApiServiceMock; + + function returnFakeTaskDetailsResults() { + return { + oauth2Auth: { + callCustomApi : () => { + return Promise.resolve(fakeTaskDetailsCloud); + } + } + }; + } + + setupTestBed({ + imports: [ + CoreModule.forRoot() + ] + }); + + beforeEach(async(() => { + alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ); + service = new TaskHeaderCloudService(alfrescoApiMock, + new AppConfigService(null), + new LogService(new AppConfigService(null))); + })); + + it('should return the task details when querying by id', (done) => { + const appName = 'taskp-app'; + const taskId = '68d54a8f'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.getTaskById(appName, taskId).subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.appName).toBe('task-app'); + expect(res.id).toBe('68d54a8f'); + done(); + }); + }); + + it('should throw error if appName is not defined when querying by id', (done) => { + const appName = null; + const taskId = '68d54a8f'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.getTaskById(appName, taskId).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should throw error if taskId is not defined when querying by id', (done) => { + const appName = 'task-app'; + const taskId = null; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.getTaskById(appName, taskId).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should return the task details when updating a task', (done) => { + const appName = 'taskp-app'; + const taskId = '68d54a8f'; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.appName).toBe('task-app'); + expect(res.id).toBe('68d54a8f'); + done(); + }); + }); + + it('should throw error if appName is not defined when updating a task', (done) => { + const appName = null; + const taskId = '68d54a8f'; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should throw error if taskId is not defined when updating a task', (done) => { + const appName = 'task-app'; + const taskId = null; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should return the task details when updating a task', (done) => { + const appName = 'taskp-app'; + const taskId = '68d54a8f'; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.appName).toBe('task-app'); + expect(res.id).toBe('68d54a8f'); + done(); + }); + }); + + it('should throw error if appName is not defined when querying by id', (done) => { + const appName = null; + const taskId = '68d54a8f'; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should throw error if taskId is not defined updating a task', (done) => { + const appName = 'task-app'; + const taskId = null; + const updatePayload = { description: 'New description' }; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.updateTask(appName, taskId, updatePayload).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should return the task details when claiming a task', (done) => { + const appName = 'taskp-app'; + const assignee = 'user12'; + const taskId = '68d54a8f'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.claimTask(appName, taskId, assignee).subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.appName).toBe('task-app'); + expect(res.id).toBe('68d54a8f'); + done(); + }); + }); + + it('should throw error if appName is not defined when claiming a task', (done) => { + const appName = null; + const taskId = '68d54a8f'; + const assignee = 'user12'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.claimTask(appName, taskId, assignee).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should throw error if taskId is not defined when claiming a task', (done) => { + const appName = 'task-app'; + const taskId = null; + const assignee = 'user12'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.claimTask(appName, taskId, assignee).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should return the task details when unclaiming a task', (done) => { + const appName = 'taskp-app'; + const taskId = '68d54a8f'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.unclaimTask(appName, taskId).subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.appName).toBe('task-app'); + expect(res.id).toBe('68d54a8f'); + done(); + }); + }); + + it('should throw error if appName is not defined when unclaiming a task', (done) => { + const appName = null; + const taskId = '68d54a8f'; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.unclaimTask(appName, taskId).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); + + it('should throw error if taskId is not defined when unclaiming a task', (done) => { + const appName = 'task-app'; + const taskId = null; + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskDetailsResults); + service.unclaimTask(appName, taskId).subscribe( + () => { }, + (error) => { + expect(error).toBe('AppName/TaskId not configured'); + done(); + }); + }); +}); diff --git a/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.ts new file mode 100644 index 0000000000..77c72bd4ea --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/services/task-header-cloud.service.ts @@ -0,0 +1,134 @@ +/*! + * @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 { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf-core'; +import { Injectable } from '@angular/core'; +import { Observable, from, throwError } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; + +@Injectable({ + providedIn: 'root' +}) +export class TaskHeaderCloudService { + contextRoot: string; + contentTypes = ['application/json']; + accepts = ['application/json']; + returnType = Object; + + constructor(private alfrescoApiService: AlfrescoApiService, + private appConfigService: AppConfigService, + private logService: LogService) { + this.contextRoot = this.appConfigService.get('bpmHost', ''); + } + + getTaskById(appName: string, taskId: string): Observable { + if (appName && taskId) { + + let queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`; + return from(this.alfrescoApiService.getInstance() + .oauth2Auth.callCustomApi(queryUrl, 'GET', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and TaskId are mandatory for querying a task'); + return throwError('AppName/TaskId not configured'); + } + } + + updateTask(appName: string, taskId: string, updatePayload: any): any { + if (appName && taskId) { + + updatePayload.payloadType = 'UpdateTaskPayload'; + + let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`; + return from(this.alfrescoApiService.getInstance() + .oauth2Auth.callCustomApi(queryUrl, 'PUT', + null, null, null, + null, updatePayload, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and TaskId are mandatory for querying a task'); + return throwError('AppName/TaskId not configured'); + } + } + + claimTask(appName: string, taskId: string, assignee: string): any { + if (appName && taskId) { + + let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; + return from(this.alfrescoApiService.getInstance() + .oauth2Auth.callCustomApi(queryUrl, 'POST', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and TaskId are mandatory for querying a task'); + return throwError('AppName/TaskId not configured'); + } + } + + unclaimTask(appName: string, taskId: string): any { + if (appName && taskId) { + + let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`; + return from(this.alfrescoApiService.getInstance() + .oauth2Auth.callCustomApi(queryUrl, 'POST', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and TaskId are mandatory for querying a task'); + return throwError('AppName/TaskId not configured'); + } + } + + private handleError(error: any) { + this.logService.error(error); + return throwError(error || 'Server error'); + } + +} diff --git a/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts new file mode 100644 index 0000000000..209c424646 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts @@ -0,0 +1,30 @@ +/*! + * @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 { TaskHeaderCloudModule } from './task-header-cloud.module'; + +describe('TaskCloudModule', () => { + let taskHeaderCloudModule: TaskHeaderCloudModule; + + beforeEach(() => { + taskHeaderCloudModule = new TaskHeaderCloudModule(); + }); + + it('should create an instance', () => { + expect(taskHeaderCloudModule).toBeTruthy(); + }); +}); diff --git a/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.ts new file mode 100644 index 0000000000..a2bec75020 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.ts @@ -0,0 +1,50 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MaterialModule } from '../../material.module'; +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; +import { TranslateLoaderService, DataTableModule, TemplateModule, CardViewModule } from '@alfresco/adf-core'; +import { TaskHeaderCloudComponent } from './components/task-header-cloud.component'; +import { TaskHeaderCloudService } from './services/task-header-cloud.service'; + +@NgModule({ + imports: [ + CommonModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderService + } + }), + MaterialModule, + DataTableModule, + TemplateModule, + CardViewModule + ], + declarations: [ + TaskHeaderCloudComponent + ], + exports: [ + TaskHeaderCloudComponent + ], + providers: [ + TaskHeaderCloudService + ] +}) +export class TaskHeaderCloudModule { } 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 03e8360f85..18d56037a1 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 @@ -85,10 +85,6 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges @Input() status: string = ''; - /** Toggles default selection of the first row. */ - @Input() - selectFirstRow: boolean = true; - /** * Define which task id should be selected after reloading. If the task id doesn't * exist or nothing is passed then the first task will be selected. @@ -220,9 +216,6 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges return currentRow.entry.id === taskIdSelected; }); } - if (!dataRow && this.selectFirstRow) { - dataRow = this.rows[0]; - } if (dataRow) { dataRow.isSelected = true; this.currentInstanceId = dataRow.entry.id; diff --git a/scripts/affected-libs.sh b/scripts/affected-libs.sh index 80542dacd7..aac1fbb015 100755 --- a/scripts/affected-libs.sh +++ b/scripts/affected-libs.sh @@ -40,7 +40,7 @@ if [ ! -d "$DIRECTORY" ]; then fi if [ ! -f $DIRECTORY/deps.txt ]; then - npm run affected:libs -- $HEAD_SHA_BRANCH "HEAD" > $DIRECTORY/deps.txt + npm run affected:libs -- $HEAD_SHA_BRANCH "HEAD" > $DIRECTORY/deps.txt || ( echo "This PR needs to be rebased"; exit 1 ) fi cat $DIRECTORY/deps.txt