diff options
author | andre.schmid <andre.schmid@est.tech> | 2021-05-05 15:31:04 +0100 |
---|---|---|
committer | Christophe Closset <christophe.closset@intl.att.com> | 2021-05-15 06:21:13 +0000 |
commit | 2152a9a43767cdd486fd8c93894f66a05083f53c (patch) | |
tree | cbb64fc5680ba724bc317e27f6a20802d5b38502 /catalog-ui/src/app | |
parent | e3de4c9d214983d38a7d66e89dae5d4bba170ca3 (diff) |
Support for selection of capabilities
Change-Id: Ib1a3e3e1a59fc84c62620932c408e231acf77024
Issue-ID: SDC-3580
Signed-off-by: André Schmid <andre.schmid@est.tech>
Diffstat (limited to 'catalog-ui/src/app')
8 files changed, 175 insertions, 27 deletions
diff --git a/catalog-ui/src/app/models/capability.ts b/catalog-ui/src/app/models/capability.ts index f365dc4940..b377ed9edd 100644 --- a/catalog-ui/src/app/models/capability.ts +++ b/catalog-ui/src/app/models/capability.ts @@ -62,6 +62,7 @@ export class Capability implements RequirementCapabilityModel { description: string; validSourceTypes: string[]; properties: PropertyModel[]; + external: boolean; // custom selected: boolean; @@ -84,6 +85,7 @@ export class Capability implements RequirementCapabilityModel { this.description = capability.description; this.validSourceTypes = capability.validSourceTypes; this.selected = capability.selected; + this.external = capability.external; this.initFilterTerm(); } diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts index 3cab4b300f..8d2357d6ad 100644 --- a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts @@ -25,7 +25,8 @@ import { ZoneInstanceAssignmentType, ZoneInstanceMode, ZoneInstanceType, - Requirement + Requirement, + Capability } from 'app/models'; import { ForwardingPath } from 'app/models/forwarding-path'; import { CompositionCiServicePathLink } from 'app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link'; @@ -649,6 +650,14 @@ export class CompositionGraphComponent implements AfterViewInit { .find(r => r.uniqueId === requirement.uniqueId).external = requirement.external; }); + this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_CAPABILITY_EXTERNAL_CHANGED, + (uniqueId: string, capability: Capability) => { + const graphCapability = this._cy.getElementById(uniqueId).data() + .componentInstance.capabilities[capability.type].find(cap => cap.uniqueId === capability.uniqueId); + graphCapability.external = capability.external; + } + ); + this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, (componentInstanceId: string) => { const nodeToDelete = this._cy.getElementById(componentInstanceId); this.nodesGraphUtils.deleteNode(this._cy, this.topologyTemplate, nodeToDelete); diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html index c73f69734f..ad25aabefd 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html @@ -5,6 +5,16 @@ <div *ngFor="let capability of capabilities" class="relations-details-container"> <div class="relations-name">{{capability.name}} </div> <div class="relations-desc"> {{capability.type}} </div> + <div class="checkbox-label-mark-as-external" *ngIf="isComponentInstanceSelected"> + <checkbox + class="checkbox-label" + [attr.data-tests-id]="'checkbox-external-cap-' + capability.name" + [label]="'External'" + (checkedChange)="onMarkCapabilityAsExternal(capability)" + [(checked)]="capability.external" + [disabled]="isViewOnly"> + </checkbox> + </div> </div> </sdc-accordion> </div> @@ -19,10 +29,20 @@ <ng-template #complexComponentTemplate> <sdc-accordion *ngIf="capabilitiesInstancesMap" [title]="'Capabilities'" [arrow-direction]="'right'" [testId]="'Capabilities-accordion'"> <sdc-accordion *ngFor="let key of objectKeys(capabilitiesInstancesMap); let i = index" [title]="key"> - <div *ngFor="let capability of capabilitiesInstancesMap[key]" class="relations-details-container"> - <div class="relations-name">{{capability.name}} </div> - <div class="relations-desc"> {{capability.type}} </div> - </div> + <div *ngFor="let capability of capabilitiesInstancesMap[key]" class="relations-details-container"> + <div class="relations-name">{{capability.name}} </div> + <div class="relations-desc"> {{capability.type}} </div> + <div class="checkbox-label-mark-as-external" *ngIf="isComponentInstanceSelected"> + <checkbox + class="checkbox-label" + [attr.data-tests-id]="'checkbox-external-cap-' + capability.name" + [label]="'External'" + (checkedChange)="onMarkCapabilityAsExternal(capability)" + [(checked)]="capability.external" + [disabled]="isViewOnly"> + </checkbox> + </div> + </div> </sdc-accordion> </sdc-accordion> diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts index 7c91cbc4b8..7bb88c7f59 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, Input, OnDestroy } from '@angular/core'; -import { Component as TopologyTemplate, Capability, Requirement, CapabilitiesGroup, RequirementsGroup, ComponentInstance, FullComponentInstance } from "app/models"; +import { Component as TopologyTemplate, Capability, Requirement, CapabilitiesGroup, RequirementsGroup, FullComponentInstance } from "app/models"; import { Store } from "@ngxs/store"; import { GRAPH_EVENTS } from "app/utils"; import { ComponentGenericResponse } from "app/ng2/services/responses/component-generic-response"; @@ -8,6 +8,7 @@ import { EventListenerService } from "app/services"; import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service"; import { CompositionService } from "app/ng2/pages/composition/composition.service"; import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions"; +import {ComponentInstanceServiceNg2} from "../../../../../services/component-instance-services/component-instance.service"; export class InstanceCapabilitiesMap { @@ -42,7 +43,8 @@ export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy { private topologyTemplateService:TopologyTemplateService, private workspaceService: WorkspaceService, private compositionService: CompositionService, - private eventListenerService:EventListenerService) { } + private eventListenerService:EventListenerService, + private componentInstanceService: ComponentInstanceServiceNg2) { } ngOnInit(): void { @@ -112,13 +114,19 @@ export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy { private initInstancesMap = ():void => { this.capabilitiesInstancesMap = new InstanceCapabilitiesMap(); - _.forEach(this.capabilities, (capability:Capability) => { - if (this.capabilitiesInstancesMap[capability.ownerName]) { - this.capabilitiesInstancesMap[capability.ownerName] = this.capabilitiesInstancesMap[capability.ownerName].concat(capability); - } else { - this.capabilitiesInstancesMap[capability.ownerName] = new Array<Capability>(capability); + let capabilityList: Array<Capability> = this.capabilities; + if (capabilityList) { + if (!this.isComponentInstanceSelected) { + capabilityList = capabilityList.filter(value => value.external); } - }); + capabilityList.forEach(capability => { + if (this.capabilitiesInstancesMap[capability.ownerName]) { + this.capabilitiesInstancesMap[capability.ownerName] = this.capabilitiesInstancesMap[capability.ownerName].concat(capability); + } else { + this.capabilitiesInstancesMap[capability.ownerName] = new Array<Capability>(capability); + } + }); + } this.requirementsInstancesMap = new InstanceRequirementsMap(); _.forEach(this.requirements, (requirement:Requirement) => { @@ -161,7 +169,21 @@ export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy { } - - + onMarkCapabilityAsExternal(capability: Capability) { + this.store.dispatch(new TogglePanelLoadingAction({isLoading: true})); + capability.external = !capability.external; + const componentId = this.workspaceService.metadata.uniqueId; + const componentInstanceId = this.component.uniqueId; + this.componentInstanceService + .updateInstanceCapability(this.workspaceService.metadata.getTypeUrl(), componentId, componentInstanceId, capability) + .subscribe(() => { + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_CAPABILITY_EXTERNAL_CHANGED, componentInstanceId, capability); + this.store.dispatch(new TogglePanelLoadingAction({isLoading: false})); + } , (error) => { + console.error("An error has occurred while setting capability '" + capability.name + "' external", error); + capability.external = !capability.external; + this.store.dispatch(new TogglePanelLoadingAction({isLoading: false})); + }); + } } diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html index ebaed0441a..ee8277971b 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html @@ -17,7 +17,7 @@ *ngIf="isInstanceSelected"> <checkbox class="checkbox-label" - [attr.data-tests-id]="'checkbox-mark-as-external-' + requirement.name" + [attr.data-tests-id]="'checkbox-external-req-' + requirement.name" [label]="'External'" (checkedChange)="onMarkAsExternal(requirement)" [(checked)]="requirement.external" diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.spec.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.spec.ts new file mode 100644 index 0000000000..4de556cdd5 --- /dev/null +++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.spec.ts @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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 {TestBed} from '@angular/core/testing'; +import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config"; +import {ComponentInstanceServiceNg2} from "./component-instance.service"; +import {Capability} from "../../../models/capability"; +import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing"; + +describe('ComponentInstanceServiceNg2', () => { + let httpTestingController: HttpTestingController; + let componentInstanceService: ComponentInstanceServiceNg2; + let rootApi: string = 'http://localhost/' + let componentApiRoot: string = 'catalog/' + beforeEach(() => { + const sdcConfigToken: Partial<ISdcConfig> = { + 'api': { + 'root': rootApi, + 'component_api_root': componentApiRoot, + } + }; + TestBed.configureTestingModule({ + providers: [ComponentInstanceServiceNg2, + {provide: SdcConfigToken, useValue: sdcConfigToken} + ], + imports: [HttpClientTestingModule] + }); + httpTestingController = TestBed.get(HttpTestingController); + componentInstanceService = TestBed.get(ComponentInstanceServiceNg2); + }); + + it('should be created', () => { + expect(componentInstanceService).toBeTruthy(); + }); + + it('updateInstanceCapability call should return the expected data', () => { + const capabilityToUpdate = new Capability(); + capabilityToUpdate.type = "tosca.capabilities.Scalable"; + capabilityToUpdate.name = "capScalable"; + capabilityToUpdate.ownerId = "191f8a83-d362-4db4-af30-75d71a55c959.a822dd1c-3560-47ea-b8a2-f557fed5e186.vfcapreq10"; + capabilityToUpdate.uniqueId = "2047eb3c-de31-4413-a358-8710a3dd2670"; + capabilityToUpdate.external = true; + + const componentTypeUrl = "services/"; + let actualCapability: Capability; + componentInstanceService.updateInstanceCapability(componentTypeUrl, "componentId", "componentInstanceId", capabilityToUpdate) + .subscribe(capability => { + actualCapability = capability; + }); + + const request = + httpTestingController.expectOne(`${rootApi}${componentApiRoot}${componentTypeUrl}componentId/componentInstances/componentInstanceId/capability/`); + + expect(request.request.method).toEqual('PUT'); + + request.flush(capabilityToUpdate); + expect(actualCapability.name).toEqual(capabilityToUpdate.name); + expect(actualCapability.type).toEqual(capabilityToUpdate.type); + expect(actualCapability.ownerId).toEqual(capabilityToUpdate.ownerId); + expect(actualCapability.uniqueId).toEqual(capabilityToUpdate.uniqueId); + expect(actualCapability.external).toEqual(capabilityToUpdate.external); + }); + +}); diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts index 5ae2918805..1e4ddda9c0 100644 --- a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts +++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts @@ -18,15 +18,25 @@ * ============LICENSE_END========================================================= */ -import {Injectable, Inject} from '@angular/core'; -import { Observable } from 'rxjs/Observable'; -import {PropertyFEModel, PropertyBEModel, Requirement} from "app/models"; -import {CommonUtils, ComponentType, ServerTypeUrl, ComponentInstanceFactory} from "app/utils"; -import {Component, ComponentInstance, Capability, PropertyModel, ArtifactGroupModel, ArtifactModel, AttributeModel, IFileDownload} from "app/models"; -import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { InputBEModel } from '../../../models/properties-inputs/input-be-model'; -import { HttpHelperService } from '../http-hepler.service'; +import {Inject, Injectable} from '@angular/core'; +import {Observable} from 'rxjs/Observable'; +import { + ArtifactGroupModel, + ArtifactModel, + AttributeModel, + Capability, + Component, + ComponentInstance, + IFileDownload, + PropertyBEModel, + PropertyModel, + Requirement +} from "app/models"; +import {CommonUtils, ComponentInstanceFactory, ComponentType, ServerTypeUrl} from "app/utils"; +import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config"; +import {HttpClient, HttpHeaders} from '@angular/common/http'; +import {InputBEModel} from '../../../models/properties-inputs/input-be-model'; +import {HttpHelperService} from '../http-hepler.service'; import {AttributeBEModel} from "../../../models/attributes-outputs/attribute-be-model"; import {OutputBEModel} from "../../../models/attributes-outputs/output-be-model"; @@ -158,6 +168,11 @@ export class ComponentInstanceServiceNg2 { '/requirementName/' + requirement.name, requirement); } + updateInstanceCapability(componentTypeUrl: string, componentId: string, componentInstanceId: string, capability: Capability): Observable<Capability> { + const url = `${this.baseUrl}${componentTypeUrl}${componentId}/componentInstances/${componentInstanceId}/capability/`; + return this.http.put<Capability>(url, capability); + } + updateInstanceInputs(component: Component, componentInstanceId: string, inputs: PropertyBEModel[]): Observable<PropertyBEModel[]> { return this.http.post<Array<PropertyModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/inputs', inputs) @@ -203,7 +218,6 @@ export class ComponentInstanceServiceNg2 { } addInstanceArtifact = (componentType:string, componentId:string, instanceId:string, artifact:ArtifactModel):Observable<ArtifactModel> => { - // let deferred = this.$q.defer<ArtifactModel>(); let headerObj = new HttpHeaders(); if (artifact.payloadData) { headerObj = headerObj.set('Content-MD5', HttpHelperService.getHeaderMd5(artifact)); @@ -217,7 +231,7 @@ export class ComponentInstanceServiceNg2 { updateInstanceArtifact = (componentType:string, componentId:string, instanceId:string, artifact:ArtifactModel):Observable<ArtifactModel> => { return this.http.post<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + instanceId + '/artifacts/' + artifact.uniqueId, artifact).map((res) => { return new ArtifactModel(res); - });; + }); }; deleteInstanceArtifact = (componentId:string, componentType:string, instanceId:string, artifactId:string, artifactLabel:string):Observable<ArtifactModel> => { diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts index 3e86ec9e96..f7cbf8d7b0 100644 --- a/catalog-ui/src/app/utils/constants.ts +++ b/catalog-ui/src/app/utils/constants.ts @@ -349,6 +349,7 @@ export class GRAPH_EVENTS { static ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL = 'onPaletteComponentHidePopupPanel'; static ON_COMPONENT_INSTANCE_NAME_CHANGED = 'onComponentInstanceNameChanged'; static ON_COMPONENT_INSTANCE_REQUIREMENT_EXTERNAL_CHANGED = 'onComponentInstanceRequirementExternalChanged' + static ON_COMPONENT_INSTANCE_CAPABILITY_EXTERNAL_CHANGED = 'onComponentInstanceCapabilityExternalChanged' static ON_ZONE_INSTANCE_NAME_CHANGED = 'onZoneInstanceNameChanged'; static ON_DELETE_COMPONENT_INSTANCE = 'onDeleteComponentInstance'; static ON_DELETE_ZONE_INSTANCE = 'onDeleteZoneInstance'; |