aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs')
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap50
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts303
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html119
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less169
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts204
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html)6
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts127
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts158
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html)4
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts)30
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html47
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts39
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less13
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts133
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html39
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts64
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html27
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts67
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts71
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap66
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html174
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less51
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts98
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts189
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts55
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less65
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html50
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts39
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less0
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html28
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts72
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts68
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less12
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html)6
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less)49
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts113
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts)105
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html97
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less66
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts212
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html36
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less57
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts165
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html20
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts40
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html15
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.less (renamed from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less)0
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts89
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html18
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less3
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts95
51 files changed, 2956 insertions, 867 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap
new file mode 100644
index 0000000000..c143e8106b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap
@@ -0,0 +1,50 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact-tab component should match current snapshot of artifact-tab component 1`] = `
+<artifacts-tab
+ addOrUpdate={[Function Function]}
+ allowDeleteAndUpdateArtifact={[Function Function]}
+ artifactService={[Function Object]}
+ componentInstanceService="undefined"
+ compositionService={[Function Object]}
+ delete={[Function Function]}
+ getEnvArtifact={[Function Function]}
+ getTitle={[Function Function]}
+ heatToEnv={[Function Map]}
+ isLicenseArtifact={[Function Function]}
+ loadArtifacts={[Function Function]}
+ store={[Function Store]}
+ topologyTemplateService="undefined"
+ updateEnvParams={[Function Function]}
+ viewEnvParams={[Function Function]}
+ workspaceService="undefined"
+>
+ <div
+ class="w-sdc-designer-sidebar-tab-content artifacts"
+ >
+ <div
+ class="w-sdc-designer-sidebar-section"
+ >
+ <ng2-expand-collapse
+ state="0"
+ >
+ <header
+ sdc-tooltip=""
+ >
+
+ </header>
+ <content
+ class="artifacts-container"
+ >
+ <div
+ class="w-sdc-designer-sidebar-section-content"
+ >
+
+ </div>
+
+ </content>
+ </ng2-expand-collapse>
+ </div>
+ </div>
+</artifacts-tab>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts
new file mode 100644
index 0000000000..258f2295ab
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts
@@ -0,0 +1,303 @@
+import { async, ComponentFixture } from '@angular/core/testing';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { NgxsModule, Store } from '@ngxs/store';
+import { WorkspaceState } from '../../../../../store/states/workspace.state';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ArtifactsTabComponent } from './artifacts-tab.component';
+import { CompositionService } from '../../../composition.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { ComponentInstanceServiceNg2 } from '../../../../../services/component-instance-services/component-instance.service';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ArtifactsService } from '../../../../../components/forms/artifacts-form/artifacts.service';
+import { ArtifactModel } from '../../../../../../models/artifacts';
+import { ArtifactType } from '../../../../../../utils/constants';
+import { FullComponentInstance } from '../../../../../../models/componentsInstances/fullComponentInstance';
+import { ComponentInstance } from '../../../../../../models/componentsInstances/componentInstance';
+import { Component } from '../../../../../../models/components/component';
+import { GetInstanceArtifactsByTypeAction } from '../../../../../store/actions/instance-artifacts.actions';
+import { Observable } from 'rxjs';
+
+
+describe('artifact-tab component', () => {
+
+ let fixture: ComponentFixture<ArtifactsTabComponent>;
+ let compositionMockService: Partial<CompositionService>;
+ const workspaceMockService: Partial<WorkspaceService>;
+ const componentInstanceMockService: Partial<ComponentInstanceServiceNg2>;
+ const topologyTemplateMockService: Partial<TopologyTemplateService>;
+ let artifactsServiceMockService: Partial<ArtifactsService>;
+ let store: Store;
+
+ beforeEach(
+ async(() => {
+ compositionMockService = {
+ updateInstance: jest.fn()
+ }
+
+ artifactsServiceMockService = {
+ deleteArtifact: jest.fn(),
+ openUpdateEnvParams: jest.fn(),
+ openArtifactModal: jest.fn()
+ }
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [ArtifactsTabComponent],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: CompositionService, useValue: compositionMockService},
+ {provide: WorkspaceService, useValue: workspaceMockService},
+ {provide: ComponentInstanceServiceNg2, useValue: componentInstanceMockService},
+ {provide: TopologyTemplateService, useValue: topologyTemplateMockService},
+ {provide: ArtifactsService, useValue: artifactsServiceMockService}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(ArtifactsTabComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it ('on delete -> deleteArtifact is being called from artifactService', () => {
+ const artifact = new ArtifactModel();
+ const topologyTemplateType: string = undefined;
+ const topologyTemplateId: string = undefined;
+
+ fixture.componentInstance.delete(artifact);
+ expect(artifactsServiceMockService.deleteArtifact).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, artifact);
+ });
+
+ it('should match current snapshot of artifact-tab component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+
+ it ('should get API Artifacts as Title', () => {
+ const artifactType = ArtifactType.SERVICE_API;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('API Artifacts');
+ });
+
+
+ it ('should get Deployment Artifacts as Title', () => {
+ const artifactType = ArtifactType.DEPLOYMENT;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('Deployment Artifacts');
+ });
+
+ it ('should get Informational Artifacts as Title', () => {
+ const artifactType = ArtifactType.INFORMATION;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('Informational Artifacts');
+ });
+
+ it ('should get SomeString as Title - This is the default case (return the last val)', () => {
+ // So the last value will be "SomeString"
+ fixture.componentInstance.getTitle('SomeString');
+
+ const res = fixture.componentInstance.getTitle('SomeString');
+ expect(res).toBe('SomeString Artifacts');
+ });
+
+
+ it ('should return isLicenseArtifact false', () => {
+ const artifact = new ArtifactModel();
+ const componentInstance = new ComponentInstance();
+ const component = new Component();
+ fixture.componentInstance.component = new FullComponentInstance(componentInstance, component);
+
+ let res = fixture.componentInstance.isLicenseArtifact(artifact);
+ expect(res).toBe(false);
+ });
+
+ it ('should return isLicenseArtifact true', () => {
+ const artifact = new ArtifactModel();
+ const componentInstance = new ComponentInstance();
+ const component = new Component();
+ fixture.componentInstance.component = new FullComponentInstance(componentInstance, component);
+ fixture.componentInstance.component.isResource = jest.fn(() => true);
+ fixture.componentInstance.component.isCsarComponent = true;
+
+ artifact.artifactType = ArtifactType.VENDOR_LICENSE;
+ const res = fixture.componentInstance.isLicenseArtifact(artifact);
+ expect(res).toBe(true);
+ });
+
+ it ('should verify getEnvArtifact with match', () => {
+ const artifact = new ArtifactModel();
+ artifact.uniqueId = 'matchUniqueID';
+
+ const testItem1 = new ArtifactModel();
+ testItem1.generatedFromId = 'matchUniqueID';
+
+ const testItem2 = new ArtifactModel();
+ testItem2.generatedFromId = '123456';
+
+ const artifacts: ArtifactModel[] = [testItem1, testItem2];
+
+ const res = fixture.componentInstance.getEnvArtifact(artifact, artifacts);
+ expect(res.generatedFromId).toBe('matchUniqueID');
+ });
+
+ it ('should verify getEnvArtifact with no match', () => {
+ const artifact = new ArtifactModel();
+ artifact.uniqueId = 'matchUniqueID';
+
+ const testItem1 = new ArtifactModel();
+ testItem1.generatedFromId = '654321';
+
+ const testItem2 = new ArtifactModel();
+ testItem2.generatedFromId = '123456';
+
+ const artifacts: ArtifactModel[] = [testItem1, testItem2];
+
+ const res = fixture.componentInstance.getEnvArtifact(artifact, artifacts);
+ expect(res).toBe(undefined);
+ });
+
+ it ('on updateEnvParams -> openUpdateEnvParams is being called from artifactService when isComponentInstanceSelected = true', () => {
+ const artifact = new ArtifactModel();
+ artifact.envArtifact = new ArtifactModel();
+
+ const topologyTemplateType: string = undefined;
+ const topologyTemplateId: string = undefined;
+
+ const component = new Component();
+ component.uniqueId = 'id';
+
+ const isComponentInstanceSelected = true;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.updateEnvParams(artifact);
+
+ expect(artifactsServiceMockService.openUpdateEnvParams).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, undefined, component.uniqueId);
+ });
+
+ it ('on updateEnvParams -> openUpdateEnvParams is being called from artifactService when isComponentInstanceSelected = false', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = undefined
+ const topologyTemplateId: string = undefined;
+
+ const component = new Component();
+
+ const isComponentInstanceSelected = false;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.updateEnvParams(artifact);
+
+ expect(artifactsServiceMockService.openUpdateEnvParams).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, artifact);
+ });
+
+ it ('on addOrUpdate -> openArtifactModal is being called from artifactService when isComponentInstanceSelected = true', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = 'testType';
+ const topologyTemplateId: string = 'testID';
+ const type: string = 'testType';
+ const isViewOnly: boolean = false;
+
+ const component = new Component();
+ component.uniqueId = 'id';
+
+ const isComponentInstanceSelected = true;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.type = type;
+ fixture.componentInstance.topologyTemplateId = topologyTemplateId;
+ fixture.componentInstance.topologyTemplateType = topologyTemplateType;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.isViewOnly = isViewOnly;
+ fixture.componentInstance.addOrUpdate(artifact);
+
+
+ expect(artifactsServiceMockService.openArtifactModal).toHaveBeenCalledWith(topologyTemplateId, topologyTemplateType, artifact, type, isViewOnly, component.uniqueId);
+ });
+
+ it ('on addOrUpdate -> openArtifactModal is being called from artifactService when isComponentInstanceSelected = false', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = 'testType';
+ const topologyTemplateId: string = 'testID';
+ const type: string = 'testType';
+ const isViewOnly: boolean = false;
+
+ const isComponentInstanceSelected = false;
+
+ fixture.componentInstance.type = type;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.topologyTemplateId = topologyTemplateId;
+ fixture.componentInstance.topologyTemplateType = topologyTemplateType;
+ fixture.componentInstance.isViewOnly = isViewOnly;
+ fixture.componentInstance.addOrUpdate(artifact);
+
+ expect(artifactsServiceMockService.openArtifactModal).toHaveBeenCalledWith(topologyTemplateId, topologyTemplateType, artifact, type, isViewOnly);
+ });
+
+
+ it ('verify allowDeleteAndUpdateArtifact return false since isViewOnly=true', () => {
+ const artifact = new ArtifactModel();
+ fixture.componentInstance.isViewOnly = true;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(false)
+ });
+
+ it ('verify allowDeleteAndUpdateArtifact return artifact.isFromCsar since isViewOnly=false && artifactGroupType = DEPLOYMENT', () => {
+ const artifact = new ArtifactModel();
+ artifact.artifactGroupType = ArtifactType.DEPLOYMENT;
+ artifact.isFromCsar = false;
+
+ fixture.componentInstance.isViewOnly = false;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(!artifact.isFromCsar);
+ });
+
+ it ('verify allowDeleteAndUpdateArtifact return !artifact.isHEAT() && !artifact.isThirdParty() &&' +
+ ' !this.isLicenseArtifact(artifact) since isViewOnly=false && artifactGroupType != DEPLOYMENT', () => {
+ const artifact = new ArtifactModel();
+ artifact.artifactGroupType = 'NOT_DEPLOYMENT';
+ artifact.isHEAT = () => false;
+ artifact.isThirdParty = () => false;
+
+ fixture.componentInstance.isLicenseArtifact = jest.fn(() => false);
+
+ fixture.componentInstance.isViewOnly = false;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(true )
+ });
+
+ it('verify action on loadArtifacts in case isComponentInstanceSelected = true', () => {
+ fixture.componentInstance.isComponentInstanceSelected = true;
+ fixture.componentInstance.topologyTemplateType = 'topologyTemplateType';
+ fixture.componentInstance.topologyTemplateId = 'topologyTemplateId';
+ const component = new Component();
+ component.uniqueId = 'uniqueId';
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.type = 'type';
+
+ const action = new GetInstanceArtifactsByTypeAction(({
+ componentType: 'topologyTemplateType',
+ componentId: 'topologyTemplateId',
+ instanceId: 'uniqueId',
+ artifactType: 'type'
+ }))
+
+ fixture.componentInstance.store.dispatch = jest.fn(() => Observable.of(true));
+ fixture.componentInstance.loadArtifacts();
+
+ expect(store.dispatch).toBeCalledWith(action);
+
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html
new file mode 100644
index 0000000000..264444b674
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html
@@ -0,0 +1,119 @@
+<div class="w-sdc-designer-sidebar-tab-content artifacts">
+ <div class="w-sdc-designer-sidebar-section">
+ <ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{title}}">{{title}}</header>
+ <content class="artifacts-container">
+ <div class="w-sdc-designer-sidebar-section-content">
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngFor="let artifact of artifacts$ | async">
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact"
+ *ngIf="(!isComponentInstanceSelected || artifact.esId) && 'HEAT_ENV' !== artifact.artifactType"
+ attr.data-tests-id="'artifact-item-' + artifact.artifactDisplayName">
+ <span *ngIf="artifact.heatParameters?.length"
+ class="i-sdc-designer-sidebar-section-content-item-file-link"></span>
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-details"
+ [class.heat]="artifact.isHEAT() && artifact.heatParameters?.length">
+ <div *ngIf="artifact.artifactName"
+ class="i-sdc-designer-sidebar-section-content-item-artifact-filename"
+ attr.data-tests-id="artifactName-{{artifact.artifactDisplayName}}"
+ sdc-tooltip tooltip-text="{{artifact.artifactName}}">{{artifact.artifactName}}
+ </div>
+ <div class="artifact-buttons-container upper-buttons">
+
+
+ <svg-icon
+ *ngIf="!isViewOnly && !artifact.isFromCsar && artifact.artifactName"
+ name="trash-o" clickable="true" size="medium" mode="info"
+ class="artifact-button" testId="delete_{{artifact.artifactDisplayName}}"
+ (click)="delete(artifact)"></svg-icon>
+
+ <!--Display env parameters edit button for Instance -->
+ <svg-icon
+ *ngIf="!isViewOnly && artifact.isHEAT() && isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="indesign_status" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="edit-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="updateEnvParams(artifact)"
+ tooltip="Edit ENV Params"
+ ></svg-icon>
+
+ <!--Display env parameters VIEW button for Instance -->
+ <svg-icon
+ *ngIf="isViewOnly && artifact.isHEAT() && isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="inputs-o" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="view-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="viewEnvParams(artifact)"
+ tooltip="View ENV Params"
+ ></svg-icon>
+
+ <!--Display env parameters edit button for VF -->
+ <svg-icon
+ *ngIf = "!isViewOnly && !isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="indesign_status" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="edit-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="updateEnvParams(artifact)"></svg-icon>
+
+
+ <download-artifact *ngIf="artifact.esId && 'deployment' != type"
+ class="artifact-button"
+ [artifact]="artifact" [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ testId="download_{{artifact.artifactDisplayName}}"
+ [isInstance]="isComponentInstanceSelected"></download-artifact>
+ <download-artifact *ngIf="artifact.esId && 'deployment' == type"
+ class="artifact-button"
+ [artifact]="artifact" [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ [isInstance]="isComponentInstanceSelected"
+ testId="download_{{artifact.artifactDisplayName}}"
+ [showLoader]="artifact.isHEAT()"></download-artifact>
+
+ <button *ngIf="!isViewOnly && !artifact.esId && type==='deployment' && !isComponentInstanceSelected && !artifact.isThirdParty()"
+ class="artifact-button attach sprite e-sdc-small-icon-upload"
+ (click)="addOrUpdate(artifact)" type="button"
+ attr.data-tests-id="add_Artifact"></button>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-name"
+ attr.data-tests-id="artifact_Display_Name-{{artifact.artifactDisplayName}}"
+ [ngClass]="{'hand enabled': artifact.allowDeleteAndUpdate}"
+ (click)="artifact.allowDeleteAndUpdate && addOrUpdate(artifact)"
+ sdc-tooltip tooltip-text="{{artifact.artifactDisplayName}}">{{artifact.artifactDisplayName}}</span>
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-heat-env"
+ *ngIf="artifact.heatParameters?.length">
+ <span attr.data-tests-id="heat_env_{{artifact.artifactDisplayName}}">{{artifact.artifactDisplayName}} (ENV)</span>
+ <div class="artifact-buttons-container">
+ <svg-icon *ngIf="!isViewOnly && envArtifactOf(artifact)"
+ name="edit-o" clickable="true" size="medium"
+ mode="info" class="artifact-button edit-pencil"
+ testId="edit_{{artifact.artifactDisplayName}}"
+ (click)="addOrUpdate(envArtifactOf(artifact))"></svg-icon>
+
+ <download-artifact [artifact]="envArtifactOf(artifact)"
+ class="artifact-button"
+ [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ [isInstance]="isComponentInstanceSelected"
+ testId="download_env_{{artifact.artifactDisplayName}}"></download-artifact>
+ </div>
+ </div>
+ </div>
+
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc">
+ <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label"
+ *ngIf="artifact.description">Description:</span>{{artifact.description}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="w-sdc-designer-sidebar-section-footer"
+ *ngIf="!isViewOnly && type!=='api' && (!isComponentInstanceSelected || isVfOrPnf() && (type !== 'deployment') || isComplex)">
+ <sdc-button testId="add_Artifact_Button" size="large" type="primary" text="Add Artifact"
+ (click)="addOrUpdate({})"></sdc-button>
+ </div>
+ </content>
+ </ng2-expand-collapse>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less
new file mode 100644
index 0000000000..fef199dd97
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less
@@ -0,0 +1,169 @@
+@import '../../../../../../../assets/styles/override';
+
+
+.artifacts /deep/ .expand-collapse-content {
+ padding: 10px 0px;
+
+ &.collapsed {
+ padding: 0 0;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-artifact {
+
+ &:not(:hover) .artifact-button {
+ display:none;
+ }
+ .artifact-buttons-container {
+ display: inline-flex;
+ flex-direction: row-reverse;
+ position: absolute;
+ right:0;
+
+ &.upper-buttons {
+ margin-top: 8px;
+ }
+
+ .artifact-button {
+ cursor:pointer;
+ padding-right:5px;
+
+ &.edit-pencil {
+ margin-top: 10px;
+ }
+ }
+ }
+}
+
+.w-sdc-designer-sidebar-section-footer {
+ padding: 20px;
+ display: flex;
+ justify-content: center;
+
+}
+
+
+.w-sdc-designer-sidebar-tab-content.artifacts {
+
+ .i-sdc-designer-sidebar-section-content-item-artifact.hand {
+ cursor: pointer;
+ }
+
+ .w-sdc-designer-sidebar-section-content {
+ padding: 0;
+ }
+ .w-sdc-designer-sidebar-section-title {
+ &.expanded {
+ margin-bottom: 0;
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details {
+ display: inline-block;
+ margin-left: 5px;
+ vertical-align: middle;
+ width: 180px;
+ &.heat {
+ line-height: 18px;
+ width: 250px;
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-name {
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width:220px;
+ display: inline-block;
+ //text-transform: capitalize;
+ &.enabled {
+ &:hover {
+ color: @sdcui_color_dark-blue;
+ }
+ }
+
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-heat-env {
+ color: @sdcui_color_dark-gray;
+ margin-top: 6px;
+ line-height: 42px;
+ padding-top: 10px;
+ border-top:1px solid #c8cdd1;
+ .enabled {
+ &:hover {
+ cursor: pointer;
+ color: @sdcui_color_dark-blue;
+ }
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-filename {
+ color: @sdcui_color_dark-gray;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width: 225px;
+ display: inline-block;
+ font-weight: bold;
+ &.enabled {
+ &:hover {
+ color: @sdcui_color_dark-blue;
+ }
+ }
+ }
+
+
+ .i-sdc-designer-sidebar-section-content-item-file-link{
+ border-left: 1px #848586 solid;
+ height: 58px;
+ margin-left: -11px;
+ margin-top: 11px;
+ border-top: 1px #848586 solid;
+ border-bottom: 1px #848586 solid;
+ width: 12px;
+ float: left;
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-desc {
+ display: none;
+ line-height: 16px;
+ word-wrap: break-word;
+ white-space: normal;
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label {
+ color: @sdcui_color_dark-gray;
+ }
+
+
+ .i-sdc-designer-sidebar-section-content-item-artifact {
+ border-bottom: 1px solid #c8cdd1;
+ padding: 5px 10px 5px 18px;
+ position: relative;
+ // line-height: 36px;
+ min-height: 61px;
+ //cursor: default;
+ display: flex;
+ align-items: center;
+
+
+ .i-sdc-designer-sidebar-section-content-item-button {
+ top: 20px;
+ line-height: 10px;
+ }
+
+ &:hover {
+ //background-color: @color_c;
+ background-color: white;
+ transition: all .3s;
+
+ .i-sdc-designer-sidebar-section-content-item-button {
+ display: block;
+
+ }
+
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts
new file mode 100644
index 0000000000..53a6c267e2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts
@@ -0,0 +1,204 @@
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import { ArtifactModel, Component as TopologyTemplate, FullComponentInstance, Resource } from 'app/models';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
+import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ArtifactType } from 'app/utils';
+import * as _ from 'lodash';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Observable';
+import { map } from 'rxjs/operators';
+import { ArtifactsService } from '../../../../../components/forms/artifacts-form/artifacts.service';
+import { GetArtifactsByTypeAction } from '../../../../../store/actions/artifacts.action';
+import { GetInstanceArtifactsByTypeAction } from '../../../../../store/actions/instance-artifacts.actions';
+import { ArtifactsState } from '../../../../../store/states/artifacts.state';
+import { InstanceArtifactsState } from '../../../../../store/states/instance-artifacts.state';
+import { SelectedComponentType, TogglePanelLoadingAction } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'artifacts-tab',
+ styleUrls: ['./artifacts-tab.component.less'],
+ templateUrl: './artifacts-tab.component.html',
+ providers: [SdcUiServices.ModalService]
+})
+
+export class ArtifactsTabComponent {
+
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() isViewOnly: boolean;
+ @Input() input: any;
+ @Input() componentType: SelectedComponentType;
+
+ public title: string;
+ public type: string;
+ public isComponentInstanceSelected: boolean;
+ public artifacts$: Observable<ArtifactModel[]>;
+ private topologyTemplateType: string;
+ private topologyTemplateId: string;
+ private heatToEnv: Map<string, ArtifactModel>;
+ private resourceType: string;
+ private isComplex: boolean;
+
+ constructor(private store: Store,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
+ private topologyTemplateService: TopologyTemplateService,
+ private artifactService: ArtifactsService) {
+ this.heatToEnv = new Map();
+ }
+
+ ngOnInit() {
+ this.topologyTemplateType = this.workspaceService.metadata.componentType;
+ this.topologyTemplateId = this.workspaceService.metadata.uniqueId;
+ this.type = this.input.type;
+ this.title = this.getTitle(this.type);
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.resourceType = this.component['resourceType'];
+ this.isComplex = this.component.isComplex();
+ this.loadArtifacts();
+ }
+
+ public addOrUpdate = (artifact: ArtifactModel): void => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openArtifactModal(this.topologyTemplateId, this.topologyTemplateType, artifact, this.type, this.isViewOnly, this.component.uniqueId);
+ } else {
+ this.artifactService.openArtifactModal(this.topologyTemplateId, this.topologyTemplateType, artifact, this.type, this.isViewOnly);
+ }
+ }
+
+ public updateEnvParams = (artifact: ArtifactModel) => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openUpdateEnvParams(this.topologyTemplateType, this.topologyTemplateId, this.heatToEnv.get(artifact.uniqueId), this.component.uniqueId);
+ } else {
+ this.artifactService.openUpdateEnvParams(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public viewEnvParams = (artifact: ArtifactModel) => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openViewEnvParams(this.topologyTemplateType, this.topologyTemplateId, this.heatToEnv.get(artifact.uniqueId), this.component.uniqueId);
+ } else {
+ this.artifactService.openViewEnvParams(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public getEnvArtifact = (heatArtifact: ArtifactModel, artifacts: ArtifactModel[]): ArtifactModel => {
+ const envArtifact = _.find(artifacts, (item: ArtifactModel) => {
+ return item.generatedFromId === heatArtifact.uniqueId;
+ });
+ if (envArtifact && heatArtifact) {
+ envArtifact.artifactDisplayName = heatArtifact.artifactDisplayName;
+ envArtifact.timeout = heatArtifact.timeout;
+ }
+ return envArtifact;
+ }
+
+ public delete = (artifact: ArtifactModel): void => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.deleteArtifact(this.topologyTemplateType, this.topologyTemplateId, artifact, this.component.uniqueId);
+ } else {
+ this.artifactService.deleteArtifact(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public isVfOrPnf(): boolean {
+ if (this.component.isResource()){
+ if (this.resourceType) {
+ return this.resourceType === 'VF' || this.resourceType == 'PNF';
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ private envArtifactOf(artifact: ArtifactModel): ArtifactModel {
+ return this.heatToEnv.get(artifact.uniqueId);
+ }
+
+ private isLicenseArtifact = (artifact: ArtifactModel): boolean => {
+ let isLicense: boolean = false;
+ if (this.component.isResource && (this.component as Resource).isCsarComponent) {
+ if (ArtifactType.VENDOR_LICENSE === artifact.artifactType || ArtifactType.VF_LICENSE === artifact.artifactType) {
+ isLicense = true;
+ }
+ }
+
+ return isLicense;
+ }
+
+ private getTitle = (artifactType: string): string => {
+ switch (artifactType) {
+ case ArtifactType.SERVICE_API:
+ return 'API Artifacts';
+ case ArtifactType.DEPLOYMENT:
+ return 'Deployment Artifacts';
+ case ArtifactType.INFORMATION:
+ return 'Informational Artifacts';
+ default:
+ return ResourceNamePipe.getDisplayName(artifactType) + ' Artifacts';
+ }
+ }
+
+ private loadArtifacts = (forceLoad?: boolean): void => {
+
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ let action;
+ if (this.isComponentInstanceSelected) {
+ action = new GetInstanceArtifactsByTypeAction(({
+ componentType: this.topologyTemplateType,
+ componentId: this.topologyTemplateId,
+ instanceId: this.component.uniqueId,
+ artifactType: this.type
+ }));
+ } else {
+ action = new GetArtifactsByTypeAction({
+ componentType: this.topologyTemplateType,
+ componentId: this.topologyTemplateId,
+ artifactType: this.type
+ });
+ }
+ this.store.dispatch(action).subscribe(() => {
+ const stateSelector = this.isComponentInstanceSelected ? InstanceArtifactsState.getArtifactsByType : ArtifactsState.getArtifactsByType;
+ this.artifacts$ = this.store.select(stateSelector).pipe(map((filterFn) => filterFn(this.type))).pipe(map((artifacts) => {
+ _.forEach(artifacts, (artifact: ArtifactModel): void => {
+ const envArtifact = this.getEnvArtifact(artifact, artifacts); // Extract the env artifact (if exist) of the HEAT artifact
+ if (envArtifact) {
+ // Set a mapping between HEAT to HEAT_ENV
+ this.heatToEnv.set(artifact.uniqueId, envArtifact);
+ }
+ });
+ return _.orderBy(artifacts, ['mandatory', 'artifactDisplayName'], ['desc', 'asc']);
+ }));
+
+ this.artifacts$.subscribe((artifacts) => {
+ _.forEach(artifacts, (artifact: ArtifactModel) => {
+ artifact.allowDeleteAndUpdate = this.allowDeleteAndUpdateArtifact(artifact);
+ });
+ if (this.component instanceof FullComponentInstance) {
+ this.compositionService.updateInstance(this.component);
+ }
+ });
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ }, () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ });
+ }
+
+ private allowDeleteAndUpdateArtifact = (artifact: ArtifactModel): boolean => {
+ if (!this.isViewOnly) {
+ if (artifact.artifactGroupType === ArtifactType.DEPLOYMENT) {
+ return !artifact.isFromCsar;
+ } else {
+
+ return (!artifact.isHEAT() && !artifact.isThirdParty() && !this.isLicenseArtifact(artifact));
+ }
+ }
+ return false;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html
index 6585ad2da9..8c5c9c7663 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<div class="w-sdc-designer-sidebar-section-title" tooltip="Members">Members
+<h1 class="w-sdc-designer-sidebar-section-title" tooltip="Members">Members
<svg-icon-label *ngIf="!isViewOnly"
class="add-members-btn"
name="plus-circle-o"
@@ -24,7 +24,7 @@
labelPlacement="right"
(click)="openAddMembersModal()">
</svg-icon-label>
-</div>
+</h1>
<div class="expand-collapse-content">
<ul>
<li *ngFor="let member of members; let i = index" class="component-details-panel-large-item"
@@ -40,7 +40,7 @@
</li>
</ul>
- <div *ngIf="members.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!members || members.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No data to display yet</div>
<div class="component-details-panel-tab-no-data-content">Add members to group to see members</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts
new file mode 100644
index 0000000000..43f6aac2c7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts
@@ -0,0 +1,127 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Rx';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { GroupInstance } from '../../../../../../models/graph/zones/group-instance';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { GroupsService } from '../../../../../services/groups.service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { CompositionService } from '../../../composition.service';
+import { GroupMembersTabComponent } from './group-members-tab.component';
+
+describe('group members tab component', () => {
+
+ let fixture: ComponentFixture<GroupMembersTabComponent>;
+
+ // Mocks
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let eventsListenerServiceMock: Partial<EventListenerService>;
+ let groupServiceMock: Partial<GroupsService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let compositionServiceMock: Partial<CompositionService>;
+ let modalServiceMock: Partial<SdcUiServices.ModalService>;
+
+ const membersToAdd = [
+ {uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ ];
+
+ beforeEach(
+ async(() => {
+
+ eventsListenerServiceMock = {};
+
+ groupServiceMock = Mock.of<GroupsService>(
+ {
+ updateMembers: jest.fn().mockImplementation((compType, uid, groupUniqueId, updatedMembers) => {
+ if (updatedMembers === undefined) {
+ return Observable.throwError('error');
+ } else {
+ return Observable.of(updatedMembers);
+ }
+ }
+ )});
+
+ compositionServiceMock = {
+ getComponentInstances: jest.fn().mockImplementation( () => {
+ return [{uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ {uniqueId: '3', name: 'inst3'},
+ {uniqueId: '4', name: 'inst4'},
+ {uniqueId: '5', name: 'inst5'}
+ ];
+ }
+ )
+ };
+
+ workspaceServiceMock = {
+ metadata: Mock.of<ComponentMetadata>()
+ };
+
+ const addMemberModalInstance = {
+ innerModalContent: { instance: { existingElements: membersToAdd }},
+ closeModal: jest.fn()
+ };
+
+ modalServiceMock = {
+ openInfoModal: jest.fn(),
+ openCustomModal: jest.fn().mockImplementation(() => addMemberModalInstance)
+ };
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const groupInstanceMock = Mock.of<GroupInstance>();
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [GroupMembersTabComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: { translate: jest.fn() }},
+ {provide: GroupsService, useValue: groupServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock },
+ {provide: EventListenerService, useValue: eventsListenerServiceMock },
+ {provide: CompositionService, useValue: compositionServiceMock },
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(GroupMembersTabComponent);
+ fixture.componentInstance.group = groupInstanceMock;
+ });
+ })
+ );
+
+ it('test that initially all members are available for adding', () => {
+ const testedComponent = fixture.componentInstance;
+
+ // No members are currently in the group, all 5 members should be returned
+ const optionalMembersToAdd = testedComponent.getOptionalsMembersToAdd();
+ expect(optionalMembersToAdd).toHaveLength(5);
+ });
+
+ it('test list of available instances to add does not include existing members', () => {
+ const testedComponent = fixture.componentInstance;
+
+ // Mock the group instance to return the members that we are about to add
+ testedComponent.group.getMembersAsUiObject = jest.fn().mockImplementation( () => membersToAdd);
+
+ // The opened modal shall return 2 members to be added
+ testedComponent.openAddMembersModal();
+ testedComponent.addMembers(); // Shall add 2 members (1,2)
+
+ // Now the getOptionalsMembersToAdd shall return 3 which are the members that were no added yet
+ const optionalMembersToAdd = testedComponent.getOptionalsMembersToAdd();
+ expect(optionalMembersToAdd).toHaveLength(3);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts
new file mode 100644
index 0000000000..7f1222367d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts
@@ -0,0 +1,158 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. 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 { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
+import { Select } from '@ngxs/store';
+import { GroupInstance } from 'app/models/graph/zones/group-instance';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { EventListenerService } from 'app/services/event-listener-service';
+import { GRAPH_EVENTS } from 'app/utils';
+import * as _ from 'lodash';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable, Subscription } from 'rxjs';
+import { tap } from 'rxjs/operators';
+import { ComponentInstance } from '../../../../../../models/componentsInstances/componentInstance';
+import { MemberUiObject } from '../../../../../../models/ui-models/ui-member-object';
+import { AddElementsComponent } from '../../../../../components/ui/modal/add-elements/add-elements.component';
+import {GraphState} from "../../../common/store/graph.state";
+import { GroupsService } from '../../../../../services/groups.service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+
+@Component({
+ selector: 'group-members-tab',
+ templateUrl: './group-members-tab.component.html',
+ styleUrls: ['./../policy-targets-tab/policy-targets-tab.component.less']
+})
+
+export class GroupMembersTabComponent implements OnInit, OnDestroy {
+
+ @Input() group: GroupInstance;
+ @Input() isViewOnly: boolean;
+ @Select(GraphState.getSelectedComponent) group$: Observable<GroupInstance>;
+ @HostBinding('class') classes = 'component-details-panel-tab-group-members';
+
+ private members: MemberUiObject[];
+ private addMemberModalInstance: SdcUiComponents.ModalComponent;
+ private subscription: Subscription;
+
+ constructor(
+ private translateService: TranslateService,
+ private groupsService: GroupsService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService
+ ) {
+ }
+
+ ngOnInit() {
+ this.subscription = this.group$.pipe(
+ tap((group) => {
+ this.group = group;
+ this.members = this.group.getMembersAsUiObject(this.compositionService.componentInstances);
+ })).subscribe();
+ }
+
+ ngOnDestroy() {
+ if (this.subscription) {
+ this.subscription.unsubscribe();
+ }
+ }
+
+ deleteMember = (member: MemberUiObject): void => {
+ this.loaderService.activate();
+ this.groupsService.deleteGroupMember(
+ this.workspaceService.metadata.componentType,
+ this.workspaceService.metadata.uniqueId,
+ this.group,
+ member.uniqueId).subscribe(
+ (updatedMembers: string[]) => {
+ this.group.members = updatedMembers;
+ this.initMembers();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
+ },
+ () => console.log('Error deleting member!'),
+ () => this.loaderService.deactivate()
+ );
+ }
+
+ addMembers = (): void => {
+ // TODO refactor sdc-ui modal in order to return the data
+ const membersToAdd: MemberUiObject[] = this.addMemberModalInstance.innerModalContent.instance.existingElements;
+ if (membersToAdd.length > 0) {
+ this.addMemberModalInstance.closeModal();
+ this.loaderService.activate();
+ const locallyUpdatedMembers: MemberUiObject[] = _.union(this.members, membersToAdd);
+ this.groupsService.updateMembers(
+ this.workspaceService.metadata.componentType,
+ this.workspaceService.metadata.uniqueId,
+ this.group.uniqueId,
+ locallyUpdatedMembers).subscribe(
+ (updatedMembers: string[]) => {
+ this.group.members = updatedMembers;
+ this.initMembers();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
+ },
+ () => {
+ console.log('Error updating members!');
+ }, () =>
+ this.loaderService.deactivate()
+ );
+ }
+ }
+
+ getOptionalsMembersToAdd(): MemberUiObject[] {
+ const optionalsMembersToAdd: MemberUiObject[] = [];
+ // adding all instances as optional members to add if not already exist
+ _.forEach(this.compositionService.getComponentInstances(), (instance: ComponentInstance) => {
+ if (!_.some(this.members, (member: MemberUiObject) => {
+ return member.uniqueId === instance.uniqueId;
+ })) {
+ optionalsMembersToAdd.push(new MemberUiObject(instance.uniqueId, instance.name));
+ }
+ });
+ return optionalsMembersToAdd;
+ }
+
+ openAddMembersModal(): void {
+ const addMembersModalConfig = {
+ title: this.group.name + ' ADD MEMBERS',
+ size: 'md',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'addMembersModal',
+ buttons: [
+ {text: 'ADD MEMBERS', size: 'medium', callback: this.addMembers, closeModal: false},
+ {text: 'CANCEL', size: 'sm', type: 'secondary', closeModal: true}
+ ]
+ } as SdcUiCommon.IModalConfig;
+ const optionalsMembersToAdd = this.getOptionalsMembersToAdd();
+ this.addMemberModalInstance = this.modalService.openCustomModal(addMembersModalConfig, AddElementsComponent, {
+ elementsToAdd: optionalsMembersToAdd,
+ elementName: 'member'
+ });
+ }
+
+ private initMembers = (groupInstance?: GroupInstance) => {
+ this.group = groupInstance ? groupInstance : this.group;
+ this.members = this.group.getMembersAsUiObject(this.compositionService.getComponentInstances());
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html
index fe1f6b4f0d..c57f99786c 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html
@@ -18,7 +18,7 @@
<header tooltip="Properties">Properties</header>
<content>
<ul>
- <li *ngFor="let property of properties; let i = index"
+ <li *ngFor="let property of component.properties; let i = index"
class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow">
<div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label hand"
[attr.data-tests-id]="'propertyName_'+property.name"
@@ -32,7 +32,7 @@
</li>
</ul>
- <div *ngIf="properties.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!component.properties || component.properties.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No properties to display</div>
</div>
</content>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts
index 5862135df2..24ae8b2833 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts
@@ -19,44 +19,32 @@
*/
import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, OnChanges, SimpleChanges } from "@angular/core";
+import { Component, Inject, Input} from "@angular/core";
import { TranslateService } from './../../../../../shared/translator/translate.service';
import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-import { PropertyBEModel } from 'app/models';
import { PropertyModel } from './../../../../../../models/properties';
import { ModalsHandler } from "app/utils";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
+import { Component as TopologyTemplate, GroupInstance } from "app/models";
@Component({
- selector: 'policy-properties-tab',
- templateUrl: './policy-properties-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'policy-properties-tab.component.less'],
- host: {'class': 'component-details-panel-tab-policy-properties'}
+ selector: 'group-or-policy-properties-tab',
+ templateUrl: './group-or-policy-properties-tab.component.html',
+ styleUrls: ['./../properties-tab/properties-tab.component.less'],
})
-export class PolicyPropertiesTabComponent implements OnChanges {
+export class GroupOrPolicyPropertiesTab {
- @Input() policy:PolicyInstance;
+ @Input() component: GroupInstance | PolicyInstance;
@Input() topologyTemplate:TopologyTemplate;
@Input() isViewOnly: boolean;
+ @Input() input: {type: string};
- private properties:Array<PropertyModel>;
constructor(private translateService:TranslateService, private ModalsHandler:ModalsHandler) {
}
- ngOnChanges(changes: SimpleChanges): void {
- console.log("PolicyPropertiesTabComponent: ngAfterViewInit: ");
- console.log("policy: " + this.policy);
- this.properties = [];
- this.initProperties();
- }
-
- initProperties = ():void => {
- this.properties= this.policy.properties;
- }
editProperty = (property?:PropertyModel):void => {
- this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.properties, false, 'policy', this.policy.uniqueId).then((updatedProperty:PropertyModel) => {
+ this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.component.properties, false, this.input.type, this.component.uniqueId).then((updatedProperty:PropertyModel) => {
console.log("ok");
});
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html
deleted file mode 100644
index 953b57bda1..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
- -->
-
-
-<ng2-expand-collapse state="0">
-
- <header tooltip="General Information">General Info</header>
-
- <content>
- <!-- CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_category" tooltip="Group">Group</span>
- </div>
-
- <!-- SUB CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_subCategory" tooltip="Group">Group</span>
- </div>
-
- <!-- VERSION -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
- <span class="value" data-tests-id="rightTab_version" tooltip="{{group.version}}">{{group.version}}</span>
- </div>
-
- <!-- DESCRIPTION -->
- <div class="component-details-panel-item description">
- <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
- <span class="value" ellipsis="group.description" max-chars="55" data-tests-id="rightTab_description">{{group.description}}</span>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts
deleted file mode 100644
index 26602224da..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter } from "@angular/core";
-import { GroupInstance } from 'app/models/graph/zones/group-instance';
-
-@Component({
- selector: 'group-information-tab',
- templateUrl: './group-information-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less']
-})
-export class GroupInformationTabComponent {
-
- @Input() group: GroupInstance;
- @Input() isViewOnly: boolean;
-
- constructor() {
-
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less
deleted file mode 100644
index 1006e864fa..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less
+++ /dev/null
@@ -1,13 +0,0 @@
-/deep/
-.component-details-panel-tab-group-members {
- .component-details-panel-large-item {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
-
- .w-sdc-designer-sidebar-section-title {
- display: flex;
- justify-content: space-between;
- }
-} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts
deleted file mode 100644
index 148f2133e8..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Input, Output, EventEmitter, OnChanges, HostBinding } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate } from "app/models";
-import { GroupInstance } from "app/models/graph/zones/group-instance";
-import { GroupsService } from "../../../../../services/groups.service";
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-import { MemberUiObject } from "../../../../../../models/ui-models/ui-member-object";
-import { IModalConfig } from "sdc-ui/lib/angular/modals/models/modal-config";
-import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component";
-import { GRAPH_EVENTS } from 'app/utils';
-import { EventListenerService } from 'app/services/event-listener-service';
-import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-
-@Component({
- selector: 'group-members-tab',
- templateUrl: './group-members-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'group-members-tab.component.less']
-})
-
-export class GroupMembersTabComponent implements OnChanges {
-
-
- private members: Array<MemberUiObject>;
-
- @Input() group: GroupInstance;
- @Input() topologyTemplate: TopologyTemplate;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
- @HostBinding('class') classes = 'component-details-panel-tab-group-members';
-
- constructor(private translateService: TranslateService,
- private groupsService: GroupsService,
- private modalService: SdcUiComponents.ModalService,
- private eventListenerService: EventListenerService
- ) {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.initMembers)
- }
-
- ngOnChanges(changes:SimpleChanges):void {
- this.initMembers();
- }
-
- deleteMember = (member: MemberUiObject):void => {
- this.isLoading.emit(true);
- this.groupsService.deleteGroupMember(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.group, member.uniqueId).subscribe(
- (updatedMembers:Array<string>) => {
- this.group.members = updatedMembers;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
- },
- error => console.log("Error deleting member!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private initMembers = (groupInstance?: GroupInstance) => {
- this.group = groupInstance ? groupInstance : this.group;
- this.members = this.group.getMembersAsUiObject(this.topologyTemplate.componentInstances);
- }
-
- addMembers = ():void => {
- var membersToAdd:Array<MemberUiObject> = this.modalService.getCurrentInstance().innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
- if(membersToAdd.length > 0) {
- this.modalService.closeModal();
- this.isLoading.emit(true);
- var updatedMembers: Array<MemberUiObject> = _.union(this.members, membersToAdd);
- this.groupsService.updateMembers(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.group.uniqueId, updatedMembers).subscribe(
- (updatedMembers:Array<string>) => {
- this.group.members = updatedMembers;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
- },
- error => {
- console.log("Error updating members!");
- }, () =>
- this.isLoading.emit(false)
- );
- }
- }
-
- getOptionalsMembersToAdd():Array<MemberUiObject> {
-
- let optionalsMembersToAdd:Array<MemberUiObject> = [];
-
- // adding all instances as optional members to add if not already exist
- _.forEach(this.topologyTemplate.componentInstances, (instance:ComponentInstance) => {
- if (!_.some(this.members, (member:MemberUiObject) => {
- return member.uniqueId === instance.uniqueId
- })) {
- optionalsMembersToAdd.push(new MemberUiObject(instance.uniqueId, instance.name));
- }
- });
- return optionalsMembersToAdd;
- }
-
- openAddMembersModal():void {
- let addMembersModalConfig:IModalConfig = {
- title: this.group.name + " ADD MEMBERS",
- size: "md",
- type: "custom",
- testId: "addMembersModal",
- buttons: [
- {text: 'ADD MEMBERS', size: 'xsm', callback: this.addMembers, closeModal: false},
- {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
- ]
- };
- var optionalsMembersToAdd = this.getOptionalsMembersToAdd();
- this.modalService.openCustomModal(addMembersModalConfig, AddElementsComponent, {
- elementsToAdd: optionalsMembersToAdd,
- elementName: "member"
- });
- }
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html
deleted file mode 100644
index fe1f6b4f0d..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
- -->
-
-<ng2-expand-collapse state="0">
- <header tooltip="Properties">Properties</header>
- <content>
- <ul>
- <li *ngFor="let property of properties; let i = index"
- class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow">
- <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label hand"
- [attr.data-tests-id]="'propertyName_'+property.name"
- tooltip="{{property.name}}"
- (click)="!isViewOnly && editProperty(property)">{{property.name}}
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item-property-value"
- [attr.data-tests-id]="'value_'+property.name"
- tooltip="{{property.value || property.defaultValue}}">{{property.value || property.defaultValue}}
- </div>
- </li>
- </ul>
-
- <div *ngIf="properties.length===0" class="component-details-panel-tab-no-data">
- <div class="component-details-panel-tab-no-data-title">No properties to display</div>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts
deleted file mode 100644
index 69079347c4..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, OnChanges, SimpleChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { GroupInstance } from 'app/models/graph/zones/group-instance';
-import { PropertyBEModel } from 'app/models';
-import { PropertyModel } from './../../../../../../models/properties';
-import { ModalsHandler } from "app/utils";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-
-@Component({
- selector: 'group-properties-tab',
- templateUrl: './group-properties-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'group-properties-tab.component.less'],
- host: {'class': 'component-details-panel-tab-group-properties'}
-})
-export class GroupPropertiesTabComponent implements OnChanges {
-
- @Input() group:GroupInstance;
- @Input() topologyTemplate:TopologyTemplate;
- @Input() isViewOnly: boolean;
-
- private properties:Array<PropertyModel>;
-
- constructor(private translateService:TranslateService, private ModalsHandler:ModalsHandler) {
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- console.log("GroupPropertiesTabComponent: ngAfterViewInit: ");
- console.log("group: " + JSON.stringify(this.group));
- this.properties = [];
- this.initProperties();
- }
-
- initProperties = ():void => {
- this.properties= this.group.properties;
- }
-
- editProperty = (property?:PropertyModel):void => {
- this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.properties, false, 'group', this.group.uniqueId).then((updatedProperty:PropertyModel) => {
- console.log("ok");
- });
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html
deleted file mode 100644
index 482de5eacf..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
- -->
-
-<sdc-tabs>
- <sdc-tab titleIcon="info-circle">
- <group-information-tab [group]="group" [isViewOnly]="isViewOnly" *ngIf="group"></group-information-tab>
- </sdc-tab>
- <sdc-tab titleIcon="inputs-o">
- <group-members-tab [group]="group" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" (isLoading)="setIsLoading($event)" *ngIf="group"></group-members-tab>
- </sdc-tab>
- <sdc-tab titleIcon="settings-o">
- <group-properties-tab [group]="group" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" *ngIf="group"></group-properties-tab>
- </sdc-tab>
-</sdc-tabs>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts
deleted file mode 100644
index 975d5c6153..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, SimpleChanges, OnChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { GroupsService } from '../../../../../services/groups.service';
-import { GroupInstance } from "app/models/graph/zones/group-instance";
-
-@Component({
- selector: 'group-tabs',
- templateUrl: './group-tabs.component.html'
-})
-export class GroupTabsComponent implements OnChanges {
-
- @Input() topologyTemplate:TopologyTemplate;
- @Input() selectedZoneInstanceType:string;
- @Input() selectedZoneInstanceId:string;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
-
- private group:GroupInstance;
-
- constructor(private translateService:TranslateService,
- private groupsService:GroupsService
- ) {
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- this.initGroup();
- }
-
- private initGroup = ():void => {
- this.isLoading.emit(true);
- this.groupsService.getSpecificGroup(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).subscribe(
- group => {
- this.group = group;
- console.log(JSON.stringify(group));
- },
- error => console.log("Error getting group!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private setIsLoading = (value) :void => {
- this.isLoading.emit(value);
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts
deleted file mode 100644
index 50797f862c..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 { NgModule } from "@angular/core";
-import { HttpModule } from "@angular/http";
-import { FormsModule } from "@angular/forms";
-import { BrowserModule } from "@angular/platform-browser";
-import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
-import { ExpandCollapseComponent } from 'app/ng2/components/ui/expand-collapse/expand-collapse.component';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { GroupInformationTabComponent } from './group-information-tab.component';
-import { TooltipModule } from './../../../../../components/ui/tooltip/tooltip.module';
-import { GroupTabsComponent } from "./group-tabs.component";
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { GroupMembersTabComponent } from './group-members-tab.component';
-import { TranslateModule } from './../../../../../shared/translator/translate.module';
-import { GroupPropertiesTabComponent } from "./group-properties-tab.component";
-
-@NgModule({
- declarations: [
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- TooltipModule,
- UiElementsModule,
- SdcUiComponentsModule,
- TranslateModule
- ],
- entryComponents: [
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent,
- ExpandCollapseComponent
- ],
- exports: [
- TooltipModule,
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent
- ],
- providers: [
- PoliciesService
- ]
-})
-export class GroupTabsModule {
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap
new file mode 100644
index 0000000000..fdd0dcf75c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`InfoTabComponent can load instance 1`] = `
+<panel-info-tab
+ componentInstanceService={[Function Object]}
+ compositionPaletteService={[Function Object]}
+ compositionService={[Function Object]}
+ eventListenerService={[Function Object]}
+ flatLeftPaletteElementsFromService={[Function Function]}
+ getPathNamesVersionChangeModal={[Function Function]}
+ initEditResourceVersion={[Function Function]}
+ modalService={[Function Object]}
+ onChangeVersion={[Function Function]}
+ sdcMenu={[Function Object]}
+ serviceService={[Function Object]}
+ store={[Function Object]}
+ versioning={[Function Function]}
+ workspaceService={[Function Object]}
+>
+ <ng2-expand-collapse
+ state="0"
+ >
+ <header
+ tooltip="General Information"
+ >
+ General Info
+ </header>
+ <content
+ class="general-info-container"
+ >
+
+
+ <div
+ class="component-details-panel-item"
+ >
+ <span
+ class="name"
+ />
+
+
+ </div>
+
+
+
+
+
+
+
+
+
+
+
+ <div
+ class="component-details-panel-item description"
+ >
+ <span
+ class="name"
+ />
+ <chars-ellipsis />
+ </div>
+
+
+ </content>
+ </ng2-expand-collapse>
+</panel-info-tab>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html
new file mode 100644
index 0000000000..71545f8143
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html
@@ -0,0 +1,174 @@
+<!--
+ ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
+ -->
+
+<ng2-expand-collapse state="0">
+ <header tooltip="General Information">General Info</header>
+ <content class="general-info-container">
+ <!-- TYPE -->
+ <div class="component-details-panel-item" *ngIf="component.componentType">
+ <span class="name" [innerHTML]="'Type:'"></span>
+ <span class="value" data-tests-id="rightTab_componentType" tooltip="{{component.componentType}}">{{component.componentType}}</span>
+ </div>
+
+ <!-- RESOURCE TYPE-->
+ <div class="component-details-panel-item" *ngIf="component.resourceType">
+ <span class="name" [innerHTML]="'Resource Type:'"></span>
+ <span class="value" data-tests-id="rightTab_resourceType" tooltip="{{component.resourceType}}">{{component.resourceType}}</span>
+ </div>
+
+ <!-- VERSION -->
+ <div class="component-details-panel-item" >
+ <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
+ <span class="value" *ngIf="!isComponentSelectedFlag" data-tests-id="rightTab_version" tooltip="{{component.version}}">{{component.version}}</span>
+ <ng-container *ngIf="isComponentSelectedFlag">
+ <select #versionDropdown (change)="onChangeVersion(versionDropdown)" [ngModel]="component.getComponentUid()" data-tests-id="changeVersion">
+ <option *ngFor="let version of versions" value="{{version.value}}"
+ [disabled]="isDisabledFlag" [class.minor]="(component.componentVersion)%1"
+ >{{version.label}}</option>
+ </select>
+ </ng-container>
+ </div>
+
+ <!-- CATEGORY -->
+ <ng-container *ngIf="component.categories && component.categories[0]">
+ <div class="component-details-panel-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="{{component.categories[0].name}}">{{component.categories[0].name}}</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item" *ngIf="component.categories[0].subcategories && component.categories[0].subcategories[0]">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="{{component.categories[0].subcategories[0].name}}">{{component.categories[0].subcategories[0].name}}</span>
+ </div>
+ </ng-container>
+
+ <!-- CREATION DATE -->
+ <div class="component-details-panel-item" *ngIf="component.creationDate">
+ <span class="name" [innerHTML]="'Creation Date:'"></span>
+ <span class="value" data-tests-id="rightTab_version" tooltip="{{component.creationDate | date: 'MM/dd/yyyy'}}">{{component.creationDate | date: 'MM/dd/yyyy'}}</span>
+ </div>
+
+ <!-- AUTHOR -->
+ <div class="component-details-panel-item" *ngIf="component.creatorFullName">
+ <span class="name" [innerHTML]="'Author:'"></span>
+ <span class="value" data-tests-id="rightTab_author" tooltip="{{component.creatorFullName}}">{{component.creatorFullName}}</span>
+ </div>
+
+ <!-- Vendor Name data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.vendorName">
+ <span class="name" [innerHTML]="'Vendor Name:'"></span>
+ <span class="value" data-tests-id="rightTab_vendorName" tooltip="{{component.vendorName}}">{{component.vendorName}}</span>
+ </div>
+
+ <!-- Vendor Release data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.vendorRelease">
+ <span class="name" [innerHTML]="'Vendor Release:'"></span>
+ <span class="value" data-tests-id="rightTab_vendorRelease" tooltip="{{component.vendorRelease}}">{{component.vendorRelease}}</span>
+ </div>
+
+ <!-- Vendor Release data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.resourceVendorModelNumber">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_RESOURCE_MODEL_NUMBER' | translate"></span>
+ <span class="value" data-tests-id="rightTab_resourceVendorModelNumber" tooltip="{{component.resourceVendorModelNumber}}">{{component.resourceVendorModelNumber}}</span>
+ </div>
+
+ <!-- Service Type data-ng-if="selectedComponent.isService()"-->
+ <div class="component-details-panel-item" *ngIf="component.serviceType">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SERVICE_TYPE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_serviceType" tooltip="{{component.serviceType}}">{{component.serviceType}}</span>
+ </div>
+
+ <!-- Service Role data-ng-if="selectedComponent.isService()"-->
+ <div class="component-details-panel-item" *ngIf="component.serviceRole">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SERVICE_ROLE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_serviceRole" tooltip="{{component.serviceRole}}">{{component.serviceRole}}</span>
+ </div>
+
+ <!-- Contact ID -->
+ <div class="component-details-panel-item" *ngIf="component.contactId">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CONTACT_ID' | translate"></span>
+ <span class="value" data-tests-id="rightTab_contactId" tooltip="{{component.contactId}}">{{component.contactId}}</span>
+ </div>
+
+ <!-- Service Name data-ng-if="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()"-->
+ <div class="component-details-panel-item" *ngIf="component.sourceModelName">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SOURCE_SERVICE_NAME' | translate"></span>
+ <span class="value" data-tests-id="rightTab_sourceModelName" tooltip="{{component.sourceModelName}}">{{component.sourceModelName}}</span>
+ </div>
+
+ <!-- Customization UUID data-ng-if="isViewMode() && currentComponent.isService() && selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.customizationUUID">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_RESOURCE_CUSTOMIZATION_UUID' | translate"></span>
+ <span class="value" data-tests-id="rightTab_customizationModuleUUID" tooltip="{{component.customizationUUID}}">{{component.customizationUUID}}</span>
+ </div>
+
+ <!-- DESCRIPTION -->
+ <div class="component-details-panel-item description">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
+ <chars-ellipsis [text]="component.description" [maxChars]="55" [testId]="'rightTab_description'"></chars-ellipsis>
+ </div>
+
+
+ <!--TODO: move to separate component!-->
+ <ng-container *ngIf="componentType == 'POLICY'">
+ <!-- TYPE -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_TYPE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_componentType" tooltip="{{component.policyTypeUid}}">{{component.policyTypeUid}}</span>
+ </div>
+
+ <!-- CATEGORY -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="Policy">Policy</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="Policy">Policy</span>
+ </div>
+ </ng-container>
+
+ <!--TODO: move to separate component!-->
+ <ng-container *ngIf="componentType == 'GROUP'">
+ <!-- CATEGORY -->
+ <div class="component-details-panel-item group-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="Group">Group</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item group-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="Group">Group</span>
+ </div>
+
+ </ng-container>
+
+ </content>
+</ng2-expand-collapse>
+
+<ng2-expand-collapse *ngIf="component.tags || isComponentInstanceSelected()">
+ <header tooltip="Tags">Tags</header>
+ <content class="tags-container">
+ <span *ngIf="component.tags?.indexOf(component.name)===-1" class="i-sdc-designer-sidebar-section-content-item-tag"
+ data-tests-id="rightTab_tag" tooltip="{{component.name}}">{{component.name}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-tag" *ngFor="let tag of component.tags"
+ data-tests-id="rightTab_tag" tooltip="{{tag}}">{{tag}}</span>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less
new file mode 100644
index 0000000000..c8da4e3e68
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less
@@ -0,0 +1,51 @@
+@import '../../../../../../../assets/styles/variables';
+
+.general-info-container {
+ display: flex;
+ flex-direction: column;
+ padding: 10px 20px;
+}
+
+.component-details-panel-item {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-bottom: 5px;
+ order:1;
+
+ .name { font-family: OpenSans-Semibold, sans-serif; }
+ .value { padding-left: 10px; }
+
+
+ &.description {
+ margin-top: 28px;
+ white-space: normal;
+ word-wrap: break-word;
+ overflow: ellipsis;
+
+ .value {
+ padding-left: 0;
+ max-width: none;
+ font-weight: normal;
+ font-family: @font-opensans-regular;
+ }
+ }
+
+ &.group-item, &.policy-item {
+ order:0;
+ }
+}
+
+.tags-container {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 10px 20px;
+
+ .i-sdc-designer-sidebar-section-content-item-tag {
+ padding: 5px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ user-select: all;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts
new file mode 100644
index 0000000000..6915d651f1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts
@@ -0,0 +1,98 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { Store } from '@ngxs/store';
+import { CompositionPaletteService } from '../../../../../pages/composition/palette/services/palette.service';
+import { IAppMenu, SdcMenuToken } from '../../../../../../../app/ng2/config/sdc-menu.config';
+import { CompositionService } from '../../../../../pages/composition/composition.service';
+import { ServiceServiceNg2 } from '../../../../../../../app/services-ng2';
+import { WorkspaceService } from '../../../../../../../app/ng2/pages/workspace/workspace.service';
+import { ComponentInstanceServiceNg2 } from '../../../../../../../app/ng2/services/component-instance-services/component-instance.service';
+import { EventListenerService } from '../../../../../../../app/services';
+import { InfoTabComponent } from './info-tab.component';
+import { ConfigureFn, configureTests } from "../../../../../../../jest/test-config.helper";
+import { Observable } from "rxjs";
+import { leftPaletteElements } from "../../../../../../../jest/mocks/left-paeltte-elements.mock";
+import { TranslatePipe } from "../../../../../shared/translator/translate.pipe";
+import { HttpClientModule } from "@angular/common/http";
+import { TranslateModule } from "../../../../../../../app/ng2/shared/translator/translate.module";
+import _ from "lodash";
+import { TranslateService } from "../../../../../shared/translator/translate.service";
+import { SdcUiServices } from "onap-ui-angular";
+import { Component as TopologyTemplate, FullComponentInstance, ComponentInstance } from '../../../../../../../app/models';
+
+
+describe('InfoTabComponent', () => {
+ // let comp: InfoTabComponent;
+ let fixture: ComponentFixture<InfoTabComponent>;
+
+ // let eventServiceMock: Partial<EventListenerService>;
+ let storeStub:Partial<Store>;
+ let compositionPaletteServiceStub:Partial<CompositionPaletteService>;
+ let iAppMenuStub:Partial<IAppMenu>;
+ let compositionServiceStub:Partial<CompositionService>;
+ let serviceServiceNg2Stub:Partial<ServiceServiceNg2>;
+ let workspaceServiceStub:Partial<WorkspaceService>;
+ let componentInstanceServiceNg2Stub:Partial<ComponentInstanceServiceNg2>;
+ let eventListenerServiceStub:Partial<EventListenerService>;
+
+ beforeEach(
+ async(() => {
+ storeStub = {};
+ iAppMenuStub = {};
+ eventListenerServiceStub = {
+ notifyObservers: jest.fn()
+ }
+ compositionPaletteServiceStub = {
+ getLeftPaletteElements: jest.fn().mockImplementation(()=> Observable.of(leftPaletteElements))
+ }
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ imports: [ ],
+ declarations: [ InfoTabComponent, TranslatePipe ],
+ schemas: [ NO_ERRORS_SCHEMA ],
+ providers: [
+ { provide: Store, useValue: {} },
+ { provide: CompositionPaletteService, useValue: compositionPaletteServiceStub },
+ { provide: SdcMenuToken, useValue: {} },
+ { provide: CompositionService, useValue: {} },
+ { provide: SdcUiServices.ModalService, useValue: {}},
+ { provide: ServiceServiceNg2, useValue: {} },
+ { provide: WorkspaceService, useValue: {} },
+ { provide: ComponentInstanceServiceNg2, useValue: {} },
+ { provide: EventListenerService, useValue: eventListenerServiceStub },
+ { provide: TranslateService, useValue: {}}
+ ]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(InfoTabComponent);
+ let comp = fixture.componentInstance;
+
+ });
+ })
+ );
+
+
+ it('can load instance', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ describe('Version dropdown', () => {
+ it('is undefined for topologyTemplate', () => {
+ fixture.componentInstance.component = <TopologyTemplate>{};
+ fixture.componentInstance.initEditResourceVersion(fixture.componentInstance.component, fixture.componentInstance.flatLeftPaletteElementsFromService(leftPaletteElements));
+ expect(fixture.componentInstance.versions).toBe(undefined);
+ });
+ it('does not contain the highest minor version if it is checked out', () => {
+ fixture.componentInstance.component = new ComponentInstance();
+ fixture.componentInstance.component.allVersions =
+ {'1.0': "9c829122-af05-4bc9-b537-5d84f4c8ae25", '1.1': "930d56cb-868d-4e35-bd0f-e737d2fdb171"};
+ fixture.componentInstance.component.version = "1.0";
+ fixture.componentInstance.component.uuid = "a8cf015e-e4e5-4d4b-a01e-8624e8d36095";
+ fixture.componentInstance.initEditResourceVersion(fixture.componentInstance.component, fixture.componentInstance.flatLeftPaletteElementsFromService(leftPaletteElements));
+ expect(fixture.componentInstance.versions).toHaveLength(1);
+ });
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts
new file mode 100644
index 0000000000..45f31e7b35
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts
@@ -0,0 +1,189 @@
+import { Component, OnInit, Input, Inject, OnDestroy } from '@angular/core';
+import {
+ PolicyInstance,
+ GroupInstance,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ LeftPaletteComponent,
+ FullComponentInstance
+} from "app/models";
+import {Store} from "@ngxs/store";
+import { EVENTS, GRAPH_EVENTS } from 'app/utils';
+import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
+import { CompositionPaletteService } from "app/ng2/pages/composition/palette/services/palette.service";
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from "onap-ui-angular";
+import { SdcMenuToken, IAppMenu } from "app/ng2/config/sdc-menu.config";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { ServiceServiceNg2 } from "app/services-ng2";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+import { EventListenerService } from "app/services";
+import * as _ from 'lodash';
+import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
+import Dictionary = _.Dictionary;
+
+
+@Component({
+ selector: 'panel-info-tab',
+ templateUrl: './info-tab.component.html',
+ styleUrls: ['./info-tab.component.less'],
+ // providers: [SdcUiServices.ModalService]
+})
+export class InfoTabComponent implements OnInit, OnDestroy {
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | PolicyInstance | GroupInstance | ComponentInstance;
+ public versions: IDropDownOption[];
+ private leftPalletElements: LeftPaletteComponent[];
+ private isDisabledFlag: boolean;
+ private isComponentSelectedFlag: boolean;
+
+ constructor(private store: Store,
+ private compositionPaletteService: CompositionPaletteService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private modalService: SdcUiServices.ModalService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
+ private serviceService: ServiceServiceNg2,
+ private eventListenerService: EventListenerService,
+ @Inject(SdcMenuToken) public sdcMenu:IAppMenu) {
+ }
+
+ ngOnInit() {
+ this.leftPalletElements = this.flatLeftPaletteElementsFromService(this.compositionPaletteService.getLeftPaletteElements());
+ this.initEditResourceVersion(this.component, this.leftPalletElements);
+ this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, (comp) => {
+ this.component = comp;
+ });
+ this.isComponentSelectedFlag = this.isComponentInstanceSelected();
+ this.isDisabledFlag = this.isDisabled();
+
+ }
+
+ ngOnDestroy() {
+ this.eventListenerService.unRegisterObserver(EVENTS.ON_CHECKOUT);
+ }
+
+ flatLeftPaletteElementsFromService = (leftPalleteElementsFromService: Dictionary<Dictionary<LeftPaletteComponent[]>>): LeftPaletteComponent[] => {
+ let retValArr = [];
+ for (const category in leftPalleteElementsFromService) {
+ for (const subCategory in leftPalleteElementsFromService[category]) {
+ retValArr = retValArr.concat(leftPalleteElementsFromService[category][subCategory].slice(0));
+ }
+ }
+ return retValArr;
+ }
+
+ private isComponentInstanceSelected () {
+ return this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ }
+
+ private versioning: Function = (versionNumber: string): string => {
+ let version: Array<string> = versionNumber && versionNumber.split('.');
+ return '00000000'.slice(version[0].length) + version[0] + '.' + '00000000'.slice(version[1].length) + version[1];
+ };
+
+
+ private onChangeVersion = (versionDropdown) => {
+ let newVersionValue = versionDropdown.value;
+ versionDropdown.value = (<FullComponentInstance>this.component).getComponentUid();
+
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ // let service = <Service>this.$scope.currentComponent;
+ if(this.component instanceof FullComponentInstance) {
+
+ let onCancel = (error:any) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ if (error) {
+ console.log(error);
+ }
+ };
+
+ let onUpdate = () => {
+ //this function will update the instance version than the function call getComponent to update the current component and return the new instance version
+ this.componentInstanceService.changeResourceInstanceVersion(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.component.uniqueId, newVersionValue)
+ .subscribe((component) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_VERSION_CHANGED, component);
+ }, onCancel);
+ };
+
+ if (this.component.isService() || this.component.isServiceProxy()) {
+ this.serviceService.checkComponentInstanceVersionChange(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId,
+ this.component.uniqueId, newVersionValue).subscribe((pathsToDelete:string[]) => {
+ if (pathsToDelete && pathsToDelete.length) {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+
+
+ const {title, message} = this.sdcMenu.alertMessages['upgradeInstance'];
+ let pathNames:string = this.getPathNamesVersionChangeModal(pathsToDelete);
+ let onOk: Function = () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ onUpdate();
+ };
+ const okButton = {testId: "OK", text: "OK", type: SdcUiCommon.ButtonType.info, callback: onOk, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ const cancelButton = {testId: "Cancel", text: "Cancel", type: SdcUiCommon.ButtonType.secondary, callback: <Function>onCancel, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ const modal = this.modalService.openInfoModal(title, message.format([pathNames]), 'confirm-modal', [okButton, cancelButton]);
+ modal.getCloseButton().onClick(onCancel);
+ } else {
+ onUpdate();
+ }
+ }, onCancel);
+ } else {
+ onUpdate();
+ }
+ }
+ };
+
+
+ private getPathNamesVersionChangeModal = (pathsToDelete:string[]):string => {
+ const relatedPaths = _.filter(this.compositionService.forwardingPaths, path =>
+ _.find(pathsToDelete, id =>
+ path.uniqueId === id
+ )
+ ).map(path => path.name);
+ const pathNames = _.join(relatedPaths, ', ') || 'none';
+ return pathNames;
+ };
+
+
+ private initEditResourceVersion = (component, leftPaletteComponents): void => {
+ if(this.component instanceof ComponentInstance) {
+
+ this.versions = [];
+ let sorted:any = _.sortBy(_.toPairs(component.allVersions), (item) => {
+ return item[0] !== "undefined" && this.versioning(item[0]);
+ });
+ _.forEach(sorted, (item) => {
+ this.versions.push({label: item[0], value: item[1]});
+ });
+
+ let highestVersion = _.last(sorted)[0];
+
+ if (parseFloat(highestVersion) % 1) { //if highest is minor, make sure it is the latest checked in -
+ let latestVersionComponent: LeftPaletteComponent = _.maxBy(
+ _.filter(leftPaletteComponents, (leftPaletteComponent: LeftPaletteComponent) => { //latest checked in
+ return (leftPaletteComponent.systemName === component.systemName || leftPaletteComponent.uuid === component.uuid);
+ })
+ , (component) => {
+ return component.version
+ });
+
+ let latestVersion: string = latestVersionComponent ? latestVersionComponent.version : highestVersion;
+
+ if (latestVersion && highestVersion != latestVersion) { //highest is checked out - remove from options
+ this.versions = this.versions.filter(version => version.label != highestVersion);
+ }
+ }
+ }
+ }
+
+ private isDisabled() {
+ return this.isViewOnly || this.component['archived'] || this.component['resourceType'] === 'CVFC'
+ }
+
+};
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts
new file mode 100644
index 0000000000..c148a4e579
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts
@@ -0,0 +1,55 @@
+import { NgModule, Component, Compiler, ViewContainerRef, ViewChild, Input, ComponentRef, ComponentFactoryResolver, ChangeDetectorRef } from '@angular/core';
+import {Component as TopologyTemplate} from "app/models";
+import { SdcUiServices } from "onap-ui-angular";
+
+// Helper component to add dynamic tabs
+@Component({
+ selector: 'panel-tab',
+ template: `<div #content></div>`
+})
+export class PanelTabComponent {
+ @ViewChild('content', { read: ViewContainerRef }) content;
+ @Input() isActive:boolean;
+ @Input() panelTabType;
+ @Input() input;
+ @Input() isViewOnly:boolean;
+ @Input() component:TopologyTemplate;
+ @Input() componentType;
+ cmpRef: ComponentRef<any>;
+ private isViewInitialized: boolean = false;
+
+ constructor(private componentFactoryResolver: ComponentFactoryResolver,
+ private cdRef: ChangeDetectorRef) { }
+
+ updateComponent() {
+ if (!this.isViewInitialized || !this.isActive) {
+ return;
+ }
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+
+ let factory = this.componentFactoryResolver.resolveComponentFactory(this.panelTabType);
+ this.cmpRef = this.content.createComponent(factory);
+ this.cmpRef.instance.input = this.input;
+ this.cmpRef.instance.isViewOnly = this.isViewOnly;
+ this.cmpRef.instance.component = this.component;
+ this.cmpRef.instance.componentType = this.componentType;
+ this.cdRef.detectChanges();
+ }
+
+ ngOnChanges() {
+ this.updateComponent();
+ }
+
+ ngAfterViewInit() {
+ this.isViewInitialized = true;
+ this.updateComponent();
+ }
+
+ ngOnDestroy() {
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less
new file mode 100644
index 0000000000..b3c03f85c5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less
@@ -0,0 +1,65 @@
+@import '../../../../../../assets/styles/variables';
+@import '../../../../../../assets/styles/override';
+
+
+// ---------------------------------------------------------------------------------------------------
+///* override sdc-ui library tabs */
+// ---------------------------------------------------------------------------------------------------
+
+
+:host ::ng-deep .sdc-tabs {
+
+ .sdc-tabs-list {
+ display: flex;
+ border-bottom: 1px solid @sdcui_color_silver;
+ min-height: min-content;
+ }
+ .sdc-tab {
+ background-color: @sdcui_color_white;
+ border: 1px solid @sdcui_color_silver;
+ border-left: none;
+ border-bottom: none;
+ height: 36px;
+ width: 60px;
+ display: flex;
+ align-content: center;
+ justify-content: center;
+ cursor: pointer;
+ padding: 0;
+ margin: 0;
+
+
+ &.sdc-tab-active {
+ background-color: @sdcui_color_silver;
+ border-bottom: none;
+ }
+ &[disabled] {
+ opacity: 0.3;
+ cursor: default;
+ }
+ }
+ &.sdc-tabs-header {
+ .sdc-tab {
+ font-size: 24px;
+ }
+ }
+ &.sdc-tabs-menu {
+ .sdc-tab {
+ font-size: 14px;
+ padding: 0px 10px 4px 10px;
+ }
+ }
+ .sdc-tab-content {
+ margin-top: 0;
+ flex:1;
+ overflow-y:auto;
+ }
+}
+
+
+:host ::ng-deep .expand-collapse-title {
+ margin-top: 1px;
+ background-color: #eaeaea;
+ color: #5a5a5a;
+ font-family: OpenSans-Semibold, sans-serif;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
deleted file mode 100644
index 2a1c58c4cf..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
- -->
-
-<ng2-expand-collapse state="0">
- <header tooltip="General Information">General Info</header>
- <content>
- <!-- TYPE -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_TYPE' | translate"></span>
- <span class="value" data-tests-id="rightTab_componentType" tooltip="{{policy.policyTypeUid}}">{{policy.policyTypeUid}}</span>
- </div>
-
- <!-- CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_category" tooltip="Policy">Policy</span>
- </div>
-
- <!-- SUB CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_subCategory" tooltip="Policy">Policy</span>
- </div>
-
- <!-- VERSION -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
- <span class="value" data-tests-id="rightTab_version" tooltip="{{policy.version}}">{{policy.version}}</span>
- </div>
-
- <!-- DESCRIPTION -->
- <div class="component-details-panel-item description">
- <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
- <span class="value" ellipsis="policy.description" max-chars="55" data-tests-id="rightTab_description">{{policy.description}}</span>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts
deleted file mode 100644
index 3639639c88..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-
-@Component({
- selector: 'policy-information-tab',
- templateUrl: './policy-information-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less']
-})
-export class PolicyInformationTabComponent {
-
- @Input() policy:PolicyInstance;
- @Input() isViewOnly: boolean;
-
- constructor(private translateService:TranslateService) {
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
deleted file mode 100644
index e69de29bb2..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
+++ /dev/null
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html
deleted file mode 100644
index 8d1730f68c..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. 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.
- -->
-
-<sdc-tabs>
- <sdc-tab titleIcon="info-circle">
- <policy-information-tab [policy]="policy" [isViewOnly]="isViewOnly" *ngIf="policy"></policy-information-tab>
- </sdc-tab>
- <sdc-tab titleIcon="inputs-o">
- <policy-targets-tab [policy]="policy" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" (isLoading)="setIsLoading($event)" *ngIf="policy"></policy-targets-tab>
- </sdc-tab>
- <sdc-tab titleIcon="settings-o">
- <policy-properties-tab [policy]="policy" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" *ngIf="policy"></policy-properties-tab>
- </sdc-tab>
-</sdc-tabs>
-
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts
deleted file mode 100644
index 1e2739901d..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, AfterViewInit, OnChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-import { GRAPH_EVENTS } from './../../../../../../utils/constants';
-import { EventListenerService } from 'app/services/event-listener-service';
-import { ZoneInstance } from 'app/models/graph/zones/zone-instance';
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-
-@Component({
- selector: 'policy-tabs',
- templateUrl: './policy-tabs.component.html'
-})
-export class PolicyTabsComponent implements OnChanges {
-
- @Input() topologyTemplate:TopologyTemplate;
- @Input() selectedZoneInstanceType:string;
- @Input() selectedZoneInstanceId:string;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
-
- private policy:PolicyInstance;
-
- constructor(private translateService:TranslateService,
- private policiesService:PoliciesService
- ) {
-
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- this.initPolicy();
- }
-
- private initPolicy = ():void => {
- this.isLoading.emit(true);
- this.policiesService.getSpecificPolicy(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).subscribe(
- policy => {
- this.policy = policy;
- console.log(JSON.stringify(policy));
- },
- error => console.log("Error getting policy!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private setIsLoading = (value) :void => {
- this.isLoading.emit(value);
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts
deleted file mode 100644
index 38dc19e1af..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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 { NgModule } from "@angular/core";
-import { HttpModule } from "@angular/http";
-import { FormsModule } from "@angular/forms";
-import { BrowserModule } from "@angular/platform-browser";
-import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
-import { ExpandCollapseComponent } from 'app/ng2/components/ui/expand-collapse/expand-collapse.component';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { PolicyInformationTabComponent } from "./policy-information-tab.component";
-import { PolicyTargetsTabComponent } from "./policy-targets-tab.component";
-import { PolicyTabsComponent } from "./policy-tabs.component";
-import { PolicyPropertiesTabComponent } from "./policy-properties-tab.component";
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { TranslateModule } from './../../../../../shared/translator/translate.module';
-
-@NgModule({
- declarations: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- SdcUiComponentsModule,
- TranslateModule,
- UiElementsModule
- ],
- entryComponents: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent,
- ExpandCollapseComponent
- ],
- exports: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent
- ],
- providers: [
- PoliciesService
- ]
-})
-export class PolicyTabsModule {
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less
deleted file mode 100644
index cd7ace2b6f..0000000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less
+++ /dev/null
@@ -1,12 +0,0 @@
-/deep/
-.component-details-panel-tab-policy-targets {
- .component-details-panel-large-item {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
- .w-sdc-designer-sidebar-section-title {
- display: flex;
- justify-content: space-between;
- }
-} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html
index e263836fb1..838fd8bb51 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<div class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets
+<h1 class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets
<svg-icon-label *ngIf="!isViewOnly"
class="add-policy-button"
name="plus-circle-o"
@@ -24,7 +24,7 @@
labelPlacement="right"
(click)="openAddTargetModal()">
</svg-icon-label>
-</div>
+</h1>
<div class="expand-collapse-content">
<ul>
<li *ngFor="let target of targets; let i = index" class="component-details-panel-large-item"
@@ -40,7 +40,7 @@
</li>
</ul>
- <div *ngIf="targets.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!targets || targets.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No data to display yet</div>
<div class="component-details-panel-tab-no-data-content">Add targets to policy to see targets</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less
index aa8e75115f..d16a1595df 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less
@@ -1,8 +1,6 @@
@import './../../../../../../../assets/styles/mixins';
-@import "./../../../../../../../assets/styles/variables-old";
-@import './../../../../../../../assets/styles/mixins_old';
-/deep/
+
.expand-collapse-content {
padding: 20px;
}
@@ -25,7 +23,9 @@
white-space: nowrap;
height: 32px;
line-height: 32px;
- vertical-align: middle;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
&:hover {
background-color: #f8f8f8;
@@ -37,30 +37,25 @@
}
}
-.component-details-panel-item {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- height: 22px;
- line-height: 22px;
- vertical-align: middle;
-
- &.description {
- margin-top: 28px;
- white-space: normal;
- word-wrap: break-word;
- .value {
- max-width: none;
- font-weight: normal;
- font-family: @font-opensans-regular;
- }
- }
-
- .name { font-family: OpenSans-Semibold, sans-serif; }
- .value { }
-}
-
.component-details-panel-item-delete {
cursor: pointer;
visibility: hidden;
}
+
+/deep/ .w-sdc-designer-sidebar-section-title {
+ color: #5a5a5a;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ background-color: #eaeaea;
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ text-transform: uppercase;
+ line-height: 32px;
+ padding: 0 10px 0 20px;
+ margin-top: 1px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts
new file mode 100644
index 0000000000..7774138cab
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts
@@ -0,0 +1,113 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Rx';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { CompositionService } from '../../../composition.service';
+import { PolicyTargetsTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component";
+import { PoliciesService } from "app/services-ng2";
+import { PolicyInstance, GroupInstance } from "app/models";
+import { NgxsModule } from "@ngxs/store";
+import { GraphState } from "app/ng2/pages/composition/common/store/graph.state";
+import { WorkspaceState } from "app/ng2/store/states/workspace.state";
+import { TargetUiObject } from "app/models/ui-models/ui-target-object";
+import { TargetOrMemberType } from "app/utils";
+
+
+
+
+describe('policy targets tab component', () => {
+
+ let fixture: ComponentFixture<PolicyTargetsTabComponent>;
+ let component: PolicyTargetsTabComponent;
+
+ let policiesServiceMock = Mock.of<PoliciesService>(
+ {
+ updateTargets: jest.fn().mockImplementation((compType, uid, policyUniqueId, updatedTargets) => {
+ if (updatedTargets === undefined) {
+ return Observable.throwError('error');
+ } else {
+ return Observable.of(updatedTargets);
+ }
+ }
+ )});
+
+ let compositionServiceMock = {
+ componentInstances: [{uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ {uniqueId: '3', name: 'inst3'},
+ {uniqueId: '4', name: 'inst4'},
+ {uniqueId: '5', name: 'inst5'}
+ ],
+ groupInstances : [
+ Mock.of<GroupInstance>({uniqueId: "group1", name: "group1"}),
+ Mock.of<GroupInstance>({uniqueId: "group2", name: "group2"}),
+ Mock.of<GroupInstance>({uniqueId: "group3", name: "group3"})
+ ]
+ };
+
+ let workspaceServiceMock = {
+ metadata: Mock.of<ComponentMetadata>()
+ };
+
+ let modalServiceMock = {
+ openInfoModal: jest.fn(),
+ openCustomModal: jest.fn().mockImplementation(() => { return {
+ innerModalContent: { instance: { existingElements: targetsToAdd }},
+ closeModal: jest.fn()
+ }})
+ };
+
+ let loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const targetsToAdd = [
+ <TargetUiObject>{uniqueId: '1', name: 'inst1', type: TargetOrMemberType.COMPONENT_INSTANCES},
+ <TargetUiObject>{uniqueId: "group1", name: "group1", type: TargetOrMemberType.GROUPS}
+ ];
+
+ const policyInstanceMock = Mock.of<PolicyInstance>(
+ { getTargetsAsUiObject: jest.fn().mockImplementation( () => targetsToAdd)
+ });
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [PolicyTargetsTabComponent],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: { translate: jest.fn() }},
+ {provide: PoliciesService, useValue: policiesServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock },
+ {provide: EventListenerService, useValue: {} },
+ {provide: CompositionService, useValue: compositionServiceMock },
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+
+ fixture = TestBed.createComponent(PolicyTargetsTabComponent);
+ component = fixture.componentInstance;
+ component.policy = policyInstanceMock;
+ });
+
+
+ it('if there are no existing targets, all component instances AND all groups are available for adding', () => {
+ component.targets = [];
+ const optionalTargetsToAdd = component.getOptionalsTargetsToAdd();
+ expect(optionalTargetsToAdd).toHaveLength(8);
+ });
+
+ it('list of available instances to add does not include existing targets', () => {
+ component.targets = targetsToAdd;
+ const optionalMembersToAdd = component.getOptionalsTargetsToAdd();
+ expect(optionalMembersToAdd).toHaveLength(6);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts
index b79f4d9e07..f117290397 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts
@@ -19,84 +19,106 @@
*/
import * as _ from "lodash";
-import { Component, Input, Output, EventEmitter, OnChanges, HostBinding, OnDestroy } from "@angular/core";
+import { Component, Input, Output, EventEmitter, OnChanges, HostBinding, OnDestroy, OnInit } from "@angular/core";
import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate } from "app/models";
import { PoliciesService } from "../../../../../services/policies.service";
-import { PolicyInstance, PolicyTargetsMap } from './../../../../../../models/graph/zones/policy-instance';
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-import { IModalConfig } from "sdc-ui/lib/angular/modals/models/modal-config";
+import { PolicyInstance } from './../../../../../../models/graph/zones/policy-instance';
+import { SdcUiComponents, SdcUiCommon, SdcUiServices } from "onap-ui-angular";
import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component";
import { TargetUiObject } from "../../../../../../models/ui-models/ui-target-object";
import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance";
import { TargetOrMemberType } from "../../../../../../utils/constants";
import { GRAPH_EVENTS } from 'app/utils';
import { EventListenerService } from 'app/services/event-listener-service';
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { Store } from "@ngxs/store";
+import { Select } from "@ngxs/store";
+import { Observable } from "rxjs";
+import { tap } from "rxjs/operators";
+import {GraphState} from "../../../common/store/graph.state";
@Component({
selector: 'policy-targets-tab',
templateUrl: './policy-targets-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'policy-targets-tab.component.less']
+ styleUrls: ['policy-targets-tab.component.less']
})
+
+export class PolicyTargetsTabComponent implements OnInit {
-export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
+ @Input() input:any;
- private targets: Array<TargetUiObject>; // UI object to hold all targets with names.
- @Input() policy: PolicyInstance;
- @Input() topologyTemplate: TopologyTemplate;
@Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
@HostBinding('class') classes = 'component-details-panel-tab-policy-targets';
+ @Select(GraphState.getSelectedComponent) policy$: Observable<PolicyInstance>;
+ public policy: PolicyInstance;
+ private subscription;
+
+ private addModalInstance: SdcUiComponents.ModalComponent;
+ public targets: Array<TargetUiObject>; // UI object to hold all targets with names.
+
constructor(private translateService: TranslateService,
private policiesService: PoliciesService,
- private modalService: SdcUiComponents.ModalService,
- private eventListenerService: EventListenerService
- ) {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, this.initTargets)
- }
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService,
+ private store: Store
+ ) { }
- ngOnChanges(changes:SimpleChanges):void {
- this.initTargets();
+ ngOnInit() {
+ this.subscription = this.policy$.pipe(
+ tap((policy) => {
+ if(policy instanceof PolicyInstance){
+ this.policy = policy;
+ this.targets = this.policy.getTargetsAsUiObject(<ComponentInstance[]>this.compositionService.componentInstances, this.compositionService.groupInstances);
+ }
+ })).subscribe();
}
- ngOnDestroy() {
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE);
+ ngOnDestroy () {
+ if(this.subscription)
+ this.subscription.unsubscribe();
}
deleteTarget(target: TargetUiObject): void {
- this.isLoading.emit(true);
- this.policiesService.deletePolicyTarget(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.policy, target.uniqueId, target.type).subscribe(
+ this.loaderService.activate();
+ this.policiesService.deletePolicyTarget(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy, target.uniqueId, target.type).subscribe(
(policyInstance:PolicyInstance) => {
+ this.targets = this.targets.filter(item => item.uniqueId !== target.uniqueId);
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, policyInstance);
+ // this.store.dispatch(new UpdateSelectedComponentAction({uniqueId: policyInstance.uniqueId, type:ComponentType.}));
+ },
+ error => {
+ console.log("Error deleting target!");
+ this.loaderService.deactivate();
},
- error => console.log("Error deleting target!"),
- () => this.isLoading.emit(false)
+ () => this.loaderService.deactivate()
);
}
- private initTargets = (policyInstance?: PolicyInstance) => {
- this.policy = policyInstance ? policyInstance : this.policy;
- this.targets = this.policy.getTargetsAsUiObject(this.topologyTemplate.componentInstances, this.topologyTemplate.groupInstances);
- }
addTargets = ():void => {
- var targetsToAdd:Array<TargetUiObject> = this.modalService.getCurrentInstance().innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
+ var targetsToAdd:Array<TargetUiObject> = this.addModalInstance.innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
if(targetsToAdd.length > 0) {
- this.modalService.closeModal();
- this.isLoading.emit(true);
- var updatedTarget: Array<TargetUiObject> = _.union(this.targets, targetsToAdd);
- this.policiesService.updateTargets(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.policy.uniqueId, updatedTarget).subscribe(
+ this.addModalInstance.closeModal();
+ this.loaderService.activate();
+ var updatedTargets: Array<TargetUiObject> = _.union(this.targets, targetsToAdd);
+ this.policiesService.updateTargets(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy.uniqueId, updatedTargets).subscribe(
(updatedPolicyInstance:PolicyInstance) => {
+ this.targets = updatedTargets;
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, updatedPolicyInstance);
+ // this.store.dispatch(new UpdateSelectedComponentAction({component: updatedPolicyInstance}));
},
error => {
console.log("Error updating targets!");
+ this.loaderService.deactivate();
},
- () => this.isLoading.emit(false)
+ () => this.loaderService.deactivate()
);
}
}
@@ -104,7 +126,7 @@ export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
getOptionalsTargetsToAdd():Array<TargetUiObject> {
let optionalsTargetsToAdd:Array<TargetUiObject> = [];
// adding all instances as optional targets to add if not already exist
- _.forEach(this.topologyTemplate.componentInstances, (instance:ComponentInstance) => {
+ _.forEach(this.compositionService.componentInstances, (instance:ComponentInstance) => {
if (!_.some(this.targets, (target:TargetUiObject) => {
return target.uniqueId === instance.uniqueId
})) {
@@ -113,7 +135,7 @@ export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
});
// adding all groups as optional targets to add if not already exist
- _.forEach(this.topologyTemplate.groupInstances, (groupInstance:ComponentInstance) => { // adding all instances as optional targets to add if not already exist
+ _.forEach(this.compositionService.groupInstances, (groupInstance:ComponentInstance) => { // adding all instances as optional targets to add if not already exist
if (!_.some(this.targets, (target:TargetUiObject) => {
return target.uniqueId === groupInstance.uniqueId
})) {
@@ -125,21 +147,20 @@ export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
}
openAddTargetModal(): void {
- let addTargetModalConfig: IModalConfig = {
+ let addTargetModalConfig = {
title: this.policy.name + " ADD TARGETS",
size: "md",
- type: "custom",
+ type: SdcUiCommon.ModalType.custom,
testId: "addTargetsModal",
buttons: [
{text: "ADD TARGETS", size: 'xsm', callback: this.addTargets, closeModal: false},
{text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
]
- };
+ } as SdcUiCommon.IModalConfig;
var optionalTargetsToAdd = this.getOptionalsTargetsToAdd();
- this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, {
+ this.addModalInstance = this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, {
elementsToAdd: optionalTargetsToAdd,
elementName: "target"
});
-
}
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
new file mode 100644
index 0000000000..86c6fea1ef
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
@@ -0,0 +1,97 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <div class="w-sdc-designer-sidebar-section">
+ <div *ngIf="properties">
+ <ng-container *ngFor="let key of objectKeys(properties); let idx = index">
+ <sdc-accordion [title]="groupNameByKey(key) + ' Properties'" [css-class]="'properties-accordion'" [arrow-direction]="'right'" [testId]="groupNameByKey(key) + 'properties'" [open]="true">
+
+ <!--ng-show="isShowDetailsSection" -->
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngIf="!groupPropertiesByInstance">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" attr.data-tests-id="propertyRow"
+ *ngFor="let property of properties[key]">
+
+ <div class="property-details">
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{property.name}}"
+ (click)="!isViewOnly && updateProperty(property)"
+ attr.data-tests-id="{{property.name}}">{{property.name}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{property.defaultValue}}">{{property.defaultValue}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="!isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{property.value}}"
+ attr.data-tests-id="value_{{property.name}}">{{property.value}}</span>
+ </div>
+ <div class="property-buttons">
+ <svg-icon *ngIf="!isViewOnly && (isPropertyOwner() && !property.readonly)" name="trash-o" clickable="true" size="medium" mode="info" testId="delete_{{property.name}}" (click)="deleteProperty(property)"></svg-icon>
+ </div>
+ </div>
+ </div>
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngIf="groupPropertiesByInstance">
+ <ng-container *ngFor="let InstanceProperties of properties[key]; let propIndex = index">
+ <div class="vfci-properties-group">
+ <div class="second-level">
+ <div class="expand-collapse-title-icon"></div>
+ <span class="w-sdc-designer-sidebar-section-title-text" sdc-tooltip tooltip-text="{{getComponentInstanceNameFromInstanceByKey(InstanceProperties.key)}}&nbsp;Properties"
+ attr.data-tests-id="vfci-properties">{{getComponentInstanceNameFromInstanceByKey(InstanceProperties.key) + ' Properties'}}</span>
+ </div>
+ </div>
+ <div class="w-sdc-designer-sidebar-section-content instance-properties {{propIndex}}">
+ <div class="i-sdc-designer-sidebar-section-content-item">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" attr.data-tests-id="propertyRow"
+ *ngFor="let instanceProperty of InstanceProperties.value">
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{instanceProperty.name}}"
+ attr.data-tests-id="vfci-property">{{instanceProperty.name}}</span>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value"
+ sdc-tooltip tooltip-text="{{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}">
+ {{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-container>
+ </div>
+ <!--<div class="w-sdc-designer-sidebar-section-footer" *ngIf="(!isViewOnly && isPropertyOwner()) || showAddPropertyButton">-->
+ <!--<button class="w-sdc-designer-sidebar-section-footer-action tlv-btn blue" attr.data-tests-id="addGrey" (click)="addProperty()" type="button">-->
+ <!--Add Property-->
+ <!--</button>-->
+ <!--</div>-->
+ </sdc-accordion>
+ </ng-container>
+ </div>
+
+ <!--attributes-->
+ <div *ngIf="attributes">
+ <ng-container *ngFor="let key of objectKeys(attributes); let attrIndex = index">
+ <sdc-accordion [title]="groupNameByKey(key) + ' Attributes'" [arrow-direction]="'right'" [testId]="groupNameByKey(key) + 'attributes'" [css-class]="'attributes-accordion'">
+ <!--ng-show="isShowDetailsSection" -->
+ <div class="i-sdc-designer-sidebar-section-content-item">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute"
+ *ngFor="let attribute of attributes[key]">
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{attribute.name}}"
+ (click)="!isViewOnly && viewAttribute(attribute)"
+ attr.data-tests-id="{{attribute.name}}-attr">{{attribute.name}}</span>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{attribute.defaultValue}}">{{attribute.defaultValue}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="!isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{attribute.value}}" attr.data-tests-id="value-of-{{attribute.name}}">{{attribute.value}}</span>
+ </div>
+ </div>
+ </div>
+ </sdc-accordion>
+ </ng-container>
+ </div>
+ </div>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
new file mode 100644
index 0000000000..5cb0697da1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
@@ -0,0 +1,66 @@
+.scroll-container {
+ display: flex;
+ overflow-y: auto;
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute {
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ border-bottom: 1px solid #cdcdcd;
+ min-height: 72px;
+ padding: 15px 10px 10px 18px;
+ // position: relative;
+ display:flex;
+
+ .property-details {
+ flex:1;
+ }
+
+ .property-buttons {
+ flex: 0 0 auto;
+ align-self: center;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute-label {
+ display: block;
+ font-weight: bold;
+ &:hover {
+ color: #3b7b9b;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute-label, .i-sdc-designer-sidebar-section-content-item-property-value {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 245px;
+ white-space: nowrap;
+ display: block;
+}
+
+
+
+/deep/ .expand-collapse-content {
+ max-height: max-content;
+ padding: 10px 0;
+
+ .sdc-accordion .sdc-accordion-header {
+
+ background-color: #e6f6fb;
+ border-left: solid #009fdb 4px;
+ box-shadow: 0 0px 3px -1px rgba(0, 0, 0, 0.3);
+ margin-bottom: 2px;
+ width: auto;
+ height: auto;
+ padding: 10px;
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+
+ }
+
+ /deep/.sdc-accordion .sdc-accordion-body {
+ padding-left: 0;
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
new file mode 100644
index 0000000000..b4b8248ed0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
@@ -0,0 +1,212 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ AttributeModel,
+ AttributesGroup,
+ Component as TopologyTemplate,
+ ComponentMetadata,
+ FullComponentInstance,
+ PropertiesGroup,
+ PropertyModel
+} from 'app/models';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe';
+import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { ModalsHandler } from 'app/utils';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
+
+@Component({
+ selector: 'properties-tab',
+ templateUrl: './properties-tab.component.html',
+ styleUrls: ['./properties-tab.component.less']
+})
+export class PropertiesTabComponent implements OnInit {
+ attributes: AttributesGroup;
+ isComponentInstanceSelected: boolean;
+ properties: PropertiesGroup;
+ groupPropertiesByInstance: boolean;
+ propertiesMessage: string;
+ metadata: ComponentMetadata;
+ objectKeys = Object.keys;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() input: {title: string};
+
+ constructor(private store: Store,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private modalsHandler: ModalsHandler,
+ private topologyTemplateService: TopologyTemplateService,
+ private modalService: SdcUiServices.ModalService,
+ private translateService: TranslateService,
+ private groupByPipe: GroupByPipe) {
+ }
+
+ ngOnInit() {
+ this.metadata = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.getComponentInstancesPropertiesAndAttributes();
+ }
+
+ public isPropertyOwner = (): boolean => {
+ return this.component instanceof TopologyTemplate && this.component.isResource();
+ }
+
+ public updateProperty = (property: PropertyModel): void => {
+ this.openEditPropertyModal(property);
+ }
+
+ public deleteProperty = (property: PropertyModel): void => {
+
+ const onOk: Function = (): void => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+ this.topologyTemplateService.deleteProperty(this.component.componentType, this.component.uniqueId, property.uniqueId)
+ .subscribe((response) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.component.properties = this.component.properties.filter((prop) => prop.uniqueId !== property.uniqueId);
+ this.initComponentProperties();
+ }, () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ });
+ };
+
+ const title: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TITLE');
+ const message: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TEXT', {name: property.name});
+ const okButton = {
+ testId: 'OK',
+ text: 'OK',
+ type: SdcUiCommon.ButtonType.info,
+ callback: onOk,
+ closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
+ }
+
+ public groupNameByKey = (key: string): string => {
+ switch (key) {
+ case 'derived':
+ return 'Derived';
+
+ case this.metadata.uniqueId:
+ return ResourceNamePipe.getDisplayName(this.metadata.name);
+
+ default:
+ return this.getComponentInstanceNameFromInstanceByKey(key);
+ }
+ }
+
+ public getComponentInstanceNameFromInstanceByKey = (key: string): string => {
+ let instanceName: string = '';
+ const componentInstance = this.compositionService.getComponentInstances().find((item) => item.uniqueId === key);
+ if (key !== undefined && componentInstance) {
+
+ instanceName = ResourceNamePipe.getDisplayName(componentInstance.name);
+ }
+ return instanceName;
+ }
+
+ private getComponentInstancesPropertiesAndAttributes = () => {
+ this.topologyTemplateService.getComponentInstanceAttributesAndProperties(
+ this.workspaceService.metadata.uniqueId,
+ this.workspaceService.metadata.componentType)
+ .subscribe((genericResponse: ComponentGenericResponse) => {
+ this.compositionService.componentInstancesAttributes = genericResponse.componentInstancesAttributes || new AttributesGroup();
+ this.compositionService.componentInstancesProperties = genericResponse.componentInstancesProperties;
+ this.initPropertiesAndAttributes();
+ });
+ }
+
+ private initComponentProperties = (): void => {
+ let result: PropertiesGroup = {};
+
+ this.propertiesMessage = undefined;
+ this.groupPropertiesByInstance = false;
+ if (this.component instanceof FullComponentInstance) {
+ result[this.component.uniqueId] = _.orderBy(this.compositionService.componentInstancesProperties[this.component.uniqueId], ['name']);
+ if (this.component.originType === 'VF') {
+ this.groupPropertiesByInstance = true;
+ result[this.component.uniqueId] = Array.from(this.groupByPipe.transform(result[this.component.uniqueId], 'path'));
+ }
+ } else if (this.metadata.isService()) {
+ // Temporally fix to hide properties for service (UI stack when there are many properties)
+ result = this.compositionService.componentInstancesProperties;
+ this.propertiesMessage = 'Note: properties for service are disabled';
+ } else {
+ const componentUid = this.component.uniqueId;
+ result[componentUid] = Array<PropertyModel>();
+ const derived = Array<PropertyModel>();
+ _.forEach(this.component.properties, (property: PropertyModel) => {
+ if (componentUid === property.parentUniqueId) {
+ result[componentUid].push(property);
+ } else {
+ property.readonly = true;
+ derived.push(property);
+ }
+ });
+ if (derived.length) {
+ result['derived'] = derived;
+ }
+ this.objectKeys(result).forEach((key) => { result[key] = _.orderBy(result[key], ['name']); });
+ }
+ this.properties = result;
+ }
+
+ private initComponentAttributes = (): void => {
+ let result: AttributesGroup = {};
+
+ if (this.component) {
+ if (this.component instanceof FullComponentInstance) {
+ result[this.component.uniqueId] = this.compositionService.componentInstancesAttributes[this.component.uniqueId] || [];
+ } else if (this.metadata.isService()) {
+ result = this.compositionService.componentInstancesAttributes;
+ } else {
+ result[this.component.uniqueId] = (this.component as TopologyTemplate).attributes;
+ }
+ this.attributes = result;
+ this.objectKeys(this.attributes).forEach((key) => {
+ this.attributes[key] = _.orderBy(this.attributes[key], ['name']);
+ });
+
+ }
+ }
+
+ /**
+ * This function is checking if the component is the value owner of the current property
+ * in order to notify the edit property modal which fields to disable
+ */
+ private isPropertyValueOwner = (): boolean => {
+ return this.metadata.isService() || !!this.component;
+ }
+
+ /**
+ * The function opens the edit property modal.
+ * It checks if the property is from the VF or from one of it's resource instances and sends the needed property list.
+ * For create property reasons an empty array is transferd
+ *
+ * @param property the wanted property to edit/create
+ */
+ private openEditPropertyModal = (property: PropertyModel): void => {
+ this.modalsHandler.newOpenEditPropertyModal(property,
+ (this.isPropertyOwner() ?
+ this.properties[property.parentUniqueId] :
+ this.properties[property.resourceInstanceUniqueId]) || [],
+ this.isPropertyValueOwner(), 'component', property.resourceInstanceUniqueId).then((updatedProperty: PropertyModel) => {
+ if (updatedProperty) {
+ const oldProp = _.find(this.properties[updatedProperty.resourceInstanceUniqueId],
+ (prop: PropertyModel) => prop.uniqueId === updatedProperty.uniqueId);
+ oldProp.value = updatedProperty.value;
+ }
+ });
+ }
+
+ private initPropertiesAndAttributes = (): void => {
+ this.initComponentProperties();
+ this.initComponentAttributes();
+ }
+}
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
new file mode 100644
index 0000000000..27e05ec1f0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html
@@ -0,0 +1,36 @@
+<div class="w-sdc-designer-sidebar-tab-content sdc-general-tab relations">
+ <div *ngIf="!isCurrentDisplayComponentIsComplex(); else complexComponentTemplate">
+ <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
+ <sdc-accordion [title]="'Capabilities'" [arrow-direction]="'right'" [testId]="'Capabilities-accordion'">
+ <div *ngFor="let capability of capabilities" class="relations-details-container">
+ <div class="relations-name">{{capability.name}}&nbsp;</div>
+ <div class="relations-desc"> {{capability.type}} </div>
+ </div>
+ </sdc-accordion>
+ </div>
+ <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
+ <sdc-accordion [title]="'Requirements'" [arrow-direction]="'right'" [testId]="'Requirements-accordion'">
+ <requirement-list [component]='component' [requirements]="requirements" [isInstanceSelected]="isComponentInstanceSelected"></requirement-list>
+ </sdc-accordion>
+
+ </div>
+ </div>
+
+ <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}}&nbsp;</div>
+ <div class="relations-desc"> {{capability.type}} </div>
+ </div>
+ </sdc-accordion>
+ </sdc-accordion>
+
+ <sdc-accordion *ngIf="requirementsInstancesMap" [title]="'Requirements'" [arrow-direction]="'right'" [testId]="'Requirements-accordion'">
+ <sdc-accordion *ngFor="let key of objectKeys(requirementsInstancesMap); let i = index" [title]="key">
+ <requirement-list [component]='component' [requirements]="requirementsInstancesMap[key]" [isInstanceSelected]="isComponentInstanceSelected"></requirement-list>
+ </sdc-accordion>
+ </sdc-accordion>
+
+ </ng-template>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less
new file mode 100644
index 0000000000..fe4573aadc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less
@@ -0,0 +1,57 @@
+
+/deep/.sdc-accordion {
+ margin-bottom: 0;
+ display: grid;
+
+ .sdc-accordion-header {
+ background-color: #e6f6fb;
+ border-left: solid #009fdb 4px;
+ box-shadow: 0 0px 3px -1px rgba(0, 0, 0, 0.3);
+ margin-bottom: 2px;
+ width: auto;
+ height: auto;
+ padding: 10px;
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ }
+
+ .sdc-accordion-body.open {
+ padding-left: 0;
+ padding-top: 0;
+ .sdc-accordion-header { /*Second level - nested accordion */
+ background-color: #f8f8f8;
+ padding: 4px 20px 4px 37px;
+ border-bottom: 1px solid #d2d2d2;
+ border-left:none;
+ height: 30px;
+ }
+ }
+}
+
+
+.relations-details-container {
+ border-bottom: 1px solid #cdcdcd;
+ padding: 10px 10px 10px 18px;
+
+ font-size: 14px;
+ font-family: OpenSans-Regular, sans-serif;
+
+ .relations-name {
+ color: #666666;
+ font-weight: bold;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ text-transform: capitalize;
+ max-width: 240px;
+ display: inline-block;
+ }
+
+ .relations-desc {
+ color: #8c8c8c;
+ word-wrap: break-word;
+ white-space: normal;
+ max-width: 265px;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 0000000000..03697b38f2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts
@@ -0,0 +1,165 @@
+import { Component, OnInit, Input, OnDestroy } from '@angular/core';
+import { Component as TopologyTemplate, Capability, Requirement, CapabilitiesGroup, RequirementsGroup, ComponentInstance, 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";
+import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service";
+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";
+
+
+export class InstanceCapabilitiesMap {
+ [key:string]:Array<Capability>;
+}
+
+export class InstanceRequirementsMap {
+ [key:string]:Array<Requirement>;
+}
+
+@Component({
+ selector: 'req-capabilities-tab',
+ templateUrl: './req-capabilities-tab.component.html',
+ styleUrls: ['./req-capabilities-tab.component.less']
+})
+export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy {
+
+ isComponentInstanceSelected: boolean;
+ capabilities:Array<Capability>;
+ requirements:Array<Requirement>;
+ capabilitiesInstancesMap:InstanceCapabilitiesMap;
+ requirementsInstancesMap:InstanceRequirementsMap;
+ objectKeys = Object.keys;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | FullComponentInstance;
+ @Input() input: any;
+
+
+ constructor(private store: Store,
+ private topologyTemplateService:TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService:EventListenerService) { }
+
+ ngOnInit(): void {
+
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+
+ this.requirements = [];
+ this.capabilities = [];
+ this.initEvents();
+ this.initRequirementsAndCapabilities();
+
+ }
+
+ private initEvents = ():void => {
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ }
+
+ ngOnDestroy(): void {
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ }
+
+ public isCurrentDisplayComponentIsComplex = ():boolean => {
+
+ if (this.component instanceof FullComponentInstance) {
+ if (this.component.originType === 'VF') {
+ return true;
+ }
+ return false;
+ } else {
+ return this.component.isComplex();
+ }
+ }
+
+ private loadComplexComponentData = () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ this.topologyTemplateService.getCapabilitiesAndRequirements(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId).subscribe((response:ComponentGenericResponse) => {
+ this.workspaceService.metadata.capabilities = response.capabilities;
+ this.workspaceService.metadata.requirements = response.requirements;
+ this.setScopeCapabilitiesRequirements(response.capabilities, response.requirements);
+ this.initInstancesMap();
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ }, (error) => { this.store.dispatch(new TogglePanelLoadingAction({isLoading: false})); });
+ }
+
+
+ private extractValuesFromMap = (map:CapabilitiesGroup | RequirementsGroup):Array<any> => {
+ let values = [];
+ _.forEach(map, (capabilitiesOrRequirements:Array<Capability> | Array<Requirement>, key) => {
+ values = values.concat(capabilitiesOrRequirements)
+ }
+ );
+ return values;
+ }
+
+ private setScopeCapabilitiesRequirements = (capabilities:CapabilitiesGroup, requirements:RequirementsGroup) => {
+ this.capabilities = this.extractValuesFromMap(capabilities);
+ this.requirements = this.extractValuesFromMap(requirements);
+ }
+
+
+ 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);
+ }
+ });
+
+ this.requirementsInstancesMap = new InstanceRequirementsMap();
+ _.forEach(this.requirements, (requirement:Requirement) => {
+ if (this.requirementsInstancesMap[requirement.ownerName]) {
+ this.requirementsInstancesMap[requirement.ownerName] = this.requirementsInstancesMap[requirement.ownerName].concat(requirement);
+ } else {
+ this.requirementsInstancesMap[requirement.ownerName] = new Array<Requirement>(requirement);
+ }
+ });
+ }
+
+ private initRequirementsAndCapabilities = (needUpdate?: boolean) => {
+
+ // if instance selected, we take the requirement and capabilities of the instance - always exist because we load them with the graph
+ if (this.component instanceof FullComponentInstance) {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.setScopeCapabilitiesRequirements(this.component.capabilities, this.component.requirements);
+ if (this.component.originType === 'VF') {
+ this.initInstancesMap();
+ }
+ } else {
+ // if instance not selected, we take the requirement and capabilities of the VF/SERVICE, if not exist we call api
+ if (needUpdate || !this.component.capabilities || !this.component.requirements) {
+ this.loadComplexComponentData();
+
+ } else {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.setScopeCapabilitiesRequirements(this.component.capabilities, this.component.requirements);
+ this.initInstancesMap();
+ }
+ }
+ }
+
+ private updateRequirementCapabilities = () => {
+ if (!this.isComponentInstanceSelected) {
+ this.loadComplexComponentData();
+ }
+ }
+
+
+
+
+}
+
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
new file mode 100644
index 0000000000..8292729cf8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html
@@ -0,0 +1,20 @@
+<div class="i-sdc-designer-sidebar-capabilities-requirements">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-group">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations"
+ *ngFor="let requirement of requirements">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-name">{{requirement.name}}&nbsp;</div>
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-desc">{{requirement.node}}
+ <div *ngIf="getRelation(requirement) != null">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-indent-box"></div>
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-child">
+ <span class="i-sdc-designer-sidebar-section-content-item-relations-details-desc">{{getRelation(requirement).type}} <br/></span>
+ <span class="i-sdc-designer-sidebar-section-content-item-relations-details-name">{{getRelation(requirement).requirementName}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts
new file mode 100644
index 0000000000..e167c47dcc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts
@@ -0,0 +1,40 @@
+import { Component, Input } from '@angular/core';
+import { Component as TopologyTemplate, RelationshipModel, Relationship, Requirement } from "app/models";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { ResourceNamePipe } from "app/ng2/pipes/resource-name.pipe";
+
+@Component({
+ selector: 'requirement-list',
+ templateUrl: './requirement-list.component.html'
+})
+export class RequirementListComponent {
+ @Input() component: TopologyTemplate;
+ @Input() requirements: Array<Requirement>;
+ @Input() isInstanceSelected:boolean;
+
+
+ constructor(private compositionService: CompositionService) { }
+
+
+ public getRelation = (requirement:any):any => {
+ if (this.isInstanceSelected && this.component.componentInstancesRelations) {
+ let relationItem:Array<RelationshipModel> = _.filter(this.component.componentInstancesRelations, (relation:RelationshipModel) => {
+ return relation.fromNode === this.component.uniqueId &&
+ _.filter(relation.relationships, (relationship:Relationship) => {
+ return relationship.relation.requirement == requirement.name && relationship.relation.requirementOwnerId == requirement.ownerId;
+ }).length;
+ });
+
+ if (relationItem && relationItem.length) {
+ return {
+ type: requirement.relationship.split('.').pop(),
+ requirementName: ResourceNamePipe.getDisplayName(this.compositionService.componentInstances[_.map
+ (this.compositionService.componentInstances, "uniqueId").indexOf(relationItem[0].toNode)].name)
+ };
+ }
+ }
+ return null;
+ };
+
+};
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html
new file mode 100644
index 0000000000..a52c841156
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html
@@ -0,0 +1,15 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <service-consumption
+ [parentService]="metadata"
+ [selectedService]="component"
+ [selectedServiceInstanceId]="component.uniqueId"
+ [instancesMappedList]="instancesMappedList"
+ [parentServiceInputs]="componentInputs"
+ [instancesCapabilitiesMap]="instancesCapabilitiesMap"
+ [readonly]="isViewOnly">
+ </service-consumption>
+ </content>
+</ng2-expand-collapse>
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.less
index e69de29bb2..e69de29bb2 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.less
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts
new file mode 100644
index 0000000000..8715afd047
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts
@@ -0,0 +1,89 @@
+
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ CapabilitiesGroup,
+ Capability,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ FullComponentInstance,
+ InputBEModel,
+ InputsGroup,
+ InterfaceModel,
+ PropertiesGroup
+} from 'app/models';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { ServiceInstanceObject } from '../../../../../../models/service-instance-properties-and-interfaces';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../../../services/responses/component-generic-response';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { SelectedComponentType } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'service-consumption-tab',
+ templateUrl: './service-consumption-tab.component.html',
+ styleUrls: ['./service-consumption-tab.component.less'],
+})
+export class ServiceConsumptionTabComponent {
+ isComponentInstanceSelected: boolean;
+
+ instancesMappedList: ServiceInstanceObject[];
+ componentInstancesProperties: PropertiesGroup;
+ componentInstancesInputs: InputsGroup;
+ componentInstancesInterfaces: Map<string, InterfaceModel[]>;
+ componentInputs: InputBEModel[];
+ componentCapabilities: Capability[];
+ instancesCapabilitiesMap: Map<string, Capability[]>;
+ metadata: ComponentMetadata;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | FullComponentInstance;
+ @Input() input: any;
+
+ constructor(private store: Store,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService: EventListenerService ) {}
+ ngOnInit() {
+ this.metadata = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.initInstances();
+ }
+
+ private initInstances = (): void => {
+ this.topologyTemplateService.getServiceConsumptionData(this.metadata.componentType, this.metadata.uniqueId).subscribe((genericResponse: ComponentGenericResponse) => {
+ this.componentInstancesProperties = genericResponse.componentInstancesProperties;
+ this.componentInstancesInputs = genericResponse.componentInstancesInputs;
+ this.componentInstancesInterfaces = genericResponse.componentInstancesInterfaces;
+ this.componentInputs = genericResponse.inputs;
+ this.buildInstancesCapabilitiesMap(genericResponse.componentInstances);
+ this.updateInstanceAttributes();
+ });
+ }
+
+ private buildInstancesCapabilitiesMap = (componentInstances: Array<ComponentInstance>): void => {
+ this.instancesCapabilitiesMap = new Map();
+ let flattenCapabilities = [];
+ _.forEach(componentInstances, (componentInstance) => {
+ flattenCapabilities = CapabilitiesGroup.getFlattenedCapabilities(componentInstance.capabilities);
+ this.instancesCapabilitiesMap[componentInstance.uniqueId] = _.filter(flattenCapabilities, cap => cap.properties && cap.ownerId === componentInstance.uniqueId);
+ });
+ }
+
+ private updateInstanceAttributes = (): void => {
+ if (this.isComponentInstanceSelected && this.componentInstancesProperties) {
+ this.instancesMappedList = this.compositionService.componentInstances.map((coInstance) => new ServiceInstanceObject({
+ id: coInstance.uniqueId,
+ name: coInstance.name,
+ properties: this.componentInstancesProperties[coInstance.uniqueId] || [],
+ inputs: this.componentInstancesInputs[coInstance.uniqueId] || [],
+ interfaces: this.componentInstancesInterfaces[coInstance.uniqueId] || []
+ }));
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html
new file mode 100644
index 0000000000..47351a46a1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html
@@ -0,0 +1,18 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <div *ngIf="isComponentInstanceSelected">
+ <service-dependencies
+ [compositeService]="metaData"
+ [currentServiceInstance]="component"
+ [selectedInstanceProperties]="selectedInstanceProperties"
+ [selectedInstanceSiblings]="selectedInstanceSiblings"
+ [selectedInstanceConstraints]="selectedInstanceConstraints"
+ [readonly]="isViewOnly"
+ (dependencyStatus)="notifyDependencyEventsObserver($event)"
+ (updateRulesListEvent)="updateSelectedInstanceConstraints($event)"
+ (loadRulesListEvent)="loadConstraints()">
+ </service-dependencies>
+ </div>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less
new file mode 100644
index 0000000000..47e26e2d64
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less
@@ -0,0 +1,3 @@
+:host /deep/ .expand-collapse-content {
+ padding: 0 0 10px;
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts
new file mode 100644
index 0000000000..5171e3b607
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts
@@ -0,0 +1,95 @@
+
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ CapabilitiesGroup,
+ Capability,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ FullComponentInstance,
+ InputBEModel,
+ InputsGroup,
+ InterfaceModel,
+ PropertiesGroup,
+ PropertyBEModel,
+} from 'app/models';
+import { DEPENDENCY_EVENTS } from 'app/utils/constants';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { ServiceInstanceObject } from '../../../../../../models/service-instance-properties-and-interfaces';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { ConstraintObject } from '../../../../../components/logic/service-dependencies/service-dependencies.component';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../../../services/responses/component-generic-response';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { SelectedComponentType } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'service-dependencies-tab',
+ templateUrl: 'service-dependencies-tab.component.html',
+ styleUrls: ['service-dependencies-tab.component.less']
+})
+export class ServiceDependenciesTabComponent {
+ isComponentInstanceSelected: boolean;
+
+ selectedInstanceSiblings: ServiceInstanceObject[];
+ componentInstancesConstraints: any[];
+ selectedInstanceConstraints: ConstraintObject[];
+ selectedInstanceProperties: PropertyBEModel[];
+ componentInstanceProperties: PropertiesGroup;
+ metaData: ComponentMetadata;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() input: any;
+
+ constructor(private store: Store,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService: EventListenerService) {
+ }
+
+ ngOnInit() {
+ this.metaData = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.initInstancesWithProperties();
+ this.loadConstraints();
+ this.initInstancesWithProperties();
+ }
+
+ public loadConstraints = (): void => {
+ this.topologyTemplateService.getServiceFilterConstraints(this.metaData.componentType, this.metaData.uniqueId).subscribe((response) => {
+ this.componentInstancesConstraints = response.nodeFilterData;
+ });
+ }
+
+ public notifyDependencyEventsObserver = (isChecked: boolean): void => {
+ this.eventListenerService.notifyObservers(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, isChecked);
+ }
+
+ public updateSelectedInstanceConstraints = (constraintsList:Array<ConstraintObject>):void => {
+ this.componentInstancesConstraints[this.component.uniqueId].properties = constraintsList;
+ this.selectedInstanceConstraints = this.componentInstancesConstraints[this.component.uniqueId].properties;
+ }
+
+ private initInstancesWithProperties = (): void => {
+ this.topologyTemplateService.getComponentInstanceProperties(this.metaData.componentType, this.metaData.uniqueId).subscribe((genericResponse: ComponentGenericResponse) => {
+ this.componentInstanceProperties = genericResponse.componentInstancesProperties;
+ this.updateInstanceAttributes();
+ });
+ }
+
+ private updateInstanceAttributes = (): void => {
+ if (this.isComponentInstanceSelected && this.componentInstanceProperties) {
+ const instancesMappedList = this.compositionService.componentInstances.map((coInstance) => new ServiceInstanceObject({
+ id: coInstance.uniqueId,
+ name: coInstance.name,
+ properties: this.componentInstanceProperties[coInstance.uniqueId] || []
+ }));
+ this.selectedInstanceProperties = this.componentInstanceProperties[this.component.uniqueId];
+ this.selectedInstanceSiblings = instancesMappedList.filter((coInstance) => coInstance.id !== this.component.uniqueId);
+ }
+ }
+}