complex types selectable in Operation params
[sdc.git] / catalog-ui / src / app / ng2 / pages / interface-operation / operation-creator / operation-creator.component.ts
1 import * as _ from "lodash";
2 import {Component, ViewChild} from '@angular/core';
3
4 import {Subscription} from "rxjs/Subscription";
5
6 import {TranslateService} from "app/ng2/shared/translator/translate.service";
7 import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
8 import {OperationModel, OperationParameter, InputBEModel, RadioButtonModel, WORKFLOW_ASSOCIATION_OPTIONS} from 'app/models';
9
10 import {Tabs, Tab} from "app/ng2/components/ui/tabs/tabs.component";
11 import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
12
13 export interface OperationCreatorInput {
14     operation: OperationModel,
15     inputProperties: Array<InputBEModel>,
16     enableWorkflowAssociation: boolean,
17     readonly: boolean,
18     isService: boolean
19 }
20
21 @Component({
22     selector: 'operation-creator',
23     templateUrl: './operation-creator.component.html',
24     styleUrls: ['./operation-creator.component.less'],
25     providers: [TranslateService]
26 })
27
28 export class OperationCreatorComponent {
29
30     input: OperationCreatorInput;
31     operation: OperationModel;
32
33     workflows: Array<DropdownValue> = [];
34     workflowVersions: Array<DropdownValue> = [];
35     inputProperties: Array<InputBEModel> = [];
36     archivedWorkflowId: string = '&';
37
38     inputParameters: Array<OperationParameter> = [];
39     noAssignInputParameters: Array<OperationParameter> = [];
40     assignInputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
41
42     outputParameters: Array<OperationParameter> = [];
43     noAssignOutputParameters: Array<OperationParameter> = [];
44     assignOutputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
45
46     tableParameters: Array<OperationParameter> = [];
47
48     associationOptions: Array<DropdownValue>;
49
50     enableWorkflowAssociation: boolean;
51     isEditMode: boolean = false;
52     isLoading: boolean = false;
53     readonly: boolean;
54
55     propertyTooltipText: String;
56
57     TYPE_INPUT = 'Inputs';
58     TYPE_OUTPUT = 'Outputs';
59
60     @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
61     currentTab: String;
62
63     constructor(private workflowServiceNg2: WorkflowServiceNg2, private translateService: TranslateService) {
64         this.translateService.languageChangedObservable.subscribe(lang => {
65             this.propertyTooltipText = this.translateService.translate("OPERATION_PROPERTY_TOOLTIP_TEXT");
66
67             this.associationOptions = [
68                 new DropdownValue(WORKFLOW_ASSOCIATION_OPTIONS.NONE, this.translateService.translate("NO_WORKFLOW_ASSOCIATION")),
69                 new DropdownValue(WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.translateService.translate("EXISTING_WORKFLOW_ASSOCIATION"))
70             ];
71         });
72
73         this.currentTab = this.TYPE_INPUT;
74     }
75
76     ngOnInit() {
77         this.readonly = this.input.readonly;
78         this.enableWorkflowAssociation = this.input.enableWorkflowAssociation;
79         this.inputProperties = this.input.inputProperties;
80
81         const inputOperation = this.input.operation;
82         this.operation = new OperationModel(inputOperation || {});
83         if (!inputOperation) {
84             this.operation.workflowAssociationType = WORKFLOW_ASSOCIATION_OPTIONS.NONE;
85         }
86
87         if (this.enableWorkflowAssociation) {
88             this.isLoading = true;
89             this.workflowServiceNg2.getWorkflows().subscribe(workflows => {
90                 this.isLoading = false;
91                 this.workflows = _.map(
92                     _.filter(
93                         workflows,
94                         (workflow: any) => {
95                             if (workflow.archiving === this.workflowServiceNg2.WF_STATE_ACTIVE) {
96                                 return true;
97                             }
98                             if (workflow.archiving === this.workflowServiceNg2.WF_STATE_ARCHIVED &&
99                                 workflow.id === this.operation.workflowId) {
100                                 this.archivedWorkflowId = workflow.id;
101                                 return true;
102                             }
103                             return false;
104                         }
105                     ),
106                     (workflow: any) => new DropdownValue(workflow.id, workflow.name)
107                 );
108                 this.reconstructOperation();
109             });
110         } else {
111             this.reconstructOperation();
112         }
113     }
114
115     reconstructOperation = () => {
116         const inputOperation = this.input.operation;
117         if (inputOperation) {
118             if (this.enableWorkflowAssociation && inputOperation.workflowVersionId && this.isUsingExistingWF(inputOperation)) {
119                 this.onSelectWorkflow(inputOperation.workflowVersionId).add(() => {
120                     this.buildParams();
121                     this.updateTable();
122                 });
123             } else {
124                 this.inputParameters = this.noAssignInputParameters;
125                 this.outputParameters = this.noAssignOutputParameters;
126                 this.buildParams();
127                 this.updateTable();
128             }
129
130             if (inputOperation.uniqueId) {
131                 this.isEditMode = true;
132             }
133         }
134         this.updateTable();
135     }
136
137     buildParams = () => {
138         if (this.input.operation.outputParams) {
139             this.currentTab = this.TYPE_OUTPUT;
140             this.updateTable();
141             _.forEach(
142                 [...this.input.operation.outputParams.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
143                 (output: OperationParameter) => {
144                     this.addParam(output);
145                 }
146             );
147         }
148         this.currentTab = this.TYPE_INPUT;
149         this.updateTable();
150         if (this.input.operation.inputParams) {
151             _.forEach(
152                 [...this.input.operation.inputParams.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
153                 (input: OperationParameter) => {
154                     this.addParam(input);
155                 }
156             );
157         }
158     }
159
160     onSelectWorkflow(selectedVersionId?: string): Subscription {
161
162         this.operation.workflowVersionId = selectedVersionId || null;
163         if (!this.assignInputParameters[this.operation.workflowId]) {
164             this.assignInputParameters[this.operation.workflowId] = {};
165             this.assignOutputParameters[this.operation.workflowId] = {};
166         }
167
168         this.isLoading = true;
169         return this.workflowServiceNg2.getWorkflowVersions(this.operation.workflowId).subscribe((versions: Array<any>) => {
170             this.isLoading = false;
171
172             this.workflowVersions = _.map(
173                 _.filter(
174                     versions, version => version.state === this.workflowServiceNg2.VERSION_STATE_CERTIFIED
175                 ).sort((a, b) => a.name.localeCompare(b.name)),
176                 (version: any) => {
177                     if (!this.assignInputParameters[this.operation.workflowId][version.id] && version.id !== selectedVersionId) {
178                         this.assignInputParameters[this.operation.workflowId][version.id] = _.map(version.inputs, (input: OperationParameter) => {
179                             return new OperationParameter({...input, type: input.type.toLowerCase()});
180                         })
181                         .sort((a, b) => a.name.localeCompare(b.name));
182
183                         this.assignOutputParameters[this.operation.workflowId][version.id] = _.map(version.outputs, (output: OperationParameter) => {
184                             return new OperationParameter({...output, type: output.type.toLowerCase()});
185                         })
186                         .sort((a, b) => a.name.localeCompare(b.name));
187                     }
188                     return new DropdownValue(version.id, `V ${version.name}`);
189                 }
190             );
191
192             if (selectedVersionId) {
193                 this.assignInputParameters[this.operation.workflowId][selectedVersionId] = [];
194                 this.assignOutputParameters[this.operation.workflowId][selectedVersionId] = [];
195             }
196             if (!selectedVersionId && this.workflowVersions.length) {
197                 this.operation.workflowVersionId = _.last(this.workflowVersions).value;
198             }
199
200             this.changeWorkflowVersion();
201         });
202
203     }
204
205     changeWorkflowVersion() {
206         this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
207         this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
208         this.updateTable();
209     }
210
211     toggleAssociateWorkflow() {
212
213         if (!this.isUsingExistingWF()) {
214             this.inputParameters = this.noAssignInputParameters;
215             this.outputParameters = this.noAssignOutputParameters;
216         } else {
217             if (!this.operation.workflowId || !this.operation.workflowVersionId) {
218                 this.inputParameters = [];
219                 this.outputParameters = [];
220             } else {
221                 this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
222                 this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
223             }
224         }
225
226         this.updateTable();
227
228     }
229
230     tabChanged = (event) => {
231         this.currentTab = event.title;
232         this.updateTable();
233     }
234
235     updateTable() {
236         switch (this.currentTab) {
237             case this.TYPE_INPUT:
238                 this.tableParameters = this.inputParameters;
239                 break;
240             case this.TYPE_OUTPUT:
241                 this.tableParameters = this.outputParameters;
242                 break;
243         }
244     }
245
246     addParam(param?: OperationParameter): void {
247         this.tableParameters.push(new OperationParameter(param));
248     }
249
250     canAdd(): boolean {
251         let valid = true;
252         if (this.currentTab === this.TYPE_INPUT) {
253             _.forEach(this.inputParameters, param => {
254                 if (!param.name || !param.property) {
255                     valid = false;
256                 }
257             });
258         } else {
259             _.forEach(this.outputParameters, param => {
260                 if (!param.name || !param.type) {
261                     valid = false;
262                 }
263             });
264         }
265         return valid;
266     }
267
268     isParamsValid(): boolean {
269         let valid = true;
270         _.forEach(this.inputParameters, param => {
271             if (!param.name || !param.property) {
272                 valid = false;
273             }
274         });
275         _.forEach(this.outputParameters, param => {
276             if (!param.name || !param.type) {
277                 valid = false;
278             }
279         });
280         return valid;
281     }
282
283     onRemoveParam = (param: OperationParameter): void => {
284         let index = _.indexOf(this.tableParameters, param);
285         this.tableParameters.splice(index, 1);
286     }
287
288     createParamLists(): void {
289         this.operation.createInputParamsList(this.inputParameters);
290         this.operation.createOutputParamsList(this.outputParameters);
291     }
292
293     isUsingExistingWF = (operation?: OperationModel): boolean => {
294         operation = operation || this.operation;
295         return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING;
296     }
297
298     shouldCreateWF(operation?: OperationModel): boolean {
299         operation = operation || this.operation;
300         return this.operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW;
301     }
302
303     checkFormValidForSubmit(): boolean {
304         return this.operation.operationType &&
305             (!this.isUsingExistingWF() || this.operation.workflowVersionId) &&
306             this.isParamsValid();
307     }
308
309 }