2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2022 Nordix Foundation. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, ViewChild} from '@angular/core';
24 import {TranslateService} from "app/ng2/shared/translator/translate.service";
25 import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
32 WORKFLOW_ASSOCIATION_OPTIONS
35 import {Tabs} from "app/ng2/components/ui/tabs/tabs.component";
38 } from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
39 import {IDropDownOption} from 'onap-ui-angular';
40 import {DropDownComponent} from "onap-ui-angular/dist/components";
41 import {DROPDOWN_OPTION_TYPE} from "app/utils";
42 import {Subscription} from "rxjs";
44 export class DropDownOption implements IDropDownOption {
48 constructor(value: string, label?: string) {
50 this.label = label || value;
54 class TypedDropDownOption extends DropDownOption {
57 constructor(value: string, label?: string, type?: string) {
63 export interface OperationCreatorInput {
64 allWorkflows: Array<any>,
65 inputOperation: OperationModel,
66 interfaces: Array<InterfaceModel>,
67 inputProperties: Array<InputBEModel>,
68 enableWorkflowAssociation: boolean,
70 interfaceTypes: { [interfaceType: string]: Array<string> },
71 validityChangedCallback: Function,
72 workflowIsOnline: boolean,
73 capabilities: Array<Capability>
77 selector: 'operation-creator-interface-definition',
78 templateUrl: './operation-creator-interface-definition.component.html',
79 styleUrls: ['./operation-creator-interface-definition.component.less'],
80 providers: [TranslateService]
83 export class OperationCreatorInterfaceDefinitionComponent implements OperationCreatorInput {
85 input: OperationCreatorInput;
86 inputOperation: OperationModel;
87 interfaces: Array<InterfaceModel>;
88 operation: OperationModel;
89 interfaceNames: Array<TypedDropDownOption> = [];
90 interfaceTypes: { [interfaceType: string]: Array<string> };
91 operationNames: Array<TypedDropDownOption> = [];
92 validityChangedCallback: Function;
93 capabilities: Array<Capability>;
95 allWorkflows: Array<any>;
96 workflows: Array<DropdownValue> = [];
97 workflowVersions: Array<DropdownValue> = [];
98 inputProperties: Array<InputBEModel> = [];
99 archivedWorkflowId: string = '&';
101 inputParameters: Array<OperationParameter> = [];
102 noAssignInputParameters: Array<OperationParameter> = [];
103 assignInputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
105 outputParameters: Array<OperationParameter> = [];
106 noAssignOutputParameters: Array<OperationParameter> = [];
107 assignOutputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
108 componentCapabilities: Array<Capability> = [];
110 tableParameters: Array<OperationParameter> = [];
111 operationOutputs: Array<OperationModel> = [];
113 associationOptions: Array<DropdownValue> = [];
114 workflowAssociationType: string;
116 enableWorkflowAssociation: boolean;
117 workflowIsOnline: boolean;
118 isEditMode: boolean = false;
119 isLoading: boolean = false;
122 propertyTooltipText: String;
124 TYPE_INPUT = 'Inputs';
125 TYPE_OUTPUT = 'Outputs';
127 INTERFACE_OTHER_HEADER = 'Local Interfaces';
128 INTERFACE_OTHER = 'Local';
130 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
131 @ViewChild('operationNamesDropdown') operationNamesDropdown: DropDownComponent;
132 @ViewChild('workflowAssignmentDropdown') workflowAssignmentDropdown: DropDownComponent;
135 constructor(private workflowServiceNg2: WorkflowServiceNg2, private translateService: TranslateService) {
136 this.translateService.languageChangedObservable.subscribe(lang => {
137 this.propertyTooltipText = this.translateService.translate("OPERATION_PROPERTY_TOOLTIP_TEXT");
139 this.associationOptions = [
140 new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL, this.translateService.translate("EXTERNAL_WORKFLOW_ASSOCIATION")),
141 new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.translateService.translate("EXISTING_WORKFLOW_ASSOCIATION")),
144 this.workflowAssociationType = this.operation.workflowAssociationType;
147 this.currentTab = this.TYPE_INPUT;
150 createInterfaceDropdown(type: string) {
152 const lastDot = label.lastIndexOf('.');
154 label = label.substr(lastDot + 1);
156 return new TypedDropDownOption(type, label);
160 this.interfaceNames = _.map(
161 _.keys(this.interfaceTypes),
162 type => this.createInterfaceDropdown(type)
164 this.interfaceNames.unshift(new TypedDropDownOption('Existing Interfaces', 'Existing Interfaces', DROPDOWN_OPTION_TYPE.HEADER));
165 this.interfaceNames = this.interfaceNames.concat([
166 new TypedDropDownOption(' ', ' ', DROPDOWN_OPTION_TYPE.HORIZONTAL_LINE),
167 new TypedDropDownOption(this.INTERFACE_OTHER_HEADER, this.INTERFACE_OTHER_HEADER, DROPDOWN_OPTION_TYPE.HEADER),
168 new TypedDropDownOption(this.INTERFACE_OTHER)
170 const inputOperation = this.inputOperation;
171 this.operation = new OperationModel(inputOperation || {});
173 this.operationOutputs = _.reduce(
175 (acc: Array<OperationModel>, interf) => [
179 op => op.uniqueId !== this.operation.uniqueId
184 if (this.enableWorkflowAssociation) {
185 if (this.workflowIsOnline) {
186 this.workflows = _.map(
190 if (workflow.archiving === this.workflowServiceNg2.WF_STATE_ACTIVE) {
193 if (workflow.archiving === this.workflowServiceNg2.WF_STATE_ARCHIVED &&
194 workflow.id === this.operation.workflowId) {
195 this.archivedWorkflowId = workflow.id;
201 (workflow: any) => new DropdownValue(workflow.id, workflow.name)
207 this.reconstructOperation();
208 this.filterCapabilities();
209 this.validityChanged();
214 if (this.workflowAssignmentDropdown) {
215 this.workflowAssignmentDropdown.allOptions = this.associationOptions && this.associationOptions.length ?
216 this.associationOptions :
218 new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL, this.translateService.translate("EXTERNAL_WORKFLOW_ASSOCIATION")),
219 new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.translateService.translate("EXISTING_WORKFLOW_ASSOCIATION")),
224 reconstructOperation = () => {
226 const buildAndUpdate = () => {
231 const inputOperation = this.inputOperation;
232 if (inputOperation) {
233 this.onSelectInterface(new DropDownOption(this.operation.interfaceType));
235 if (this.enableWorkflowAssociation && inputOperation.workflowVersionId && this.isUsingExistingWF(inputOperation)) {
236 this.assignInputParameters[this.operation.workflowId] = {[inputOperation.workflowVersionId]: []};
237 this.assignOutputParameters[this.operation.workflowId] = {[inputOperation.workflowVersionId]: []};
238 this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
239 this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
241 const sub = this.onSelectWorkflow(new DropDownOption(inputOperation.workflowId), inputOperation.workflowVersionId);
245 this.operation.workflowVersionId = '-1';
246 setTimeout(() => this.operation.workflowVersionId = this.inputOperation.workflowVersionId);
252 this.inputParameters = this.noAssignInputParameters;
253 this.outputParameters = this.noAssignOutputParameters;
257 if (inputOperation.uniqueId) {
258 this.isEditMode = true;
264 filterCapabilities() {
265 this.componentCapabilities = _.filter(this.capabilities, (cap: Capability) => cap.properties);
268 buildParams = () => {
270 if (this.inputOperation.outputs) {
271 this.currentTab = this.TYPE_OUTPUT;
274 [...this.inputOperation.outputs.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
275 (output: OperationParameter) => {
276 this.addParam({...output, required: Boolean(output.required)});
281 this.currentTab = this.TYPE_INPUT;
283 if (this.inputOperation.inputs) {
285 [...this.inputOperation.inputs.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
286 (input: OperationParameter) => {
287 this.addParam({...input, required: Boolean(input.required)});
294 isInterfaceOther(): boolean {
295 return this.operation.interfaceType === this.INTERFACE_OTHER;
298 onSelectInterface(interf: IDropDownOption) {
299 if (interf && this.operation.interfaceType !== interf.value) {
300 this.operation.name = null;
302 this.operation.interfaceType = interf && interf.value;
303 this.operationNames = !this.operation.interfaceType ? [] : (
305 this.interfaceTypes[this.operation.interfaceType],
307 const curInterf = _.find(
309 interf => interf.type === this.operation.interfaceType
311 const existingOp = _.find(
312 curInterf && curInterf.operations || [],
313 op => op.name === name
315 const ddType = (existingOp && existingOp.uniqueId !== this.operation.uniqueId) ? DROPDOWN_OPTION_TYPE.HORIZONTAL_LINE : DROPDOWN_OPTION_TYPE.SIMPLE;
316 return new TypedDropDownOption(name, name, ddType);
320 if (this.operationNamesDropdown) {
321 this.operationNamesDropdown.allOptions = <IDropDownOption[]>this.operationNames;
323 this.validityChanged();
326 onSelectOperationName(name: IDropDownOption) {
328 this.operation.name = name.value;
330 this.validityChanged();
334 this.validityChanged();
337 get descriptionValue() {
338 return this.operation.description;
341 set descriptionValue(v) {
342 this.operation.description = v || null;
343 this.validityChanged();
346 onSelectWorkflow(workflowId: DropDownOption, selectedVersionId?: string): Subscription {
348 if (_.isUndefined(workflowId) || !this.workflowIsOnline) {
352 if (this.operation.workflowId === workflowId.value && !selectedVersionId) {
356 this.operation.workflowId = workflowId.value;
357 if (!this.assignInputParameters[this.operation.workflowId]) {
358 this.assignInputParameters[this.operation.workflowId] = {};
359 this.assignOutputParameters[this.operation.workflowId] = {};
361 this.operation.workflowName = workflowId.label;
362 if (!this.assignInputParameters[this.operation.workflowName]) {
363 this.assignInputParameters[this.operation.workflowName] = {};
364 this.assignOutputParameters[this.operation.workflowName] = {};
367 this.isLoading = true;
368 this.validityChanged();
369 return this.workflowServiceNg2.getWorkflowVersions(this.operation.workflowId).subscribe((versions: Array<any>) => {
370 this.isLoading = false;
372 this.workflowVersions = _.map(
374 versions, version => version.state === this.workflowServiceNg2.VERSION_STATE_CERTIFIED
375 ).sort((a, b) => a.name.localeCompare(b.name)),
377 if (!this.assignInputParameters[this.operation.workflowId][version.id] && version.id !== selectedVersionId) {
378 this.assignInputParameters[this.operation.workflowId][version.id] = _.map(version.inputs, (input: any) => {
379 return new OperationParameter({
381 type: input.type.toLowerCase(),
382 required: Boolean(input.mandatory)
385 .sort((a, b) => a.name.localeCompare(b.name));
387 this.assignOutputParameters[this.operation.workflowId][version.id] = _.map(version.outputs, (output: any) => {
388 return new OperationParameter({
390 type: output.type.toLowerCase(),
391 required: Boolean(output.mandatory)
394 .sort((a, b) => a.name.localeCompare(b.name));
396 return new DropdownValue(version.id, `V ${version.name}`);
399 if (!selectedVersionId && this.workflowVersions.length) {
400 this.operation.workflowVersionId = _.last(this.workflowVersions).value;
401 this.operation.workflowVersion = _.last(this.workflowVersions).label;
404 this.changeWorkflowVersion(new DropDownOption(this.operation.workflowVersionId));
405 this.validityChanged();
410 changeWorkflowVersion(versionId: DropDownOption) {
412 if (_.isUndefined(versionId) || !this.workflowIsOnline) {
416 this.operation.workflowVersionId = versionId.value;
417 this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
418 this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
420 this.validityChanged();
424 toggleAssociateWorkflow(type: DropDownOption) {
426 if (_.isUndefined(type)) {
430 this.operation.workflowAssociationType = type.value;
431 this.workflowAssociationType = this.operation.workflowAssociationType;
433 if (!this.isUsingExistingWF()) {
434 this.inputParameters = this.noAssignInputParameters;
435 this.outputParameters = this.noAssignOutputParameters;
437 if (!this.operation.workflowId || !this.operation.workflowVersionId) {
438 this.inputParameters = [];
439 this.outputParameters = [];
441 this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
442 this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
447 this.validityChanged();
451 onChangeArtifactFile(e: any) {
452 const file = e.target.files && e.target.files[0];
453 this.operation.artifactFileName = file && file.name;
455 if (!this.operation.artifactFileName) {
456 this.operation.artifactData = null;
457 this.validityChanged();
461 const reader = new FileReader();
462 reader.onloadend = () => {
463 this.isLoading = false;
464 const result = <String>reader.result;
465 this.operation.artifactData = result.substring(result.indexOf(',') + 1);
466 this.validityChanged();
469 this.isLoading = true;
470 reader.readAsDataURL(file);
473 tabChanged = (event) => {
475 this.currentTab = event.title;
482 switch (this.currentTab) {
483 case this.TYPE_INPUT:
484 this.tableParameters = this.inputParameters;
486 case this.TYPE_OUTPUT:
487 this.tableParameters = this.outputParameters;
493 addParam(param?: OperationParameter): void {
494 this.tableParameters.push(new OperationParameter(param || {required: false}));
495 this.validityChanged();
498 canAdd = (): boolean => {
501 if (this.currentTab === this.TYPE_INPUT) {
502 _.forEach(this.inputParameters, param => {
503 if (!param.name || !param.inputId) {
508 _.forEach(this.outputParameters, param => {
509 if (!param.name || !param.type) {
519 isParamsValid = (): boolean => {
522 _.forEach(this.inputParameters, param => {
523 if (!param.name || !param.inputId) {
527 _.forEach(this.outputParameters, param => {
528 if (!param.name || !param.type) {
537 onRemoveParam = (param: OperationParameter): void => {
538 let index = _.indexOf(this.tableParameters, param);
539 this.tableParameters.splice(index, 1);
540 this.validityChanged();
543 createParamLists = () => {
544 this.operation.createInputsList(this.inputParameters);
545 this.operation.createOutputsList(this.outputParameters);
548 isUsingExistingWF = (operation?: OperationModel): boolean => {
549 operation = operation || this.operation;
550 return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING;
553 isUsingExternalWF = (operation?: OperationModel): boolean => {
554 operation = operation || this.operation;
555 return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL;
558 shouldCreateWF = (operation?: OperationModel): boolean => {
559 operation = operation || this.operation;
560 return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW;
563 checkFormValidForSubmit = (): boolean => {
564 return this.operation.name &&
565 (!this.isUsingExistingWF() || this.operation.workflowVersionId) &&
566 this.isParamsValid();
569 validityChanged = () => {
570 let validState = this.checkFormValidForSubmit();
571 this.validityChangedCallback(validState);
574 getSelectedDropdown(options: DropdownValue[], selectedValue: string): DropdownValue {
575 const selectedDropdown = _.find(options, (option) => option.value === selectedValue);
576 return selectedDropdown || this.toDropDownOption(null);
579 toDropDownOption(val: string) {
580 return {value: val, label: val};