aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/pages/composition
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition')
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html14
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less34
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts135
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts51
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less66
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html30
-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.html31
-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.html23
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less0
-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.html11
-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/policies/policy-information-tab.component.html34
-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.html23
-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-properties-tab.component.ts64
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html12
-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.html32
-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/policies/policy-targets-tab.component.ts145
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html34
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less11
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts60
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts54
31 files changed, 1442 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html
new file mode 100644
index 0000000000..731d6a3855
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html
@@ -0,0 +1,14 @@
+<div class="component-details-panel-header" data-tests-id="w-sdc-designer-sidebar-head">
+
+ <div class="icon">
+ <div class="large {{iconClassName}}">
+ <div [ngClass]="{'non-certified': nonCertified}" tooltip="Not certified"></div>
+ </div>
+ </div>
+
+ <div class="title" data-tests-id="selectedCompTitle" tooltip="&#8203;{{name}}">{{name}}</div>
+
+ <svg-icon-label *ngIf="!isViewOnly" name="edit-file-o" clickable="true" size="small" class="rename-instance" data-tests-id="renameInstance" (click)="renameInstance()"></svg-icon-label>
+ <svg-icon-label *ngIf="!isViewOnly" name="trash-o" clickable="true" size="small" class="delete-instance" data-tests-id="deleteInstance" (click)="deleteInstance()"></svg-icon-label>
+
+</div> \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less
new file mode 100644
index 0000000000..9bbc765761
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less
@@ -0,0 +1,34 @@
+/deep/
+.component-details-panel-header {
+ display: flex;
+ flex-direction: row;
+ height: 120px;
+ align-items: center;
+
+ .icon {
+ margin: 0 20px;
+ }
+
+ .title {
+ font-size: 16px;
+ text-overflow: ellipsis;
+ max-width: 180px;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ .rename-instance {
+ position: absolute;
+ top: 14px;
+ right: 20px;
+ cursor: pointer;
+ }
+
+ .delete-instance {
+ position: absolute;
+ top: 14px;
+ right: 40px;
+ cursor: pointer;
+ }
+
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts
new file mode 100644
index 0000000000..ab659a3b8f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts
@@ -0,0 +1,135 @@
+/*-
+ * ============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, Input, AfterViewInit, SimpleChanges, OnInit, OnChanges } from "@angular/core";
+import { SdcUiComponents } from "sdc-ui/lib/angular";
+import { IModalConfig } from 'sdc-ui/lib/angular/modals/models/modal-config';
+import { ZoneInstanceType } from 'app/models/graph/zones/zone-instance';
+import { ValueEditComponent } from './../../../../components/ui/forms/value-edit/value-edit.component';
+import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
+import { PoliciesService } from '../../../../services/policies.service';
+import { GroupsService } from '../../../../services/groups.service';
+import {IZoneService} from "../../../../../models/graph/zones/zone";
+import { EventListenerService, LoaderService } from "../../../../../services";
+import { GRAPH_EVENTS, EVENTS } from "../../../../../utils";
+import { UIZoneInstanceObject } from "../../../../../models/ui-models/ui-zone-instance-object";
+import { ModalButtonComponent } from "sdc-ui/lib/angular/components";
+
+@Component({
+ selector: 'ng2-composition-panel-header',
+ templateUrl: './panel-header.component.html',
+ styleUrls: ['./panel-header.component.less']
+})
+export class CompositionPanelHeaderComponent implements OnInit, OnChanges {
+
+ @Input() topologyTemplate: TopologyTemplate;
+ @Input() selectedZoneInstanceType: ZoneInstanceType;
+ @Input() selectedZoneInstanceId: string;
+ @Input() name: string;
+ @Input() nonCertified: boolean;
+ @Input() isViewOnly: boolean;
+ @Input() isLoading: boolean;
+
+ constructor(private groupsService:GroupsService, private policiesService: PoliciesService,
+ private modalService:SdcUiComponents.ModalService, private eventListenerService:EventListenerService) { }
+
+ private service:IZoneService;
+ private iconClassName: string;
+
+ ngOnInit(): void {
+ this.init();
+ }
+
+ ngOnChanges (changes:SimpleChanges):void {
+ if(changes.selectedZoneInstanceId){
+ this.init();
+ }
+ }
+
+ ngOnDestroy() {
+
+
+ }
+ private init = (): void => {
+ if (this.selectedZoneInstanceType === ZoneInstanceType.POLICY) {
+ this.iconClassName = "sprite-policy-icons policy";
+ this.service = this.policiesService;
+ } else if (this.selectedZoneInstanceType === ZoneInstanceType.GROUP) {
+ this.iconClassName = "sprite-group-icons group";
+ this.service = this.groupsService;
+ } else {
+ this.iconClassName = "sprite-resource-icons defaulticon";
+ }
+ }
+
+ private renameInstance = (): void => {
+ const modalConfig = {
+ title: "Edit Name",
+ size: "sm",
+ type: "custom",
+ testId: "renameInstanceModal",
+ buttons: [
+ {id: 'saveButton', text: 'OK', size: 'xsm', callback: this.saveInstanceName, closeModal: false},
+ {id: 'cancelButton', text: 'Cancel', size: 'sm', closeModal: true}
+ ] as ModalButtonComponent[]
+ } as IModalConfig;
+ this.modalService.openCustomModal(modalConfig, ValueEditComponent, {name: this.name, validityChangedCallback: this.enableOrDisableSaveButton});
+ };
+
+ private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
+ let saveButton: ModalButtonComponent = this.modalService.getCurrentInstance().getButtonById('saveButton');
+ saveButton.disabled = !shouldEnable;
+ }
+
+ private saveInstanceName = ():void => {
+ let currentModal = this.modalService.getCurrentInstance();
+ let nameFromModal:string = currentModal.innerModalContent.instance.name;
+
+ if(nameFromModal != this.name){
+ currentModal.buttons[0].disabled = true;
+ this.service.updateName(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId, nameFromModal).subscribe((success)=>{
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_INSTANCE_NAME_CHANGED, nameFromModal);
+ this.modalService.closeModal();
+ }, (error)=> {
+ currentModal.buttons[0].disabled = false;
+ });
+ } else {
+ this.modalService.closeModal();
+ }
+ };
+
+ private deleteInstance = (): void => {
+ let title:string = "Delete Confirmation";
+ let message:string = "Are you sure you would like to delete "+ this.name + "?";
+ this.modalService.openAlertModal(title, message, "OK", this.deleteInstanceConfirmed, "deleteInstanceModal");
+ };
+
+ private deleteInstanceConfirmed = () => {
+ this.eventListenerService.notifyObservers(EVENTS.SHOW_LOADER_EVENT + 'composition-graph');
+ this.service.deleteZoneInstance(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).finally(()=> {
+ this.eventListenerService.notifyObservers(EVENTS.HIDE_LOADER_EVENT + 'composition-graph');
+ }).subscribe(()=> {
+ let deletedItem:UIZoneInstanceObject = new UIZoneInstanceObject(this.selectedZoneInstanceId, this.selectedZoneInstanceType, this.name);
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE, deletedItem);
+ });
+ };
+
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts
new file mode 100644
index 0000000000..bde0a14669
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts
@@ -0,0 +1,51 @@
+/*-
+ * ============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 { CompositionPanelHeaderComponent } from "./panel-header.component";
+import { UiElementsModule } from './../../../../components/ui/ui-elements.module';
+import { ValueEditComponent } from './../../../../components/ui/forms/value-edit/value-edit.component';
+import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
+import { ModalFormsModule } from "app/ng2/components/ui/forms/modal-forms.module";
+
+@NgModule({
+ declarations: [
+ CompositionPanelHeaderComponent
+ ],
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ UiElementsModule,
+ SdcUiComponentsModule,
+ ModalFormsModule
+ ],
+ entryComponents: [
+ CompositionPanelHeaderComponent, ValueEditComponent
+ ],
+ exports: [
+ CompositionPanelHeaderComponent
+ ],
+})
+export class CompositionPanelHeaderModule {
+
+}
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/base/base-tab.component.less
new file mode 100644
index 0000000000..aa8e75115f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less
@@ -0,0 +1,66 @@
+@import './../../../../../../../assets/styles/mixins';
+@import "./../../../../../../../assets/styles/variables-old";
+@import './../../../../../../../assets/styles/mixins_old';
+
+/deep/
+.expand-collapse-content {
+ padding: 20px;
+}
+
+.component-details-panel-tab-no-data {
+ margin: 0 auto;
+ padding-top: 30px;
+ text-align: center;
+
+ .component-details-panel-tab-no-data-title {
+ font-family: @font-opensans-bold;
+ }
+
+}
+
+.component-details-panel-large-item {
+ font-family: OpenSans-Semibold, sans-serif;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ height: 32px;
+ line-height: 32px;
+ vertical-align: middle;
+
+ &:hover {
+ background-color: #f8f8f8;
+ margin: 0 -20px; /* to fill expand-collapse-content padding */
+ padding: 0 20px;
+ .component-details-panel-item-delete {
+ visibility: visible;
+ }
+ }
+}
+
+.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;
+}
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
new file mode 100644
index 0000000000..3c875fd930
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html
@@ -0,0 +1,30 @@
+<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
new file mode 100644
index 0000000000..26602224da
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts
@@ -0,0 +1,39 @@
+/*-
+ * ============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.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html
new file mode 100644
index 0000000000..f298a39a87
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html
@@ -0,0 +1,31 @@
+<div class="w-sdc-designer-sidebar-section-title" tooltip="Members">Members
+ <svg-icon-label *ngIf="!isViewOnly"
+ class="add-members-btn"
+ name="plus-circle-o"
+ mode="primary"
+ size="medium"
+ label="ADD"
+ labelPlacement="right"
+ (click)="openAddMembersModal()">
+ </svg-icon-label>
+</div>
+<div class="expand-collapse-content">
+ <ul>
+ <li *ngFor="let member of members; let i = index" class="component-details-panel-large-item"
+ tooltip="{{member.name}}">
+ <span>{{member.name}}</span>
+ <svg-icon-label *ngIf="!isViewOnly"
+ name="trash-o"
+ clickable="true"
+ size="small"
+ class="component-details-panel-item-delete"
+ data-tests-id="delete_member"
+ (click)="deleteMember(member)"></svg-icon-label>
+ </li>
+ </ul>
+
+ <div *ngIf="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>
+</div>
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
new file mode 100644
index 0000000000..1006e864fa
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less
@@ -0,0 +1,13 @@
+/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
new file mode 100644
index 0000000000..148f2133e8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts
@@ -0,0 +1,133 @@
+/*-
+ * ============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
new file mode 100644
index 0000000000..9de489e316
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html
@@ -0,0 +1,23 @@
+<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.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less
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
new file mode 100644
index 0000000000..69079347c4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts
@@ -0,0 +1,64 @@
+/*-
+ * ============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
new file mode 100644
index 0000000000..94b6619500
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html
@@ -0,0 +1,11 @@
+<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
new file mode 100644
index 0000000000..975d5c6153
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts
@@ -0,0 +1,67 @@
+/*-
+ * ============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
new file mode 100644
index 0000000000..50797f862c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts
@@ -0,0 +1,71 @@
+/*-
+ * ============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/policies/policy-information-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
new file mode 100644
index 0000000000..a1b942d56b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
@@ -0,0 +1,34 @@
+<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
new file mode 100644
index 0000000000..3639639c88
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts
@@ -0,0 +1,39 @@
+/*-
+ * ============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.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html
new file mode 100644
index 0000000000..9de489e316
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html
@@ -0,0 +1,23 @@
+<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/policies/policy-properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
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/policies/policy-properties-tab.component.ts
new file mode 100644
index 0000000000..5862135df2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts
@@ -0,0 +1,64 @@
+/*-
+ * ============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 { 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";
+
+@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'}
+})
+export class PolicyPropertiesTabComponent implements OnChanges {
+
+ @Input() policy:PolicyInstance;
+ @Input() topologyTemplate:TopologyTemplate;
+ @Input() isViewOnly: boolean;
+
+ 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) => {
+ console.log("ok");
+ });
+ }
+
+}
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
new file mode 100644
index 0000000000..b11ad7ebf9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html
@@ -0,0 +1,12 @@
+<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
new file mode 100644
index 0000000000..1e2739901d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts
@@ -0,0 +1,72 @@
+/*-
+ * ============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
new file mode 100644
index 0000000000..38dc19e1af
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts
@@ -0,0 +1,68 @@
+/*-
+ * ============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.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html
new file mode 100644
index 0000000000..097b3a4584
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html
@@ -0,0 +1,32 @@
+<div class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets
+ <svg-icon-label *ngIf="!isViewOnly"
+ class="add-policy-button"
+ name="plus-circle-o"
+ mode="primary"
+ size="medium"
+ label="ADD"
+ labelPlacement="right"
+ (click)="openAddTargetModal()">
+ </svg-icon-label>
+</div>
+<div class="expand-collapse-content">
+ <ul>
+ <li *ngFor="let target of targets; let i = index" class="component-details-panel-large-item"
+ tooltip="{{target.name}}">
+ <span>{{target.name}}</span>
+ <svg-icon-label *ngIf="!isViewOnly"
+ name="trash-o"
+ clickable="true"
+ size="small"
+ class="component-details-panel-item-delete"
+ data-tests-id="delete_target"
+ (click)="deleteTarget(target)"></svg-icon-label>
+ </li>
+ </ul>
+
+ <div *ngIf="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>
+</div>
+
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
new file mode 100644
index 0000000000..cd7ace2b6f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less
@@ -0,0 +1,12 @@
+/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.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts
new file mode 100644
index 0000000000..b79f4d9e07
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts
@@ -0,0 +1,145 @@
+/*-
+ * ============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, OnDestroy } 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 { 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';
+
+@Component({
+ selector: 'policy-targets-tab',
+ templateUrl: './policy-targets-tab.component.html',
+ styleUrls: ['./../base/base-tab.component.less', 'policy-targets-tab.component.less']
+})
+
+export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
+
+ 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';
+
+ 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)
+ }
+
+ ngOnChanges(changes:SimpleChanges):void {
+ this.initTargets();
+ }
+
+ ngOnDestroy() {
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE);
+ }
+
+ deleteTarget(target: TargetUiObject): void {
+ this.isLoading.emit(true);
+ this.policiesService.deletePolicyTarget(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.policy, target.uniqueId, target.type).subscribe(
+ (policyInstance:PolicyInstance) => {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, policyInstance);
+ },
+ error => console.log("Error deleting target!"),
+ () => this.isLoading.emit(false)
+ );
+ }
+
+ 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
+ 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(
+ (updatedPolicyInstance:PolicyInstance) => {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, updatedPolicyInstance);
+ },
+ error => {
+ console.log("Error updating targets!");
+ },
+ () => this.isLoading.emit(false)
+ );
+ }
+ }
+
+ 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) => {
+ if (!_.some(this.targets, (target:TargetUiObject) => {
+ return target.uniqueId === instance.uniqueId
+ })) {
+ optionalsTargetsToAdd.push(new TargetUiObject(instance.uniqueId, TargetOrMemberType.COMPONENT_INSTANCES, instance.name));
+ }
+ });
+
+ // 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
+ if (!_.some(this.targets, (target:TargetUiObject) => {
+ return target.uniqueId === groupInstance.uniqueId
+ })) {
+ optionalsTargetsToAdd.push(new TargetUiObject(groupInstance.uniqueId, TargetOrMemberType.GROUPS, groupInstance.name));
+ }
+ });
+
+ return optionalsTargetsToAdd;
+ }
+
+ openAddTargetModal(): void {
+ let addTargetModalConfig: IModalConfig = {
+ title: this.policy.name + " ADD TARGETS",
+ size: "md",
+ type: "custom",
+ testId: "addTargetsModal",
+ buttons: [
+ {text: "ADD TARGETS", size: 'xsm', callback: this.addTargets, closeModal: false},
+ {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
+ ]
+ };
+ var optionalTargetsToAdd = this.getOptionalsTargetsToAdd();
+ this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, {
+ elementsToAdd: optionalTargetsToAdd,
+ elementName: "target"
+ });
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html
new file mode 100644
index 0000000000..430b272ff0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html
@@ -0,0 +1,34 @@
+<ng2-composition-panel-header
+ [name]="selectedZoneInstanceName"
+ [topologyTemplate]="topologyTemplate"
+ [selectedZoneInstanceType]="selectedZoneInstanceType"
+ [selectedZoneInstanceId]="selectedZoneInstanceId"
+ [nonCertified]="nonCertified"
+ [isViewOnly]="isViewOnly"
+ [isLoading]="isLoading"
+></ng2-composition-panel-header>
+
+<div class="component-details-panel-tabs">
+ <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader>
+
+ <div *ngIf="selectedZoneInstanceType === zoneInstanceType.POLICY">
+ <policy-tabs
+ [topologyTemplate]="topologyTemplate"
+ [selectedZoneInstanceType]="selectedZoneInstanceType"
+ [selectedZoneInstanceId]="selectedZoneInstanceId"
+ [isViewOnly]="isViewOnly"
+ (isLoading)="setIsLoading($event)"
+ ></policy-tabs>
+ </div>
+
+ <div *ngIf="selectedZoneInstanceType === zoneInstanceType.GROUP">
+ <group-tabs
+ [topologyTemplate]="topologyTemplate"
+ [selectedZoneInstanceType]="selectedZoneInstanceType"
+ [selectedZoneInstanceId]="selectedZoneInstanceId"
+ [isViewOnly]="isViewOnly"
+ (isLoading)="setIsLoading($event)"
+ ></group-tabs>
+ </div>
+
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less
new file mode 100644
index 0000000000..1777d54486
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less
@@ -0,0 +1,11 @@
+/deep/
+.component-details-panel {
+
+ color: #666666;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+
+ .component-details-panel-tabs {
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts
new file mode 100644
index 0000000000..53599d6366
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts
@@ -0,0 +1,60 @@
+/*-
+ * ============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, SimpleChanges, HostBinding } from "@angular/core";
+import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
+import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { ZoneInstanceType } from "app/models/graph/zones/zone-instance";
+import { GroupsService } from "../../../services/groups.service";
+import { PoliciesService } from "../../../services/policies.service";
+import { SdcUiComponents } from "sdc-ui/lib/angular";
+import { IZoneService } from "../../../../models/graph/zones/zone";
+
+@Component({
+ selector: 'ng2-composition-panel',
+ templateUrl: './panel.component.html',
+ styleUrls: ['./panel.component.less'],
+ providers: [TranslateService]
+})
+export class CompositionPanelComponent {
+
+ @Input() topologyTemplate: TopologyTemplate;
+ @Input() selectedZoneInstanceType: ZoneInstanceType;
+ @Input() selectedZoneInstanceId: string;
+ @Input() selectedZoneInstanceName: string;
+ @Input() nonCertified: boolean;
+ @Input() isViewOnly: boolean;
+ @Input() isLoading: boolean;
+
+
+ @HostBinding('class') classes = 'component-details-panel';
+
+ private zoneInstanceType = ZoneInstanceType; // Expose ZoneInstanceType to use in template.
+
+ constructor(){
+ }
+
+ private setIsLoading = (value):void => {
+ this.isLoading = value;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts
new file mode 100644
index 0000000000..57f6be8b8e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts
@@ -0,0 +1,54 @@
+/*-
+ * ============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 {CompositionPanelComponent} from "./panel.component";
+import {CompositionPanelHeaderModule} from "app/ng2/pages/composition/panel/panel-header/panel-header.module";
+import {GroupTabsModule} from "./panel-tabs/groups/group-tabs.module";
+import {PolicyTabsModule} from "./panel-tabs/policies/policy-tabs.module";
+import {SdcUiComponents} from "sdc-ui/lib/angular";
+import {UiElementsModule} from 'app/ng2/components/ui/ui-elements.module';
+import {AddElementsModule} from "../../../components/ui/modal/add-elements/add-elements.module";
+
+@NgModule({
+ declarations: [
+ CompositionPanelComponent
+ ],
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ CompositionPanelHeaderModule,
+ PolicyTabsModule,
+ GroupTabsModule,
+ UiElementsModule,
+ AddElementsModule
+ ],
+ entryComponents: [
+ CompositionPanelComponent
+ ],
+ exports: [],
+ providers: [SdcUiComponents.ModalService]
+})
+export class CompositionPanelModule {
+
+}