aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java40
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java22
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java18
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.html3
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.ts28
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html4
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts29
-rw-r--r--catalog-ui/src/app/ng2/services/data-type.service.ts5
-rw-r--r--catalog-ui/src/assets/languages/en_US.json1
9 files changed, 133 insertions, 17 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java
index 0f6257157c..05c1fb7ad3 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java
@@ -38,6 +38,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -169,6 +170,45 @@ public class DataTypeServlet extends BeGenericServlet {
return Response.status(Status.CREATED).entity(property).build();
}
+ @PUT
+ @Path("{id}/properties")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(summary = "Update a property in the given data type", method = "POST", description = "Update a property in the given data type",
+ responses = {
+ @ApiResponse(content = @Content(schema = @Schema(implementation = PropertyDefinitionDto.class))),
+ @ApiResponse(responseCode = "201", description = "Property updated in the data type"),
+ @ApiResponse(responseCode = "400", description = "Invalid payload"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "404", description = "Data type not found")
+ })
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ public Response updateProperty(@Parameter(in = ParameterIn.PATH, required = true, description = "The data type id")
+ @PathParam("id") final String id,
+ @RequestBody(description = "Property to update", required = true) final PropertyDefinitionDto propertyDefinitionDto) {
+ Optional<DataTypeDataDefinition> dataTypeOptional = dataTypeOperation.getDataTypeByUid(id);
+ dataTypeOptional.orElseThrow(() -> {
+ throw new OperationException(ActionStatus.DATA_TYPE_NOT_FOUND, String.format("Failed to find data type '%s'", id));
+ });
+ DataTypeDataDefinition dataType = dataTypeOptional.get();
+ String model = dataType.getModel();
+ Optional<DataTypeDataDefinition> propertyDataType = dataTypeOperation.getDataTypeByNameAndModel(propertyDefinitionDto.getType(), model);
+ if (propertyDataType.isEmpty()) {
+ if (StringUtils.isEmpty(model)) {
+ model = Constants.DEFAULT_MODEL_NAME;
+ }
+ throw new OperationException(ActionStatus.INVALID_MODEL,
+ String.format("Property model is not the same as the data type model. Must be '%s'", model));
+ }
+ if (StringUtils.isEmpty(dataType.getModel())) {
+ dataType.setModel(Constants.DEFAULT_MODEL_NAME);
+ }
+ final PropertyDefinitionDto property = dataTypeOperation.updateProperty(id, propertyDefinitionDto);
+ dataTypeOperation.addPropertyToAdditionalTypeDataType(dataType, property);
+ dataTypeBusinessLogic.updateApplicationDataTypeCache(id);
+ return Response.status(Status.CREATED).entity(property).build();
+ }
+
@GET
@Path("{dataTypeName}/models")
@Consumes(MediaType.APPLICATION_JSON)
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
index bbc70f6c3f..391add9a94 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
@@ -281,6 +281,28 @@ public class DataTypeOperation extends AbstractOperation {
return PropertyDefinitionDtoMapper.mapFrom(propertyDataDefinition);
}
+ public PropertyDefinitionDto updateProperty(final String dataTypeId, final PropertyDefinitionDto propertyDefinitionDto) {
+ final String propertyName = propertyDefinitionDto.getName();
+ LOGGER.debug("Updating property '{}' to data type '{}'.", propertyName, dataTypeId);
+
+ getDataTypeByUid(dataTypeId).orElseThrow(DataTypeOperationExceptionSupplier.dataTypeNotFound(dataTypeId));
+
+ final Either<PropertyDefinition, JanusGraphOperationStatus> resultEither =
+ propertyOperation.updatePropertyAssociatedToNode(NodeTypeEnum.DataType, dataTypeId, PropertyDefinitionDtoMapper.mapTo(propertyDefinitionDto));
+ if (resultEither.isRight()) {
+ final JanusGraphOperationStatus status = resultEither.right().value();
+ LOGGER.debug("Could not update property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status);
+ if (status == JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) {
+ throw DataTypeOperationExceptionSupplier.dataTypePropertyAlreadyExists(dataTypeId, propertyName).get();
+ }
+ LOGGER.error("Could not update property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status);
+ throw DataTypeOperationExceptionSupplier.unexpectedErrorWhileCreatingProperty(dataTypeId, propertyName).get();
+ }
+ LOGGER.debug("Property '{}' was updated in data type '{}'.", propertyName, dataTypeId);
+ final PropertyDefinition propertyData = resultEither.left().value();
+ return PropertyDefinitionDtoMapper.mapFrom(propertyData);
+ }
+
public void addPropertyToAdditionalTypeDataType(DataTypeDataDefinition dataTypeDataDefinition, PropertyDefinitionDto property) {
modelOperation.addPropertyToAdditionalType(ElementTypeEnum.DATA_TYPE, property, dataTypeDataDefinition.getModel(), dataTypeDataDefinition.getName());
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
index 0b8d2c8cb1..516474331b 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
@@ -382,6 +382,23 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe
return Either.left(createNodeResult.left().value());
}
+ public Either<PropertyDefinition, JanusGraphOperationStatus> updatePropertyAssociatedToNode(NodeTypeEnum nodeType, String uniqueId,
+ PropertyDefinition newProperty) {
+ Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> oldPropertiesRes = findPropertiesOfNode(nodeType, uniqueId);
+
+ if (oldPropertiesRes.isRight()) {
+ return Either.right(oldPropertiesRes.right().value());
+ } else {
+ Map<String, PropertyDefinition> oldProperties = oldPropertiesRes.left().value();
+ PropertyDefinition oldPropDef = oldProperties.get(newProperty.getName());
+ JanusGraphOperationStatus status = updateOldProperty(newProperty, oldPropDef);
+ if (status != JanusGraphOperationStatus.OK) {
+ return Either.right(status);
+ }
+ }
+ return Either.left(newProperty);
+ }
+
public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> findPropertiesOfNode(NodeTypeEnum nodeType, String uniqueId) {
Map<String, PropertyDefinition> resourceProps = new HashMap<>();
Either<List<ImmutablePair<PropertyData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
@@ -501,6 +518,7 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe
oldPropDef.setDefaultValue(newPropDef.getDefaultValue());
oldPropDef.setDescription(newPropDef.getDescription());
oldPropDef.setRequired(newPropDef.isRequired());
+ oldPropDef.setConstraints(newPropDef.getConstraints());
// Type is updated to fix possible null type issue in janusGraph DB
oldPropDef.setType(newPropDef.getType());
}
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.html
index a2e4f48531..3ac4f7a31d 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.html
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.html
@@ -6,6 +6,7 @@
<div class="i-sdc-form-item">
<label class="i-sdc-form-label required">{{'PROPERTY_NAME_LABEL' | translate}}</label>
<input class="i-sdc-form-input"
+ [ngClass]="{ 'disabled': property ? true : false }"
type="text"
data-tests-id="property-name"
formControlName="name"
@@ -13,7 +14,7 @@
</div>
<div class="i-sdc-form-item">
<label class="i-sdc-form-label required">{{'PROPERTY_TYPE_LABEL' | translate}}</label>
- <select formControlName="type" (change)="onTypeChange()" [attr.disabled]="readOnly ? readOnly : null">
+ <select formControlName="type" (change)="onTypeChange()" [ngClass]="{ 'disabled': property ? true : false }">
<option [ngValue]="null">{{'GENERAL_LABEL_SELECT' | translate}}</option>
<option *ngFor="let type of typeList"
[ngValue]="type">{{type}}</option>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.ts
index 56db2cefeb..8eb04c0cbb 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/add-property/add-property.component.ts
@@ -45,7 +45,7 @@ export class AddPropertyComponent implements OnInit, OnDestroy {
private validConstraints: boolean = true;
private valueChangesSub: Subscription;
private descriptionForm: FormControl = new FormControl(undefined);
- private requiredForm: FormControl = new FormControl(false, Validators.required);
+ private requiredForm: FormControl = new FormControl(false);
nameForm: FormControl = new FormControl(undefined, [Validators.required]);
typeForm: FormControl = new FormControl(undefined, Validators.required);
schemaForm: FormControl = new FormControl(undefined, (control: AbstractControl): ValidationErrors | null => {
@@ -163,9 +163,10 @@ export class AddPropertyComponent implements OnInit, OnDestroy {
private emitValidityChange(): void {
const isValid: boolean = this.formGroup.valid;
+ this.findInvalidControls().forEach(name => console.error("Validation error in field: " + name));
this.onValidityChange.emit({
isValid: isValid && this.validConstraints,
- property: isValid ? this.buildPropertyFromForm() : undefined
+ property: isValid ? this.buildPropertyFromForm() : this.nameForm.value
});
}
@@ -173,6 +174,7 @@ export class AddPropertyComponent implements OnInit, OnDestroy {
const property = new PropertyBEModel();
property.name = this.nameForm.value;
property.type = this.typeForm.value;
+ property.required = this.requiredForm.value;
property.constraints = this.constraintsForm.value;
if (this.schemaForm.value) {
property.schemaType = this.schemaForm.value;
@@ -241,15 +243,27 @@ export class AddPropertyComponent implements OnInit, OnDestroy {
}
this.property.constraints = constraints.constraints;
}
- else {
- this.constraintsForm.setValue(constraints.constraints);
- }
+
+ this.constraintsForm.setValue(constraints.constraints);
+
this.validConstraints = constraints.valid;
+ let formValid = constraints.valid && this.findInvalidControls().length === 0;
this.onValidityChange.emit({
- isValid: constraints.valid,
- property: constraints.valid ? this.buildPropertyFromForm() : undefined
+ isValid: formValid,
+ property: formValid ? this.buildPropertyFromForm() : undefined
});
}
+
+ findInvalidControls() {
+ const invalid = [];
+ const controls = this.formGroup.controls;
+ for (const name in controls) {
+ if (controls[name].invalid) {
+ invalid.push(name);
+ }
+ }
+ return invalid;
+ }
}
export class PropertyValidationEvent {
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html
index ec67a02a1b..e657520ee4 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html
@@ -38,9 +38,9 @@
<div *ngIf="filteredProperties.length === 0" class="no-row-text">
{{'PROPERTY_LIST_EMPTY_MESSAGE' | translate}}
</div>
- <div *ngFor="let property of filteredProperties" [attr.data-tests-id]="'property-row-' + property.name" class="flex-container data-row" (click)="onRowClick(property)">
+ <div *ngFor="let property of filteredProperties" [attr.data-tests-id]="'property-row-' + property.name" class="flex-container data-row" (click)="onNameClick(property)">
<div class="table-col-general flex-item text" [title]="property.name">
- <a [attr.data-tests-id]="'property-name-' + property.name" [ngClass]="{'disabled': isViewOnly}">{{property.name}}</a>
+ <a [attr.data-tests-id]="'property-name-' + property.name" [ngClass]="{'disabled': false}">{{property.name}}</a>
</div>
<div class="table-col-general flex-item text" [title]="property.type">
<span [attr.data-tests-id]="'property-type-' + property.name">{{property.type}}</span>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts
index 83651fc73c..60edd13c2d 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts
@@ -132,12 +132,20 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
this.filter();
}
+ private updateProperty(oldProperty: PropertyBEModel, newProperty: PropertyBEModel) {
+ this.properties.forEach((value,index)=>{
+ if(value.name == oldProperty.name) this.properties.splice(index,1);
+ });
+ this.properties.push(newProperty);
+ this.filter();
+ }
+
onClickAddProperty() {
- this.openAddPropertyModal();
+ this.openAddPropertyModal(null, false);
}
private openAddPropertyModal(property?: PropertyBEModel, readOnly: boolean = false) {
- const modalTitle = this.translateService.translate('PROPERTY_ADD_MODAL_TITLE');
+ const modalTitle = this.translateService.translate(property ? 'PROPERTY_EDIT_MODAL_TITLE' : 'PROPERTY_ADD_MODAL_TITLE');
const modalButtons = [];
let disableSaveButtonFlag = true;
let propertyFromModal: PropertyBEModel = undefined;
@@ -156,9 +164,16 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
() => {
disableSaveButtonFlag = true;
- this.dataTypeService.createProperty(this.dataType.uniqueId, propertyFromModal).subscribe(property => {
- this.addProperty(new PropertyBEModel(property));
- });
+ if (property) {
+ this.dataTypeService.updateProperty(this.dataType.uniqueId, propertyFromModal).subscribe(property => {
+ this.updateProperty(propertyFromModal, new PropertyBEModel(property));
+ });
+ }
+ else {
+ this.dataTypeService.createProperty(this.dataType.uniqueId, propertyFromModal).subscribe(property => {
+ this.addProperty(new PropertyBEModel(property));
+ });
+ }
this.modalService.closeCurrentModal();
},
(): boolean => {
@@ -185,8 +200,8 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
modal.instance.open();
}
- onRowClick(property: PropertyBEModel) {
- this.openAddPropertyModal(property, true);
+ onNameClick(property: PropertyBEModel) {
+ this.openAddPropertyModal(property, this.isViewOnly);
}
private showPropertiesMap(properties: Array<PropertyBEModel>): void {
diff --git a/catalog-ui/src/app/ng2/services/data-type.service.ts b/catalog-ui/src/app/ng2/services/data-type.service.ts
index 7e18d0a4ba..38714c96da 100644
--- a/catalog-ui/src/app/ng2/services/data-type.service.ts
+++ b/catalog-ui/src/app/ng2/services/data-type.service.ts
@@ -92,6 +92,11 @@ export class DataTypeService {
return this.httpClient.post<PropertyBEModel>(url, property);
}
+ public updateProperty(id: string, property: PropertyBEModel): Observable<PropertyBEModel> {
+ const url = `${this.dataTypeUrl}/${id}/properties`;
+ return this.httpClient.put<PropertyBEModel>(url, property);
+ }
+
public createImportedType(model: string, importingFile: File): Observable<any> {
const url = `${this.dataTypeUploadUrl}/datatypesyaml`;
const formData = new FormData();
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index bb2ebd596d..a98bf4c8c1 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -594,6 +594,7 @@
"PROPERTY_LIST_EMPTY_MESSAGE": "There are no properties to display",
"PROPERTY_SHOWING_LABEL": "Showing Properties",
"PROPERTY_ADD_MODAL_TITLE": "Add Property",
+ "PROPERTY_EDIT_MODAL_TITLE": "Update Property",
"PROPERTY_VIEW_MODAL_TITLE": "View Property",
"PROPERTY_DESCRIPTION_LABEL": "Description",
"PROPERTY_DEFAULT_VALUE_LABEL": "Default Value",