mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ADF-3543] Start Process Component for APS 2 (#4105)
* [ADF-3543] Start Process Component for APS 2 * [ADF-3543] Fix e2e tests * [ADF-3543] Process filter data automation id with process key * [ADF-3543] Fix Process Services e2e tests * [ADF-3543] Fix Search e2e tests * [ADF-3543] Fix Search e2e tests
This commit is contained in:
parent
dd25467a98
commit
2acd1b4e26
@ -74,6 +74,7 @@ import { StartTaskCloudDemoComponent } from './components/app-layout/cloud/start
|
||||
import { CloudBreadcrumbsComponent } from './components/app-layout/cloud/cloud-breadcrumb-component';
|
||||
import { TasksCloudDemoComponent } from './components/app-layout/cloud/tasks-cloud-demo.component';
|
||||
import { CloudFiltersDemoComponent } from './components/app-layout/cloud/cloud-filters-demo.component';
|
||||
import { StartProcessCloudDemoComponent } from './components/app-layout/cloud/start-process-cloud-demo.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -130,6 +131,7 @@ import { CloudFiltersDemoComponent } from './components/app-layout/cloud/cloud-f
|
||||
ProcessesCloudDemoComponent,
|
||||
TaskDetailsCloudDemoComponent,
|
||||
StartTaskCloudDemoComponent,
|
||||
StartProcessCloudDemoComponent,
|
||||
CloudBreadcrumbsComponent,
|
||||
CloudFiltersDemoComponent
|
||||
],
|
||||
|
@ -29,10 +29,8 @@ import { FormNodeViewerComponent } from './components/process-service/form-node-
|
||||
import { AppsViewComponent } from './components/process-service/apps-view.component';
|
||||
import { SearchResultComponent } from './components/search/search-result.component';
|
||||
import { SearchExtendedComponent } from './components/search/search-extended.component';
|
||||
|
||||
import { FilesComponent } from './components/files/files.component';
|
||||
import { FormComponent } from './components/form/form.component';
|
||||
|
||||
import { FormListComponent } from './components/form/form-list.component';
|
||||
import { OverlayViewerComponent } from './components/overlay-viewer/overlay-viewer.component';
|
||||
import { SharedLinkViewComponent } from './components/shared-link-view/shared-link-view.component';
|
||||
@ -47,6 +45,7 @@ import { TaskDetailsCloudDemoComponent } from './components/app-layout/cloud/tas
|
||||
import { AppsCloudDemoComponent } from './components/app-layout/cloud/apps-cloud-demo.component';
|
||||
import { TasksCloudDemoComponent } from './components/app-layout/cloud/tasks-cloud-demo.component';
|
||||
import { StartTaskCloudDemoComponent } from './components/app-layout/cloud/start-task-cloud-demo.component';
|
||||
import { StartProcessCloudDemoComponent } from './components/app-layout/cloud/start-process-cloud-demo.component';
|
||||
|
||||
export const appRoutes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
@ -167,6 +166,10 @@ export const appRoutes: Routes = [
|
||||
path: 'start-task',
|
||||
component: StartTaskCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'start-process',
|
||||
component: StartProcessCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'task-details/:taskId',
|
||||
component: TaskDetailsCloudDemoComponent
|
||||
|
@ -9,13 +9,19 @@
|
||||
<ng-template>
|
||||
<adf-sidebar-action-menu [expanded]="true" [width]="205"
|
||||
title="{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.CREATE' | translate}}">
|
||||
<mat-icon sidebar-menu-title-icon>arrow_drop_down</mat-icon>
|
||||
<div sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-task" (click)="onStartTask()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_TASK' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<mat-icon sidebar-menu-title-icon>arrow_drop_down</mat-icon>
|
||||
<div sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-task" (click)="onStartTask()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_TASK' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-process" (click)="onStartProcess()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_PROCESS' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</adf-sidebar-action-menu>
|
||||
<app-cloud-filters-demo [appName]="applicationName"></app-cloud-filters-demo>
|
||||
</ng-template>
|
||||
|
@ -39,4 +39,8 @@ export class CloudLayoutComponent implements OnInit {
|
||||
onStartTask() {
|
||||
this.router.navigate([`/cloud/${this.applicationName}/start-task/`]);
|
||||
}
|
||||
|
||||
onStartProcess() {
|
||||
this.router.navigate([`/cloud/${this.applicationName}/start-process/`]);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
<adf-cloud-start-process
|
||||
[appName]="applicationName"
|
||||
[name]="processName"
|
||||
(error)="openSnackMessage($event)"
|
||||
(success)="onStartProcessSuccess()"
|
||||
(cancel)="onCancelStartProcess()">
|
||||
</adf-cloud-start-process>
|
@ -0,0 +1,61 @@
|
||||
/*!
|
||||
* @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, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NotificationService, AppConfigService } from '@alfresco/adf-core';
|
||||
import { CloudLayoutService } from './services/cloud-layout.service';
|
||||
@Component({
|
||||
templateUrl: './start-process-cloud-demo.component.html',
|
||||
styleUrls: ['./start-process-cloud-demo.component.scss']
|
||||
})
|
||||
export class StartProcessCloudDemoComponent implements OnInit {
|
||||
|
||||
applicationName;
|
||||
processName: string;
|
||||
|
||||
constructor(private appConfig: AppConfigService,
|
||||
private cloudLayoutService: CloudLayoutService,
|
||||
private route: ActivatedRoute,
|
||||
private notificationService: NotificationService,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.parent.params.subscribe((params) => {
|
||||
this.applicationName = params.applicationName;
|
||||
});
|
||||
|
||||
this.processName = this.appConfig.get<string>('adf-start-process.name');
|
||||
}
|
||||
|
||||
onStartProcessSuccess() {
|
||||
this.router.navigate([`/cloud/${this.applicationName}`]);
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ key: 'running-processes' });
|
||||
}
|
||||
|
||||
onCancelStartProcess() {
|
||||
this.router.navigate([`/cloud/${this.applicationName}`]);
|
||||
}
|
||||
|
||||
openSnackMessage(event: any) {
|
||||
this.notificationService.openSnackMessage(
|
||||
event.response.body.message,
|
||||
4000
|
||||
);
|
||||
}
|
||||
}
|
49
docs/process-services-cloud/start-process-cloud.component.md
Executable file
49
docs/process-services-cloud/start-process-cloud.component.md
Executable file
@ -0,0 +1,49 @@
|
||||
# Start Process Cloud Component
|
||||
|
||||
Starts a process.
|
||||
|
||||

|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-cloud-start-process
|
||||
[appName]="YOUR_APP_NAME">
|
||||
</adf-cloud-start-process>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| appName | `string` | | Limit the list of processes that can be started to those contained in the specified app. |
|
||||
| name | `string` | "" | (optional) Name to assign to the current process. |
|
||||
| processDefinitionName | `string` | | (optional) Definition name of the process to start. |
|
||||
| showSelectProcessDropdown | `boolean` | true | (optional) Hide or show the process selection dropdown. |
|
||||
| variables | `Map<string, any>[]` | | (optional) Variables in the input to the process. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| cancel | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`ProcessInstanceCloud`](../../lib/process-services-cloud/src/lib/process-cloud/models/process-instance-cloud.model.ts)`>` | Emitted when the process is canceled. |
|
||||
| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`ProcessInstanceCloud`](../../lib/process-services-cloud/src/lib/process-cloud/models/process-instance-cloud.model.ts)`>` | Emitted when an error occurs. |
|
||||
| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`ProcessInstanceCloud`](../../lib/process-services-cloud/src/lib/process-cloud/models/process-instance-cloud.model.ts)`>` | Emitted when the process starts. |
|
||||
|
||||
## Details
|
||||
|
||||
### Starting a process with a default name and a pre-selected process definition name
|
||||
|
||||
```html
|
||||
<adf-cloud-start-process
|
||||
[appId]="YOUR_APP_ID"
|
||||
[name]="PROCESS_NAME"
|
||||
[processDefinitionName]="PROCESS_DEFINITION_NAME">
|
||||
</adf-cloud-start-process>
|
||||
```
|
||||
|
||||
You can use the `processDefinitionName` property to select which process will be selected by default on the dropdown (when there is more than one process to choose from). Use the `name` property to set the name shown on the dropdown item.
|
||||
|
||||
If the app contains only one process definition, this process definition will be selected by default
|
@ -24,9 +24,9 @@ import { element, by } from 'protractor';
|
||||
|
||||
export class ProcessCloudDemoPage {
|
||||
|
||||
allProcesses = element(by.css('span[data-automation-id="ADF_CLOUD_PROCESS_FILTERS.ALL_PROCESSES_filter"]'));
|
||||
runningProcesses = element(by.css('span[data-automation-id="ADF_CLOUD_PROCESS_FILTERS.RUNNING_PROCESSES_filter"]'));
|
||||
completedProcesses = element(by.css('span[data-automation-id="ADF_CLOUD_PROCESS_FILTERS.COMPLETED_PROCESSES_filter"]'));
|
||||
allProcesses = element(by.css('span[data-automation-id="all-processes_filter"]'));
|
||||
runningProcesses = element(by.css('span[data-automation-id="running-processes_filter"]'));
|
||||
completedProcesses = element(by.css('span[data-automation-id="completed-processes_filter"]'));
|
||||
activeFilter = element(by.css("mat-list-item[class*='active'] span"));
|
||||
processFilters = element(by.css("mat-expansion-panel[data-automation-id='Process Filters']"));
|
||||
|
||||
|
@ -62,10 +62,6 @@ export class DatePickerPage {
|
||||
return `${('0' + date.getDate()).slice(-2)}-${this.months[date.getMonth()]}-${date.getFullYear().toString().substr(-2)}`;
|
||||
}
|
||||
|
||||
convertDateToNewFormat(date) { // Format : mm-dd-yy
|
||||
return `${date.getMonth() + 1}-${('0' + date.getDate()).slice(-2)}-${date.getFullYear().toString().substr(-2)}`;
|
||||
}
|
||||
|
||||
selectTodayDate() {
|
||||
this.checkDatePickerIsDisplayed();
|
||||
let todayDate = element(by.css('.mat-calendar-body-today'));
|
||||
|
@ -29,6 +29,7 @@ import TestConfig = require('../../test.config');
|
||||
|
||||
import AlfrescoApi = require('alfresco-js-api-node');
|
||||
import { browser } from 'protractor';
|
||||
import moment from 'moment-es6';
|
||||
|
||||
describe('Search Date Range Filter', () => {
|
||||
|
||||
@ -199,6 +200,7 @@ describe('Search Date Range Filter', () => {
|
||||
describe('configuration change', () => {
|
||||
|
||||
let jsonFile;
|
||||
let dateFormat = 'MM-DD-YY';
|
||||
|
||||
beforeAll(() => {
|
||||
let searchConfiguration = new SearchConfiguration();
|
||||
@ -206,7 +208,7 @@ describe('Search Date Range Filter', () => {
|
||||
});
|
||||
|
||||
it('[C277117] Should be able to change date format', () => {
|
||||
jsonFile.categories[4].component.settings.dateFormat = 'MM-DD-YY';
|
||||
jsonFile.categories[4].component.settings.dateFormat = dateFormat;
|
||||
|
||||
navigationBar.clickConfigEditorButton();
|
||||
configEditor.clickSearchConfiguration();
|
||||
@ -221,7 +223,7 @@ describe('Search Date Range Filter', () => {
|
||||
dateRangeFilter.checkFromFieldIsDisplayed()
|
||||
.openFromDatePicker();
|
||||
|
||||
let todayDate = datePicker.convertDateToNewFormat(new Date());
|
||||
let todayDate = moment().format(dateFormat);
|
||||
datePicker.selectTodayDate();
|
||||
|
||||
browser.controlFlow().execute(async () => {
|
||||
|
@ -2,18 +2,40 @@
|
||||
"ADF_CLOUD_PROCESS_LIST": {
|
||||
"MESSAGES": {
|
||||
"TITLE": "No Processes Found",
|
||||
"SUBTITLE":"Create a new process that you want to easily find later",
|
||||
"SUBTITLE": "Create a new process that you want to easily find later",
|
||||
"NONE": "No process instance filter selected."
|
||||
},
|
||||
"PROPERTIES": {
|
||||
"NAME": "Name",
|
||||
"CREATED": "Created"
|
||||
},
|
||||
"ADF_CLOUD_START_PROCESS": {
|
||||
"BUTTON": "Start Process",
|
||||
"NO_PROCESS_DEFINITIONS": "You can't start a process as there are no process definitions available",
|
||||
"FORM": {
|
||||
"TITLE": "Start Process",
|
||||
"LABEL": {
|
||||
"TYPE": "Select Process",
|
||||
"NAME": "Process Name"
|
||||
},
|
||||
"TYPE_PLACEHOLDER": "Choose one...",
|
||||
"ACTION": {
|
||||
"START": "Start Process",
|
||||
"CANCEL": "Cancel"
|
||||
}
|
||||
},
|
||||
"ERROR": {
|
||||
"LOAD_PROCESS_DEFS": "Couldn't load process definitions, check you have access.",
|
||||
"START": "Couldn't start new process instance, check you have access.",
|
||||
"PROCESS_NAME_REQUIRED": "Process Name is required",
|
||||
"PROCESS_DEFINITION_REQUIRED": "Process Definition is required"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ADF_CLOUD_TASK_LIST": {
|
||||
"APPS": {
|
||||
"TITLE": "No Applications Found",
|
||||
"SUBTITLE":"Create a new application that you want to easily find later"
|
||||
"SUBTITLE": "Create a new application that you want to easily find later"
|
||||
},
|
||||
"START_TASK": {
|
||||
"FORM": {
|
||||
@ -40,7 +62,7 @@
|
||||
"LIST": {
|
||||
"MESSAGES": {
|
||||
"TITLE": "No Tasks Found",
|
||||
"SUBTITLE":"Create a new task that you want to easily find later",
|
||||
"SUBTITLE": "Create a new task that you want to easily find later",
|
||||
"NONE": "No task lists found"
|
||||
}
|
||||
}
|
||||
|
@ -18,15 +18,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { TRANSLATION_PROVIDER } from '@alfresco/adf-core';
|
||||
import { AppListCloudModule } from './app/app-list-cloud.module';
|
||||
import { ProcessListCloudModule } from './process/process-list/process-list-cloud.module';
|
||||
import { ProcessFiltersCloudModule } from './process/process-filters/process-filters-cloud.module';
|
||||
import { TaskCloudModule } from './task/task-cloud.module';
|
||||
import { ProcessCloudModule } from './process/process-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AppListCloudModule,
|
||||
ProcessListCloudModule,
|
||||
ProcessFiltersCloudModule,
|
||||
ProcessCloudModule,
|
||||
TaskCloudModule
|
||||
],
|
||||
providers: [
|
||||
@ -41,8 +39,7 @@ import { TaskCloudModule } from './task/task-cloud.module';
|
||||
],
|
||||
exports: [
|
||||
AppListCloudModule,
|
||||
ProcessListCloudModule,
|
||||
ProcessFiltersCloudModule,
|
||||
ProcessCloudModule,
|
||||
TaskCloudModule
|
||||
]
|
||||
})
|
||||
|
@ -18,15 +18,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ProcessFiltersCloudModule } from './process-filters/process-filters-cloud.module';
|
||||
import { ProcessListCloudModule } from './process-list/process-list-cloud.module';
|
||||
import { StartProcessCloudModule } from './start-process/start-process-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
ProcessFiltersCloudModule,
|
||||
ProcessListCloudModule
|
||||
ProcessListCloudModule,
|
||||
StartProcessCloudModule
|
||||
],
|
||||
exports: [
|
||||
ProcessFiltersCloudModule,
|
||||
ProcessListCloudModule
|
||||
ProcessListCloudModule,
|
||||
StartProcessCloudModule
|
||||
]
|
||||
})
|
||||
export class ProcessCloudModule { }
|
||||
|
@ -4,7 +4,7 @@
|
||||
class="adf-filters__entry" [class.adf-active]="currentFilter === filter">
|
||||
<mat-icon *ngIf="showIcons && filter.icon" matListIcon class="adf-filters__entry-icon">{{filter.icon}}
|
||||
</mat-icon>
|
||||
<span matLine [attr.data-automation-id]="filter.name + '_filter'">{{filter.name | translate}}</span>
|
||||
<span matLine [attr.data-automation-id]="filter.key + '_filter'">{{filter.name | translate}}</span>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<ng-template #loading>
|
||||
|
@ -40,6 +40,7 @@ describe('ProcessFiltersCloudComponent', () => {
|
||||
}),
|
||||
new ProcessFilterCloudModel({
|
||||
name: 'FakeRunningProcesses',
|
||||
key: 'FakeRunningProcesses',
|
||||
icon: 'inbox',
|
||||
id: '11',
|
||||
state: 'RUNNING'
|
||||
|
@ -17,4 +17,6 @@
|
||||
|
||||
export * from './process-list/public-api';
|
||||
export * from './process-filters/public-api';
|
||||
export * from './start-process/public-api';
|
||||
|
||||
export * from './process-cloud.module';
|
||||
|
@ -0,0 +1,70 @@
|
||||
<mat-card class="adf-start-process">
|
||||
|
||||
<mat-card-title>{{'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.TITLE' | translate}}
|
||||
</mat-card-title>
|
||||
|
||||
<mat-card-content *ngIf="!isProcessDefinitionsEmpty(); else emptyProcessDefinitionsList">
|
||||
<mat-card-subtitle id="error-message" *ngIf="errorMessageId">
|
||||
{{ errorMessageId | translate }}
|
||||
</mat-card-subtitle>
|
||||
|
||||
<form [formGroup]="processForm">
|
||||
<mat-form-field class="adf-process-input-container">
|
||||
<mat-label>{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.LABEL.NAME' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="processInstanceName"
|
||||
id="processName">
|
||||
<mat-error *ngIf="processInstanceName.hasError('required')">
|
||||
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.PROCESS_NAME_REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="adf-process-input-container">
|
||||
<mat-label>{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.LABEL.TYPE' | translate }}</mat-label>
|
||||
<input
|
||||
#inputAutocomplete
|
||||
matInput
|
||||
formControlName="processDefinition"
|
||||
[matAutocomplete]="auto"
|
||||
id="processDefinitionName">
|
||||
<div class="adf-process-input-autocomplete">
|
||||
<mat-autocomplete #auto="matAutocomplete" id="processDefinitionOptions" [displayWith]="displayProcessNameOnDropdown">
|
||||
<mat-option *ngFor="let processDef of filteredProcesses" [value]="processDef.name">
|
||||
{{ processDef.name }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
<button id="adf-select-process-dropdown" *ngIf="showSelectProcessDropdown" mat-icon-button (click)="displayDropdown($event)">
|
||||
<mat-icon>arrow_drop_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<mat-error *ngIf="processDefinition.hasError('required')">
|
||||
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.PROCESS_DEFINITION_REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
|
||||
<ng-template #emptyProcessDefinitionsList>
|
||||
<mat-card-content>
|
||||
<mat-card-subtitle class="error-message" id="no-process-message">
|
||||
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.NO_PROCESS_DEFINITIONS' | translate | uppercase}}
|
||||
</mat-card-subtitle>
|
||||
</mat-card-content>
|
||||
</ng-template>
|
||||
|
||||
<mat-card-actions>
|
||||
<button mat-button (click)="cancelStartProcess()" id="cancel_process">
|
||||
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.CANCEL' | translate | uppercase}}
|
||||
</button>
|
||||
<button
|
||||
color="primary"
|
||||
mat-button
|
||||
[disabled]="!processForm.valid || isLoading"
|
||||
(click)="startProcess()"
|
||||
data-automation-id="btn-start"
|
||||
id="button-start" class="btn-start">
|
||||
{{'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.START' | translate | uppercase}}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
@ -0,0 +1,56 @@
|
||||
.adf {
|
||||
&-start-process {
|
||||
width: 66%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.mat-select-trigger {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
mat-select {
|
||||
width: 100%;
|
||||
padding: 16px 0 0;
|
||||
}
|
||||
mat-card-actions {
|
||||
text-align: right;
|
||||
.mat-button {
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-process-input-container {
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
&-process-input-autocomplete {
|
||||
display: flex;
|
||||
button {
|
||||
position: absolute;
|
||||
right: -14px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
&-start-form-container {
|
||||
.mat-card {
|
||||
box-shadow: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
&-start-form-actions {
|
||||
text-align: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.adf-start-process {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
@ -0,0 +1,380 @@
|
||||
/*!
|
||||
* @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 { SimpleChange } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { StartProcessCloudService } from '../services/start-process-cloud.service';
|
||||
|
||||
import { StartProcessCloudComponent } from './start-process-cloud.component';
|
||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||
import { ProcessCloudModule } from '../../process-cloud.module';
|
||||
import { fakeProcessDefinitions, fakeProcessInstance, fakeProcessPayload } from '../mock/start-process.component.mock';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('StartProcessCloudComponent', () => {
|
||||
|
||||
let component: StartProcessCloudComponent;
|
||||
let fixture: ComponentFixture<StartProcessCloudComponent>;
|
||||
let processService: StartProcessCloudService;
|
||||
let getDefinitionsSpy: jasmine.Spy;
|
||||
let startProcessSpy: jasmine.Spy;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
ProcessServiceCloudTestingModule,
|
||||
ProcessCloudModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
processService = TestBed.get(StartProcessCloudService);
|
||||
fixture = TestBed.createComponent(StartProcessCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
getDefinitionsSpy = spyOn(processService, 'getProcessDefinitions').and.returnValue(of(fakeProcessDefinitions));
|
||||
startProcessSpy = spyOn(processService, 'startProcess').and.returnValue(of(fakeProcessInstance));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
it('should create instance of StartProcessInstanceComponent', () => {
|
||||
expect(fixture.componentInstance instanceof StartProcessCloudComponent).toBe(true, 'should create StartProcessInstanceComponent');
|
||||
});
|
||||
|
||||
describe('first step', () => {
|
||||
|
||||
describe('without start form', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
component.name = 'My new process';
|
||||
component.appName = 'myApp';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should enable start button when name and process filled out', async(() => {
|
||||
spyOn(component, 'loadProcessDefinitions').and.callThrough();
|
||||
component.processDefinitionList = fakeProcessDefinitions;
|
||||
component.processForm.controls['processInstanceName'].setValue('My Process 1');
|
||||
component.processForm.controls['processDefinition'].setValue('NewProcess 1');
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
let startBtn = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(startBtn.disabled).toBe(false);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should have start button disabled when name not filled out', async(() => {
|
||||
spyOn(component, 'loadProcessDefinitions').and.callThrough();
|
||||
component.processForm.controls['processInstanceName'].setValue('');
|
||||
component.processForm.controls['processDefinition'].setValue(fakeProcessInstance.name);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let startBtn = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(startBtn.disabled).toBe(true);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should have start button disabled when no process is selected', async(() => {
|
||||
component.processPayloadCloud.processDefinitionKey = null;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let startBtn = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(startBtn.disabled).toBe(true);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('process definitions list', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.name = 'My new process';
|
||||
component.appName = 'myApp';
|
||||
fixture.detectChanges();
|
||||
let change = new SimpleChange(null, 'MyApp', true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should call service to fetch process definitions with appId', () => {
|
||||
fixture.whenStable().then(() => {
|
||||
expect(getDefinitionsSpy).toHaveBeenCalledWith('myApp');
|
||||
});
|
||||
});
|
||||
|
||||
it('should display the correct number of processes in the select list', () => {
|
||||
fixture.whenStable().then(() => {
|
||||
let selectElement = fixture.nativeElement.querySelector('mat-select');
|
||||
expect(selectElement.children.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should display the option def details', () => {
|
||||
component.processDefinitionList = fakeProcessDefinitions;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let selectElement = fixture.nativeElement.querySelector('mat-select > .mat-select-trigger');
|
||||
let optionElement = fixture.nativeElement.querySelectorAll('mat-option');
|
||||
selectElement.click();
|
||||
expect(selectElement).not.toBeNull();
|
||||
expect(selectElement).toBeDefined();
|
||||
expect(optionElement).not.toBeNull();
|
||||
expect(optionElement).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
it('should indicate an error to the user if process defs cannot be loaded', async(() => {
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(throwError({}));
|
||||
let change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
let errorEl = fixture.nativeElement.querySelector('#error-message');
|
||||
expect(errorEl.innerText.trim()).toBe('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.LOAD_PROCESS_DEFS');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show no process available message when no process definition is loaded', async(() => {
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([]));
|
||||
let change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
const noProcessElement = fixture.nativeElement.querySelector('#no-process-message');
|
||||
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
|
||||
expect(noProcessElement.innerText.trim()).toBe('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.NO_PROCESS_DEFINITIONS');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should select processDefinition based on processDefinition input', async(() => {
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.processForm.controls['processInstanceName'].setValue('NewProcess 1');
|
||||
component.processForm.controls['processDefinition'].setValue('NewProcess 1');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.processPayloadCloud.processDefinitionKey).toBe(JSON.parse(JSON.stringify(fakeProcessDefinitions[0])).name);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should select automatically the processDefinition if the app contain only one', async(() => {
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([fakeProcessDefinitions[0]]));
|
||||
let change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.processForm.controls['processDefinition'].value).toBe(JSON.parse(JSON.stringify(fakeProcessDefinitions[0])).name);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not select automatically any processDefinition if the app contain multiple process and does not have any processDefinition as input', async(() => {
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.appName = 'myApp';
|
||||
component.ngOnChanges({});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.processPayloadCloud.processInstanceName).toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
describe('dropdown', () => {
|
||||
|
||||
it('should hide the process dropdown button if showSelectProcessDropdown is false', async(() => {
|
||||
fixture.detectChanges();
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.appName = 'myApp';
|
||||
component.showSelectProcessDropdown = false;
|
||||
component.ngOnChanges({});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
|
||||
expect(selectElement).toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the process dropdown button if showSelectProcessDropdown is false', async(() => {
|
||||
fixture.detectChanges();
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.appName = 'myApp';
|
||||
component.processDefinitionName = 'NewProcess 2';
|
||||
component.showSelectProcessDropdown = true;
|
||||
component.ngOnChanges({});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
|
||||
expect(selectElement).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the process dropdown button by default', async(() => {
|
||||
fixture.detectChanges();
|
||||
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
component.appName = 'myApp';
|
||||
component.processDefinitionName = 'NewProcess 2';
|
||||
component.ngOnChanges({});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
|
||||
expect(selectElement).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('input changes', () => {
|
||||
|
||||
let change = new SimpleChange('myApp', 'myApp1', true);
|
||||
|
||||
beforeEach(async(() => {
|
||||
component.appName = 'myApp';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
getDefinitionsSpy.calls.reset();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should reload processes when appId input changed', async(() => {
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(getDefinitionsSpy).toHaveBeenCalledWith('myApp1');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should get current processDef', () => {
|
||||
component.ngOnChanges({ appName: change });
|
||||
fixture.detectChanges();
|
||||
expect(getDefinitionsSpy).toHaveBeenCalled();
|
||||
expect(component.processDefinitionList).toBe(fakeProcessDefinitions);
|
||||
});
|
||||
});
|
||||
|
||||
describe('start process', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
component.name = 'NewProcess 1';
|
||||
component.appName = 'myApp';
|
||||
component.ngOnChanges({});
|
||||
});
|
||||
|
||||
it('should call service to start process if required fields provided', async(() => {
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
component.startProcess();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(startProcessSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should avoid calling service to start process if required fields NOT provided', async(() => {
|
||||
component.processForm.controls['processInstanceName'].setValue('');
|
||||
component.processForm.controls['processDefinition'].setValue('');
|
||||
fixture.whenStable().then(() => {
|
||||
let startProcessButton = fixture.debugElement.query(By.css('[data-automation-id="btn-start"]'));
|
||||
expect(startProcessButton.nativeElement.disabled).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should call service to start process with the correct parameters', async(() => {
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
component.startProcess();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(startProcessSpy).toHaveBeenCalledWith('myApp', fakeProcessPayload);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should call service to start process with the variables setted', async(() => {
|
||||
let inputProcessVariable: Map<string, object>[] = [];
|
||||
inputProcessVariable['name'] = {value: 'Josh'};
|
||||
|
||||
component.variables = inputProcessVariable;
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
|
||||
component.startProcess();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.processPayloadCloud.variables).toBe(inputProcessVariable);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should output start event when process started successfully', async(() => {
|
||||
let emitSpy = spyOn(component.success, 'emit');
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
component.startProcess();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(emitSpy).toHaveBeenCalledWith(fakeProcessInstance);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should throw error event when process cannot be started', async(() => {
|
||||
let errorSpy = spyOn(component.error, 'emit');
|
||||
let error = { message: 'My error' };
|
||||
startProcessSpy = startProcessSpy.and.returnValue(throwError(error));
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
component.startProcess();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(errorSpy).toHaveBeenCalledWith(error);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should indicate an error to the user if process cannot be started', async(() => {
|
||||
getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
|
||||
let change = new SimpleChange('myApp', 'myApp1', true);
|
||||
component.ngOnChanges({ appName: change });
|
||||
startProcessSpy = startProcessSpy.and.returnValue(throwError({}));
|
||||
component.startProcess();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
let errorEl = fixture.nativeElement.querySelector('#error-message');
|
||||
expect(errorEl.innerText.trim()).toBe('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.START');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit start event when start select a process and add a name', (done) => {
|
||||
let disposableStart = component.success.subscribe(() => {
|
||||
disposableStart.unsubscribe();
|
||||
done();
|
||||
});
|
||||
|
||||
component.processPayloadCloud = fakeProcessPayload;
|
||||
component.name = 'NewProcess 1';
|
||||
component.startProcess();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should able to start the process when the required fields are filled up', (done) => {
|
||||
component.processForm.controls['processInstanceName'].setValue('My Process 1');
|
||||
component.processForm.controls['processDefinition'].setValue('NewProcess 1');
|
||||
|
||||
let disposableStart = component.success.subscribe(() => {
|
||||
disposableStart.unsubscribe();
|
||||
done();
|
||||
});
|
||||
|
||||
component.startProcess();
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,237 @@
|
||||
/*!
|
||||
* @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, EventEmitter, Input, OnChanges, OnInit,
|
||||
Output, SimpleChanges, ViewChild, ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
|
||||
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
|
||||
import { StartProcessCloudService } from '../services/start-process-cloud.service';
|
||||
import { FormControl, Validators, FormGroup, AbstractControl, FormBuilder, ValidatorFn } from '@angular/forms';
|
||||
import { MatAutocompleteTrigger } from '@angular/material';
|
||||
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-start-process',
|
||||
templateUrl: './start-process-cloud.component.html',
|
||||
styleUrls: ['./start-process-cloud.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class StartProcessCloudComponent implements OnChanges, OnInit {
|
||||
|
||||
@ViewChild(MatAutocompleteTrigger)
|
||||
inputAutocomplete: MatAutocompleteTrigger;
|
||||
|
||||
/** (required) Name of the app. */
|
||||
@Input()
|
||||
appName: string;
|
||||
|
||||
/** Name of the process. */
|
||||
@Input()
|
||||
name: string = '';
|
||||
|
||||
/** Name of the process definition. */
|
||||
@Input()
|
||||
processDefinitionName: string;
|
||||
|
||||
/** Variables to attach to the payload */
|
||||
@Input()
|
||||
variables: Map<string, object>[];
|
||||
|
||||
/** This flag displays/hides the process dropdown list */
|
||||
@Input()
|
||||
showSelectProcessDropdown: boolean = true;
|
||||
|
||||
/** Emitted when the starting process is successfully created. */
|
||||
@Output()
|
||||
success: EventEmitter<ProcessInstanceCloud> = new EventEmitter<ProcessInstanceCloud>();
|
||||
|
||||
/** Emitted when the starting process is cancelled */
|
||||
@Output()
|
||||
cancel: EventEmitter<ProcessInstanceCloud> = new EventEmitter<ProcessInstanceCloud>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<ProcessInstanceCloud> = new EventEmitter<ProcessInstanceCloud>();
|
||||
|
||||
processDefinitionList: ProcessDefinitionCloud[] = [];
|
||||
errorMessageId: string = '';
|
||||
processForm: FormGroup;
|
||||
processPayloadCloud = new ProcessPayloadCloud();
|
||||
filteredProcesses: ProcessDefinitionCloud[] = [];
|
||||
isLoading = false;
|
||||
|
||||
constructor(private startProcessCloudService: StartProcessCloudService,
|
||||
private formBuilder: FormBuilder) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.processForm = this.formBuilder.group({
|
||||
processInstanceName: new FormControl(this.name, Validators.required),
|
||||
processDefinition: new FormControl('', [Validators.required, this.processDefinitionNameValidator()])
|
||||
});
|
||||
|
||||
this.processDefinition.valueChanges
|
||||
.pipe(debounceTime(300))
|
||||
.subscribe((processDefinitionName) => {
|
||||
this.processPayloadCloud.processDefinitionKey = null;
|
||||
if (this.processDefinition.valid) {
|
||||
this.setProcessDefinitionOnForm(processDefinitionName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['appName'] && changes['appName'].currentValue !== changes['appName'].previousValue) {
|
||||
this.appName = changes['appName'].currentValue;
|
||||
this.loadProcessDefinitions();
|
||||
}
|
||||
}
|
||||
|
||||
setProcessDefinitionOnForm(processDefinitionName: string) {
|
||||
this.filteredProcesses = this.getProcessDefinitionList(processDefinitionName);
|
||||
const selectedProcess = this.getProcessIfExists(processDefinitionName);
|
||||
this.processPayloadCloud.processDefinitionKey = selectedProcess.key;
|
||||
}
|
||||
|
||||
private getProcessDefinitionList(processDefinitionName: string): ProcessDefinitionCloud[] {
|
||||
return this.processDefinitionList.filter((option) => option.name.toLowerCase().includes(processDefinitionName.toLowerCase()));
|
||||
}
|
||||
|
||||
private getProcessIfExists(processDefinitionName: string): ProcessDefinitionCloud {
|
||||
let matchedProcess = this.processDefinitionList.find((option) => option.name.toLowerCase() === processDefinitionName.toLowerCase());
|
||||
if (!matchedProcess) {
|
||||
matchedProcess = new ProcessDefinitionCloud();
|
||||
}
|
||||
|
||||
return matchedProcess;
|
||||
}
|
||||
|
||||
private getProcessDefinitionByName(processDefinitionName: string): ProcessDefinitionCloud {
|
||||
const matchedProcess = processDefinitionName ? this.getProcessIfExists(processDefinitionName) : this.processDefinitionList[0];
|
||||
return matchedProcess;
|
||||
}
|
||||
|
||||
private selectDefaultProcessDefinition() {
|
||||
let selectedProcess = this.getProcessDefinitionByName(this.processDefinitionName);
|
||||
if (selectedProcess) {
|
||||
this.processForm.controls['processDefinition'].setValue(selectedProcess.name);
|
||||
this.processPayloadCloud.processDefinitionKey = selectedProcess.key;
|
||||
}
|
||||
}
|
||||
|
||||
public loadProcessDefinitions() {
|
||||
this.resetErrorMessage();
|
||||
|
||||
this.startProcessCloudService.getProcessDefinitions(this.appName).subscribe(
|
||||
(processDefinitionRepresentations: ProcessDefinitionCloud[]) => {
|
||||
this.processDefinitionList = processDefinitionRepresentations;
|
||||
if (processDefinitionRepresentations.length > 0) {
|
||||
this.selectDefaultProcessDefinition();
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.errorMessageId = 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.LOAD_PROCESS_DEFS';
|
||||
});
|
||||
}
|
||||
|
||||
isProcessDefinitionsEmpty(): boolean {
|
||||
return this.processDefinitionList.length === 0;
|
||||
}
|
||||
|
||||
startProcess() {
|
||||
this.isLoading = true;
|
||||
|
||||
this.processPayloadCloud.processInstanceName = this.processInstanceName.value;
|
||||
this.processPayloadCloud.payloadType = 'StartProcessPayload';
|
||||
if (this.variables) {
|
||||
this.processPayloadCloud.variables = this.variables;
|
||||
}
|
||||
|
||||
this.startProcessCloudService.startProcess(this.appName, this.processPayloadCloud).subscribe(
|
||||
(res) => {
|
||||
this.success.emit(res);
|
||||
this.isLoading = false;
|
||||
},
|
||||
(err) => {
|
||||
this.errorMessageId = 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.START';
|
||||
this.error.emit(err);
|
||||
this.isLoading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
cancelStartProcess() {
|
||||
this.cancel.emit();
|
||||
}
|
||||
|
||||
private resetErrorMessage() {
|
||||
this.errorMessageId = '';
|
||||
}
|
||||
|
||||
private resetProcessDefinitionList() {
|
||||
this.processForm.controls['processDefinition'].setValue('');
|
||||
this.filteredProcesses = this.processDefinitionList;
|
||||
}
|
||||
|
||||
displayProcessNameOnDropdown(process: any) {
|
||||
if (process) {
|
||||
let processName = process;
|
||||
if (typeof process !== 'string') {
|
||||
processName = process.name;
|
||||
}
|
||||
return processName;
|
||||
}
|
||||
}
|
||||
|
||||
displayDropdown(event) {
|
||||
event.stopPropagation();
|
||||
if (!this.inputAutocomplete.panelOpen) {
|
||||
this.resetProcessDefinitionList();
|
||||
this.inputAutocomplete.openPanel();
|
||||
} else {
|
||||
this.inputAutocomplete.closePanel();
|
||||
}
|
||||
}
|
||||
|
||||
processDefinitionNameValidator(): ValidatorFn {
|
||||
return (control: AbstractControl): { [key: string]: any } | null => {
|
||||
const processDefinitionFieldValue = control.value;
|
||||
let processDefinitionNameError = false;
|
||||
|
||||
if (processDefinitionFieldValue) {
|
||||
const processDefinition = this.getProcessIfExists(processDefinitionFieldValue);
|
||||
if (!processDefinition.key) {
|
||||
processDefinitionNameError = true;
|
||||
}
|
||||
}
|
||||
|
||||
return processDefinitionNameError ? { 'invalid name': true } : null;
|
||||
};
|
||||
}
|
||||
|
||||
get processInstanceName(): AbstractControl {
|
||||
return this.processForm.get('processInstanceName');
|
||||
}
|
||||
|
||||
get processDefinition(): AbstractControl {
|
||||
return this.processForm.get('processDefinition');
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*!
|
||||
* @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 { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
|
||||
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
|
||||
import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model';
|
||||
|
||||
export let fakeProcessInstance = new ProcessInstanceCloud({
|
||||
appName: 'simple-app',
|
||||
appVersion: '',
|
||||
serviceName: 'simple-app-rb',
|
||||
serviceFullName: 'simple-app-rb',
|
||||
serviceType: 'runtime-bundle',
|
||||
serviceVersion: '',
|
||||
id: 'd0b30377-dc5a-11e8-ae24-0a58646001fa',
|
||||
name: 'My Process Name',
|
||||
startDate: '2018-10-30T15:45:24.136+0000',
|
||||
initiator: 'usermock',
|
||||
status: 'RUNNING',
|
||||
processDefinitionId: 'BasicProcess:1:d05062f1-c6fb-11e8-ae24-0a58646001fa',
|
||||
processDefinitionKey: 'BasicProcess'
|
||||
});
|
||||
|
||||
export let fakeProcessDefinitions: ProcessDefinitionCloud[] = [
|
||||
new ProcessDefinitionCloud({
|
||||
appName: 'myApp',
|
||||
appVersion: 0,
|
||||
id: 'NewProcess:1',
|
||||
key: 'NewProcess 1',
|
||||
name: 'NewProcess 1',
|
||||
serviceFullName: 'myApp-rb',
|
||||
serviceName: 'myApp-rb',
|
||||
serviceType: 'runtime-bundle',
|
||||
serviceVersion: null
|
||||
}),
|
||||
new ProcessDefinitionCloud({
|
||||
appName: 'myApp',
|
||||
appVersion: 0,
|
||||
id: 'NewProcess:2',
|
||||
key: 'NewProcess 2',
|
||||
name: 'NewProcess 2',
|
||||
serviceFullName: 'myApp-rb',
|
||||
serviceName: 'myApp-rb',
|
||||
serviceType: 'runtime-bundle',
|
||||
serviceVersion: null
|
||||
})
|
||||
];
|
||||
|
||||
export let fakeProcessPayload = new ProcessPayloadCloud({
|
||||
processDefinitionKey: 'NewProcess:1',
|
||||
processInstanceName: 'NewProcess 1',
|
||||
payloadType: 'string'
|
||||
});
|
@ -0,0 +1,42 @@
|
||||
/*!
|
||||
* @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 class ProcessDefinitionCloud {
|
||||
id: string;
|
||||
appName: string;
|
||||
key: string;
|
||||
appVersion: number;
|
||||
version: number;
|
||||
name: string;
|
||||
serviceFullName: string;
|
||||
serviceName: string;
|
||||
serviceType: string;
|
||||
serviceVersion: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.id = obj && obj.id || null;
|
||||
this.name = obj && obj.name || null;
|
||||
this.appName = obj && obj.appName || null;
|
||||
this.key = obj && obj.key || null;
|
||||
this.version = obj && obj.version || 0;
|
||||
this.appVersion = obj && obj.appVersion || 0;
|
||||
this.serviceFullName = obj && obj.serviceFullName || null;
|
||||
this.serviceType = obj && obj.serviceType || null;
|
||||
this.serviceName = obj && obj.serviceName || null;
|
||||
this.serviceVersion = obj && obj.serviceVersion || null;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* @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 class ProcessInstanceCloud {
|
||||
appName: string;
|
||||
id: string;
|
||||
name: string;
|
||||
startDate: Date;
|
||||
initiator: string;
|
||||
status: string;
|
||||
processDefinitionId: string;
|
||||
processDefinitionKey: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.appName = obj && obj.appName || null;
|
||||
this.id = obj && obj.id || null;
|
||||
this.name = obj && obj.name || null;
|
||||
this.startDate = obj && obj.startDate || null;
|
||||
this.initiator = obj && obj.initiator || null;
|
||||
this.status = obj && obj.status || null;
|
||||
this.processDefinitionId = obj && obj.processDefinitionId || null;
|
||||
this.processDefinitionKey = obj && obj.processDefinitionKey || null;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @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 class ProcessPayloadCloud {
|
||||
processDefinitionKey: string;
|
||||
processInstanceName: string;
|
||||
businessKey: string;
|
||||
variables: Map<string, object>[];
|
||||
payloadType: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.processDefinitionKey = obj && obj.processDefinitionKey ? obj.processDefinitionKey : null;
|
||||
this.processInstanceName = obj && obj.processInstanceName ? obj.processInstanceName : null;
|
||||
this.businessKey = obj && obj.businessKey ? obj.businessKey : null;
|
||||
this.variables = obj && obj.variables ? obj.variables : null;
|
||||
this.payloadType = obj && obj.valueUrl ? obj.payloadType : null;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*!
|
||||
* @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/start-process-cloud.component';
|
||||
|
||||
export * from './models/process-definition-cloud.model';
|
||||
export * from './models/process-instance-cloud.model';
|
||||
export * from './models/process-payload-cloud.model';
|
||||
|
||||
export * from './services/start-process-cloud.service';
|
||||
export * from './start-process-cloud.module';
|
@ -0,0 +1,111 @@
|
||||
/*!
|
||||
* @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 { TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
AppConfigService,
|
||||
LogService,
|
||||
StorageService
|
||||
} from '@alfresco/adf-core';
|
||||
import { StartProcessCloudService } from './start-process-cloud.service';
|
||||
import { fakeProcessPayload } from '../mock/start-process.component.mock';
|
||||
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model';
|
||||
import { ProcessCloudModule } from '../../process-cloud.module';
|
||||
|
||||
describe('StartTaskCloudService', () => {
|
||||
|
||||
let service: StartProcessCloudService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessCloudModule],
|
||||
providers: [StartProcessCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(StartProcessCloudService);
|
||||
});
|
||||
|
||||
it('should be able to create a new process', (done) => {
|
||||
spyOn(service, 'startProcess').and.returnValue(of({ id: 'fake-id', name: 'fake-name' }));
|
||||
service.startProcess('appName1', fakeProcessPayload)
|
||||
.subscribe(
|
||||
(res: ProcessInstanceCloud) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.id).toEqual('fake-id');
|
||||
expect(res.name).toEqual('fake-name');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not be able to create a process if error occurred', () => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'startProcess').and.returnValue(throwError(errorResponse));
|
||||
service.startProcess('appName1', fakeProcessPayload)
|
||||
.subscribe(
|
||||
() => {
|
||||
fail('expected an error, not applications');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should be able to get all the process definitions', (done) => {
|
||||
spyOn(service, 'getProcessDefinitions').and.returnValue(of([{ id: 'fake-id', name: 'fake-name' }]));
|
||||
service.getProcessDefinitions('appName1')
|
||||
.subscribe(
|
||||
(res: ProcessDefinitionCloud[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res[0].id).toEqual('fake-id');
|
||||
expect(res[0].name).toEqual('fake-name');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not be able to get all the process definitions if error occurred', () => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
spyOn(service, 'getProcessDefinitions').and.returnValue(throwError(errorResponse));
|
||||
service.getProcessDefinitions('appName1')
|
||||
.subscribe(
|
||||
() => {
|
||||
fail('expected an error, not applications');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
@ -0,0 +1,99 @@
|
||||
/*!
|
||||
* @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, AppConfigService, LogService } from '@alfresco/adf-core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, from, throwError } from 'rxjs';
|
||||
import { map, catchError } from 'rxjs/operators';
|
||||
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
|
||||
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
|
||||
import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class StartProcessCloudService {
|
||||
|
||||
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 process definitions associated with an app.
|
||||
* @param appId ID of a target app
|
||||
* @returns Array of process definitions
|
||||
*/
|
||||
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
|
||||
|
||||
if (appName) {
|
||||
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-definitions`;
|
||||
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||
null, null, null,
|
||||
null, null, null,
|
||||
this.contentTypes, this.accepts,
|
||||
this.returnType, null, null)
|
||||
).pipe(
|
||||
map((res: any) => {
|
||||
return res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry));
|
||||
}),
|
||||
catchError((err) => this.handleProcessError(err))
|
||||
);
|
||||
} else {
|
||||
this.logService.error('AppName is mandatory for querying task');
|
||||
return throwError('AppName not configured');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a process based on a process definition, name, form values or variables.
|
||||
* @param appName name of the Application
|
||||
* @param processDefinitionId Process definition ID
|
||||
* @param name Process name
|
||||
* @param outcome Process outcome
|
||||
* @param startFormValues Values for the start form
|
||||
* @param variables Array of process instance variables
|
||||
* @returns Details of the process instance just started
|
||||
*/
|
||||
startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> {
|
||||
|
||||
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-instances`;
|
||||
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||
null, null, null,
|
||||
null, requestPayload, null,
|
||||
this.contentTypes, this.accepts,
|
||||
this.returnType, null, null)
|
||||
).pipe(
|
||||
map((processInstance) => new ProcessInstanceCloud(processInstance)),
|
||||
catchError((err) => this.handleProcessError(err))
|
||||
);
|
||||
}
|
||||
|
||||
private handleProcessError(error: any) {
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
}
|
@ -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 { StartProcessCloudModule } from './start-process-cloud.module';
|
||||
|
||||
describe('ProcessCloudModule', () => {
|
||||
let startProcessCloudModule: StartProcessCloudModule;
|
||||
|
||||
beforeEach(() => {
|
||||
startProcessCloudModule = new StartProcessCloudModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(startProcessCloudModule).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,51 @@
|
||||
/*!
|
||||
* @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 { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { MaterialModule } from '../../material.module';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateLoaderService } from '@alfresco/adf-core';
|
||||
import { StartProcessCloudComponent } from './components/start-process-cloud.component';
|
||||
import { StartProcessCloudService } from './services/start-process-cloud.service';
|
||||
@NgModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
}),
|
||||
MaterialModule,
|
||||
FlexLayoutModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
declarations: [
|
||||
StartProcessCloudComponent
|
||||
],
|
||||
exports: [
|
||||
StartProcessCloudComponent
|
||||
],
|
||||
providers: [
|
||||
StartProcessCloudService
|
||||
]
|
||||
})
|
||||
export class StartProcessCloudModule { }
|
Loading…
x
Reference in New Issue
Block a user