diff --git a/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts b/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts new file mode 100644 index 0000000000..1d747c5d0e --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts @@ -0,0 +1,99 @@ +/*! + * @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 { FormModel, FormValues } from '@alfresco/adf-core'; +import { UploadApi } from '@alfresco/js-api'; +import { Observable, of } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; +import { FormContent } from '../../services/form-fields.interfaces'; +import { TaskDetailsCloudModel } from '../../task/public-api'; +import { taskDetailsContainer } from '../../task/task-header/mocks/task-details-cloud.mock'; +import { fakeCloudForm } from '../mocks/cloud-form.mock'; +import { TaskVariableCloud } from '../models/task-variable-cloud.model'; +import { FormCloudInterface } from '../services/form-cloud.interface'; + +export class FormCloudServiceMock implements FormCloudInterface { + + uploadApi: UploadApi; + + getTaskForm(appName: string, taskId: string, version?: number): Observable { + return this.getTask(appName, taskId).pipe( + switchMap((task) => { + return this.getForm(appName, task.formKey, version).pipe( + map((form: FormContent) => { + const flattenForm = { + ...form.formRepresentation, + ...form.formRepresentation.formDefinition, + taskId: task.id, + taskName: task.name, + processDefinitionId: task.processDefinitionId, + processInstanceId: task.processInstanceId + }; + delete flattenForm.formDefinition; + return flattenForm; + }) + ); + }) + ); + } + + getTask(_appName: string, taskId: string): Observable { + return of(taskDetailsContainer[taskId]); + } + + getForm(_appName: string, _formKey: string, _version?: number): Observable { + return of(fakeCloudForm); + } + + getTaskVariables(_appName: string, _taskId: string): Observable { + return of([new TaskVariableCloud({ name: 'name1', value: 5, type: 'text', id: '52' })]); + } + + saveTaskForm( + _appName: string, + taskId: string, + _processInstanceId: string, + _formId: string, + _values: FormValues + ): Observable { + return of(taskDetailsContainer[taskId]); + } + + completeTaskForm( + _appName: string, + taskId: string, + _processInstanceId: string, + _formId: string, + _formValues: FormValues, + _outcome: string, + _version: number + ): Observable { + return of(taskDetailsContainer[taskId]); + } + + createTemporaryRawRelatedContent(_file: any, _nodeId: string, _contentHost: string): Observable { + throw new Error('Method not implemented.'); + } + + getDropDownJsonData(_url: string): Observable { + throw new Error('Method not implemented.'); + } + + parseForm(_json: any, _data?: TaskVariableCloud[], _readOnly: boolean = false): FormModel { + throw new Error('Method not implemented.'); + } +} diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.interface.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.interface.ts new file mode 100644 index 0000000000..408edde94e --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.interface.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 { UploadApi } from '@alfresco/js-api'; +import { FormModel, FormValues } from '@alfresco/adf-core'; +import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model'; +import { TaskVariableCloud } from '../models/task-variable-cloud.model'; +import { FormContent } from '../../services/form-fields.interfaces'; +import { Observable } from 'rxjs'; + +export interface FormCloudInterface { + + uploadApi: UploadApi; + + getTaskForm(appName: string, taskId: string, version?: number): Observable; + saveTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, values: FormValues): Observable; + createTemporaryRawRelatedContent(file: any, nodeId: string, contentHost: string): Observable; + completeTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues, outcome: string, version: number): Observable; + getTask(appName: string, taskId: string): Observable; + getTaskVariables(appName: string, taskId: string): Observable; + getForm(appName: string, formKey: string, version?: number): Observable; + getDropDownJsonData(url: string): Observable; + parseForm(json: any, data?: TaskVariableCloud[], readOnly?: boolean): FormModel; +} diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index c1fe09769c..7415024edf 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -30,11 +30,12 @@ import { CompleteFormRepresentation, UploadApi } from '@alfresco/js-api'; import { TaskVariableCloud } from '../models/task-variable-cloud.model'; import { BaseCloudService } from '../../services/base-cloud.service'; import { FormContent } from '../../services/form-fields.interfaces'; +import { FormCloudInterface } from './form-cloud.interface'; @Injectable({ providedIn: 'root' }) -export class FormCloudService extends BaseCloudService { +export class FormCloudService extends BaseCloudService implements FormCloudInterface { private _uploadApi; get uploadApi(): UploadApi { diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.mock.ts b/lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts similarity index 98% rename from lib/process-services-cloud/src/lib/task/services/task-cloud.service.mock.ts rename to lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts index db5ab8c747..e65d3c4a52 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.mock.ts +++ b/lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts @@ -21,9 +21,9 @@ import { from, Observable, of, Subject, throwError } from 'rxjs'; import { DEFAULT_TASK_PRIORITIES, TaskPriorityOption, TASK_ASSIGNED_STATE, TASK_CREATED_STATE } from '../models/task.model'; import { TaskDetailsCloudModel } from '../start-task/public-api'; import { taskDetailsContainer } from '../task-header/mocks/task-details-cloud.mock'; -import { TaskCloudInterface } from './task-cloud.interface'; import { ProcessDefinitionCloud } from '../../models/process-definition-cloud.model'; import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; +import { TaskCloudInterface } from '../services/task-cloud.interface'; @Injectable({ providedIn: 'root' @@ -43,6 +43,7 @@ export class TaskCloudServiceMock implements TaskCloudInterface { if (taskId === 'mock-no-candidate-users') { return of([]); } + return of(['user1', 'user2']); } @@ -50,6 +51,7 @@ export class TaskCloudServiceMock implements TaskCloudInterface { if (taskId === 'mock-no-candidate-groups') { return of([]); } + return of(['group1', 'group2']); } diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.stories.ts new file mode 100644 index 0000000000..d848cce0c2 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.stories.ts @@ -0,0 +1,90 @@ +/*! + * @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 { Meta, moduleMetadata, Story } from '@storybook/angular'; +import { FormCloudService } from '../../../form/public-api'; +import { TaskCloudService } from '../../services/task-cloud.service'; +import { TaskFormModule } from '../task-form.module'; +import { TaskFormCloudComponent } from './task-form-cloud.component'; +import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock'; +import { FormCloudServiceMock } from '../../../form/mocks/form-cloud.service.mock'; +import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module'; + +export default { + component: TaskFormCloudComponent, + title: 'Process Services Cloud/Components/Task Form', + decorators: [ + moduleMetadata({ + imports: [ProcessServicesCloudStoryModule, TaskFormModule], + providers: [ + { provide: TaskCloudService, useClass: TaskCloudServiceMock }, + { provide: FormCloudService, useClass: FormCloudServiceMock } + ] + }) + ], + argTypes: { + appName: { table: { disable: true } }, + taskId: { table: { disable: true } }, + readOnly: { table: { disable: true } } + } +} as Meta; + +const template: Story = (args: TaskFormCloudComponent) => ({ + props: args +}); + +export const primary = template.bind({}); +primary.args = { + appName: 'app', + readOnly: false, + showCancelButton: true, + showCompleteButton: true, + showRefreshButton: false, + showTitle: true, + showValidationIcon: true, + taskId: 'mock-task-with-form' +}; + +export const readOnly = template.bind({}); +readOnly.args = { + ...primary.args, + readOnly: true +}; + +export const showRefreshButton = template.bind({}); +showRefreshButton.args = { + ...primary.args, + showRefreshButton: true +}; + +export const hideValidationIcon = template.bind({}); +hideValidationIcon.args = { + ...primary.args, + showValidationIcon: false +}; + +export const invalidOrMissingApp = template.bind({}); +invalidOrMissingApp.args = { + ...primary.args, + appName: undefined +}; + +export const invalidOrMissingTaskId = template.bind({}); +invalidOrMissingTaskId.args = { + ...primary.args, + taskId: undefined +}; diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index fda9604442..d21f7a93e3 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -175,7 +175,7 @@ export class TaskFormCloudComponent implements OnInit, OnChanges { hasCandidateUsersOrGroups(): boolean { let hasCandidateUsersOrGroups = false; - if (this.taskDetails.status === 'ASSIGNED') { + if (this.taskDetails?.status === 'ASSIGNED') { hasCandidateUsersOrGroups = this.hasCandidateUsers() || this.hasCandidateGroups(); } return hasCandidateUsersOrGroups; diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts index 6bc0487cdc..640054ab77 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts @@ -16,31 +16,20 @@ */ import { Meta, moduleMetadata, Story } from '@storybook/angular'; -import { TRANSLATION_PROVIDER, CoreModule } from '@alfresco/adf-core'; import { TaskHeaderCloudModule } from '../task-header-cloud.module'; import { TaskHeaderCloudComponent } from './task-header-cloud.component'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TaskCloudService } from '../../services/task-cloud.service'; -import { TaskCloudServiceMock } from '../../services/task-cloud.service.mock'; -import { TranslateModule } from '@ngx-translate/core'; +import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock'; +import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module'; export default { component: TaskHeaderCloudComponent, title: 'Process Services Cloud/Components/Task Header', decorators: [ moduleMetadata({ - declarations: [], - imports: [TranslateModule.forRoot(), CoreModule.forRoot(), TaskHeaderCloudModule, BrowserAnimationsModule], + imports: [ProcessServicesCloudStoryModule, TaskHeaderCloudModule], providers: [ - { provide: TaskCloudService, useClass: TaskCloudServiceMock }, - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services-cloud', - source: 'assets/adf-process-services-cloud' - } - } + { provide: TaskCloudService, useClass: TaskCloudServiceMock } ] }) ], 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 index ac1ad01cf5..39702cce78 100644 --- 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 @@ -260,6 +260,23 @@ export const noCandidateGroupsTaskDetailsCloudMock: TaskDetailsCloudModel = { 'standalone': false }; +export const taskWithFormDetailsMock: TaskDetailsCloudModel = { + 'appName': 'mock-app-name', + 'assignee': 'AssignedTaskUser', + 'completedDate': null, + 'createdDate': new Date(1555419255340), + 'dueDate': new Date(1558419255340), + 'description': null, + 'formKey': '4', + 'priority': 1, + 'parentTaskId': 'bd6b1741-6046-11e9-80f0-0a586460040d', + 'id': 'bd6b1741-6046-11e9-80f0-0a586460040d', + 'name': 'Task1', + 'owner': 'fakeAdmin', + 'standalone': true, + 'status': 'ASSIGNED' +}; + export const taskDetailsContainer = { 'mock-assigned-task': assignedTaskDetailsCloudMock, 'mock-completed-task': completedTaskDetailsCloudMock, @@ -267,5 +284,6 @@ export const taskDetailsContainer = { 'mock-parent-task-id': taskDetailsWithParentTaskIdMock, 'mock-suspended-task': suspendedTaskDetailsCloudMock, 'mock-no-candidate-users': noCandidateUsersTaskDetailsCloudMock, - 'mock-no-candidate-groups': noCandidateGroupsTaskDetailsCloudMock + 'mock-no-candidate-groups': noCandidateGroupsTaskDetailsCloudMock, + 'mock-task-with-form': taskWithFormDetailsMock }; diff --git a/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts b/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts new file mode 100644 index 0000000000..7548978969 --- /dev/null +++ b/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts @@ -0,0 +1,40 @@ +/*! + * @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 { CoreModule, TRANSLATION_PROVIDER } from '@alfresco/adf-core'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { TranslateModule } from '@ngx-translate/core'; + +@NgModule({ + imports: [ + TranslateModule.forRoot(), + CoreModule.forRoot(), + BrowserAnimationsModule + ], + providers: [ + { + provide: TRANSLATION_PROVIDER, + multi: true, + useValue: { + name: 'adf-process-services-cloud', + source: 'assets/adf-process-services-cloud' + } + } + ] +}) +export class ProcessServicesCloudStoryModule { }