diff options
23 files changed, 287 insertions, 38 deletions
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml index 0530298219..fe32ad0b22 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml @@ -2869,4 +2869,11 @@ errors: code: 400, message: "Cannot change this properties constraints as the resource is an instance.", messageId: "SVC4015" + } + + #---------SVC4016----------------------------- + INPUT_NAME_ALREADY_EXIST: { + code: 400, + message: "Input name already exist.", + messageId: "SVC4016" }
\ No newline at end of file diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java index 12a6936895..b632abfcca 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.ListUtils; @@ -398,6 +399,11 @@ public class InputsBusinessLogic extends BaseBusinessLogic { try { validateUserExists(userId); component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp); + StorageOperationStatus status = validateInputName(component, componentInstInputsMapUi); + if (status != StorageOperationStatus.OK) { + log.debug("Input name already exist"); + throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.INPUT_NAME_ALREADY_EXIST)); + } result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi).left() .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)).right() .map(componentsUtils::getResponseFormat); @@ -423,6 +429,31 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } } + private StorageOperationStatus validateInputName(final Component component, final ComponentInstInputsMap componentInstInputsMap) { + AtomicReference<StorageOperationStatus> storageOperationStatus = new AtomicReference<>(StorageOperationStatus.OK); + Map<String, List<ComponentInstancePropInput>> inputDeclaredProperties = new HashMap<>(); + if (MapUtils.isNotEmpty(componentInstInputsMap.getComponentInstanceProperties())) { + inputDeclaredProperties = componentInstInputsMap.getComponentInstanceProperties(); + } else if (MapUtils.isNotEmpty(componentInstInputsMap.getServiceProperties())) { + inputDeclaredProperties = componentInstInputsMap.getServiceProperties(); + } + + if (MapUtils.isNotEmpty(inputDeclaredProperties) && CollectionUtils.isNotEmpty(component.getInputs())) { + inputDeclaredProperties.values() + .forEach(componentInstancePropInputs -> + componentInstancePropInputs + .forEach(componentInstancePropInput -> component.getInputs() + .forEach(existingInput -> { + if (existingInput.getName().equals(componentInstancePropInput.getInputName())) { + storageOperationStatus.set(StorageOperationStatus.INVALID_VALUE); + } + }) + ) + ); + } + return storageOperationStatus.get(); + } + /** * Creates a list input with a data type which has properties specified. * diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java index eba66d271a..31a27b0457 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java @@ -255,7 +255,12 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties generatedInputPrefix = generatedInputPrefix == null || generatedInputPrefix.isEmpty() ? capName : generatedInputPrefix + UNDERSCORE + capName; } - String generatedInputName = generateInputName(generatedInputPrefix, propInput); + String generatedInputName = null; + if (StringUtils.isNotEmpty(propInput.getInputName())) { + generatedInputName = propInput.getInputName(); + } else { + generatedInputName = generateInputName(generatedInputPrefix, propInput); + } log.debug("createInput: propOwner.uniqueId={}, propInput.parentUniqueId={}", propertiesOwner.getUniqueId(), propInput.getParentUniqueId()); return createInputFromProperty(component.getUniqueId(), propertiesOwner, generatedInputName, propInput, prop); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 245fec39b0..186bcd2987 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -1764,8 +1764,24 @@ public class ToscaExportHandler { if (component == null || CollectionUtils.isEmpty(component.getInputs())) { return Collections.emptyMap(); } - return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName) - .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1)); + Map<String, String[]> propertyMapping = new HashMap<>(); + List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect( + Collectors.toList()); + + if (CollectionUtils.isNotEmpty(propertyMappedInputList)) { + propertyMappedInputList.forEach(inputDefinition -> { + if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) { + Optional<PropertyDefinition> property = component.getProperties().stream() + .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst(); + if (property.isPresent()) { + propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()}); + } + } else { + propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()}); + } + }); + } + return propertyMapping; } private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) { diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index d2b1409c86..2717c0ca0c 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -92,7 +92,7 @@ public enum ActionStatus { // cache CONVERT_COMPONENT_ERROR, COMPONENT_NOT_FOUND, // Inputs - INPUT_IS_NOT_CHILD_OF_COMPONENT, CFVC_LOOP_DETECTED, INPUT_ALREADY_EXIST, + INPUT_IS_NOT_CHILD_OF_COMPONENT, CFVC_LOOP_DETECTED, INPUT_ALREADY_EXIST, INPUT_NAME_ALREADY_EXIST, // Outputs OUTPUT_IS_NOT_CHILD_OF_COMPONENT, OUTPUT_ALREADY_EXIST, //Forwarding Path related diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstancePropInput.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstancePropInput.java index 048a952bd8..c32838d4ac 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstancePropInput.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstancePropInput.java @@ -19,10 +19,16 @@ */ package org.openecomp.sdc.be.model; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter public class ComponentInstancePropInput extends ComponentInstanceProperty { private String propertiesName; private PropertyDefinition input; + private String inputName; public ComponentInstancePropInput() { super(); @@ -32,22 +38,6 @@ public class ComponentInstancePropInput extends ComponentInstanceProperty { super(p); } - public String getPropertiesName() { - return propertiesName; - } - - public void setPropertiesName(String propertiesName) { - this.propertiesName = propertiesName; - } - - public PropertyDefinition getInput() { - return input; - } - - public void setInput(PropertyDefinition input) { - this.input = input; - } - public String[] getParsedPropNames() { String[] tokens = null; if (propertiesName != null && !propertiesName.isEmpty()) { diff --git a/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts b/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts index c2ea1ecbdf..7ca1fee21d 100644 --- a/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts +++ b/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts @@ -45,7 +45,8 @@ export class DerivedFEProperty extends PropertyBEModel { canBeDeclared: boolean; mapKey: string; mapKeyError: string; - mapInlist: boolean; + mapInlist: boolean + inputName: string; parentMapKey: string; constructor(property: PropertyBEModel, parentName?: string, createChildOfListOrMap?: boolean, key?:string, value?:any) { @@ -69,7 +70,7 @@ export class DerivedFEProperty extends PropertyBEModel { this.parentName = parentName; this.propertiesName = parentName + '#' + this.name; - if (property.type == PROPERTY_TYPES.LIST) { + if (property.type == PROPERTY_TYPES.LIST) { let parentKey : string = null; if(property.value != null) { const valueJson = JSON.parse(property.value); @@ -128,6 +129,7 @@ export class DerivedFEProperty extends PropertyBEModel { // this.constraints = property ? property.constraints : null; this.valueObjIsValid = true; this.derivedDataType = this.getDerivedPropertyType(); + this.inputName = property.inputName; } public getActualMapKey() { diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts index ae72977b80..e4c0f8165c 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -69,6 +69,7 @@ export class PropertyBEModel { parentPropertyType: string; subPropertyInputPath: string; inputPath: string; + inputName: string; toscaPresentation: ToscaPresentationData; metadata: Metadata; propertyConstraints: any; @@ -103,6 +104,7 @@ export class PropertyBEModel { this.toscaPresentation = property.toscaPresentation; this.getPolicyValues = property.getPolicyValues; this.inputPath = property.inputPath; + this.inputName = property.inputName; this.metadata = property.metadata; if (property.toscaFunction) { this.toscaFunction = property.toscaFunction; diff --git a/catalog-ui/src/app/models/properties-inputs/property-declare-api-model.ts b/catalog-ui/src/app/models/properties-inputs/property-declare-api-model.ts index 5b1c12091b..84970ad0f9 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-declare-api-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-declare-api-model.ts @@ -25,6 +25,7 @@ import { PropertyBEModel, PropertyFEModel, DerivedFEProperty } from "../../model export class PropertyDeclareAPIModel extends PropertyBEModel{ input: PropertyBEModel; propertiesName: string; + inputName: string; constructor(property: PropertyFEModel, childProperty?: DerivedFEProperty) { @@ -32,6 +33,7 @@ export class PropertyDeclareAPIModel extends PropertyBEModel{ if (childProperty) { this.input = childProperty; this.propertiesName = childProperty.propertiesName; + this.inputName = childProperty.inputName; } } diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index adc88cbc6d..40e701aa35 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -99,6 +99,7 @@ import {ToscaFunctionComponent} from '../ng2/pages/properties-assignment/tosca-f import {ConstraintsComponent} from '../ng2/pages/properties-assignment/constraints/constraints.component'; import {TypeWorkspaceComponent} from "../ng2/pages/type-workspace/type-workspace.component"; import {TypeWorkspaceGeneralComponent} from "../ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component"; +import {DeclareInputComponent} from "../ng2/pages/properties-assignment/declare-input/declare-input.component"; let moduleName: string = 'Sdc.Directives'; let directiveModule: ng.IModule = angular.module(moduleName, []); @@ -342,3 +343,9 @@ directiveModule.directive('appTypeWorkspaceGeneral', downgradeComponent({ inputs: [], outputs: [] }) as angular.IDirectiveFactory); + +directiveModule.directive('declareInput', downgradeComponent({ + component: DeclareInputComponent, + inputs: ['property'], + outputs: [] +}) as angular.IDirectiveFactory); diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 1e23bb6c4e..0c5b10f1e4 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -110,6 +110,7 @@ import {ModelService} from "./services/model.service"; import {ToscaArtifactService} from "./services/tosca-artifact.service"; import {InterfaceDefinitionModule} from "./pages/interface-definition/interface-definition.module"; import {TypeWorkspaceModule} from "./pages/type-workspace/type-workspace.module"; +import {DeclareInputModule} from "./pages/properties-assignment/declare-input/declare-input.module"; declare const __ENV__: string; @@ -158,6 +159,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent PropertiesAssignmentModule, AttributesOutputsModule, PropertyCreatorModule, + DeclareInputModule, DeclareListModule, ToscaFunctionModule, ConstraintsModule, diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.html new file mode 100644 index 0000000000..19b23598fa --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.html @@ -0,0 +1,22 @@ +<!-- + ~ ============LICENSE_START======================================================= + ~ Copyright (C) 2023 Nordix Foundation + ~ ================================================================================ + ~ 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. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + ~ ============LICENSE_END========================================================= + --> + +<div class="declare-input"> + <input id="myText" type="text" (keyup)="setInputName($event)"/> +</div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.spec.ts new file mode 100644 index 0000000000..c3fa1f506f --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.spec.ts @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeclareInputComponent } from './declare-input.component'; + +describe('DeclareInputComponent', () => { + let component: DeclareInputComponent; + let fixture: ComponentFixture<DeclareInputComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DeclareInputComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DeclareInputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.ts new file mode 100644 index 0000000000..d156383f6b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.component.ts @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +import {Component, Input, OnInit} from '@angular/core'; +import {FormControl, FormGroup} from "@angular/forms"; + +@Component({ + selector: 'declare-input', + templateUrl: './declare-input.component.html' +}) +export class DeclareInputComponent implements OnInit { + inputNameForm: FormControl = new FormControl(undefined); + formGroup: FormGroup = new FormGroup({ + 'inputName': this.inputNameForm, + }); + inputName: string; + constructor() { } + ngOnInit() { + } + setInputName(event) { + this.inputName = event.target.value; + this.inputNameForm.setValue(this.inputName); + } + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.module.ts new file mode 100644 index 0000000000..0dae0a2421 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-input/declare-input.module.ts @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import {DeclareInputComponent} from "./declare-input.component"; + +@NgModule({ + imports: [ + CommonModule, + FormsModule + ], + declarations: [DeclareInputComponent], + exports: [DeclareInputComponent], + entryComponents: [ + DeclareInputComponent + ], +}) + +export class DeclareInputModule { } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html index 1eed6dfba1..36d316ee5d 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html @@ -78,12 +78,12 @@ <span class="sprite search-icon" data-tests-id="search-button"></span> <filter-properties-assignment *ngIf="isPropertiesTabSelected" #advanceSearch class="advance-search" [componentType]="component.componentType" (searchProperties)="searchPropertiesInstances($event)"></filter-properties-assignment> </div> - <button (click)="selectToscaFunctionAndValues()" + <button (click)="openToscaGetFunctionModal()" *ngIf="isPropertiesTabSelected && !isSelf()" [disabled]="(checkedPropertiesCount != 1 || isReadonly || hasChangedData) && !enableToscaFunction" class="tlv-btn blue declare-button" data-tests-id="declare-button select-tosca-function">{{'TOSCA_FUNCTION_LABEL' | translate}}</button> - <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="openAddInputNameAndDeclareInputModal()" data-tests-id="declare-button declare-input">Declare Input</button> <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData || isSelf()" (click)="declarePropertiesToPolicies()" data-tests-id="declare-button declare-policy">Declare Policy</button> <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || checkedChildPropertiesCount || isReadonly || hasChangedData" (click)="declareListProperties()" data-tests-id="declare-but($event)ton declare-list-input">Create List Input</button> </div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index a1e4f415be..2592227afa 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -70,6 +70,7 @@ import {Observable} from "rxjs"; import {TranslateService} from "../../shared/translator/translate.service"; import {ToscaFunction} from "../../../models/tosca-function"; import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function"; +import {DeclareInputComponent} from "./declare-input/declare-input.component"; const SERVICE_SELF_TITLE = "SELF"; @Component({ @@ -728,7 +729,7 @@ export class PropertiesAssignmentComponent { } /*** DECLARE PROPERTIES/INPUTS ***/ - declareProperties = (): void => { + declareInputFromProperties = (inputName:string): void => { console.debug("==>" + this.constructor.name + ": declareProperties"); let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); @@ -743,6 +744,9 @@ export class PropertiesAssignmentComponent { if (!this.isInput(selectedInstanceData.originType)) { // convert Property FE model -> Property BE model, extract only checked selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); + if (inputName) { + selectedComponentInstancesProperties[instanceId][0].inputName = inputName; + } } else { selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); } @@ -801,6 +805,37 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + private openAddInputNameAndDeclareInputModal = (): void => { + const modalTitle = this.translateService.translate('ADD_INPUT_NAME_TO_DECLARE'); + const modalButtons = []; + const modal = this.modalService.createCustomModal(new ModalModel( + 'sm', + modalTitle, + null, + modalButtons, + null /* type */ + )); + modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue', + () => { + const inputName: string = modal.instance.dynamicContent.instance.inputNameForm.value; + if (inputName) { + this.declareInputFromProperties(inputName); + } else { + this.notification.warning({ + message: 'Failed to set input name', + title: 'Warning' + }); + } + this.modalService.closeCurrentModal(); + } + )); + modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => { + this.modalService.closeCurrentModal(); + })); + this.modalService.addDynamicContentToModal(modal, DeclareInputComponent, {}); + modal.instance.open(); + } + declareListProperties = (): void => { // get selected properties let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index 0b984ac2a4..bc5345c386 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -65,9 +65,6 @@ export class PropertiesUtils { newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children this.dataTypeService.checkForCustomBehavior(newFEProp); - if (newFEProp.isToscaFunction()) { - return; - } //if this prop (or any children) are declared, set isDeclared and disable checkbox on parents/children if (newFEProp.getInputValues && newFEProp.getInputValues.length) { newFEProp.getInputValues.forEach(propInputDetail => { diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json index 58288840d6..18813280d6 100644 --- a/catalog-ui/src/assets/languages/en_US.json +++ b/catalog-ui/src/assets/languages/en_US.json @@ -518,6 +518,8 @@ "=========== PROPERTIES ASSIGNMENT DECLARE AS POLICY ===========": "", "DELETE_POLICY_TITLE": "Delete Policy", "DELETE_POLICY_MSG": "Are you sure you want to delete policy '{{policyName}}'?", + "=========== PROPERTIES ASSIGNMENT DECLARE AS INPUT ===========": "", + "ADD_INPUT_NAME_TO_DECLARE": "Enter name of input to be created", "=========== PROPERTIES ASSIGNMENT TOSCA FUNCTION BUTTON ===========": "", "TOSCA_FUNCTION_LABEL": "TOSCA function", "TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL": "Property Source", diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java index 7409588970..6652ada806 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java @@ -485,9 +485,9 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { private void declareInputToBaseService(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName) { propertiesAssignmentPage.selectProperty(propertyName); - propertiesAssignmentPage.clickOnDeclareInput(); + propertiesAssignmentPage.clickOnDeclareInput("inputName1"); propertiesAssignmentPage.clickInputTab(propertyName); - propertiesAssignmentPage.isInputPresent(vfResourceCreateData.getName() + "_" + propertyName); + propertiesAssignmentPage.isInputPresent("inputName1"); } private void declareInputToInstanceProperties(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName) { @@ -495,9 +495,9 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { propertiesAssignmentPage.loadCompositionTab(); propertiesAssignmentPage.loadComponentInstanceProperties(vfcs.get(0).getName().concat(" 0")); propertiesAssignmentPage.selectProperty(propertyName); - propertiesAssignmentPage.clickOnDeclareInput(); + propertiesAssignmentPage.clickOnDeclareInput("inputName2"); propertiesAssignmentPage.clickInputTab(propertyName); - propertiesAssignmentPage.isInputPresent(vfResourceCreateData.getName() + "_" + vfcs.get(0).getName()); + propertiesAssignmentPage.isInputPresent("inputName2"); } private CreateVfFlow createVF() { @@ -815,7 +815,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { final Map<String, Object> inputsTosca = getMapEntry(topologyTemplateTosca, "inputs"); assertThat(String.format("'%s' should contain a inputs entry", toscaYaml), inputsTosca, notNullValue()); assertEquals(2, inputsTosca.keySet().stream() - .filter(s -> (s.contains("resourceSubtype") || s.contains("property1"))).count()); + .filter(s -> (s.contains("inputName"))).count()); final Map<String, Object> substitutionMapping = getMapEntry(topologyTemplateTosca, "substitution_mappings"); assertThat(String.format("'%s' should contain a substitution_mappings entry", toscaYaml), substitutionMapping, notNullValue()); diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentInputTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentInputTab.java index b83be254ef..937740bc53 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentInputTab.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentInputTab.java @@ -136,7 +136,7 @@ public class ResourcePropertiesAssignmentInputTab extends AbstractPageObject { public boolean isInputPresent(final String inputName) { isInputPropertiesTableLoaded(); try { - waitForElementVisibility(By.xpath(XpathSelector.INPUT_CHECKBOX.formatXpath(inputName)), 5); + waitForElementVisibility(By.xpath(XpathSelector.INPUT_TABLE.formatXpath(inputName)), 5); } catch (final Exception ignored) { return false; } @@ -151,7 +151,7 @@ public class ResourcePropertiesAssignmentInputTab extends AbstractPageObject { private enum XpathSelector { INPUT_TAB("//*[contains(@data-tests-id, 'Inputs') and contains(@class, 'active')]"), PROPERTIES_TABLE("//div[contains(@class,'properties-table')]"), - INPUT_CHECKBOX("//checkbox[@data-tests-id='%s']"), + INPUT_TABLE("//*[contains(@class, 'property-name') and text()='%s']"), NO_DATA_MESSAGE("//div[contains(@class,'no-data') and text()='No data to display']"), PROPERTY_SAVE_BTN("//button[@data-tests-id='properties-save-button']"), PROPERTY_SAVE_MESSAGE("//div[contains(text(), 'Successfully saved')]"), diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java index cb4345c7cc..83d4c3fba3 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java @@ -138,8 +138,8 @@ public class ResourcePropertiesAssignmentPage extends ComponentPage { resourcePropertiesAssignmentTab.loadComponentInstanceProperties(instanceName); } - public void clickOnDeclareInput(){ - resourcePropertiesAssignmentTab.clickOnDeclareInput(); + public void clickOnDeclareInput(final String inputName){ + resourcePropertiesAssignmentTab.clickOnDeclareInput(inputName); } public void loadCompositionTab(){ diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java index 81ce7ffec1..2b3d2e0b86 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java @@ -344,8 +344,16 @@ public class ResourcePropertiesAssignmentTab extends AbstractPageObject { waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.INSTANCE_SPAN.getXpath(instanceName))).click(); } - public void clickOnDeclareInput(){ + public void clickOnDeclareInput(final String inputName){ waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.DECLARE_INPUT_BTN.getXpath())).click(); + declareInputWithSetInputName(inputName); + } + + private void declareInputWithSetInputName(final String inputName) { + final By setInputNameLocator = By.xpath(XpathSelector.SET_INPUT_NAME_FIELD.getXpath()); + final WebElement inputNameField = waitForElementVisibility(setInputNameLocator, 5); + inputNameField.sendKeys(inputName); + waitToBeClickable(By.xpath(XpathSelector.INPUT_NAME_SAVE_BTN.getXpath())).click(); } public void loadCompositionTab(){ @@ -364,6 +372,7 @@ public class ResourcePropertiesAssignmentTab extends AbstractPageObject { SOFTWARE_VERSION_PROPERTY_CHECKBOX("software_versions", "//checkbox[@data-tests-id='%s']"), SOFTWARE_VERSION_INPUT("value-prop-software_versions", "//input[starts-with(@data-tests-id,'%s')]"), PROPERTY_CHECKBOX("//checkbox[@data-tests-id='%s']"), + SET_INPUT_NAME_FIELD("//*[@id=\"myText\"]"), PROPERTY_SAVE_BTN("properties-save-button", "//button[@data-tests-id='%s']"), PROPERTY_ADD_RIGHT_COLUMN_DIV("right-column", "//div[@class='%s']"), PROPERTY_ADD_BTN("add-btn", "//div[contains(@class,'%s')]"), @@ -376,6 +385,7 @@ public class ResourcePropertiesAssignmentTab extends AbstractPageObject { PROPERTY_TYPES("//*[contains(@data-tests-id, 'propertyType')]"), PROPERTY_NAMES("//*[contains(@data-tests-id, 'propertyName')]"), DECLARE_INPUT_BTN("declare-button declare-input", "//button[@data-tests-id='%s']"), + INPUT_NAME_SAVE_BTN("//button[@data-tests-id='Save']"), COMPOSITION_TAB("Composition", "//div[contains(@class,'tab') and contains(text(), '%s')]"), INSTANCE_SPAN("//span[@data-tests-id='%s']"); |