From 3849231a17930b1bb2ba09af15673bfd07538b9d Mon Sep 17 00:00:00 2001 From: KrupaNagabhushan Date: Thu, 19 Nov 2020 14:28:00 +0000 Subject: Create inputs independent of properties Issue-ID: SDC-3431 Signed-off-by: KrupaNagabhushan Change-Id: I4f29d0e490a14292fd1aa9f96ca6621b37f325d8 --- .../files/default/error-configuration.yaml | 17 +++- .../be/components/impl/InputsBusinessLogic.java | 110 ++++++++++++++++++++- .../sdc/be/servlets/BeGenericServlet.java | 56 ++++++++++- .../openecomp/sdc/be/servlets/InputsServlet.java | 62 ++++++++++++ .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 3 + .../operations/ToscaOperationFacade.java | 43 +++++++- .../logic/inputs-table/inputs-table.component.html | 6 +- .../logic/inputs-table/inputs-table.component.less | 3 +- .../logic/inputs-table/inputs-table.component.ts | 12 +-- .../properties-assignment.page.component.html | 5 +- .../properties-assignment.page.component.ts | 35 +++++++ .../properties-assignment/services/inputs.utils.ts | 11 ++- .../topology-template.service.ts | 10 ++ 13 files changed, 353 insertions(+), 20 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 4aa93cb268..ecaf852a16 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 @@ -2410,10 +2410,23 @@ errors: message: 'Error: Invalid Content. %1 has invalid format.', messageId: "SVC4723" } -#---------SVC4732------------------------------ +#---------SVC4734------------------------------ # %1 - list of validation errors INVALID_PM_DICTIONARY_FILE: { code: 400, message: 'Error: Invalid PM Dictionary File. %1', - messageId: "SVC4732" + messageId: "SVC4734" + } +#-----------SVC4735--------------------------- + #%1 - input name + INPUT_ALREADY_EXIST: { + code: 409, + message: "Error: Input with '%1' name already exists.", + messageId: "SVC4735" + } +#---------SVC4736------------------------------ + INVALID_INPUT_NAME: { + code: 400, + message: "Error: Input name contains invalid characters. It should have only letters, numbers and underscores.", + messageId: "SVC4736" } 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 69adb90493..5b197de183 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 @@ -23,6 +23,7 @@ package org.openecomp.sdc.be.components.impl; import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang.BooleanUtils; @@ -33,6 +34,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponent import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator; import org.openecomp.sdc.be.components.validation.ComponentValidations; +import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.utils.MapUtil; @@ -40,7 +42,9 @@ import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUti import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstInputsMap; import org.openecomp.sdc.be.model.ComponentInstListInput; import org.openecomp.sdc.be.model.ComponentInstance; @@ -61,15 +65,16 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; +import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; +import org.openecomp.sdc.be.resources.data.EntryData; import org.openecomp.sdc.common.log.elements.LoggerSupportability; import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions; import org.openecomp.sdc.common.log.enums.StatusCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Arrays; @@ -81,7 +86,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -@Component("inputsBusinessLogic") +@org.springframework.stereotype.Component("inputsBusinessLogic") public class InputsBusinessLogic extends BaseBusinessLogic { private static final String CREATE_INPUT = "CreateInput"; @@ -874,4 +879,105 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } + public Either, ResponseFormat> addInputToComponent(String componentId, + String inputName, + InputDefinition newInputDefinition, + String userId) { + Either, ResponseFormat> result = null; + + validateUserExists(userId); + + Either serviceElement = + toscaOperationFacade.getToscaElement(componentId); + if (serviceElement.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + return result; + } + + Component component = serviceElement.left().value(); + NodeTypeEnum nodeType = component.getComponentType().getNodeType(); + + StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType); + if (!lockResult.equals(StorageOperationStatus.OK)) { + BeEcompErrorManager.getInstance() + .logBeFailedLockObjectError(CREATE_INPUT, nodeType.name().toLowerCase(), componentId); + log.info("Failed to lock component {}. Error - {}", componentId, lockResult); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return result; + } + + try { + if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + return result; + } + + List inputs = component.getInputs(); + + if (CollectionUtils.isEmpty(inputs)) { + inputs = new ArrayList<>(); + } + + if (isInputExistInComponent(inputs, inputName)) { + + result = Either.right(componentsUtils.getResponseFormat(ActionStatus + .INPUT_ALREADY_EXIST, inputName)); + return result; + } + + Map allDataTypes = getAllDataTypes(applicationDataTypeCache); + + // validate input default values + Either defaultValuesValidation = validatePropertyDefaultValue( + newInputDefinition, allDataTypes); + if (defaultValuesValidation.isRight()) { + result = Either.right(defaultValuesValidation.right().value()); + return result; + } + + // convert Input + ToscaPropertyType type = getType(newInputDefinition.getType()); + if (type != null) { + PropertyValueConverter converter = type.getConverter(); + // get inner type + String innerType = null; + SchemaDefinition schema = newInputDefinition.getSchema(); + if (schema != null) { + PropertyDataDefinition prop = schema.getProperty(); + if (prop != null) { + innerType = prop.getType(); + } + } + if (newInputDefinition.getDefaultValue() != null) { + String convertedValue = converter + .convert(newInputDefinition.getDefaultValue(), innerType, allDataTypes); + newInputDefinition.setDefaultValue(convertedValue); + } + } + + Either addInputEither = + toscaOperationFacade.addInputToComponent(inputName, newInputDefinition, component); + + if (addInputEither.isRight()) { + log.info("Failed to add new input {}. Error - {}", componentId, + addInputEither.right().value()); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus + .GENERAL_ERROR)); + return result; + } + + result = Either.left(new EntryData<>(inputName, newInputDefinition)); + return result; + } finally { + commitOrRollback(result); + // unlock component + graphLockOperation.unlockComponent(componentId, nodeType); + } + } + + private boolean isInputExistInComponent(List inputs, String inputName) { + return CollectionUtils.isNotEmpty(inputs) && + inputs.stream().anyMatch(input -> input.getName().equals(inputName)); + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java index b497b702c3..1a8a305d2a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java @@ -68,6 +68,7 @@ import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ComponentInstInputsMap; import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintJacksonDeserializer; @@ -393,6 +394,19 @@ public class BeGenericServlet extends BasicServlet { return Either.left(propertyDefinition); } + private Either getInputDefinitionFromJson(String componentId, String inputName, JSONObject value) { + String jsonString = value.toJSONString(); + Either convertJsonToObject = convertJsonToObject(jsonString, InputDefinition.class); + if (convertJsonToObject.isRight()) { + return Either.right(convertJsonToObject.right().value()); + } + InputDefinition inputDefinition = convertJsonToObject.left().value(); + String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(componentId, inputName); + inputDefinition.setUniqueId(uniqueId); + + return Either.left(inputDefinition); + } + protected Either, ActionStatus> getPropertiesListForUpdate(String data) { Map properties = new HashMap<>(); @@ -421,7 +435,6 @@ public class BeGenericServlet extends BasicServlet { } - protected String propertyToJson(Map.Entry property) { JSONObject root = new JSONObject(); String propertyName = property.getKey(); @@ -565,4 +578,45 @@ public class BeGenericServlet extends BasicServlet { return getInputBL(context); } + + protected Either, ActionStatus> getInputModel(String componentId, String data) { + JSONParser parser = new JSONParser(); + JSONObject root; + try { + Map inputs = new HashMap<>(); + root = (JSONObject) parser.parse(data); + + Set entrySet = root.entrySet(); + Iterator iterator = entrySet.iterator(); + while (iterator.hasNext()) { + Entry next = (Entry) iterator.next(); + String inputName = (String) next.getKey(); + + if(!isInputNameValid(inputName)) { + return Either.right(ActionStatus.INVALID_INPUT_NAME); + } + + JSONObject value = (JSONObject) next.getValue(); + Either inputDefinitionEither = + getInputDefinitionFromJson(componentId, inputName, value); + + if(inputDefinitionEither.isRight()) { + return Either.right(inputDefinitionEither.right().value()); + } + + inputs.put(inputName, inputDefinitionEither.left().value()); + } + + return Either.left(inputs); + } catch (ParseException e) { + log.warn("Input content is invalid - {}", data, e); + return Either.right(ActionStatus.INVALID_CONTENT); + } + } + + protected boolean isInputNameValid(String inputName) { + return Objects.nonNull(inputName) + && inputName.matches(PROPERTY_NAME_REGEX); + + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java index bff8436fa4..1f80b4be87 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java @@ -57,6 +57,7 @@ import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.resources.data.EntryData; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; @@ -84,6 +85,7 @@ import javax.ws.rs.core.Response; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Map; @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Tags({@Tag(name = "SDC Internal APIs")}) @@ -97,6 +99,7 @@ public class InputsServlet extends AbstractValidationsServlet { private static final Logger log = Logger.getLogger(InputsServlet.class); private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(InputsServlet.class.getName()); private static final String START_HANDLE_REQUEST_OF = "(get) Start handle request of {}"; + private static final String CREATE_INPUT = "CreateInput"; private final DataTypeBusinessLogic businessLogic; private final InputsBusinessLogic inputsBusinessLogic; @@ -334,6 +337,21 @@ public class InputsServlet extends AbstractValidationsServlet { DeclarationTypeEnum.INPUT, request); } + @POST + @Path("/{componentType}/{componentId}/create/input") + @Operation(description = "Create inputs on service", method = "POST", summary = "Return inputs list", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))), + @ApiResponse(responseCode = "200", description = "Component found"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "404", description = "Component not found")}) + public Response createInput(@PathParam("componentType") final String componentType, + @PathParam("componentId") final String componentId, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @Parameter(description = "ComponentIns Inputs Object to be created", + required = true) String componentInstInputsMapObj) { + + return createInput(componentId, componentInstInputsMapObj, request, userId); + } /** * Creates a "list input" and updates given list of properties to get value from the input. @@ -566,4 +584,48 @@ public class InputsServlet extends AbstractValidationsServlet { return response; } } + + private Response createInput(String componentId, String data, HttpServletRequest request,String userId) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, StatusCode.STARTED,"CREATE_INPUTS by user {} ", userId); + + try{ + Either, ActionStatus> inputDefinition = + getInputModel(componentId, data); + if (inputDefinition.isRight()) { + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(inputDefinition.right().value()); + return buildErrorResponse(responseFormat); + } + + Map inputs = inputDefinition.left().value(); + if (inputs == null || inputs.size() != 1) { + log.info("Input content is invalid - {}", data); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + return buildErrorResponse(responseFormat); + } + + Map.Entry entry = inputs.entrySet().iterator().next(); + InputDefinition newInputDefinition = entry.getValue(); + newInputDefinition.setParentUniqueId(componentId); + String inputName = newInputDefinition.getName(); + + Either, ResponseFormat> addInputEither = + inputsBusinessLogic.addInputToComponent(componentId, inputName, newInputDefinition, userId); + + if(addInputEither.isRight()) { + return buildErrorResponse(addInputEither.right().value()); + } + + loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, StatusCode.COMPLETE,"CREATE_INPUTS by user {} ", userId); + return buildOkResponse(newInputDefinition); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_INPUT); + log.debug("create input failed with exception", e); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } } 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 09a941347c..1d0c54b747 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 @@ -100,6 +100,8 @@ public enum ActionStatus { // Inputs INPUT_IS_NOT_CHILD_OF_COMPONENT, CFVC_LOOP_DETECTED, + INPUT_ALREADY_EXIST, + //Forwarding Path related FORWARDING_PATH_NAME_MAXIMUM_LENGTH, FORWARDING_PATH_NAME_ALREADY_IN_USE, FORWARDING_PATH_NAME_EMPTY, FORWARDING_PATH_PROTOCOL_MAXIMUM_LENGTH, FORWARDING_PATH_DESTINATION_PORT_MAXIMUM_LENGTH, @@ -158,6 +160,7 @@ public enum ActionStatus { INTERFACE_LIFECYCLE_TYPES_NOT_FOUND, INVALID_PROPERTY_NAME, + INVALID_INPUT_NAME, //Property Constraints INVALID_PROPERTY_CONSTRAINTS, INVALID_PROPERTY_CONSTRAINTS_FORMAT, CANNOT_DELETE_VALID_VALUES, diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java index 957c5f9d66..532a641e2f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java @@ -2482,6 +2482,46 @@ public class ToscaOperationFacade { return Either.left(newProperty); } + public Either addInputToComponent(String inputName, + InputDefinition newInputDefinition, + Component component) { + newInputDefinition.setName(inputName); + + StorageOperationStatus status = getToscaElementOperation(component) + .addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, newInputDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the input {} to the component {}. Status is {}. ", inputName, component.getName(), status); + return Either.right(status); + } + + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + filter.setIgnoreInputs(false); + Either getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated component {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + return Either.right(status); + } + + InputDefinition newInput = null; + List inputs = + (getUpdatedComponentRes.left().value()).getInputs(); + if (CollectionUtils.isNotEmpty(inputs)) { + Optional inputOptional = inputs.stream().filter( + inputEntry -> inputEntry.getName().equals(inputName)).findAny(); + if (inputOptional.isPresent()) { + newInput = inputOptional.get(); + } + } + if (newInput == null) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added input {} " + + "on the component {}. Status is {}. ", inputs, component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + return Either.left(newInput); + } + public StorageOperationStatus deletePropertyOfComponent(Component component, String propertyName) { return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME); } @@ -2536,8 +2576,7 @@ public class ToscaOperationFacade { return result; } - - public Either addAttributeOfResource(Component component, AttributeDataDefinition newAttributeDef) { + public Either addAttributeOfResource(Component component, AttributeDataDefinition newAttributeDef) { Either getUpdatedComponentRes = null; Either result = null; diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html index ee090245f0..e1638fb00f 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html @@ -49,6 +49,9 @@ +
+ +
@@ -124,9 +127,6 @@ [testId]="'input-' + input.name" [constraints] = "getConstraints(input)"> -
- -
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less index 74520b6314..ae6d58e72e 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less @@ -182,7 +182,8 @@ // Column: Property Name &.col1 { flex: 1 0 130px; - max-width: 250px; + max-width: 300px; + display: flex; justify-content: space-between; diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts index 3fa7ab4a80..5ca119c075 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts @@ -43,14 +43,14 @@ export class InputsTableComponent { @Input() readonly: boolean; @Input() isLoading: boolean; @Input() componentType: string; - + @Input() showDelete:boolean; @Output() inputChanged: EventEmitter = new EventEmitter(); @Output() deleteInput: EventEmitter = new EventEmitter(); @Input() fePropertiesMap: InstanceFePropertiesMap; @ViewChildren('metadataViewChildren') public metadataViewChildren: QueryList; - + sortBy: String; reverse: boolean; selectedInputToDelete: InputFEModel; @@ -107,15 +107,15 @@ export class InputsTableComponent { var mapKeyError = input.metadataMapKeyError; if(input.metadataMapKeyError){ dynamicElementComponent.cmpRef.instance.control.setErrors({mapKeyError}); - } + } }; onMetadataValueChanged = (input: InputFEModel, event, metadataEntry: MetadataEntry) => { input.updateMetadataValue(metadataEntry, event.value); this.inputChanged.emit(input); }; - - + + createNewMetadataEntry = (input: InputFEModel): void => { let metadataEntry = new MetadataEntry("", ""); input.addMetadataEntry(metadataEntry); @@ -126,7 +126,7 @@ export class InputsTableComponent { input.deleteMetadataEntry(metadataEntry); this.inputChanged.emit(input); } - + onDeleteInput = () => { this.deleteInput.emit(this.selectedInputToDelete); this.modalService.closeCurrentModal(); 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 6856ae8358..6b3e92adfd 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 @@ -44,6 +44,7 @@
-
Add Property
+
Add Input
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 e4a8749386..74e2680b80 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 @@ -1052,6 +1052,41 @@ export class PropertiesAssignmentComponent { modal.instance.open(); } + /*** addInput ***/ + addInput = () => { + let modalTitle = 'Add Input'; + let modal = this.ModalService.createCustomModal(new ModalModel( + 'sm', + modalTitle, + null, + [ + new ButtonModel('Save', 'blue', () => { + modal.instance.dynamicContent.instance.isLoading = true; + const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel; + this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput) + .subscribe((response) => { + modal.instance.dynamicContent.instance.isLoading = false; + const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response); + this.inputs.push(newInputProp); + modal.instance.close(); + }, (error) => { + modal.instance.dynamicContent.instance.isLoading = false; + this.Notification.error({ + message: 'Failed to add input:' + error, + title: 'Failure' + }); + }); + }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()), + new ButtonModel('Cancel', 'outline grey', () => { + modal.instance.close(); + }), + ], + null + )); + this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {}); + modal.instance.open(); + } + /*** SEARCH RELATED FUNCTIONS ***/ searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => { let instanceBePropertiesMap:InstanceBePropertiesMap; diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts index 408a00e7b4..948c9032bf 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts @@ -19,12 +19,13 @@ */ import { Injectable } from '@angular/core'; -import { InputFEModel} from "app/models"; +import { InputBEModel, InputFEModel } from "app/models"; +import { DataTypeService } from "app/ng2/services/data-type.service"; @Injectable() export class InputsUtils { - constructor() {} + constructor(private dataTypeService:DataTypeService) {} public initDefaultValueObject = (input: InputFEModel): void => { input.resetDefaultValueObjValidation(); @@ -37,4 +38,10 @@ export class InputsUtils { this.initDefaultValueObject(input); } + public convertInputBEToInputFE = (input: InputBEModel): InputFEModel => { + const newFEInput: InputFEModel = new InputFEModel(input); //Convert input to FE + this.initDefaultValueObject(newFEInput); + return newFEInput; + } + } diff --git a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts index 14bf84599c..492acdc1d6 100644 --- a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts @@ -227,6 +227,16 @@ export class TopologyTemplateService { }); } + createServiceInput(componentId: string, inputModel: InputBEModel): Observable { + const serverObject = {}; + serverObject[inputModel.name] = inputModel; + return this.http.post(this.baseUrl + 'services/' + componentId + '/create/input', serverObject) + .map((res) => { + const input: InputBEModel = new InputBEModel(res); + return input; + }); + } + getDependencies(componentType: string, componentId: string): Observable { return this.http.get(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies'); } -- cgit 1.2.3-korg