summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfranciscovila <javier.paradela.vila@est.tech>2022-11-24 10:29:04 +0000
committerMichael Morris <michael.morris@est.tech>2023-01-26 23:32:10 +0000
commit701e441228724c5b701d94cc3f1e520ce656398a (patch)
tree5900482086d86f8b8e465e6d4b57db4bd7a94184
parent1bbecd7edbdd907a53812d303d378236d23d071e (diff)
Import data type in UI
Develop all necessary changes in the UI to allow importing a data type from a yaml file Issue-ID: SDC-4279 Signed-off-by: franciscovila <javier.paradela.vila@est.tech> Change-Id: Id413386fad8b362e8c4a1d25c859a22178189074
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java8
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java15
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java58
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java16
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java2
-rw-r--r--catalog-ui/src/app/app.ts8
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.html51
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.less60
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.spec.ts45
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.ts47
-rw-r--r--catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts7
-rw-r--r--catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap2
-rw-r--r--catalog-ui/src/app/ng2/pages/home/home.component.html1
-rw-r--r--catalog-ui/src/app/ng2/pages/home/home.component.spec.ts4
-rw-r--r--catalog-ui/src/app/ng2/pages/home/home.component.ts53
-rw-r--r--catalog-ui/src/app/ng2/pages/home/home.module.ts5
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html15
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts32
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts104
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts30
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts38
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html4
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts26
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts66
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts5
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html4
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts17
-rw-r--r--catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts7
-rw-r--r--catalog-ui/src/app/ng2/services/data-type.service.ts25
-rw-r--r--catalog-ui/src/app/ng2/services/model.service.ts3
-rw-r--r--catalog-ui/src/app/services/data-types-service.ts15
-rw-r--r--catalog-ui/src/app/utils/service-data-type-reader.ts88
-rw-r--r--catalog-ui/src/app/view-models/workspace/workspace-view-model.ts3
-rw-r--r--catalog-ui/src/assets/languages/en_US.json5
34 files changed, 814 insertions, 55 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java
index 474df3f9e5..bfbebf398a 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java
@@ -127,7 +127,10 @@ public class CommonImportManager {
private Map<String, Object> convertToFieldMap(String elementTypesYml) {
Map<String, Object> toscaJson = null;
try {
- toscaJson = (Map<String, Object>) new Yaml().load(elementTypesYml);
+ toscaJson = new Yaml().load(elementTypesYml);
+ if (toscaJson.containsKey("data_types")){
+ toscaJson = (Map<String, Object>) toscaJson.get("data_types");
+ }
} catch (Exception e) {
log.debug("Failed to yaml file {}", elementTypesYml, e);
}
@@ -276,11 +279,9 @@ public class CommonImportManager {
eitherResult = handleType(elementType, validator, elementInfoGetter, elementFetcher, elementAdder, elementUpgrader)
.left()
.map(elem -> append(createdElementTypes, elem));
-
if (eitherResult.isRight()) {
break;
}
-
if (!elementTypeItr.hasNext()) {
log.info("all {} were created successfully!!!", elementType);
}
@@ -295,7 +296,6 @@ public class CommonImportManager {
propertyOperation.getJanusGraphGenericDao().rollback();
}
}
-
return eitherResult;
}
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 8139237e38..a7327bf184 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
@@ -163,4 +163,19 @@ public class DataTypeServlet extends BeGenericServlet {
return Response.status(Status.CREATED).entity(property).build();
}
+ @GET
+ @Path("{dataTypeName}/models")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(description = "Get models for type", method = "GET", summary = "Returns list of models for type", responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "200", description = "dataTypeModels"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "404", description = "Data type not found")})
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ public Response getDataTypeModels(@PathParam("dataTypeName") String dataTypeName) {
+ return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
+ gson.toJson(dataTypeOperation.getAllDataTypeModels(dataTypeName)));
+ }
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
index 786c0338c4..4fcc3c0842 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
@@ -31,7 +31,9 @@ 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.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -49,6 +51,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.jetbrains.annotations.NotNull;
import org.openecomp.sdc.be.components.impl.ArtifactTypeImportManager;
import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
@@ -218,7 +221,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
@POST
@Path("/datatypes")
- @Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created data types", responses = {
+ @Operation(description = "Create Data Types from zip", method = "POST", summary = "Returns created data types", responses = {
@ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
@ApiResponse(responseCode = "201", description = "Data types created"),
@ApiResponse(responseCode = "403", description = "Restricted operation"),
@@ -234,6 +237,23 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
}
@POST
+ @Path("/datatypesyaml")
+ @Operation(description = "Create Data Types from yaml", method = "POST", summary = "Returns created data types", responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Data types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Data types already exist")})
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ public Response uploadDataTypesYaml(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesYaml") File file,
+ @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
+ @Parameter(description = "model") @FormDataParam("model") String modelName,
+ @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
+ return uploadElementTypeServletLogicYaml(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
+ includeToModelDefaultImports);
+ }
+
+ @POST
@Path("/grouptypes")
@Operation(description = "Create GroupTypes from yaml", method = "POST", summary = "Returns created group types", responses = {
@ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
@@ -323,6 +343,42 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
}
}
+ private Response uploadElementTypeServletLogicYaml(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
+ final File file, final HttpServletRequest request, final String creator,
+ final String elementTypeName, final String modelName, final boolean includeToModelDefaultImports) {
+ init();
+ final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
+ try {
+ final Wrapper<String> yamlStringWrapper = new Wrapper<>();
+ final String url = request.getMethod() + " " + request.getRequestURI();
+ log.debug(START_HANDLE_REQUEST_OF, url);
+ final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
+ if (responseWrapper.isEmpty()) {
+ final String yamlAsString = getFileAsString(file);
+ log.debug("received yaml: {}", yamlAsString);
+ yamlStringWrapper.setInnerElement(yamlAsString);
+ }
+ if (responseWrapper.isEmpty()) {
+ createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement(), modelName, includeToModelDefaultImports);
+ }
+ return responseWrapper.getInnerElement();
+ } catch (final Exception e) {
+ log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
+ BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+ }
+ }
+
+ @NotNull
+ private String getFileAsString(File file) throws IOException {
+ FileInputStream fl = new FileInputStream(file);
+ byte[] arr = new byte[(int) file.length()];
+ fl.read(arr);
+ fl.close();
+ final String yamlAsString = new String(arr, StandardCharsets.UTF_8);
+ return yamlAsString;
+ }
+
private Wrapper<Response> doUploadTypeValidations(final HttpServletRequest request, String userId, File file) {
Wrapper<Response> responseWrapper = new Wrapper<>();
Wrapper<User> userWrapper = new Wrapper<>();
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 36dcaf44ba..7d01f3f273 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
@@ -29,6 +29,7 @@ import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.janusgraph.core.JanusGraph;
@@ -37,6 +38,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.janusgraph.QueryType;
import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
@@ -124,6 +126,20 @@ public class DataTypeOperation extends AbstractOperation {
return dataTypesFound;
}
+ public List<String> getAllDataTypeModels(final String dataTypeName) {
+ final List<String> models = new ArrayList<>();
+ ImmutableTriple<QueryType, String, Object> criteria =
+ new ImmutableTriple<>(QueryType.HAS, GraphPropertiesDictionary.NAME.getProperty(), dataTypeName);
+
+ final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesForModel =
+ janusGraphGenericDao.getByCriteria(NodeTypeEnum.DataType, DataTypeData.class, List.of(criteria));
+ final var dataTypesValidated = validateDataType(getAllDataTypesForModel, null);
+ for (DataTypeData dataType : dataTypesValidated) {
+ models.add(dataType.getDataTypeDataDefinition().getModel());
+ }
+ return models;
+ }
+
private List<DataTypeData> getAllDataTypesWithModel(final String modelName) {
final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesByModel = janusGraphGenericDao
.getByCriteriaForModel(NodeTypeEnum.DataType, null, modelName, DataTypeData.class);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
index 0d462c9874..8baa9a73c0 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
@@ -296,7 +296,7 @@ public class ModelOperation {
rebuiltModelImportList = new ArrayList<>(modelImportList);
}
- final Map<String, Object> typesYamlMap = new Yaml().load(typesYaml);
+ final Map<String, Object> typesYamlMap = new Yaml().loadAs(typesYaml, Map.class);
removeExistingTypesFromDefaultImports(elementTypeEnum, typesYamlMap, rebuiltModelImportList);
final Map<String, Object> originalContent = new Yaml().load(additionalTypeDefinitionsImport.getContent());
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts
index 76c1d28489..296b63bca7 100644
--- a/catalog-ui/src/app/app.ts
+++ b/catalog-ui/src/app/app.ts
@@ -38,6 +38,7 @@ import {ComponentFactory} from "./utils/component-factory";
import {Component} from "./models/components/component";
import {IUserProperties} from "./models/user";
import {WorkspaceService} from "./ng2/pages/workspace/workspace.service";
+import {TypeWorkspaceGeneralComponent} from "./ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component";
let moduleName: string = 'sdcApp';
let viewModelsModuleName: string = 'Sdc.ViewModels';
@@ -213,8 +214,11 @@ ng1appModule.config([
$stateProvider.state(
States.TYPE_WORKSPACE, {
url: '/:previousState/type-workspace/:type/:id/:subPage',
- template: '<app-type-workspace></app-type-workspace>',
- }
+ params: {
+ 'importedFile': null
+ },
+ template: '<app-type-workspace></app-type-workspace>'
+ }
);
$stateProvider.state(
diff --git a/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.html b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.html
new file mode 100644
index 0000000000..37439f8d70
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.html
@@ -0,0 +1,51 @@
+<!--
+ ~ -
+ ~ ============LICENSE_START=======================================================
+ ~ Copyright (C) 2023 Nordix Foundation.
+ ~ ================================================================================
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ ~ SPDX-License-Identifier: Apache-2.0
+ ~ ============LICENSE_END=========================================================
+ -->
+<div class="import-type-container">
+
+ <form novalidate class="w-sdc-form" name="importForm" validation-on-load form-to-validate="importForm">
+
+ <div class="w-sdc-form-section-container">
+
+ <div class="i-sdc-form-item">
+ <label class="i-sdc-form-label required">Type</label>
+ <select class="i-sdc-form-select"
+ data-ng-class="{'view-mode': true}"
+ data-ng-disabled="false"
+
+ data-tests-id="selectType"
+ data-ng-required="true"
+
+ >
+ <option value="" selected>Data Type</option>
+ </select>
+ </div>
+
+ <div class="i-sdc-form-item">
+ <label class="i-sdc-form-label required">Select File to Import
+ <input (change)="onFileChange($event)" type="file" class="i-sdc-dashboard-item-upload-input"/>
+ </label>
+ </div>
+
+ </div>
+
+ </form>
+
+</div> \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.less b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.less
new file mode 100644
index 0000000000..8c391c52c8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.less
@@ -0,0 +1,60 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+.import-type-container {
+ max-width: 100%;
+}
+
+.default-value-container {
+ overflow: scroll;
+ max-height: 300px;
+ max-width: 100%;
+
+ ul {
+ margin: 0 0 0 20px;
+ list-style: none;
+ line-height: 2em;
+ }
+
+ &::-webkit-scrollbar-track {
+ border: 0;
+ }
+}
+
+.input-label {
+ margin: 0;
+ font-weight: bold;
+}
+
+.input-value {
+ display: flex;
+ flex-flow: row nowrap;
+ gap: 7px;
+
+ input {
+ min-width: 150px;
+ max-width: 250px;
+ }
+}
+
+.empty-value {
+ color: #aaaaaa;
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.spec.ts b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.spec.ts
new file mode 100644
index 0000000000..9e785638d8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.spec.ts
@@ -0,0 +1,45 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ModalImportTypeComponent } from './modal-import-type.component';
+
+describe('ModalImportTypeComponent', () => {
+ let component: ModalImportTypeComponent;
+ let fixture: ComponentFixture<ModalImportTypeComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ModalImportTypeComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ModalImportTypeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.ts b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.ts
new file mode 100644
index 0000000000..2c56b2ef7f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal-import-type/modal-import-type.component.ts
@@ -0,0 +1,47 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+import {Component, Inject, OnInit} from '@angular/core';
+
+@Component({
+ selector: 'app-modal-import-type',
+ templateUrl: './modal-import-type.component.html',
+ styleUrls: ['./modal-import-type.component.less']
+})
+export class ModalImportTypeComponent implements OnInit {
+
+ file:File = null;
+
+ constructor() {}
+
+ ngOnInit() {
+ }
+
+ onFileChange(event: any) {
+ this.file = event.target.files[0];
+ }
+
+ public onImportDataType(file: any): void {
+ if (file && file.filename) {
+ console.log("file: " + file.filename);
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
index cdb173cb12..8e0a66c8f5 100644
--- a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
@@ -44,6 +44,7 @@ import {FileOpenerComponent} from "./file-opener/file-opener.component";
import {DownloadArtifactComponent} from "app/ng2/components/ui/download-artifact/download-artifact.component";
import {SdcElementIconComponent} from "./sdc-element-icon/sdc-element-icon.component";
import {PanelWrapperComponent} from "./panel-wrapper/panel-wrapper.component";
+import { ModalImportTypeComponent } from './modal-import-type/modal-import-type.component';
@NgModule({
declarations: [
@@ -56,7 +57,8 @@ import {PanelWrapperComponent} from "./panel-wrapper/panel-wrapper.component";
FileOpenerComponent,
SdcElementIconComponent,
DownloadArtifactComponent,
- PanelWrapperComponent
+ PanelWrapperComponent,
+ ModalImportTypeComponent
],
imports: [
@@ -97,7 +99,8 @@ import {PanelWrapperComponent} from "./panel-wrapper/panel-wrapper.component";
SdcElementIconComponent,
FileOpenerComponent,
DownloadArtifactComponent,
- PanelWrapperComponent
+ PanelWrapperComponent,
+ ModalImportTypeComponent
],
entryComponents: [SearchWithAutoCompleteComponent, SdcElementIconComponent, PaletteAnimationComponent]
})
diff --git a/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap
index 42686c1567..dd864d48f7 100644
--- a/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap
+++ b/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap
@@ -12,7 +12,9 @@ exports[`home component should match current snapshot 1`] = `
isDefaultFilter={[Function Function]}
loaderService={[Function Object]}
modalService={[Function Object]}
+ modalServiceSdc="undefined"
modalsHandler={[Function Object]}
+ openModalImportType={[Function Function]}
resourceService={[Function Object]}
sdcConfig={[Function Object]}
sdcMenu={[Function Object]}
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.html b/catalog-ui/src/app/ng2/pages/home/home.component.html
index 0c2e41eb11..b16b30b2b2 100644
--- a/catalog-ui/src/app/ng2/pages/home/home.component.html
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.html
@@ -58,6 +58,7 @@
(fileUpload)="onImportService($event)"
[convertToBase64]="true"
></sdc-button-file-opener>
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" testId="importTypebutton" size="medium" type="secondary" text="Import Type" (click)="openModalImportType()"></sdc-button>
</div>
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts b/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts
index 1c03790e04..2642b9e41b 100644
--- a/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts
@@ -7,7 +7,7 @@ import {HomeComponent} from "./home.component";
import {ConfigureFn, configureTests} from "../../../../jest/test-config.helper";
import {NO_ERRORS_SCHEMA} from "@angular/core";
import {TranslateService} from "../../shared/translator/translate.service";
-import {AuthenticationService, CacheService, HomeService, ImportVSPService, ResourceServiceNg2} from '../../../../app/services-ng2';
+import {AuthenticationService, CacheService, HomeService, ImportVSPService, ModalService, ResourceServiceNg2} from '../../../../app/services-ng2';
import {ModalsHandler} from "../../../../app/utils";
import {SdcUiServices} from "onap-ui-angular";
import {ComponentType, ResourceType} from "../../../utils/constants";
@@ -23,6 +23,7 @@ describe('home component', () => {
let importVspService: Partial<ImportVSPService>;
let mockStateService;
let modalServiceMock :Partial<SdcUiServices.ModalService>;
+ let modalServiceMock_ :Partial<ModalService>;
let translateServiceMock : Partial<TranslateService>;
let foldersItemsMenuMock;
let homeFilterMock :Partial<HomeFilter>;
@@ -79,6 +80,7 @@ describe('home component', () => {
{provide: TranslateService, useValue: translateServiceMock},
{provide: ModalsHandler, useValue: {}},
{provide: SdcUiServices.ModalService, useValue: modalServiceMock},
+ {provide: ModalService, useValue: modalServiceMock_},
{provide: SdcUiServices.LoaderService, useValue: loaderServiceMock},
{provide: ImportVSPService, useValue: {}},
{provide: ResourceServiceNg2, useValue: resourceServiceNg2Mock}
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.ts b/catalog-ui/src/app/ng2/pages/home/home.component.ts
index 784823eacd..666b36eb8e 100644
--- a/catalog-ui/src/app/ng2/pages/home/home.component.ts
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.ts
@@ -19,10 +19,20 @@
*/
'use strict';
import {Component as NgComponent, Inject, OnInit} from '@angular/core';
-import {Component, ComponentMetadata, IConfigRoles, IUserProperties, Resource, Service} from 'app/models';
+import {
+ ButtonModel,
+ Component,
+ ComponentMetadata,
+ IConfigRoles,
+ IUserProperties,
+ ModalModel,
+ Resource,
+ Service
+} from 'app/models';
+import {ModalService} from "../../services/modal.service";
import {HomeFilter} from 'app/models/home-filter';
import {AuthenticationService, CacheService, HomeService, ResourceServiceNg2} from 'app/services-ng2';
-import {ComponentState, ModalsHandler} from 'app/utils';
+import {ComponentState, ModalsHandler, States} from 'app/utils';
import {SdcUiServices} from 'onap-ui-angular';
import {CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, ResourceType} from '../../../utils/constants';
import {ImportVSPService} from '../../components/modals/onboarding-modal/import-vsp.service';
@@ -33,6 +43,7 @@ import {TranslateService} from '../../shared/translator/translate.service';
import {FoldersItemsMenu, FoldersItemsMenuGroup, FoldersMenu} from './folders';
import {ImportVSPdata} from "../../components/modals/onboarding-modal/onboarding-modal.component";
import {DataTypeCatalogComponent} from "../../../models/data-type-catalog-component";
+import {ModalImportTypeComponent} from "../../components/ui/modal-import-type/modal-import-type.component";
@NgComponent({
selector: 'home-page',
@@ -64,6 +75,7 @@ export class HomeComponent implements OnInit {
private translateService: TranslateService,
private modalsHandler: ModalsHandler,
private modalService: SdcUiServices.ModalService,
+ private modalServiceSdc: ModalService,
private loaderService: SdcUiServices.LoaderService,
private importVSPService: ImportVSPService,
private resourceService: ResourceServiceNg2
@@ -398,4 +410,41 @@ export class HomeComponent implements OnInit {
this.notificationIconCallback = this.notificationIconCallback.bind(this);
}
+ openModalImportType = () => {
+ let modalTitle = 'Import Type';
+ let modal = this.modalServiceSdc.createCustomModal(new ModalModel(
+ 'sm',
+ modalTitle,
+ null,
+ [
+ new ButtonModel('Import', 'blue', () =>
+ { this.uploadDataTypeFile(modal.instance.dynamicContent.instance.file); modal.instance.close();}, () => false),
+ new ButtonModel('Cancel', 'outline grey', () => {
+ modal.instance.close();
+ }),
+ ],
+ null
+ ));
+ this.modalServiceSdc.addDynamicContentToModal(modal, ModalImportTypeComponent, {});
+ modal.instance.open();
+ }
+
+ private uploadDataTypeFile(file: any): void {
+ if (file && file.name) {
+ // Check that the file has valid extension.
+ const fileExtension: string = file.name.split('.').pop();
+ if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
+ this.$state.go(States.TYPE_WORKSPACE, {
+ type: "datatype",
+ subPage: "general",
+ id: "import",
+ importedFile: file
+ });
+ } else {
+ const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE');
+ const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS', {extensions: this.sdcConfig.toscaFileExtension});
+ this.modalService.openWarningModal(title, message, 'error-invalid-tosca-ext');
+ }
+ }
+ }
}
diff --git a/catalog-ui/src/app/ng2/pages/home/home.module.ts b/catalog-ui/src/app/ng2/pages/home/home.module.ts
index 1a397b44be..acfc299a31 100644
--- a/catalog-ui/src/app/ng2/pages/home/home.module.ts
+++ b/catalog-ui/src/app/ng2/pages/home/home.module.ts
@@ -7,6 +7,7 @@ import { GlobalPipesModule } from "../../pipes/global-pipes.module";
import { TranslateModule } from "../../shared/translator/translate.module";
import { SdcUiComponentsModule } from "onap-ui-angular";
import { ResourceServiceNg2 } from "../../services/component-services/resource.service";
+import {ModalImportTypeComponent} from "../../components/ui/modal-import-type/modal-import-type.component";
@NgModule({
declarations: [
@@ -19,12 +20,14 @@ import { ResourceServiceNg2 } from "../../services/component-services/resource.s
UiElementsModule,
GlobalPipesModule,
TranslateModule
+
],
exports: [
HomeComponent
],
entryComponents: [
- HomeComponent
+ HomeComponent,
+ ModalImportTypeComponent
],
providers: [ResourceServiceNg2]
})
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html
index 877c58bd58..04c334eee1 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html
@@ -33,9 +33,14 @@
<div class="i-sdc-form-item">
<label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'MODEL_LABEL' | translate}}:</label>
- <span>{{dataType.model ? dataType.model : DEFAULT_MODEL_NAME}}</span>
+ <span *ngIf="isViewOnly">{{dataType.model ? dataType.model : DEFAULT_MODEL_NAME}}</span>
+ <select *ngIf="!isViewOnly" formControlName="model" (change)="onModelChange()">
+ <option *ngFor="let model of models"
+ [value]="model.name">{{model.name}}</option>
+ </select>
</div>
+
<div class="i-sdc-form-item">
<label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'DERIVED_FROM_LABEL' | translate}}:</label>
<span>{{dataType.derivedFromName}}</span>
@@ -44,12 +49,12 @@
</div>
<div class="i-sdc-form-item description-field">
- <label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'DESCRIPTION_LABEL' | translate}}:</label>
- <textarea class="description"
+ <label class="i-sdc-form-label">{{'DESCRIPTION_LABEL' | translate}}:</label>
+ <textarea class="description" #description
formControlName="description"
- [ngClass]="{'view-mode': isViewOnly}"
- [required]="true"
+ [ngClass]="{'view-mode': true}"
[attr.test-id]="description"
+ [(ngModel)]="dataType.description"
[value]="dataType.description"></textarea>
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts
index fe7b070354..1484954e4b 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts
@@ -25,22 +25,53 @@ import {TypeWorkspaceGeneralComponent} from './type-workspace-general.component'
import {ReactiveFormsModule} from "@angular/forms";
import {TranslateModule} from "../../../shared/translator/translate.module";
import {TranslateService} from "../../../shared/translator/translate.service";
+import {SdcUiComponentsModule} from "onap-ui-angular/dist";
+import {Observable} from "rxjs/Observable";
+import {DataTypeModel} from "../../../../models/data-types";
+import {DataTypeService} from "../../../services/data-type.service";
+import {ModelService} from "../../../services/model.service";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
+import {IScope} from "angular";
+import {States} from "../../../../utils/constants";
describe('TypeWorkspaceGeneralComponent', () => {
let component: TypeWorkspaceGeneralComponent;
let fixture: ComponentFixture<TypeWorkspaceGeneralComponent>;
+ let dataTypeServiceMock: Partial<DataTypeService>;
+ let modelServiceMock: Partial<ModelService>;
let translateServiceMock: Partial<TranslateService> = {
'translate': jest.fn()
};
+ let importedFileMock: File = null;
+ let stateParamsMock: Partial<ng.ui.IStateParamsService> = {
+ 'importedFile': importedFileMock
+ };
+ let resolveMock = {"$stateParams": stateParamsMock};
+ let parentScopeMock: Partial<IScope> = {
+ '$resolve': resolveMock
+ };
+ let scopeMock_: Partial<IWorkspaceViewModelScope> = {
+ '$parent': parentScopeMock,
+ 'current': {
+ 'name': States.TYPE_WORKSPACE
+ }
+ }
+
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TypeWorkspaceGeneralComponent ],
imports: [
ReactiveFormsModule,
+ SdcUiComponentsModule,
TranslateModule
],
providers: [
+ {provide: TranslateService, useValue: translateServiceMock},
+ {provide: "$scope", useValue: scopeMock_ },
+ {provide: "$state", useValue: {}},
+ {provide: DataTypeService, useValue: dataTypeServiceMock},
+ {provide: ModelService, useValue: modelServiceMock},
{provide: TranslateService, useValue: translateServiceMock}
]
})
@@ -50,6 +81,7 @@ describe('TypeWorkspaceGeneralComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(TypeWorkspaceGeneralComponent);
component = fixture.componentInstance;
+ component.dataTypeMap$ = new Observable<Map<string, DataTypeModel>>();
fixture.detectChanges();
});
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts
index 8728c3020e..a6e4d1efeb 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts
@@ -19,10 +19,20 @@
* ============LICENSE_END=========================================================
*/
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, EventEmitter, Inject, Input, OnInit, Output} from '@angular/core';
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {DataTypeModel} from "../../../../models/data-types";
-import { DEFAULT_MODEL_NAME } from "app/utils/constants";
+import {DEFAULT_MODEL_NAME} from "app/utils/constants";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
+import {ServiceDataTypeReader} from "../../../../utils/service-data-type-reader";
+import {TranslateService} from "../../../shared/translator/translate.service";
+import {SdcUiServices} from "onap-ui-angular/dist";
+import {ModelService} from "../../../services/model.service";
+import {Model} from "../../../../models/model";
+import {DataTypesMap} from "../../../../models/data-types-map";
+import {DataTypeService} from "../../../services/data-type.service";
+import {Observable} from "rxjs/Observable";
+import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
@Component({
selector: 'app-type-workspace-general',
@@ -30,9 +40,18 @@ import { DEFAULT_MODEL_NAME } from "app/utils/constants";
styleUrls: ['./type-workspace-general.component.less']
})
export class TypeWorkspaceGeneralComponent implements OnInit {
+
@Input() isViewOnly = true;
@Input() dataType: DataTypeModel = new DataTypeModel();
-
+ @Output() onImportedType = new EventEmitter<any>();
+ importedFile: File;
+ models: Array<Model>;
+ selectedModelName: string;
+ dataTypes: DataTypesMap;
+ derivedFromName: string;
+ dataTypeMap$: Observable<Map<string, DataTypeModel>>;
+ dataTypeMap: Map<string, DataTypeModel>;
+ typeOptions: Array<IDropDownOption>;
DEFAULT_MODEL_NAME = DEFAULT_MODEL_NAME;
type: FormControl = new FormControl(undefined, [Validators.required, Validators.minLength(1), Validators.maxLength(300)]);
@@ -46,17 +65,92 @@ export class TypeWorkspaceGeneralComponent implements OnInit {
'derivedFrom': this.derivedFrom
});
+ constructor(@Inject('$scope') private $scope: IWorkspaceViewModelScope,
+ @Inject('$state') private $state: ng.ui.IStateService,
+ protected dataTypeService: DataTypeService,
+ private modalServiceSdcUI: SdcUiServices.ModalService,
+ private modelService: ModelService,
+ private translateService: TranslateService) {
+ this.typeOptions = [];
+ }
+
ngOnInit(): void {
+ this.getImportedFile();
+ if (!this.isViewOnly) {
+ console.log("file size: " + this.importedFile.size);
+ console.log("file type: " + this.importedFile.type);
+ console.log("file lastModifiedDate: " + this.importedFile.lastModifiedDate);
+
+ new ServiceDataTypeReader().read(this.importedFile).then(
+ (serviceType) => {
+ this.dataType = serviceType;
+ this.dataType.modificationTime = this.importedFile.lastModifiedDate;
+ this.dataType.creationTime = this.importedFile.lastModifiedDate;
+ this.derivedFromName = serviceType.derivedFromName;
+ this.dataType.uniqueId = this.dataType.model ? this.dataType.model + "." + this.dataType.name : this.dataType.name + ".datatype";
+ this.$scope.dataType = this.dataType;
+ this.onImportedType.emit(this.dataType);
+
+ this.models = [];
+ this.modelService.getDataTypeModels(this.derivedFromName).subscribe((modelsFound: any) => {
+ modelsFound.sort().forEach(modelName => {
+ let model:Model;
+ if (modelName === null || "" === modelName) {
+ model = new Model({"name": DEFAULT_MODEL_NAME, "derivedFrom": "", "modelType": "normative"});
+ }
+ else {
+ model = new Model({"name": modelName, "derivedFrom": "", "modelType": "normative"});
+ }
+ this.models.push(model);
+ });
+ this.onModelChange();
+ this.$scope.dataType = this.dataType;
+ });
+
+ },
+ (error) => {
+ const errorMsg = this.translateService.translate('IMPORT_DATA_TYPE_FAILURE_MESSAGE_TEXT');
+ console.error(errorMsg, error);
+ const errorDetails = {
+ 'Error': error.reason,
+ 'Details': error.message
+ };
+ console.error(error.reason);
+ this.modalServiceSdcUI.openErrorDetailModal('Error', errorMsg,
+ 'error-modal', errorDetails);
+ this.$state.go('dashboard');
+ });
+ }
this.initForm();
}
+ onModelChange(): void {
+ this.selectedModelName = this.models.filter(x => x.name == this.model.value).pop().name;
+ console.log("selected model: " + this.selectedModelName);
+ this.dataType.model = new Model({"name": this.selectedModelName, "derivedFrom": "", "modelType": "normative"});
+ this.dataType.uniqueId = this.dataType.model.name === DEFAULT_MODEL_NAME ?
+ this.dataType.name + ".datatype" : this.dataType.model.name + "." + this.dataType.name + ".datatype";
+ this.$scope.dataType.derivedFromName = this.derivedFromName;
+ this.$scope.dataType = this.dataType;
+ this.$scope.dataType.model = this.dataType.model;
+ }
+
+ private getImportedFile(): void {
+ let importedFile = this.$scope["$parent"]["$resolve"]["$stateParams"]["importedFile"];
+ this.importedFile = <File>importedFile;
+ this.$scope.importFile = this.importedFile;
+ if (this.importedFile) {
+ this.isViewOnly = false;
+ }
+ }
+
private initForm(): void {
if (!this.dataType) {
return;
}
this.type.setValue(this.dataType.name);
this.description.setValue(this.dataType.description);
- this.model.setValue(this.dataType.model);
- this.derivedFrom.setValue(this.dataType.derivedFrom);
+ this.model.setValue(this.dataType.model ? this.dataType.model : this.$scope.dataType && this.$scope.dataType.model ? this.$scope.dataType.model : DEFAULT_MODEL_NAME);
+ this.derivedFrom.setValue(this.dataType.derivedFromName);
}
}
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
index e6e9c12d14..f89be56359 100644
--- 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
@@ -31,6 +31,10 @@ import {DataTypeModel} from "../../../../models/data-types";
import {Component, ViewChild} from "@angular/core";
import {PropertyBEModel} from "../../../../models/properties-inputs/property-be-model";
import {ModalService} from "../../../services/modal.service";
+import {IScope} from "../../../../../typings/angularjs/angular";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
+import {States} from "../../../../utils/constants";
+import {SdcUiServices} from "onap-ui-angular/dist";
describe('TypeWorkspacePropertiesComponent', () => {
const messages = require("../../../../../assets/languages/en_US.json");
@@ -54,6 +58,28 @@ describe('TypeWorkspacePropertiesComponent', () => {
return messages[translateKey];
})
};
+ let importedFileMock: File = null;
+ let stateParamsMock: Partial<ng.ui.IStateParamsService> = {
+ 'importedFile': importedFileMock
+ };
+ let resolveMock = {"$stateParams": stateParamsMock};
+ let parentScopeMock: Partial<IScope> = {
+ '$resolve': resolveMock
+ };
+ let scopeMock_: Partial<IWorkspaceViewModelScope> = {
+ '$parent': parentScopeMock,
+ 'current': {
+ 'name': States.TYPE_WORKSPACE
+ }
+ }
+ let stateMock: Partial<ng.ui.IStateService> = {
+ 'current': {
+ 'name': States.TYPE_WORKSPACE
+ }
+ };
+
+ let modalServiceSdcUIMock: Partial<SdcUiServices.ModalService>;
+ let modalServiceMock: Partial<ModalService>;
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -65,6 +91,10 @@ describe('TypeWorkspacePropertiesComponent', () => {
providers: [
{provide: DataTypeService, useValue: dataTypeServiceMock},
{provide: TranslateService, useValue: translateServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceSdcUIMock},
+ {provide: ModalService, useValue: modalServiceMock},
+ {provide: "$scope", useValue: scopeMock_},
+ {provide: '$state', useValue: stateMock},
{provide: ModalService, useValue: modalService}
]
})
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 f53ad5b376..bcc5fe9c28 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
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, Inject, 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";
@@ -30,6 +30,8 @@ import {ModalModel} from "../../../../models/modal";
import {ButtonModel} from "../../../../models/button";
import {TranslateService} from "../../../shared/translator/translate.service";
import {AddPropertyComponent, PropertyValidationEvent} from "./add-property/add-property.component";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
+import {SdcUiServices} from "onap-ui-angular/dist";
@Component({
selector: 'app-type-workspace-properties',
@@ -40,6 +42,8 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
@Input() isViewOnly = true;
@Input() dataType: DataTypeModel = new DataTypeModel();
+ importedFile: File;
+ derivedFromName: string;
properties: Array<PropertyBEModel> = [];
filteredProperties: Array<PropertyBEModel> = [];
tableHeadersList: Array<TableHeader> = [];
@@ -48,7 +52,12 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
tableFilterTerm: string = undefined;
tableSearchTermUpdate = new Subject<string>();
- constructor(private dataTypeService: DataTypeService, private modalService: ModalService, private translateService: TranslateService) {
+ constructor(@Inject('$scope') private $scope: IWorkspaceViewModelScope,
+ @Inject('$state') private $state: ng.ui.IStateService,
+ protected dataTypeService: DataTypeService,
+ private modalServiceSdcUI: SdcUiServices.ModalService,
+ private modalService: ModalService,
+ private translateService: TranslateService) {
}
ngOnInit(): void {
@@ -70,22 +79,12 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
{title: 'Required', property: 'required'},
{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 => {
- const property = new PropertyBEModel(value);
- if (property.defaultValue) {
- property.defaultValue = JSON.parse(property.defaultValue);
- }
-
- return property;
- });
- this.filteredProperties = Array.from(this.properties);
- this.sort();
+ this.showPropertiesMap(properties);
});
}
@@ -188,6 +187,19 @@ export class TypeWorkspacePropertiesComponent implements OnInit {
onRowClick(property: PropertyBEModel) {
this.openAddPropertyModal(property, true);
}
+
+ private showPropertiesMap(properties: Array<PropertyBEModel>): void {
+ this.properties = properties.map(value => {
+ const property = new PropertyBEModel(value);
+ if (property.defaultValue) {
+ property.defaultValue = JSON.parse(property.defaultValue);
+ }
+
+ return property;
+ });
+ this.filteredProperties = Array.from(this.properties);
+ this.sort();
+ }
}
interface TableHeader {
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 105c89d7a4..cdd8e41503 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
@@ -32,6 +32,8 @@
<div class="progress-container">
</div>
<div class="sdc-workspace-top-bar-buttons">
+ <button *ngIf="!isViewOnly" data-ng-disabled="!isValidForm || isDisableMode() || isLoading || unsavedChanges" (click)="createImportType()" class="tlv-btn outline green" data-tests-id="create/save">Create</button>
+ <span *ngIf="!isViewOnly" class="delimiter"></span>
<span class="sprite-new x-btn" (click)="goToBreadcrumbHome()" sdc-smart-tooltip="Close" [title]="'CLOSE_LABEL' | translate"></span>
</div>
</div>
@@ -43,7 +45,7 @@
</div>
</div>
<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-general *ngIf="currentMenu.state === 'general'" [dataType]="dataType" (onImportedType)="onImportedType($event)"></app-type-workspace-general>
<app-type-workspace-properties *ngIf="currentMenu.state === 'properties'" [dataType]="dataType" [isViewOnly]="dataType.normative"></app-type-workspace-properties>
<app-type-workspace-tosca-artifact *ngIf="currentMenu.state === 'tosca_artifacts'" [dataType]="dataType"></app-type-workspace-tosca-artifact>
</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 3db2504564..a5cf20f4e9 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
@@ -41,6 +41,10 @@ import {TypeWorkspacePropertiesComponent} from "./type-workspace-properties/type
import {TypeWorkspaceToscaArtifactPageComponent} from "./type-workspace-tosca-artifacts/type-workspace-tosca-artifact-page.component";
import {NgxDatatableModule} from "@swimlane/ngx-datatable";
import {SvgIconModule} from "onap-ui-angular/dist/svg-icon/svg-icon.module";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {IScope} from "angular";
+import {IWorkspaceViewModelScope} from "../../../view-models/workspace/workspace-view-model";
+import {ModelService} from "../../services/model.service";
describe('TypeWorkspaceComponent', () => {
let component: TypeWorkspaceComponent;
@@ -50,6 +54,7 @@ describe('TypeWorkspaceComponent', () => {
'translate': jest.fn()
};
let dataTypeServiceMock: Partial<DataTypeService>;
+ let notificationMock: Partial<any>;
let cacheService: Partial<CacheService> = {
'get': jest.fn(param => {
if (param === 'version') {
@@ -65,7 +70,7 @@ describe('TypeWorkspaceComponent', () => {
'name': States.TYPE_WORKSPACE
}
};
- let stateParamsMock: Partial<ng.ui.IStateParamsService> = {};
+
let injectorMock: Partial<ng.auto.IInjectorService> = {
'get': jest.fn(param => {
if (param === '$state') {
@@ -89,6 +94,21 @@ describe('TypeWorkspaceComponent', () => {
return user;
})
};
+ let importedFileMock: File = null;
+ let stateParamsMock: Partial<ng.ui.IStateParamsService> = {
+ 'importedFile': importedFileMock
+ };
+ let resolveMock = {"$stateParams": stateParamsMock};
+ let parentScopeMock: Partial<IScope> = {
+ '$resolve': resolveMock
+ };
+ let scopeMock_: Partial<IWorkspaceViewModelScope> = {
+ '$parent': parentScopeMock,
+ 'current': {
+ 'name': States.TYPE_WORKSPACE
+ }
+ }
+ let modelServiceMock: Partial<ModelService>;
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -102,10 +122,14 @@ describe('TypeWorkspaceComponent', () => {
NgxDatatableModule,
SvgIconModule
],
+ schemas: [NO_ERRORS_SCHEMA],
providers: [
{provide: DataTypeService, useValue: dataTypeServiceMock},
{provide: TranslateService, useValue: translateServiceMock},
{provide: CacheService, useValue: cacheService},
+ {provide: "Notification", useValue: notificationMock },
+ {provide: ModelService, useValue: modelServiceMock},
+ {provide: "$scope", useValue: scopeMock_ },
{provide: '$state', useValue: stateMock},
{provide: '$stateParams', useValue: stateParamsMock},
{provide: '$injector', useValue: injectorMock},
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts
index d0d5ae8c69..e0f7ac77a0 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts
@@ -19,11 +19,17 @@
* ============LICENSE_END=========================================================
*/
-import {Component, Inject, OnInit} from '@angular/core';
+import {Component, Inject, Injector, OnInit} from '@angular/core';
import {MenuItem, MenuItemGroup} from "../../../utils/menu-handler";
import {CacheService} from "../../services/cache.service";
import {DataTypeModel} from "../../../models/data-types";
import {DataTypeService} from "../../services/data-type.service";
+import {IWorkspaceViewModelScope} from "../../../view-models/workspace/workspace-view-model";
+import {TranslateService} from "../../shared/translator/translate.service";
+import {HttpErrorResponse} from "@angular/common/http";
+import {ServerErrorResponse} from "../../../models/server-error-response";
+import {Observable} from "rxjs/Observable";
+import {SdcUiServices} from "onap-ui-angular/dist";
@Component({
selector: 'app-type-workspace',
@@ -33,27 +39,32 @@ import {DataTypeService} from "../../services/data-type.service";
export class TypeWorkspaceComponent implements OnInit {
private typeMenuItemGroup: MenuItemGroup;
-
isLoading: boolean;
disabled: boolean;
isViewOnly: boolean = true;
sdcVersion: string;
breadcrumbsModel: Array<MenuItemGroup> = [];
dataType: DataTypeModel = new DataTypeModel();
+ importedDataType: DataTypeModel = new DataTypeModel();
currentMenu: MenuItem;
- constructor(private dataTypeService: DataTypeService, private cacheService: CacheService,
+ constructor(@Inject('$scope') private $scope: IWorkspaceViewModelScope,
+ private dataTypeService: DataTypeService, private cacheService: CacheService,
+ @Inject('Notification') private Notification: any,
+ private translateService: TranslateService,
@Inject('$state') private $state: ng.ui.IStateService,
- @Inject('$stateParams') private stateParams) { }
+ @Inject('$stateParams') private stateParams,
+ private injector: Injector) { }
ngOnInit(): void {
this.sdcVersion = this.cacheService.get('version');
this.typeMenuItemGroup = this.createTypeBreadcrumb();
+
this.loadDataType();
}
private loadDataType(): void {
- if (this.stateParams.id) {
+ if (this.stateParams.id && this.stateParams.id != "import") {
this.dataTypeService.findById(this.stateParams.id).subscribe(dataType => {
this.dataType = dataType;
this.updateTypeBreadcrumb();
@@ -61,11 +72,49 @@ export class TypeWorkspaceComponent implements OnInit {
console.debug('Could not find data type %s', this.stateParams.id, error);
this.goToBreadcrumbHome();
});
+ this.isViewOnly = true;
} else {
+
+ this.isViewOnly = false;
this.dataType = new DataTypeModel();
}
}
+ onImportedType(dataType) {
+ this.typeMenuItemGroup.updateSelectedMenuItemText(`Data Type: ${dataType.name}`);
+ }
+
+ private createImportType() {
+ if (this.$scope.dataType.derivedFromName != undefined && this.$scope.dataType.model != undefined) {
+ this.dataTypeService.createImportedType(this.$scope.dataType.model.name, this.$scope.importFile)
+ .subscribe(response => {
+ this.importedDataType = new DataTypeModel(response);
+ this.Notification.success({
+ message: this.$scope.dataType.name + ' ' + this.translateService.translate('IMPORT_DATA_TYPE_SUCCESS_MESSAGE_TEXT'),
+ title: this.translateService.translate('IMPORT_DATA_TYPE_TITLE_TEXT')
+ });
+ this.$state.go(this.$state.current.name, {importedFile: null, id: this.$scope.dataType.uniqueId, isViewOnly: true}, {reload: true});
+ }, error => {//because overriding http interceptor
+ if (error instanceof HttpErrorResponse) {
+ const errorResponse: ServerErrorResponse = new ServerErrorResponse(error);
+ const modalService = this.injector.get(SdcUiServices.ModalService);
+ const errorDetails = {
+ 'Error Code': errorResponse.status != 409 ? errorResponse.messageId : "Data Type already exists",
+ 'Status Code': errorResponse.status
+ };
+ modalService.openErrorDetailModal('Error', errorResponse.status != 409 ? errorResponse.message : "Data Type already exists", 'error-modal', errorDetails);
+ return Observable.throwError(error);
+ }
+ });
+ }
+ else {
+ this.Notification.error({
+ message: this.$scope.dataType.name + ' ' + "Derived from is invalid in file",
+ title: this.translateService.translate('IMPORT_DATA_TYPE_TITLE_TEXT')
+ });
+ }
+ }
+
private updateTypeBreadcrumb(): void {
this.typeMenuItemGroup.updateSelectedMenuItemText(`Data Type: ${this.dataType.name}`);
}
@@ -82,10 +131,15 @@ export class TypeWorkspaceComponent implements OnInit {
onMenuUpdate(menuItemGroup: MenuItemGroup): void {
this.breadcrumbsModel.push(...[this.typeMenuItemGroup, menuItemGroup]);
+ if (!this.isViewOnly) {
+ this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
+ item.isDisabled = ('general' !== item.state);
+ item.disabledCategory = ('general' !== item.state);
+ });
+ }
}
onMenuClick(menuItem: MenuItem): void {
this.currentMenu = menuItem;
}
-
}
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 87b29b615d..e7ddb46602 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
@@ -38,6 +38,7 @@ import {TypeWorkspaceToscaArtifactPageComponent} from "./type-workspace-tosca-ar
import {ModalService} from "../../services/modal.service";
import {AddPropertyComponent} from './type-workspace-properties/add-property/add-property.component';
import {InterfaceOperationHandlerModule} from "../composition/interface-operatons/operation-creator/interface-operation-handler.module";
+import {AutoCompleteModule} from "onap-ui-angular/dist/autocomplete/autocomplete.module";
@NgModule({
imports: [
@@ -51,6 +52,7 @@ import {InterfaceOperationHandlerModule} from "../composition/interface-operaton
InterfaceOperationHandlerModule,
NgxDatatableModule,
SvgIconModule,
+ AutoCompleteModule
],
declarations: [
TypeWorkspaceComponent,
@@ -64,7 +66,8 @@ import {InterfaceOperationHandlerModule} from "../composition/interface-operaton
CacheService,
WorkspaceMenuComponent,
DataTypeService,
- ModalService
+ ModalService,
+ FileReader
],
entryComponents: [TypeWorkspaceComponent, AddPropertyComponent],
exports: [TypeWorkspaceComponent]
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html
index 18c6949b46..02d2683c9d 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html
@@ -25,8 +25,8 @@
</div>
<div class="i-sdc-designer-sidebar-section-content-item"
[ngClass]="{'selected': isSelected(menuItem)}"
- *ngFor="let menuItem of leftBarTabs.menuItems">
- <div class="expand-collapse-menu-box-item-text" ng-class="{'disabled': menuItem.isDisabled }">
+ *ngFor="let menuItem of $scope.leftBarTabs.menuItems">
+ <div class="expand-collapse-menu-box-item-text" [ngClass]="{ 'disabled': menuItem.isDisabled }">
<button [attr.data-tests-id]="menuItem.text + 'LeftSideMenu'" type="button" class="i-sdc-designer-sidebar-section-content-item-service-cat"
(click)="menuItem.callback()" [disabled]="menuItem.disabledCategory">{{menuItem.text}}</button>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts
index a91258c00e..d9bb8833cd 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts
@@ -26,6 +26,8 @@ import {CacheService} from "../../../services/cache.service";
import {States} from "../../../../utils/constants";
import {IAppMenu} from "../../../../models/app-config";
import {SdcMenuToken} from "../../../config/sdc-menu.config";
+import {IScope} from "../../../../../typings/angularjs/angular";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
describe('WorkspaceMenuComponent', () => {
let component: WorkspaceMenuComponent;
@@ -59,6 +61,20 @@ describe('WorkspaceMenuComponent', () => {
}
})
};
+ let importedFileMock: File = null;
+ let stateParamsMock: Partial<ng.ui.IStateParamsService> = {
+ 'importedFile': importedFileMock
+ };
+ let resolveMock = {"$stateParams": stateParamsMock};
+ let parentScopeMock: Partial<IScope> = {
+ '$resolve': resolveMock
+ };
+ let scopeMock_: Partial<IWorkspaceViewModelScope> = {
+ '$parent': parentScopeMock,
+ 'current': {
+ 'name': States.TYPE_WORKSPACE
+ }
+ }
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -66,6 +82,7 @@ describe('WorkspaceMenuComponent', () => {
providers: [
{provide: CacheService, useValue: cacheService},
{provide: '$injector', useValue: injectorMock},
+ {provide: "$scope", useValue: scopeMock_ },
{provide: SdcMenuToken, useValue: sdcMenuMock}
]
})
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts
index c5e49d4d7d..ee4f3a84bd 100644
--- a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts
+++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts
@@ -25,6 +25,7 @@ import {CacheService} from "../../../services/cache.service";
import {IAppMenu} from "../../../../models/app-config";
import {IUserProperties} from "../../../../models/user";
import {SdcMenuToken} from "../../../config/sdc-menu.config";
+import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model";
@Component({
selector: 'app-workspace-menu',
@@ -44,7 +45,10 @@ export class WorkspaceMenuComponent implements OnInit {
leftBarTabs: MenuItemGroup = new MenuItemGroup();
- constructor(private cacheService: CacheService, @Inject(SdcMenuToken) private sdcMenu: IAppMenu, @Inject('$injector') $injector) {
+ constructor(private cacheService: CacheService,
+ @Inject('$scope') private $scope: IWorkspaceViewModelScope,
+ @Inject(SdcMenuToken) private sdcMenu: IAppMenu,
+ @Inject('$injector') $injector) {
this.$state = $injector.get('$state');
this.$q = $injector.get('$q');
}
@@ -70,6 +74,7 @@ export class WorkspaceMenuComponent implements OnInit {
return menuItem;
});
this.updateSelectedMenuItem();
+ this.$scope.leftBarTabs = this.leftBarTabs;
this.onMenuUpdate.emit(this.leftBarTabs);
}
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 298ba90b31..3a27801315 100644
--- a/catalog-ui/src/app/ng2/services/data-type.service.ts
+++ b/catalog-ui/src/app/ng2/services/data-type.service.ts
@@ -26,8 +26,9 @@ import { PROPERTY_DATA } from "app/utils";
import {DerivedFEAttribute} from "../../models/attributes-outputs/derived-fe-attribute";
import {ISdcConfig} from "../config/sdc-config.config.factory";
import {SdcConfigToken} from "../config/sdc-config.config";
-import {HttpClient} from "@angular/common/http";
+import {HttpBackend, HttpClient, HttpHeaders} from "@angular/common/http";
import {Observable} from "rxjs/Observable";
+import {AuthenticationService} from "./authentication.service";
/** This is a new service for NG2, to eventually replace app/services/data-types-service.ts
*
@@ -40,14 +41,17 @@ export class DataTypeService {
public dataTypes: DataTypesMap;
private readonly baseUrl: string;
private readonly dataTypeUrl: string;
+ private readonly dataTypeUploadUrl: string;
- constructor(private dataTypeService: DataTypesService, private httpClient: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+
+ constructor(private dataTypeService: DataTypesService, private authService: AuthenticationService, private handler: HttpBackend, private httpClient: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
this.dataTypes = dataTypeService.getAllDataTypes(); //This should eventually be replaced by an NG2 call to the backend instead of utilizing Angular1 downgraded component.
this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
- this.dataTypeUrl = `${this.baseUrl}data-types`
+ this.dataTypeUrl = `${this.baseUrl}data-types`;
+ this.dataTypeUploadUrl = `${this.baseUrl}uploadType`;
+ this.httpClient = new HttpClient(handler);
}
-
public getDataTypeByModelAndTypeName(modelName: string, typeName: string): DataTypeModel {
this.dataTypes = this.dataTypeService.getAllDataTypesFromModel(modelName);
let dataTypeFound = this.dataTypes[typeName];
@@ -88,6 +92,18 @@ export class DataTypeService {
return this.httpClient.post<PropertyBEModel>(url, property);
}
+ public createImportedType(model: string, importingFile: File): Observable<any> {
+ const url = `${this.dataTypeUploadUrl}/datatypesyaml`;
+ const formData = new FormData();
+ formData.append('dataTypesYaml', importingFile);
+ formData.append('model', model != 'SDC AID' ? model : "")
+ formData.append('includeToModelImport', "true");
+ let headers = new HttpHeaders({'USER_ID': this.authService.getLoggedinUser().userId});
+ let options = {headers: headers};
+
+ return this.httpClient.post<any>(url, formData, options);
+ }
+
public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName){
// const property = this.dataTypes[rootPropertyType].properties.filter(property =>
// property.name == propertyName);
@@ -149,6 +165,5 @@ export class DataTypeService {
if (prop.name == 'instance_name') prop.hidden = generatedNamingVal;
});
}
-
}
diff --git a/catalog-ui/src/app/ng2/services/model.service.ts b/catalog-ui/src/app/ng2/services/model.service.ts
index 83e16b12c7..60b7ac902d 100644
--- a/catalog-ui/src/app/ng2/services/model.service.ts
+++ b/catalog-ui/src/app/ng2/services/model.service.ts
@@ -39,4 +39,7 @@ export class ModelService {
return this.http.get<Model[]>(this.baseUrl + "/v1/catalog/model?modelType=" + type);
}
+ getDataTypeModels(typeName: string):Observable<any> {
+ return this.http.get<Array<string>>(this.baseUrl + "/v1/catalog/data-types/" + typeName + "/models");
+ }
}
diff --git a/catalog-ui/src/app/services/data-types-service.ts b/catalog-ui/src/app/services/data-types-service.ts
index 09ece87907..5d247a14d9 100644
--- a/catalog-ui/src/app/services/data-types-service.ts
+++ b/catalog-ui/src/app/services/data-types-service.ts
@@ -134,6 +134,21 @@ export class DataTypesService implements IDataTypesService {
});
}
+ public findAllDataTypesByModelIncludingRoot = (modelName: string): Promise<Map<string, DataTypeModel>> => {
+ return new Promise<Map<string, DataTypeModel>>((resolve, reject) => {
+ this.fetchDataTypesByModel(modelName).then(response => {
+ const dataTypes = response.data;
+ const dataTypeMap = new Map<string, DataTypeModel>();
+ for(const dataTypeKey of Object.keys(dataTypes)) {
+ dataTypeMap.set(dataTypeKey, new DataTypeModel(dataTypes[dataTypeKey]))
+ }
+ resolve(dataTypeMap);
+ }).catch(reason => {
+ reject(reason);
+ });
+ });
+ }
+
public getAllDataTypes = ():DataTypesMap => {
return this.dataTypes;
};
diff --git a/catalog-ui/src/app/utils/service-data-type-reader.ts b/catalog-ui/src/app/utils/service-data-type-reader.ts
new file mode 100644
index 0000000000..fd5ee2fc19
--- /dev/null
+++ b/catalog-ui/src/app/utils/service-data-type-reader.ts
@@ -0,0 +1,88 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+import {DataTypeModel, PropertyBEModel} from "../models";
+import {load} from 'js-yaml';
+
+export class ServiceDataTypeReader {
+
+ private serviceDataType = new DataTypeModel();
+
+ public read(dataTypeFile: File): Promise<DataTypeModel> {
+
+ return new Promise<DataTypeModel>((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ try {
+ const result = <String>reader.result;
+ const loadedContent = load(result);
+ console.log("Readed content: " + loadedContent);
+ this.readName(loadedContent);
+ this.readDerivedFrom(this.getDataType(loadedContent));
+ this.readDescription(this.getDataType(loadedContent));
+ this.readProperties(this.getDataType(loadedContent));
+ resolve(this.serviceDataType);
+ } catch (error) {
+ reject(error);
+ }
+ }
+ reader.readAsText(dataTypeFile);
+ });
+ }
+
+ private getDataType(fileContent:any) {
+ const index = Object.keys(fileContent).indexOf("data_types",0)
+ if (index == -1){
+ return fileContent;
+ }
+ return fileContent["data_types"];
+ }
+
+ private readName(fileContent: any) {
+ this.serviceDataType.name = Object.keys(fileContent).values().next().value;
+ }
+
+ private readDerivedFrom(fileContent: any) {
+ let dataType = Object.keys(fileContent).values().next().value;
+ this.serviceDataType.derivedFromName = fileContent[dataType]["derived_from"];
+ }
+
+ private readDescription(fileContent: any) {
+ let dataType = Object.keys(fileContent).values().next().value;
+ this.serviceDataType.description = fileContent[dataType]["description"];
+ }
+
+ private readProperties(fileContent: any) {
+ this.serviceDataType.properties = new Array<PropertyBEModel>();
+ let dataType = Object.keys(fileContent).values().next().value;
+ const properties = fileContent[dataType]["properties"];
+ Object.keys(properties).forEach((key )=>
+ {
+ let property = new PropertyBEModel();
+ property.name = key;
+ property.description = properties[key]["description"];
+ property.type = properties[key]["type"];
+ property.schemaType = properties[key]["schema"];
+ property.required = properties[key]["required"];
+ this.serviceDataType.properties.push(property);
+ }
+ );
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts
index 0778b2d803..accc0437fb 100644
--- a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts
@@ -23,7 +23,7 @@
*/
'use strict';
import * as _ from 'lodash';
-import {Component, IAppMenu, IUserProperties, Plugin, PluginsConfiguration, Resource, Service} from 'app/models';
+import {Component, DataTypeModel, IAppMenu, IUserProperties, Plugin, PluginsConfiguration, Resource, Service} from 'app/models';
import {
CHANGE_COMPONENT_CSAR_VERSION_FLAG,
ChangeLifecycleStateHandler,
@@ -57,6 +57,7 @@ export interface IWorkspaceViewModelScope extends ng.IScope {
isLoading: boolean;
isCreateProgress: boolean;
component: Component;
+ dataType: DataTypeModel;
originComponent: Component;
componentType: string;
importFile: any;
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index 5dec922980..bb2ebd596d 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -585,6 +585,11 @@
"UNIQUE_ID_LABEL": "Unique Id",
"=========== SERVICE IMPORT ===========": "",
"IMPORT_FAILURE_MESSAGE_TEXT": "Import Failure - error reading CSAR",
+ "=========== DATA TYPE IMPORT ===========": "",
+ "IMPORT_DATA_TYPE_FAILURE_MESSAGE_TEXT": "Import Failure - error reading data type file",
+ "IMPORT_DATA_TYPE_FAILURE_PROCESSING_MESSAGE_TEXT": "Import Failure - error importing data type",
+ "IMPORT_DATA_TYPE_SUCCESS_MESSAGE_TEXT": "Successfully imported",
+ "IMPORT_DATA_TYPE_TITLE_TEXT": "Import Data Type",
"=========== PROPERTIES ===========": "",
"PROPERTY_LIST_EMPTY_MESSAGE": "There are no properties to display",
"PROPERTY_SHOWING_LABEL": "Showing Properties",