diff options
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/interface-operation')
7 files changed, 202 insertions, 56 deletions
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html index afeff48d91..e32a0b60f5 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html @@ -21,7 +21,7 @@ class="top-add-btn add-btn" *ngIf="!isListEmpty()" [ngClass]="{'disabled': readonly}" - data-tests-id="addInterfaceOperation" + data-tests-id="add-operation" (click)="onEditOperation()"> {{ 'INTERFACE_ADD_OPERATION' | translate }} </div> @@ -33,6 +33,7 @@ *ngIf="isListEmpty() && !isLoading"> <div class="empty-list-add-btn" + data-tests-id="add-operation" [ngClass]="{'disabled': readonly}" (click)="onEditOperation()"> <svg-icon @@ -50,12 +51,14 @@ <div class="expand-collapse"> <a class="link" + data-tests-id="expand-all" [ngClass]="{'disabled': isAllExpanded()}" (click)="collapseAll(false)"> {{ 'INTERFACE_EXPAND_ALL' | translate }} </a> | <a class="link" + data-tests-id="collapse-all" [ngClass]="{'disabled': isAllCollapsed()}" (click)="collapseAll()"> {{ 'INTERFACE_COLLAPSE_ALL' | translate }} @@ -64,10 +67,12 @@ <div class="interface-row" - *ngFor="let interface of interfaces"> + *ngFor="let interface of interfaces" + [attr.data-tests-id]="'interface-' + interface.displayType()"> <div class="interface-accordion" + [attr.data-tests-id]="'interface-' + interface.displayType() + '-toggle'" (click)="interface.toggleCollapse()"> <span class="chevron-container" @@ -102,25 +107,29 @@ <div class="data-row" *ngFor="let operation of interface.operations" + [attr.data-tests-id]="'operation-' + operation.name" (click)="onEditOperation(operation)"> <span - class="cell field-name"> + class="cell field-name" + [attr.data-tests-id]="'operation-' + operation.name + '-name'"> {{operation.name}} </span> <span class="cell field-description" - [ngClass]="{'collapsed': operation.isCollapsed}"> + [ngClass]="{'collapsed': operation.isCollapsed}" + [attr.data-tests-id]="'operation-' + operation.name + '-description'"> {{operation.getDescriptionEllipsis()}} <span class="more-or-less link" - (click)="operation.toggleCollapsed($event)"> + (click)="operation.toggleCollapsed($event)" + [attr.data-tests-id]="'operation-' + operation.name + '-ellipsis'"> {{!operation.isEllipsis ? '' : operation.isCollapsed ? 'More' : 'Less'}} </span> </span> <span class="cell field-actions"> <span class="delete-action" - data-tests-id="deleteOperation" + [attr.data-tests-id]="'remove-operation-' + operation.name" (click)="onRemoveOperation($event, operation)"> <svg-icon *ngIf="!readonly" diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts index 97c7b4d959..7c0f23291b 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts @@ -136,20 +136,32 @@ export class InterfaceOperationComponent { ngOnInit(): void { this.isLoading = true; - this.workflowIsOnline = false;//!_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner')); - const workflowSubscription = this.enableWorkflowAssociation && this.workflowIsOnline ? this.WorkflowServiceNg2.getWorkflows() : Promise.resolve(); + this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner')); + Observable.forkJoin( this.ComponentServiceNg2.getInterfaces(this.component), this.ComponentServiceNg2.getComponentInputs(this.component), - this.ComponentServiceNg2.getInterfaceTypes(this.component), - workflowSubscription + this.ComponentServiceNg2.getInterfaceTypes(this.component) ).subscribe((response: Array<any>) => { - this.isLoading = false; - this.initInterfaces(response[0].interfaces); - this.sortInterfaces(); - this.inputs = response[1].inputs; - this.interfaceTypes = response[2]; - this.workflows = response[3]; + const callback = (workflows) => { + this.isLoading = false; + this.initInterfaces(response[0].interfaces); + this.sortInterfaces(); + this.inputs = response[1].inputs; + this.interfaceTypes = response[2]; + this.workflows = workflows; + }; + if (this.enableWorkflowAssociation && this.workflowIsOnline) { + this.WorkflowServiceNg2.getWorkflows().subscribe( + callback, + (err) => { + this.workflowIsOnline = false; + callback([]); + } + ); + } else { + callback([]); + } }); } @@ -306,7 +318,7 @@ export class InterfaceOperationComponent { let curInterf = _.find( this.interfaces, interf => interf.type === operation.interfaceType - ) + ); if (!curInterf) { curInterf = new UIInterfaceModel({ type: response.interfaceType, @@ -318,7 +330,9 @@ export class InterfaceOperationComponent { curInterf.operations.push(new UIOperationModel(response)); this.sortInterfaces(); - if (response.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) { + if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL) { + this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, response, operation).subscribe(); + } else if (response.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) { this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, response).subscribe(); } else if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW) { this.$state.go('workspace.plugins', { path: 'workflowDesigner' }); @@ -330,20 +344,24 @@ export class InterfaceOperationComponent { this.ComponentServiceNg2.updateInterfaceOperation(this.component, operation).subscribe(newOperation => { this.openOperation = null; + let oldOpIndex, oldInterf; _.forEach(this.interfaces, interf => { _.forEach(interf.operations, op => { if (op.uniqueId === newOperation.uniqueId) { - const oldIndex = _.findIndex(interf.operations, el => el.uniqueId === op.uniqueId); - interf.operations.splice(oldIndex, 1); + oldInterf = interf; + oldOpIndex = _.findIndex(interf.operations, el => el.uniqueId === op.uniqueId); } }) }); + oldInterf.operations.splice(oldOpIndex, 1); const newInterf = _.find(this.interfaces, interf => interf.type === operation.interfaceType); newInterf.operations.push(new UIOperationModel(newOperation)); this.sortInterfaces(); - if (newOperation.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) { + if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL) { + this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, newOperation, operation).subscribe(); + } else if (newOperation.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) { this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, newOperation).subscribe(); } }); diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html index 9f78088609..5faddd829c 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html @@ -50,7 +50,8 @@ label="{{ 'OPERATION_NAME' | translate }}" [(value)]="operation.name" testId="operationName" - (valueChange)="onChangeName()"> + (valueChange)="onChangeName()" + [disabled]="readonly"> </sdc-input> </div> @@ -80,7 +81,37 @@ </sdc-dropdown> </div> - <div class="form-item" *ngIf="!isUsingExistingWF()"></div> + <div class="form-item" *ngIf="!isUsingExistingWF() && !isUsingExternalWF()"></div> + + <div + *ngIf="isUsingExternalWF()" + class="form-item sdc-input"> + <label class="sdc-input__label required">{{ 'OPERATION_ARTIFACT' | translate }}</label> + <div class="i-sdc-form-item i-sdc-form-file-upload"> + <span + class="i-sdc-form-file-name" + data-tests-id="artifactFilename"> + {{ operation.artifactFile && operation.artifactFile.name }} + </span> + <div + *ngIf="operation.artifactFile && operation.artifactFile.name" + class="i-sdc-form-file-upload-x-btn" + data-tests-id="clearArtifact" + (click)="onChangeArtifactFile({ target: {} })"></div> + <label + class="i-sdc-form-file-upload-label" + [ngClass]="{'disabled': readonly}"> + <input + type="file" + base-sixty-four-input + maxsize="10240" + data-tests-id="artifactUpload" + (change)="onChangeArtifactFile($event)" + /> + <div class="file-upload-browse-btn">Browse</div> + </label> + </div> + </div> <div class="form-item sdc-input" *ngIf="isUsingExistingWF()"> <label class="sdc-input__label required">{{ 'OPERATION_WORKFLOW' | translate }} diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less index 1d65d98b9c..f2bd0f82af 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less @@ -57,6 +57,25 @@ flex: 0.4; } + .i-sdc-form-file-upload { + height: 37px; + margin-bottom: 0; + + .i-sdc-form-file-name { + padding: 8px 10px; + } + + .i-sdc-form-file-upload-x-btn { + top: 13px; + } + + .file-upload-browse-btn { + height: 100%; + padding: 7px 6px; + z-index: 1; + } + } + } } diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts index 6099cdbe98..7b36062427 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts @@ -102,11 +102,11 @@ export class OperationCreatorComponent implements OperationCreatorInput { this.propertyTooltipText = this.translateService.translate("OPERATION_PROPERTY_TOOLTIP_TEXT"); this.associationOptions = [ - new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.NONE, this.translateService.translate("NO_WORKFLOW_ASSOCIATION")), - new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.translateService.translate("EXISTING_WORKFLOW_ASSOCIATION")) + new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL, this.translateService.translate("EXTERNAL_WORKFLOW_ASSOCIATION")), + new DropDownOption(WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.translateService.translate("EXISTING_WORKFLOW_ASSOCIATION")), ]; - this.workflowAssociationType = this.operation.workflowAssociationType || WORKFLOW_ASSOCIATION_OPTIONS.NONE; + this.workflowAssociationType = this.operation.workflowAssociationType || WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL; }); this.currentTab = this.TYPE_INPUT; @@ -167,7 +167,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { (workflow: any) => new DropdownValue(workflow.id, workflow.name) ); } else { - this.workflows = [new DropdownValue(this.operation.workflowId, this.operation.workflowId)]; + this.workflows = []; } } this.reconstructOperation(); @@ -223,7 +223,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { _.forEach( [...this.inputOperation.outputs.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)), (output: OperationParameter) => { - this.addParam(output); + this.addParam({...output, required: Boolean(output.required)}); } ); } @@ -234,7 +234,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { _.forEach( [...this.inputOperation.inputs.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)), (input: OperationParameter) => { - this.addParam(input); + this.addParam({...input, required: Boolean(input.required)}); } ); } @@ -286,7 +286,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { } set descriptionValue(v) { - this.operation.description = v; + this.operation.description = v || null; this.validityChanged(); } @@ -295,6 +295,11 @@ export class OperationCreatorComponent implements OperationCreatorInput { if (_.isUndefined(workflowId) || !this.workflowIsOnline) { return; } + + if (this.operation.workflowId === workflowId.value && !selectedVersionId) { + return; + } + this.operation.workflowId = workflowId.value; if (!this.assignInputParameters[this.operation.workflowId]) { this.assignInputParameters[this.operation.workflowId] = {}; @@ -313,12 +318,12 @@ export class OperationCreatorComponent implements OperationCreatorInput { (version: any) => { if (!this.assignInputParameters[this.operation.workflowId][version.id] && version.id !== selectedVersionId) { this.assignInputParameters[this.operation.workflowId][version.id] = _.map(version.inputs, (input: OperationParameter) => { - return new OperationParameter({...input, type: input.type.toLowerCase()}); + return new OperationParameter({...input, type: input.type.toLowerCase(), required: Boolean(input.required)}); }) .sort((a, b) => a.name.localeCompare(b.name)); this.assignOutputParameters[this.operation.workflowId][version.id] = _.map(version.outputs, (output: OperationParameter) => { - return new OperationParameter({...output, type: output.type.toLowerCase()}); + return new OperationParameter({...output, type: output.type.toLowerCase(), required: Boolean(output.required)}); }) .sort((a, b) => a.name.localeCompare(b.name)); } @@ -376,6 +381,28 @@ export class OperationCreatorComponent implements OperationCreatorInput { } + onChangeArtifactFile(e: any) { + const file = e.target.files && e.target.files[0]; + this.operation.artifactFile = file; + + if (!this.operation.artifactFile) { + this.operation.artifactData = null; + this.validityChanged(); + return; + } + + const reader = new FileReader(); + reader.onloadend = () => { + this.isLoading = false; + const result = <String>reader.result; + this.operation.artifactData = result.substring(result.indexOf(',') + 1); + this.validityChanged(); + } + + this.isLoading = true; + reader.readAsDataURL(file); + } + tabChanged = (event) => { this.currentTab = event.title; @@ -397,8 +424,8 @@ export class OperationCreatorComponent implements OperationCreatorInput { } addParam(param?: OperationParameter): void { + this.tableParameters.push(new OperationParameter(param || {required: false})); this.validityChanged(); - this.tableParameters.push(new OperationParameter(param)); } canAdd = (): boolean => { @@ -456,6 +483,11 @@ export class OperationCreatorComponent implements OperationCreatorInput { return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING; } + isUsingExternalWF = (operation?: OperationModel): boolean => { + operation = operation || this.operation; + return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL; + } + shouldCreateWF = (operation?: OperationModel): boolean => { operation = operation || this.operation; return operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW; @@ -463,7 +495,9 @@ export class OperationCreatorComponent implements OperationCreatorInput { checkFormValidForSubmit = (): boolean => { return this.operation.name && - (!this.isUsingExistingWF() || this.operation.workflowVersionId) && + (this.isUsingExternalWF() ? + (this.operation.artifactFile && this.operation.artifactFile.name) : + (!this.isUsingExistingWF() || this.operation.workflowVersionId)) && this.isParamsValid(); } diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html index aa4277c004..3ac9328487 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html @@ -39,7 +39,7 @@ <div class="cell field-property" *ngIf="isInputParam"> <select - *ngIf="filteredInputProps.length || !isAssociateWorkflow" + *ngIf="filteredInputProps.length || operationOutputCats.length || !isAssociateWorkflow" [(ngModel)]="param.inputId" (change)="onChangeProperty($event)" [ngClass]="{'disabled': readonly}" @@ -60,7 +60,7 @@ </optgroup> </select> <span - *ngIf="!filteredInputProps.length && isAssociateWorkflow" + *ngIf="!filteredInputProps.length && !operationOutputCats.length && isAssociateWorkflow" class="no-properties-error"> {{ 'PARAM_NONE_OF_TYPE' | translate }} </span> diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts index 1b51d721af..bdf1003a64 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts @@ -1,6 +1,6 @@ import {Component, Input} from '@angular/core'; import {DataTypeService} from "app/ng2/services/data-type.service"; -import {OperationModel, OperationParameter, InputBEModel} from 'app/models'; +import {OperationModel, OperationParameter, InputBEModel, DataTypeModel} from 'app/models'; import {DropDownOption} from "../operation-creator.component"; import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component"; @@ -38,12 +38,38 @@ export class ParamRowComponent { constructor(private dataTypeService: DataTypeService) {} ngOnInit() { - this.propTypeEnum = _.uniq( - _.map( - this.getPrimitiveSubtypes(), - prop => prop.type - ) - ); + if (this.isInputParam) { + this.propTypeEnum = _.uniq( + _.map( + _.concat( + this.getPrimitiveSubtypes(), + _.reduce( + this.operationOutputs, + (acc, op) => [...acc, ...op.outputs.listToscaDataDefinition], + []) + ), + prop => prop.type + ) + ); + } else { + const dataTypes: Array<DataTypeModel> = _.toArray(this.dataTypeService.getAllDataTypes()); + this.propTypeEnum = _.concat( + _.map( + _.filter( + dataTypes, + type => this.isTypePrimitive(type.name) + ), + type => type.name + ).sort(), + _.map( + _.filter( + dataTypes, + type => !this.isTypePrimitive(type.name) + ), + type => type.name + ).sort() + ); + } this.onChangeType(); this.validityChanged(); @@ -54,6 +80,11 @@ export class ParamRowComponent { } onChangeType() { + if (!this.isInputParam) { + this.validityChanged(); + return; + } + this.filteredInputProps = _.map( _.filter( this.getPrimitiveSubtypes(), @@ -115,21 +146,25 @@ export class ParamRowComponent { const dataTypes = this.dataTypeService.getAllDataTypes(); _.forEach(this.inputProps, prop => { - const type = _.find( + const type:DataTypeModel = _.find( _.toArray(dataTypes), - (type: any) => type.name === prop.type + (type: DataTypeModel) => type.name === prop.type ); flattenedProps.push(prop); - if (type.properties) { - _.forEach(type.properties, subType => { - if (this.isTypePrimitive(subType.type)) { - flattenedProps.push({ - type: subType.type, - name: `${prop.name}.${subType.name}`, - uniqueId: `${prop.uniqueId}.${subType.name}` - }); - } - }); + if (!type) { + console.error('Could not find prop in dataTypes: ', prop); + } else { + if (type.properties) { + _.forEach(type.properties, subType => { + if (this.isTypePrimitive(subType.type)) { + flattenedProps.push({ + type: subType.type, + name: `${prop.name}.${subType.name}`, + uniqueId: `${prop.uniqueId}.${subType.name}` + }); + } + }); + } } }); @@ -149,7 +184,7 @@ export class ParamRowComponent { ); } - isTypePrimitive(type): boolean { + isTypePrimitive(type: string): boolean { return ( type === 'string' || type === 'integer' || |