diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 84914b8208..cf0bbe05fc 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -79,6 +79,7 @@ import { TemplateDemoComponent } from './components/template-list/template-demo. import { PeopleGroupCloudDemoComponent } from './components/app-layout/cloud/people-groups-cloud-demo.component'; import { CloudSettingsComponent } from './components/app-layout/cloud/cloud-settings.component'; import { AppExtensionsModule } from './app-extension.module'; +import { ProcessDetailsCloudDemoComponent } from './components/app-layout/cloud/process-details-cloud-demo.component'; @NgModule({ imports: [ @@ -137,6 +138,7 @@ import { AppExtensionsModule } from './app-extension.module'; TasksCloudDemoComponent, ProcessesCloudDemoComponent, TaskDetailsCloudDemoComponent, + ProcessDetailsCloudDemoComponent, StartTaskCloudDemoComponent, StartProcessCloudDemoComponent, CloudBreadcrumbsComponent, diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 99e0abbf53..b4c596abc3 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -48,6 +48,7 @@ import { StartTaskCloudDemoComponent } from './components/app-layout/cloud/start import { StartProcessCloudDemoComponent } from './components/app-layout/cloud/start-process-cloud-demo.component'; import { TemplateDemoComponent } from './components/template-list/template-demo.component'; import { PeopleGroupCloudDemoComponent } from './components/app-layout/cloud/people-groups-cloud-demo.component'; +import { ProcessDetailsCloudDemoComponent } from './components/app-layout/cloud/process-details-cloud-demo.component'; export const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, @@ -182,7 +183,12 @@ export const appRoutes: Routes = [ { path: 'task-details/:taskId', component: TaskDetailsCloudDemoComponent + }, + { + path: 'process-details/:processInstanceId', + component: ProcessDetailsCloudDemoComponent } + ] } ] diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.html new file mode 100644 index 0000000000..41041217c3 --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.html @@ -0,0 +1,11 @@ + + + +

Simple page to show the process instance: {{ processInstanceId }} of the app: {{ appName }}

+ + + diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.scss b/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.ts new file mode 100644 index 0000000000..cfbb6c696c --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.ts @@ -0,0 +1,43 @@ +/*! + * @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 } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + templateUrl: './process-details-cloud-demo.component.html', + styleUrls: ['./process-details-cloud-demo.component.scss'] +}) +export class ProcessDetailsCloudDemoComponent { + + processInstanceId: string; + appName: string; + + constructor(private route: ActivatedRoute, private router: Router) { + this.route.params.subscribe((params) => { + this.processInstanceId = params.processInstanceId; + }); + + this.route.parent.params.subscribe((params) => { + this.appName = params.appName; + }); + } + + onGoBack() { + this.router.navigate([`/cloud/${this.appName}/`]); + } +} diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts index 0f51bdcdda..9ff71c4c4c 100644 --- a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts @@ -100,8 +100,8 @@ export class ProcessesCloudDemoComponent implements OnInit { this.selectedRows = []; } - onRowClick($event) { - this.selectedRow = $event; + onRowClick(processInstanceId) { + this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]); } onFilterChange(query: any) { diff --git a/docs/docassets/images/adf-cloud-process-header.png b/docs/docassets/images/adf-cloud-process-header.png new file mode 100644 index 0000000000..c49fb43769 Binary files /dev/null and b/docs/docassets/images/adf-cloud-process-header.png differ diff --git a/docs/process-services-cloud/process-header-cloud.component.md b/docs/process-services-cloud/process-header-cloud.component.md new file mode 100644 index 0000000000..92be7c4a9f --- /dev/null +++ b/docs/process-services-cloud/process-header-cloud.component.md @@ -0,0 +1,51 @@ +--- +Title: Process Header Cloud Component +Added: v3.0.0 +Status: Experimental +Last reviewed: 2019-03-08 +--- + +# [Process Header Cloud Component](../../lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts "Defined in process-header-cloud.component.ts") + +Shows all the information related to a process instance. + +![adf-cloud-process-header](../docassets/images/adf-cloud-process-header.png) + +## Basic Usage + +```html + + +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | | (Required) The name of the application. | +| processInstanceId | `string` | | (Required) The id of the process instance. | + +## 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: + +**_id_**, **_name_**, **_description_**, **_status_**, **_initiator_**, **_startDate_**, **_lastModified_**, **_parentId_**, **_businessKey_**. + +However, you can also choose which properties to show using a configuration in `app.config.json`: + +```json + "adf-cloud-process-header": { + "presets": { + "properties" : [ "name", "status", "initiator", "parentId"] + } + } +``` + +With this configuration, only the four listed properties will be shown. diff --git a/docs/process-services-cloud/process-header-cloud.service.md b/docs/process-services-cloud/process-header-cloud.service.md new file mode 100644 index 0000000000..02753a1c32 --- /dev/null +++ b/docs/process-services-cloud/process-header-cloud.service.md @@ -0,0 +1,31 @@ +--- +Title: Process Header Cloud Service +Added: v3.0.0 +Status: Experimental +Last reviewed: 2019-03-08 +--- + +# [Process Header Cloud Service](../../lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts "Defined in process-header-cloud.service.ts") + +Manages cloud process instances. + +## Class members + +### Methods + +- **getProcessInstanceById**(appName: `string`, processInstanceId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceCloud`](../../lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts)`>`
+ Gets details of a process instance. + - _appName:_ `string` - Name of the app + - _processInstanceId:_ `string` - ID of the process instance whose details you want + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceCloud`](../../lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts)`>` - Process instance details + +## Details + +The methods work in much the same way as the equivalent methods in the +[Processlist Cloud Component](./process-list-cloud.component.md) +but they use the cloud variants of the classes for return values. See the +[Processlist Cloud Service](./process-list-cloud.service.md) page for usage examples. + +## See also + +- [Processlist Cloud Service](./process-list-cloud.service.md) diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index a3bdb851f0..8cd8599f4a 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -204,5 +204,20 @@ "FORM_VALIDATION": { "INVALID_FIELD": "Enter a different value" } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "ID", + "NAME": "Name", + "DESCRIPTION": "Description", + "DESCRIPTION_DEFAULT": "No description", + "STATUS": "Status", + "BUSINESS_KEY": "Business Key", + "INITIATOR": "Initiator", + "START_DATE": "Start Date", + "LAST_MODIFIED": "Last Modified", + "PARENT_ID": "Parent Id", + "NONE": "None" + } } } diff --git a/lib/process-services-cloud/src/lib/process/process-cloud.module.ts b/lib/process-services-cloud/src/lib/process/process-cloud.module.ts index 8a9bf46ac1..757c16713b 100644 --- a/lib/process-services-cloud/src/lib/process/process-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process/process-cloud.module.ts @@ -20,18 +20,21 @@ import { ProcessFiltersCloudModule } from './process-filters/process-filters-clo import { ProcessListCloudModule } from './process-list/process-list-cloud.module'; import { StartProcessCloudModule } from './start-process/start-process-cloud.module'; import { CoreModule } from '@alfresco/adf-core'; +import { ProcessHeaderCloudModule } from './process-header/public-api'; @NgModule({ imports: [ ProcessFiltersCloudModule, ProcessListCloudModule, StartProcessCloudModule, + ProcessHeaderCloudModule, CoreModule ], exports: [ ProcessFiltersCloudModule, ProcessListCloudModule, - StartProcessCloudModule + StartProcessCloudModule, + ProcessHeaderCloudModule ] }) export class ProcessCloudModule { } diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.html b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.html new file mode 100644 index 0000000000..6889a8ef65 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.scss b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts new file mode 100644 index 0000000000..92a3f36bbb --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts @@ -0,0 +1,230 @@ +/*! + * @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 { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { setupTestBed, AppConfigService } from '@alfresco/adf-core'; +import { By } from '@angular/platform-browser'; +import { of } from 'rxjs'; +import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; +import { ProcessHeaderCloudComponent } from './process-header-cloud.component'; +import { ProcessHeaderCloudModule } from '../process-header-cloud.module'; +import { ProcessHeaderCloudService } from '../services/process-header-cloud.service'; + +const processInstanceDetailsCloudMock = { + appName: 'app-form-mau', + businessKey: 'MyBusinessKey', + description: 'new desc', + id: '00fcc4ab-4290-11e9-b133-0a586460016a', + initiator: 'devopsuser', + lastModified: 1552152187081, + name: 'new name', + parentId: '00fcc4ab-4290-11e9-b133-0a586460016b', + startDate: 1552152187080, + status: 'RUNNING' +}; + +describe('ProcessHeaderCloudComponent', () => { + let component: ProcessHeaderCloudComponent; + let fixture: ComponentFixture; + let service: ProcessHeaderCloudService; + let appConfigService: AppConfigService; + + setupTestBed({ + imports: [ + ProcessServiceCloudTestingModule, + ProcessHeaderCloudModule + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ProcessHeaderCloudComponent); + component = fixture.componentInstance; + service = TestBed.get(ProcessHeaderCloudService); + appConfigService = TestBed.get(AppConfigService); + spyOn(service, 'getProcessInstanceById').and.returnValue(of(processInstanceDetailsCloudMock)); + component.appName = 'myApp'; + component.processInstanceId = 'sdfsdf-323'; + }); + + it('should render empty component if no process instance details are provided', async(() => { + component.appName = undefined; + component.processInstanceId = undefined; + + component.ngOnChanges(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(component.properties).toBeUndefined(); + }); + })); + + it('should display process instance id', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-id"] span')); + expect(formNameEl.nativeElement.innerText).toBe('00fcc4ab-4290-11e9-b133-0a586460016a'); + }); + })); + + it('should display name', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-name"] span')); + expect(formNameEl.nativeElement.innerText).toBe('new name'); + }); + })); + + it('should display description', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-description"] span')); + expect(formNameEl.nativeElement.innerText).toBe('new desc'); + }); + })); + + it('should display placeholder if no description is avilable', async(() => { + processInstanceDetailsCloudMock.description = null; + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-description"] span')); + expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION_DEFAULT'); + }); + + })); + + it('should display status', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-status"] span')); + expect(formNameEl.nativeElement.innerText).toBe('RUNNING'); + }); + })); + + it('should display initiator', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-initiator"] span')); + expect(formNameEl.nativeElement.innerText).toBe('devopsuser'); + }); + })); + + it('should display start date', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-startDate"] .adf-property-value')); + expect(valueEl.nativeElement.innerText.trim()).toBe('09-03-2019'); + }); + })); + + it('should display lastModified date', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-lastModified"] .adf-property-value')); + expect(valueEl.nativeElement.innerText.trim()).toBe('09-03-2019'); + }); + })); + + it('should display parentId', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-parentId"] span')); + expect(formNameEl.nativeElement.innerText).toBe('00fcc4ab-4290-11e9-b133-0a586460016b'); + }); + })); + + it('should display default value when parentId is not available', async(() => { + processInstanceDetailsCloudMock.parentId = null; + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-parentId"] span')); + expect(formNameEl.nativeElement.innerText).toBe('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE'); + }); + })); + + it('should display businessKey', async(() => { + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-businessKey"] span')); + expect(formNameEl.nativeElement.innerText).toBe('MyBusinessKey'); + }); + })); + + it('should display default value when businessKey is not available', async(() => { + processInstanceDetailsCloudMock.businessKey = null; + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-businessKey"] span')); + expect(formNameEl.nativeElement.innerText).toBe('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE'); + }); + })); + + describe('Config Filtering', () => { + + it('should show only the properties from the configuration file', async(() => { + spyOn(appConfigService, 'get').and.returnValue(['name', 'status']); + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + expect(propertyList).toBeDefined(); + expect(propertyList).not.toBeNull(); + expect(propertyList.length).toBe(2); + expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME'); + expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.STATUS'); + }); + })); + + it('should show all the default properties if there is no configuration', async(() => { + spyOn(appConfigService, 'get').and.returnValue(null); + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const 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_PROCESS_HEADER.PROPERTIES.ID'); + expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME'); + }); + })); + }); +}); diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts new file mode 100644 index 0000000000..ed47b083a2 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts @@ -0,0 +1,142 @@ +/*! + * @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, OnChanges } from '@angular/core'; +import { CardViewItem, CardViewTextItemModel, TranslationService, AppConfigService, CardViewDateItemModel, CardViewBaseItemModel } from '@alfresco/adf-core'; +import { ProcessInstanceCloud } from '../../start-process/public-api'; +import { ProcessHeaderCloudService } from '../services/process-header-cloud.service'; + +@Component({ + selector: 'adf-cloud-process-header', + templateUrl: './process-header-cloud.component.html', + styleUrls: ['./process-header-cloud.component.scss'] +}) + +export class ProcessHeaderCloudComponent implements OnChanges { + + /** (Required) The name of the application. */ + @Input() + appName: string; + + /** (Required) The id of the process instance. */ + @Input() + processInstanceId: string; + + processInstanceDetails: ProcessInstanceCloud = new ProcessInstanceCloud(); + + properties: CardViewItem[]; + + constructor( + private processHeaderCloudService: ProcessHeaderCloudService, + private translationService: TranslationService, + private appConfig: AppConfigService) { + } + + ngOnChanges() { + if (this.appName && this.processInstanceId) { + this.loadProcessInstanceDetails(this.appName, this.processInstanceId); + } + } + + private loadProcessInstanceDetails(appName: string, processInstanceId: string) { + this.processHeaderCloudService.getProcessInstanceById(appName, processInstanceId).subscribe( + (processInstanceDetails) => { + this.processInstanceDetails = processInstanceDetails; + this.refreshData(); + }); + } + + /** + * Refresh the card data + */ + refreshData() { + if (this.processInstanceDetails) { + const defaultProperties = this.initDefaultProperties(); + const filteredProperties: string[] = this.appConfig.get('adf-cloud-process-header.presets.properties'); + this.properties = defaultProperties.filter((cardItem) => this.isValidSelection(filteredProperties, cardItem)); + } + } + + private initDefaultProperties(): any[] { + return [ + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.ID', + value: this.processInstanceDetails.id, + key: 'id' + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME', + value: this.processInstanceDetails.name, + key: 'name' + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION', + value: this.processInstanceDetails.description, + key: 'description', + default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION_DEFAULT') + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.STATUS', + value: this.processInstanceDetails.status, + key: 'status' + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.INITIATOR', + value: this.processInstanceDetails.initiator, + key: 'initiator' + }), + new CardViewDateItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.START_DATE', + value: this.processInstanceDetails.startDate, + format: 'DD-MM-YYYY', + key: 'startDate' + }), + new CardViewDateItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.LAST_MODIFIED', + value: this.processInstanceDetails.lastModified, + format: 'DD-MM-YYYY', + key: 'lastModified' + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.PARENT_ID', + value: this.processInstanceDetails.parentId, + key: 'parentId', + default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE') + }), + new CardViewTextItemModel( + { + label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.BUSINESS_KEY', + value: this.processInstanceDetails.businessKey, + key: 'businessKey', + default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE') + }) + ]; + } + + private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean { + return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true; + } + +} diff --git a/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.spec.ts b/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.spec.ts new file mode 100644 index 0000000000..72e2627563 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.spec.ts @@ -0,0 +1,30 @@ +/*! + * @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 { ProcessHeaderCloudModule } from './process-header-cloud.module'; + +describe('ProcessHeaderCloudModule', () => { + let processHeaderCloudModule: ProcessHeaderCloudModule; + + beforeEach(() => { + processHeaderCloudModule = new ProcessHeaderCloudModule(); + }); + + it('should create an instance', () => { + expect(processHeaderCloudModule).toBeTruthy(); + }); +}); diff --git a/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.ts b/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.ts new file mode 100644 index 0000000000..6517768503 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/process-header-cloud.module.ts @@ -0,0 +1,38 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MaterialModule } from '../../material.module'; +import { DataTableModule, TemplateModule, CoreModule } from '@alfresco/adf-core'; +import { ProcessHeaderCloudService } from '../process-header/services/process-header-cloud.service'; +import { ProcessHeaderCloudComponent } from './components/process-header-cloud.component'; + +@NgModule({ + imports: [ + CommonModule, + MaterialModule, + DataTableModule, + TemplateModule, + CoreModule + + ], + declarations: [ProcessHeaderCloudComponent], + exports: [ProcessHeaderCloudComponent], + providers: [ProcessHeaderCloudService] +}) +export class ProcessHeaderCloudModule { } diff --git a/lib/process-services-cloud/src/lib/process/process-header/public-api.ts b/lib/process-services-cloud/src/lib/process/process-header/public-api.ts new file mode 100644 index 0000000000..7f952041a5 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/public-api.ts @@ -0,0 +1,20 @@ +/*! + * @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. + */ + +export * from './process-header-cloud.module'; +export * from './components/process-header-cloud.component'; +export * from './services/process-header-cloud.service'; diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts new file mode 100644 index 0000000000..3e5551ee2e --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -0,0 +1,71 @@ +/*! + * @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 { 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 { ProcessInstanceCloud } from '../../start-process/public-api'; + +@Injectable({ + providedIn: 'root' +}) +export class ProcessHeaderCloudService { + 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', ''); + } + + /** + * Gets details of a process instance. + * @param appName Name of the app + * @param processInstanceId ID of the process instance whose details you want + * @returns Process instance details + */ + getProcessInstanceById(appName: string, processInstanceId: string): Observable { + if (appName && processInstanceId) { + + let queryUrl = `${this.contextRoot}/${appName}-query/v1/process-instances/${processInstanceId}`; + 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 ProcessInstanceCloud(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and ProcessInstanceId are mandatory for querying a task'); + return throwError('AppName/ProcessInstanceId not configured'); + } + } + + private handleError(error: any) { + this.logService.error(error); + return throwError(error || 'Server error'); + } +} diff --git a/lib/process-services-cloud/src/lib/process/public-api.ts b/lib/process-services-cloud/src/lib/process/public-api.ts index 1bcad182f9..8080aec215 100644 --- a/lib/process-services-cloud/src/lib/process/public-api.ts +++ b/lib/process-services-cloud/src/lib/process/public-api.ts @@ -18,5 +18,6 @@ export * from './process-list/public-api'; export * from './process-filters/public-api'; export * from './start-process/public-api'; +export * from './process-header/public-api'; export * from './process-cloud.module'; diff --git a/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts b/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts index f97b85bd7c..e9b21545b4 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts @@ -19,9 +19,13 @@ export class ProcessInstanceCloud { appName: string; id: string; name: string; + description: string; startDate: Date; initiator: string; status: string; + businessKey: string; + lastModified: Date; + parentId: string; processDefinitionId: string; processDefinitionKey: string; @@ -29,9 +33,13 @@ export class ProcessInstanceCloud { this.appName = obj && obj.appName || null; this.id = obj && obj.id || null; this.name = obj && obj.name || null; + this.description = obj && obj.description || null; this.startDate = obj && obj.startDate || null; this.initiator = obj && obj.initiator || null; this.status = obj && obj.status || null; + this.businessKey = obj && obj.businessKey || null; + this.lastModified = obj && obj.lastModified || null; + this.parentId = obj && obj.parentId || null; this.processDefinitionId = obj && obj.processDefinitionId || null; this.processDefinitionKey = obj && obj.processDefinitionKey || null; }