summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre.schmid <andre.schmid@est.tech>2022-10-04 20:29:28 +0100
committerMichael Morris <michael.morris@est.tech>2022-10-17 14:42:22 +0000
commitaa72781388f3e6408bb43f1b024d88ec1c9d2c10 (patch)
tree15002a934486557f1d62eec49e57af1e2e59b443
parentb75fe3c7ce231c86cd4c6d052da453d02809c8f9 (diff)
Add data type properties workspace
Implements the properties workspace for a data type, with the list and filter feature. Change-Id: I2ec337a0481bddd5fe32e45644abdc88e197fa49 Issue-ID: SDC-4214 Signed-off-by: André Schmid <andre.schmid@est.tech>
-rw-r--r--catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml2
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java20
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/DataTypeServletTest.java27
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java2
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java38
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java37
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java39
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java67
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java32
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java12
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java52
-rw-r--r--catalog-ui/configurations/menu.js1
-rw-r--r--catalog-ui/src/app/models/properties-inputs/property-be-model.ts12
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html62
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less141
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts111
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts115
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html6
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts6
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts7
-rw-r--r--catalog-ui/src/app/ng2/services/data-type.service.ts7
-rw-r--r--catalog-ui/src/assets/languages/en_US.json6
22 files changed, 784 insertions, 18 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 47e2851b8e..532ee3ecac 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
@@ -2826,4 +2826,4 @@ errors:
DATA_TYPE_NOT_FOUND:
code: 404
message: "Data type '%1' was not found."
- messageId: "SVC4011"
+ messageId: "SVC4011" \ No newline at end of file
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 d9846a7fb1..e39e0d2c0d 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
@@ -22,16 +22,19 @@ package org.openecomp.sdc.be.servlets;
import com.jcabi.aspects.Loggable;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -45,6 +48,8 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
import org.openecomp.sdc.be.exception.BusinessException;
import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.model.operations.impl.DataTypeOperation;
import org.openecomp.sdc.common.api.Constants;
@@ -99,4 +104,19 @@ public class DataTypeServlet extends BeGenericServlet {
return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), dataType);
}
+ @GET
+ @Path("{id}/properties")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(description = "Get a data type properties", method = "GET", summary = "Returns the data type properties", responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = PropertyDefinition.class)))),
+ @ApiResponse(responseCode = "200", description = "Data type found, properties may be empty"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "404", description = "Data type not found")})
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ public Response fetchProperties(@PathParam("id") final String id) {
+ final List<PropertyDefinition> allProperties = dataTypeOperation.findAllProperties(id);
+ return buildOkResponse(allProperties);
+ }
+
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/DataTypeServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/DataTypeServletTest.java
index d916fffc12..d2380fa96e 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/DataTypeServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/DataTypeServletTest.java
@@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
import javax.servlet.ServletContext;
import javax.ws.rs.core.MediaType;
@@ -44,6 +46,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.impl.WebAppContextWrapper;
+import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.model.operations.impl.DataTypeOperation;
import org.openecomp.sdc.common.api.Constants;
@@ -56,6 +59,7 @@ class DataTypeServletTest extends JerseySpringBaseTest {
private static final String USER_ID = "cs0008";
private static final String DATA_TYPE_UID = "ETSI SOL001 v2.5.1.tosca.datatypes.nfv.L3AddressData.datatype";
private static final String PATH = "/v1/catalog/data-types/" + DATA_TYPE_UID;
+ private static final String DATA_TYPE_PROPERTIES_PATH = "/v1/catalog/data-types/%s/properties";
@InjectMocks
private DataTypeServlet dataTypeServlet;
@@ -153,4 +157,27 @@ class DataTypeServletTest extends JerseySpringBaseTest {
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
}
+ @Test
+ void fetchDataTypePropertiesTest_Success() {
+ final DataTypeDataDefinition expectedDataType = new DataTypeDataDefinition();
+ final PropertyDefinition expectedProperty1 = new PropertyDefinition();
+ expectedProperty1.setName("property1");
+ final PropertyDefinition expectedProperty2 = new PropertyDefinition();
+ expectedProperty2.setName("property2");
+ expectedDataType.setUniqueId(DATA_TYPE_UID);
+ when(dataTypeOperation.findAllProperties(DATA_TYPE_UID)).thenReturn(List.of(expectedProperty1, expectedProperty2));
+
+ final Response response = target()
+ .path(String.format(DATA_TYPE_PROPERTIES_PATH, DATA_TYPE_UID))
+ .request(MediaType.APPLICATION_JSON)
+ .header("USER_ID", USER_ID)
+ .get(Response.class);
+ assertNotNull(response);
+ assertEquals(HttpStatus.SC_OK, response.getStatus());
+ final List<Map<String, Object>> actualResponse = response.readEntity(List.class);
+ assertEquals(2, actualResponse.size());
+ assertEquals(expectedProperty1.getName(), actualResponse.get(0).get("name"));
+ assertEquals(expectedProperty2.getName(), actualResponse.get(1).get("name"));
+ }
+
}
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 1ca0e4d048..2c7c724af7 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
@@ -75,7 +75,7 @@ public enum ActionStatus {
EMPTY_OCCURRENCES_LIST, INVALID_OCCURRENCES, NOT_TOPOLOGY_TOSCA_TEMPLATE, INVALID_NODE_TEMPLATE,
// Data type related
DATA_TYPE_ALREADY_EXIST, DATA_TYPE_NOR_PROPERTIES_NEITHER_DERIVED_FROM, DATA_TYPE_PROPERTIES_CANNOT_BE_EMPTY, DATA_TYPE_DERIVED_IS_MISSING, DATA_TYPE_PROPERTY_ALREADY_DEFINED_IN_ANCESTOR, DATA_TYPE_DUPLICATE_PROPERTY, DATA_TYPE_PROEPRTY_CANNOT_HAVE_SAME_TYPE_OF_DATA_TYPE, DATA_TYPE_CANNOT_HAVE_PROPERTIES, DATA_TYPE_CANNOT_BE_EMPTY, DATA_TYPE_CANNOT_BE_UPDATED_BAD_REQUEST,
- DATA_TYPES_NOT_LOADED, DATA_TYPE_NOT_FOUND,
+ DATA_TYPES_NOT_LOADED, DATA_TYPE_NOT_FOUND, DATA_TYPE_PROPERTIES_NOT_FOUND,
// Policy Type related
TARGETS_EMPTY, TARGETS_NON_VALID, POLICY_TYPE_ALREADY_EXIST,
// Group Type related
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java
new file mode 100644
index 0000000000..6a647b1d44
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java
@@ -0,0 +1,38 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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=========================================================
+ */
+
+package org.openecomp.sdc.be.exception;
+
+public class OperationException extends BusinessException {
+
+ public OperationException(final String message) {
+ super(message);
+ }
+
+ public OperationException(final Throwable cause) {
+ super(cause);
+ }
+
+ public OperationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java
new file mode 100644
index 0000000000..75cacdd7a8
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java
@@ -0,0 +1,37 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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=========================================================
+ */
+
+package org.openecomp.sdc.be.exception.supplier;
+
+import java.util.function.Supplier;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.openecomp.sdc.be.exception.OperationException;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DataTypeOperationExceptionSupplier {
+
+ public static Supplier<OperationException> unexpectedErrorWhileFetchingProperties(final String uniqueId) {
+ final String errorMessage = String.format("An unexpected error has occurred while retrieving the data type '%s' properties", uniqueId);
+ return () -> new OperationException(errorMessage);
+ }
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java
new file mode 100644
index 0000000000..bac73d9e1d
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java
@@ -0,0 +1,39 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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=========================================================
+ */
+
+package org.openecomp.sdc.be.model.dto;
+
+import java.util.List;
+import lombok.Data;
+import org.openecomp.sdc.be.model.PropertyConstraint;
+
+@Data
+public class PropertyDefinitionDto {
+
+ private String uniqueId;
+ private String type;
+ private String name;
+ private Boolean required;
+ private Object value;
+ private Object defaultValue;
+ private List<PropertyConstraint> constraints;
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java
new file mode 100644
index 0000000000..8566f55339
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java
@@ -0,0 +1,67 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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=========================================================
+ */
+
+package org.openecomp.sdc.be.model.mapper;
+
+import com.google.gson.Gson;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.model.PropertyConstraint;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto;
+
+public class PropertyDefinitionDtoMapper {
+
+ public static PropertyDefinition mapTo(final PropertyDefinitionDto propertyDefinitionDto) {
+ final var propertyDefinition = new PropertyDefinition();
+ propertyDefinition.setUniqueId(propertyDefinitionDto.getUniqueId());
+ propertyDefinition.setType(propertyDefinitionDto.getType());
+ propertyDefinition.setRequired(propertyDefinitionDto.getRequired());
+ propertyDefinition.setName(propertyDefinitionDto.getName());
+ if (CollectionUtils.isNotEmpty(propertyDefinitionDto.getConstraints())) {
+ final List<PropertyConstraint> propertyConstraints = new ArrayList<>();
+ propertyDefinition.setConstraints(propertyConstraints);
+ propertyConstraints.addAll(propertyDefinitionDto.getConstraints());
+ }
+ propertyDefinition.setValue(new Gson().toJson(propertyDefinitionDto.getValue()));
+ propertyDefinition.setDefaultValue(new Gson().toJson(propertyDefinitionDto.getDefaultValue()));
+ return propertyDefinition;
+ }
+
+ public static PropertyDefinitionDto mapFrom(final PropertyDataDefinition propertyDataDefinition) {
+ final var propertyDefinition = new PropertyDefinition(propertyDataDefinition);
+ final var propertyDefinitionDto = new PropertyDefinitionDto();
+ propertyDefinitionDto.setUniqueId(propertyDefinition.getUniqueId());
+ propertyDefinitionDto.setType(propertyDefinition.getType());
+ propertyDefinitionDto.setRequired(propertyDefinition.getRequired());
+ propertyDefinitionDto.setName(propertyDefinition.getName());
+ if (CollectionUtils.isNotEmpty(propertyDefinition.getConstraints())) {
+ final List<PropertyConstraint> propertyConstraints = new ArrayList<>();
+ propertyDefinitionDto.setConstraints(propertyConstraints);
+ propertyConstraints.addAll(propertyDefinition.getConstraints());
+ }
+ propertyDefinitionDto.setValue(new Gson().fromJson(propertyDataDefinition.getValue(), Object.class));
+ propertyDefinitionDto.setDefaultValue(new Gson().fromJson(propertyDataDefinition.getDefaultValue(), Object.class));
+ return propertyDefinitionDto;
+ }
+}
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 f75e3cfb17..4194ab70db 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
@@ -21,11 +21,13 @@ package org.openecomp.sdc.be.model.operations.impl;
import fj.data.Either;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.janusgraph.core.JanusGraph;
@@ -38,6 +40,8 @@ import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.exception.supplier.DataTypeOperationExceptionSupplier;
+import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.resources.data.DataTypeData;
@@ -53,6 +57,7 @@ public class DataTypeOperation extends AbstractOperation {
private static final Logger LOGGER = LoggerFactory.getLogger(DataTypeOperation.class);
private ModelOperation modelOperation;
+ private PropertyOperation propertyOperation;
@Autowired
public DataTypeOperation(final HealingJanusGraphGenericDao janusGraphGenericDao) {
@@ -65,6 +70,11 @@ public class DataTypeOperation extends AbstractOperation {
this.modelOperation = modelOperation;
}
+ @Autowired
+ public void setPropertyOperation(PropertyOperation propertyOperation) {
+ this.propertyOperation = propertyOperation;
+ }
+
public List<DataTypeData> getAllDataTypeNodes() {
final List<DataTypeData> dataTypesFound = new ArrayList<>();
final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesWithNullModel =
@@ -172,4 +182,26 @@ public class DataTypeOperation extends AbstractOperation {
}
return Optional.of(dataTypeEither.left().value().getDataTypeDataDefinition());
}
+
+ public List<PropertyDefinition> findAllProperties(final String uniqueId) {
+ final Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesEither =
+ propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
+ if (propertiesEither.isRight()) {
+ final JanusGraphOperationStatus status = propertiesEither.right().value();
+ if (status == JanusGraphOperationStatus.NOT_FOUND) {
+ return List.of();
+ }
+ LOGGER.error("Could not retrieve data type '{}' properties. JanusGraphOperationStatus: '{}'", uniqueId, status);
+
+ throw DataTypeOperationExceptionSupplier.unexpectedErrorWhileFetchingProperties(uniqueId).get();
+ }
+ final Map<String, PropertyDefinition> propertyMap = propertiesEither.left().value();
+ if (MapUtils.isEmpty(propertyMap)) {
+ return List.of();
+ }
+ final List<PropertyDefinition> propertyDefinitions = new ArrayList<>(propertyMap.values());
+ propertyDefinitions.sort(Comparator.comparing(PropertyDefinition::getName));
+ return propertyDefinitions;
+ }
+
}
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 6b580527c4..9e5c2e49bc 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
@@ -330,13 +330,9 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe
List<PropertyConstraint> constraints = propertyDefinition.getConstraints();
propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName));
PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints));
- if (log.isDebugEnabled()) {
- log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
- }
+ log.debug(BEFORE_ADDING_PROPERTY_TO_GRAPH, propertyData);
Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class);
- if (log.isDebugEnabled()) {
- log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
- }
+ log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData);
if (createNodeResult.isRight()) {
JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus);
@@ -346,8 +342,8 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe
props.put(GraphPropertiesDictionary.NAME.getProperty(), propertyName);
UniqueIdData uniqueIdData = new UniqueIdData(nodeType, uniqueId);
log.debug("Before associating {} to property {}", uniqueIdData, propertyName);
- Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
- .createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
+ Either<GraphRelation, JanusGraphOperationStatus> createRelResult =
+ janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props);
if (createRelResult.isRight()) {
JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus);
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
index 0efb751124..1f448fd875 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
@@ -20,6 +20,7 @@ package org.openecomp.sdc.be.model.operations.impl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -43,8 +44,11 @@ import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.exception.OperationException;
+import org.openecomp.sdc.be.exception.supplier.DataTypeOperationExceptionSupplier;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.resources.data.DataTypeData;
import org.springframework.test.context.ContextConfiguration;
@@ -57,6 +61,8 @@ class DataTypeOperationTest {
private ModelOperation modelOperation;
@Mock
private HealingJanusGraphGenericDao janusGraphGenericDao;
+ @Mock
+ private PropertyOperation propertyOperation;
private final String modelName = "ETSI-SDC-MODEL-TEST";
private final List<DataTypeData> dataTypesWithoutModel = new ArrayList<>();
@@ -69,6 +75,7 @@ class DataTypeOperationTest {
void beforeEachInit() {
MockitoAnnotations.openMocks(this);
dataTypeOperation.setModelOperation(modelOperation);
+ dataTypeOperation.setPropertyOperation(propertyOperation);
initTestData();
}
@@ -135,6 +142,51 @@ class DataTypeOperationTest {
assertTrue(result.isEmpty());
}
+ @Test
+ void findAllPropertiesTest_Success() {
+ final PropertyDefinition property1 = new PropertyDefinition();
+ property1.setName("property1");
+ final PropertyDefinition property2 = new PropertyDefinition();
+ property2.setName("property2");
+ final PropertyDefinition property3 = new PropertyDefinition();
+ property3.setName("property3");
+
+ when(propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, "uniqueId"))
+ .thenReturn(Either.left(Map.of(property3.getName(), property3, property1.getName(), property1, property2.getName(), property2)));
+ final List<PropertyDefinition> dataTypeProperties = dataTypeOperation.findAllProperties("uniqueId");
+ assertEquals(3, dataTypeProperties.size());
+ assertEquals(property1.getName(), dataTypeProperties.get(0).getName());
+ assertEquals(property2.getName(), dataTypeProperties.get(1).getName());
+ assertEquals(property3.getName(), dataTypeProperties.get(2).getName());
+ }
+
+ @Test
+ void findAllPropertiesTest_propertiesNotFoundSuccess() {
+ when(propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, "uniqueId"))
+ .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ final List<PropertyDefinition> dataTypeProperties = dataTypeOperation.findAllProperties("uniqueId");
+ assertTrue(dataTypeProperties.isEmpty());
+ }
+
+ @Test
+ void findAllPropertiesTest_emptyPropertiesSuccess() {
+ when(propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, "uniqueId"))
+ .thenReturn(Either.left(Map.of()));
+ final List<PropertyDefinition> dataTypeProperties = dataTypeOperation.findAllProperties("uniqueId");
+ assertTrue(dataTypeProperties.isEmpty());
+ }
+
+ @Test
+ void findAllPropertiesTest_unknownError() {
+ final String uniqueId = "uniqueId";
+ when(propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId))
+ .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
+ final OperationException actualException = assertThrows(OperationException.class, () -> dataTypeOperation.findAllProperties(uniqueId));
+ final OperationException expectedException =
+ DataTypeOperationExceptionSupplier.unexpectedErrorWhileFetchingProperties(uniqueId).get();
+ assertEquals(expectedException.getMessage(), actualException.getMessage());
+ }
+
private void initTestData() {
model = new Model(modelName, ModelTypeEnum.NORMATIVE);
final String TEST_DATA_TYPE_001 = "test.data.type001";
diff --git a/catalog-ui/configurations/menu.js b/catalog-ui/configurations/menu.js
index 4b462b752a..5a7e165a9a 100644
--- a/catalog-ui/configurations/menu.js
+++ b/catalog-ui/configurations/menu.js
@@ -302,6 +302,7 @@ const SDC_MENU_CONFIG = {
],
"DataType": [
{"text": "General", "action": "onMenuItemPressed", "state": "general"},
+ {"text": "Properties", "action": "onMenuItemPressed", "state": "properties"},
]
}
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 097bbb2c54..b8cccdd213 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
@@ -197,5 +197,17 @@ export class PropertyBEModel {
public isToscaFunction(): boolean {
return this.toscaFunction != null;
}
+
+ /**
+ * Gets the schema type, if there is a schema. Otherwise, returns undefined.
+ *
+ * @return the schema type.
+ */
+ public getSchemaType(): string {
+ if (this.schema && this.schema.property) {
+ return this.schema.property.type;
+ }
+ return undefined;
+ }
}
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
new file mode 100644
index 0000000000..61c319eb6f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html
@@ -0,0 +1,62 @@
+<!--
+ ~ -
+ ~ ============LICENSE_START=======================================================
+ ~ Copyright (C) 2022 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="workspace-properties">
+ <div id="left-top-bar">
+ <span id="properties-count">{{'PROPERTY_SHOWING_LABEL' | translate}}: {{filteredProperties.length}} of {{properties.length}}</span>
+ <input id="search-by-name" type="search" [placeholder]="'SEARCH_LABEL' | translate" [ngModel]="tableFilterTerm" (ngModelChange)="this.tableSearchTermUpdate.next($event)"/>
+ <span class="sprite magnification-glass search-button"></span>
+ </div>
+ <div class="table-container-flex">
+ <div class="table" [ngClass]="{'view-mode': isViewOnly}">
+ <div class="head flex-container">
+ <div class="table-header head-row hand flex-item" *ngFor="let header of tableHeadersList" (click)="onUpdateSort(header.property)">{{header.title}}
+ <span *ngIf="tableSortBy === header.property" class="table-header-sort-arrow" [ngClass]="{'down': tableColumnReverse, 'up': !tableColumnReverse}"></span>
+ </div>
+ <div class="table-no-text-header head-row flex-item" *ngIf="!isViewOnly"><span class="delete-col-header"></span></div>
+ </div>
+
+ <div class="body">
+ <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">
+ <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>
+ </div>
+
+ <div class="table-col-general flex-item text" [title]="property.type">
+ <span [attr.data-tests-id]="'property-type-' + property.name">{{property.type}}</span>
+ </div>
+ <div class="table-col-general flex-item text" [title]="property.getSchemaType() || ''">
+ <span [attr.data-tests-id]="'property-schema-' + property.name">{{property.getSchemaType() || ''}}</span>
+ </div>
+ <div class="table-col-general flex-item text" [title]="property.description">
+ <span [attr.data-tests-id]="'property-description-' + property.name" [title]="property.description">{{property.description}}</span>
+ </div>
+ <div class="table-btn-col flex-item" *ngIf="!isViewOnly"></div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less
new file mode 100644
index 0000000000..9c101e8ce3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less
@@ -0,0 +1,141 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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 "../../../../../assets/styles/sprite-old";
+@import "../../../../../assets/styles/mixins_old";
+
+.workspace-properties {
+
+ width: 93%;
+ display: inline-block;
+
+ #left-top-bar {
+ float: left;
+ width: 186px;
+
+ ::-webkit-input-placeholder {
+ font-style: italic;
+ }
+
+ :-moz-placeholder {
+ font-style: italic;
+ }
+
+ ::-moz-placeholder {
+ font-style: italic;
+ }
+
+ :-ms-input-placeholder {
+ font-style: italic;
+ }
+
+ #properties-count {
+ font-weight: bold;
+ float: left;
+ }
+
+ #search-by-name {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ width: 270px;
+ height: 32px;
+ line-height: 32px;
+ border: 1px solid @main_color_o;
+ text-indent: 10px;
+ }
+
+ .search-button {
+ .hand;
+ cursor: pointer;
+ float: right;
+ position: relative;
+ top: -22px;
+ right: -80px;
+ }
+ }
+
+ .delete-col-header {
+ .sprite();
+ .sprite.e-sdc-small-icon-delete();
+ }
+
+ .table {
+ height: 100%;
+ min-height: 500px;
+ margin-bottom: 0;
+ }
+
+ .data-row {
+ .table-delete-btn {
+ display: none !important;
+ }
+
+ &:hover {
+ .table-delete-btn {
+ display: inline-block !important;
+ }
+ }
+ }
+
+ .table-container-flex {
+ margin-top: 0;
+ overflow: scroll;
+ &::-webkit-scrollbar-track {
+ border: 0;
+ }
+
+ .text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: inline-block;
+ white-space: nowrap;
+ }
+
+ .flex-item:nth-child(1) {
+ flex-grow: 15;
+
+ a {
+ .hand
+ }
+ }
+
+ .flex-item:nth-child(2) {
+ flex-grow: 6;
+ }
+
+ .flex-item:nth-child(3) {
+ flex-grow: 6;
+ }
+
+ .flex-item:nth-child(4) {
+ flex-grow: 20;
+ white-space: normal;
+ }
+
+ .flex-item:nth-child(5) {
+ flex-grow: 3;
+ padding-top: 10px;
+ }
+
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts
new file mode 100644
index 0000000000..6be572d16a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts
@@ -0,0 +1,111 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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 {TypeWorkspacePropertiesComponent} from './type-workspace-properties.component';
+import {FormsModule} from "@angular/forms";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+import {TranslateService} from "../../../shared/translator/translate.service";
+import {DataTypeService} from "../../../services/data-type.service";
+import {Observable} from "rxjs/Observable";
+import {DataTypeModel} from "../../../../models/data-types";
+import {Component, ViewChild} from "@angular/core";
+import {PropertyBEModel} from "../../../../models/properties-inputs/property-be-model";
+
+describe('TypeWorkspacePropertiesComponent', () => {
+ const messages = require("../../../../../assets/languages/en_US.json");
+ let testHostComponent: TestHostComponent;
+ let testHostFixture: ComponentFixture<TestHostComponent>;
+ let dataTypeServiceMock: Partial<DataTypeService> = {
+ findAllProperties: jest.fn( (dataTypeId) => {
+ if (dataTypeId === 'dataTypeId') {
+ const property1 = new PropertyBEModel();
+ property1.name = 'property1'
+ property1.type = 'string'
+ return Observable.of([property1]);
+ }
+ return Observable.of([]);
+ })
+ };
+
+ let translateServiceMock: Partial<TranslateService> = {
+ 'translate': jest.fn( (translateKey: string) => {
+ return messages[translateKey];
+ })
+ };
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [TypeWorkspacePropertiesComponent, TestHostComponent],
+ imports: [
+ TranslateModule,
+ FormsModule
+ ],
+ providers: [
+ {provide: DataTypeService, useValue: dataTypeServiceMock},
+ {provide: TranslateService, useValue: translateServiceMock}
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+
+ it('empty property list', () => {
+ const element = testHostFixture.nativeElement;
+ const div: HTMLDivElement = element.querySelector('.no-row-text');
+ expect(div.textContent).toContain(messages.PROPERTY_LIST_EMPTY_MESSAGE);
+ });
+
+ it('test property list', () => {
+ testHostFixture = TestBed.createComponent(TestHostComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ const dataType = new DataTypeModel();
+ dataType.uniqueId = 'dataTypeId';
+ testHostComponent.typeWorkspacePropertiesComponent.dataType = dataType;
+ testHostFixture.detectChanges();
+
+ const element = testHostFixture.nativeElement;
+ expect(element.querySelector('.no-row-text')).toBeFalsy();
+ const expectedPropertyName = 'property1';
+ const propertyNameLink: HTMLAnchorElement = element.querySelector(`a[data-tests-id^="property-name-${expectedPropertyName}"]`);
+ expect(propertyNameLink.textContent).toContain(expectedPropertyName);
+ });
+
+ @Component({
+ selector: 'host-component',
+ template: `<app-type-workspace-properties></app-type-workspace-properties>`
+ })
+ class TestHostComponent {
+ @ViewChild(TypeWorkspacePropertiesComponent)
+ public typeWorkspacePropertiesComponent: TypeWorkspacePropertiesComponent;
+ }
+
+});
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
new file mode 100644
index 0000000000..931fd3d97c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts
@@ -0,0 +1,115 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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 {DataTypeModel} from "../../../../models/data-types";
+import {DataTypeService} from "../../../services/data-type.service";
+import {PropertyBEModel} from "../../../../models/properties-inputs/property-be-model";
+import { Subject } from "rxjs";
+import {debounceTime, distinctUntilChanged} from "rxjs/operators";
+
+@Component({
+ selector: 'app-type-workspace-properties',
+ templateUrl: './type-workspace-properties.component.html',
+ styleUrls: ['./type-workspace-properties.component.less']
+})
+export class TypeWorkspacePropertiesComponent implements OnInit {
+ @Input() isViewOnly = true;
+ @Input() dataType: DataTypeModel = new DataTypeModel();
+
+ properties: Array<PropertyBEModel> = [];
+ filteredProperties: Array<PropertyBEModel> = [];
+ tableHeadersList: Array<TableHeader> = [];
+ tableSortBy: string = 'name';
+ tableColumnReverse: boolean = false;
+ tableFilterTerm: string = undefined;
+ tableSearchTermUpdate = new Subject<string>();
+
+ constructor(private dataTypeService: DataTypeService) { }
+
+ ngOnInit(): void {
+ this.initTable();
+ this.initProperties();
+ this.tableSearchTermUpdate.pipe(
+ debounceTime(400),
+ distinctUntilChanged())
+ .subscribe(searchTerm => {
+ this.filter(searchTerm);
+ });
+ }
+
+ private initTable(): void {
+ this.tableHeadersList = [
+ {title: 'Name', property: 'name'},
+ {title: 'Type', property: 'type'},
+ {title: 'Schema', property: 'schema.property.type'},
+ {title: 'Description', property: 'description'},
+ ];
+
+ this.tableSortBy = this.tableHeadersList[0].property;
+ }
+
+ private initProperties(): void {
+ this.dataTypeService.findAllProperties(this.dataType.uniqueId).subscribe(properties => {
+ this.properties = properties.map(value => new PropertyBEModel(value));
+ this.filteredProperties = Array.from(this.properties);
+ this.sort();
+ });
+ }
+
+ onUpdateSort(property: string): void {
+ if (this.tableSortBy === property) {
+ this.tableColumnReverse = !this.tableColumnReverse;
+ } else {
+ this.tableColumnReverse = false;
+ this.tableSortBy = property;
+ }
+ this.sort();
+ }
+
+ private sort(): void {
+ const field = this.tableSortBy;
+ this.filteredProperties = this.filteredProperties.sort((property1, property2) => {
+ const result = property1[field] > property2[field] ? 1 : property1[field] < property2[field] ? -1 : 0;
+ return this.tableColumnReverse ? result * -1 : result;
+ });
+ }
+
+ private filter(searchTerm: string): void {
+ if (searchTerm) {
+ searchTerm = searchTerm.toLowerCase();
+ this.filteredProperties = this.properties.filter(property =>
+ property.name.toLowerCase().includes(searchTerm)
+ || property.type.toLowerCase().includes(searchTerm)
+ || (property.getSchemaType() && property.getSchemaType().toLowerCase().includes(searchTerm))
+ || (property.description && property.description.toLowerCase().includes(searchTerm))
+ );
+ } else {
+ this.filteredProperties = Array.from(this.properties);
+ }
+ this.sort();
+ }
+}
+
+interface TableHeader {
+ title: string;
+ property: string;
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html
index 8d6ae02598..193c94e6ad 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html
@@ -42,9 +42,11 @@
{{currentMenu.text}}
</div>
</div>
- <div class="w-sdc-main-container-body-content">
- <app-type-workspace-general *ngIf="currentMenu.state === 'general' && dataType" [dataType]="dataType"></app-type-workspace-general>
+ <div class="w-sdc-main-container-body-content" *ngIf="dataType">
+ <app-type-workspace-general *ngIf="currentMenu.state === 'general'" [dataType]="dataType"></app-type-workspace-general>
+ <app-type-workspace-properties *ngIf="currentMenu.state === 'properties'" [dataType]="dataType"></app-type-workspace-properties>
</div>
+
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts
index 8450da829b..fcad472890 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts
@@ -22,7 +22,7 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {TypeWorkspaceComponent} from './type-workspace.component';
-import {ReactiveFormsModule} from "@angular/forms";
+import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {TranslateModule} from "../../shared/translator/translate.module";
import {UiElementsModule} from "../../components/ui/ui-elements.module";
import {DataTypeService} from "../../services/data-type.service";
@@ -37,6 +37,7 @@ import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config";
import {States} from "../../../utils/constants";
import {IUserProperties} from "../../../models/user";
import {Observable} from "rxjs/Observable";
+import {TypeWorkspacePropertiesComponent} from "./type-workspace-properties/type-workspace-properties.component";
describe('TypeWorkspaceComponent', () => {
let component: TypeWorkspaceComponent;
@@ -88,9 +89,10 @@ describe('TypeWorkspaceComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, TypeWorkspaceGeneralComponent ],
+ declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, TypeWorkspaceGeneralComponent, TypeWorkspacePropertiesComponent ],
imports: [
ReactiveFormsModule,
+ FormsModule,
TranslateModule,
UiElementsModule,
LayoutModule
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts
index d3f391db24..021f84af09 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts
@@ -28,9 +28,10 @@ import {UiElementsModule} from "../../components/ui/ui-elements.module";
import {LayoutModule} from "../../components/layout/layout.module";
import {TypeWorkspaceGeneralComponent} from './type-workspace-general/type-workspace-general.component';
import {UpgradeModule} from "@angular/upgrade/static";
-import {ReactiveFormsModule} from "@angular/forms";
+import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {TranslateModule} from "../../shared/translator/translate.module";
import {DataTypeService} from "../../services/data-type.service";
+import { TypeWorkspacePropertiesComponent } from './type-workspace-properties/type-workspace-properties.component';
@NgModule({
imports: [
@@ -40,11 +41,13 @@ import {DataTypeService} from "../../services/data-type.service";
UpgradeModule,
ReactiveFormsModule,
TranslateModule,
+ FormsModule,
],
declarations: [
TypeWorkspaceComponent,
WorkspaceMenuComponent,
- TypeWorkspaceGeneralComponent
+ TypeWorkspaceGeneralComponent,
+ TypeWorkspacePropertiesComponent
],
providers: [
CacheService,
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 bf500ec16e..74d48d35de 100644
--- a/catalog-ui/src/app/ng2/services/data-type.service.ts
+++ b/catalog-ui/src/app/ng2/services/data-type.service.ts
@@ -20,7 +20,7 @@
import * as _ from "lodash";
import {Inject, Injectable} from '@angular/core';
-import { DataTypeModel, DataTypesMap, PropertyFEModel, DerivedFEProperty} from "app/models";
+import {DataTypeModel, DataTypesMap, PropertyFEModel, DerivedFEProperty, PropertyBEModel} from "app/models";
import { DataTypesService } from "app/services/data-types-service";
import { PROPERTY_DATA } from "app/utils";
import {DerivedFEAttribute} from "../../models/attributes-outputs/derived-fe-attribute";
@@ -78,6 +78,11 @@ export class DataTypeService {
return this.httpClient.get<DataTypeModel>(url);
}
+ public findAllProperties(id: string): Observable<Array<PropertyBEModel>> {
+ const url = `${this.dataTypeUrl}/${id}/properties`
+ return this.httpClient.get<Array<PropertyBEModel>>(url);
+ }
+
public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName){
// const property = this.dataTypes[rootPropertyType].properties.filter(property =>
// property.name == propertyName);
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index 3f5a10726c..c3a6bc9a4c 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -41,6 +41,7 @@
"GENERAL_LABEL_SYSTEM_NAME": "System Name:",
"GENERAL_LABEL_SOURCE_SERVICE_NAME": "Source Service Name:",
"GENERAL_LABEL_RESOURCE_CUSTOMIZATION_UUID": "Resource Customization UUID:",
+ "SEARCH_LABEL": "Search",
"=========== GENERAL_TAB ===========": "",
"GENERAL_TAB_LABEL_RESOURCE_MODEL_NUMBER": "Vendor Model Number",
"GENERAL_TAB_LABEL_SERVICE_TYPE": "Service Type",
@@ -578,5 +579,8 @@
"MODIFIED_LABEL": "Modified",
"UNIQUE_ID_LABEL": "Unique Id",
"=========== SERVICE IMPORT ===========": "",
- "IMPORT_FAILURE_MESSAGE_TEXT": "Import Failure - error reading CSAR"
+ "IMPORT_FAILURE_MESSAGE_TEXT": "Import Failure - error reading CSAR",
+ "=========== PROPERTIES ===========": "",
+ "PROPERTY_LIST_EMPTY_MESSAGE": "There are no properties to display",
+ "PROPERTY_SHOWING_LABEL": "Showing Properties"
}