diff options
author | ys9693 <ys9693@att.com> | 2020-01-19 13:50:02 +0200 |
---|---|---|
committer | Ofir Sonsino <ofir.sonsino@intl.att.com> | 2020-01-22 12:33:31 +0000 |
commit | 16a9fce0e104a38371a9e5a567ec611ae3fc7f33 (patch) | |
tree | 03a2aff3060ddb5bc26a90115805a04becbaffc9 /catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities | |
parent | aa83a2da4f911c3ac89318b8e9e8403b072942e1 (diff) |
Catalog alignment
Issue-ID: SDC-2724
Signed-off-by: ys9693 <ys9693@att.com>
Change-Id: I52b4aacb58cbd432ca0e1ff7ff1f7dd52099c6fe
Diffstat (limited to 'catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities')
4 files changed, 0 insertions, 1295 deletions
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html deleted file mode 100644 index 566cc5fc2c..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html +++ /dev/null @@ -1,247 +0,0 @@ -<!-- - ~ Copyright © 2016-2018 European Support Limited - ~ - ~ 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. ---> - -<div class="workspace-req-and-cap-editable"> - <loader data-display="isLoading"></loader> - - <div class="tabs-header"> - <div class="req-and-cap-tabs"> - <div data-tests-id="req-tab" data-ng-click="onSwitchTab()" class="tab" - data-ng-class="{'selected':mode=='requirements'}">Requirements - </div> - <div data-tests-id="cap-tab" data-ng-click="onSwitchTab()" class="tab" - data-ng-class="{'selected':mode=='capabilities'}">Capabilities - </div> - </div> - <div class="buttons-in-right" data-ng-if="!isListEmpty()"> - <div class="search"> - <input id="search-box" data-ng-if="filter.show" data-tests-id="search-box" placeholder="Search" - data-ng-model-options="{debounce: 200}" data-ng-model="filter.txt" data-ng-change="onFilter()"/> - <div class="search-icon-container" data-tests-id="search-icon"> - <svg-icon - class="hand" - [name]="'search-o'" - [mode]="'primary'" - [size]="'small'" - [clickable]="'true'" - data-ng-click="onSearchIconClick()"> - </svg-icon> - </div> - </div> - <div class="add-button-icon-and-label" data-ng-if="isEditable" data-ng-click="onAddBtnClicked()" - data-ng-class="{'disabled': isReadonly()}" data-tests-id="add-button"> - <svg-icon - name="plus" - mode="primary" - size="small" - clickable="true" - [disabled]="isReadonly()" - labelPlacement="top"> - </svg-icon> - <span class="icon-label-txt">{{mode === 'requirements' ? 'Add Requirement' : 'Add Capability'}}</span> - </div> - </div> - </div> - - <div class="empty-list-container" data-ng-if="isListEmpty() && !isLoading" data-tests-id="empty-list-container"> - <div class="empty-list-add-btn add-button-icon-and-label" data-ng-class="{'disabled': isReadonly()}" - data-ng-click="onAddBtnClicked()" data-tests-id="empty-list-add-btn"> - <svg-icon - name="plus-circle" - mode="primary" - size="x_large" - clickable="true" - [disabled]="isReadonly()"> - </svg-icon> - <div class="icon-label-txt">{{mode === 'requirements' ? 'Add Requirement' : 'Add Capability'}}</div> - </div> - </div> - - <div class="table-container-flex requirements-table" data-ng-if="mode=='requirements' && !isListEmpty()"> - <div class="table" data-ng-class="{'view-mode': isViewMode()}" data-tests-id="requirement-table"> - <div class="head flex-container"> - <div data-ng-repeat="header in editableRequirementsTableHeadersList track by $index" - data-ng-click="sort(header.property, requirementsSortTableDefined, false)" - class="table-header head-row hand flex-item {{header.property}}" - data-tests-id="table-header-{{header.property}}"> - {{header.title}} - <span data-ng-if="requirementsSortTableDefined.sortByField === header.property" - class="table-header-sort-arrow" data-tests-id="table-header-sort-arrow" - data-ng-class="{'down': requirementsSortTableDefined.reverse, 'up':!requirementsSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="editable-table-data"> - <div data-ng-if="filteredRequirementsList.length === 0" class="no-row-text" - data-tests-id="no-rows-in-table"> - There are no requirements to display - - </div> - <div data-ng-repeat="req in filteredRequirementsList | orderBy:requirementsSortTableDefined.sortByField:requirementsSortTableDefined.reverse track by $index" - data-tests-id="reqRow"> - <div class="flex-container data-row" data-ng-class="{'editable-row': req.isCreatedManually}" - data-ng-click="req.isCreatedManually && onEditRequirement(req)"> - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}"> - <span data-tests-id="{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}">{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}</span> - </div> - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{req.capability}}"> - <span data-tests-id="{{req.capability}}">{{req.capability && cutToscaTypePrefix(req.capability, 'capabilities.')}}</span> - </div> - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{req.node}}"> - <span data-tests-id="{{req.node}}">{{req.node && cutToscaTypePrefix(req.node, "nodes.")}}</span> - </div> - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{req.relationship}}"> - <span data-tests-id="{{req.relationship}}">{{req.relationship && cutToscaTypePrefix(req.relationship, "relationships.")}}</span> - </div> - <div class="table-col-general flex-item text ellipsis-text occurrences-col" tooltips - tooltip-content="{{req.minOccurrences}} - {{req.maxOccurrences}}"> - <span data-tests-id="{{req.minOccurrences}} - {{req.maxOccurrences}}">{{req.minOccurrences}} - {{req.maxOccurrences}}</span> - </div> - <div class="table-col-general flex-item text other-col" data-tests-id="delete-req" - data-ng-class="{'disabled': isReadonly()}"> - <svg-icon name="trash-o" class="trash-icon" size="small" - data-ng-if="req.isCreatedManually && !isReadonly()" - data-ng-click="onDeleteReq($event, req)"></svg-icon> - </div> - </div> - </div> - </perfect-scrollbar> - </div> - - </div> - </div> - <div class="table-container-flex capabilities-table" data-ng-if="mode=='capabilities' && !isListEmpty()" - data-tests-id="capabilities-table"> - <div class="table" data-ng-class="{'view-mode': isViewMode()}"> - <div class="head flex-container"> - <div data-ng-repeat="header in editableCapabilitiesTableHeadersList track by $index" - data-ng-click="sort(header.property, capabilitiesSortTableDefined, true)" - class="table-header head-row hand flex-item {{header.property}}" - data-tests-id="header-{{header.property}}"> - {{header.title}} - <span data-ng-if="capabilitiesSortTableDefined.sortByField === header.property" - class="table-header-sort-arrow" data-tests-id=="table-header-sort-arrow" - data-ng-class="{'down': capabilitiesSortTableDefined.reverse, 'up':!capabilitiesSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="editable-table-data"> - <div data-ng-if="filteredCapabilitiesList.length === 0" class="no-row-text" - data-tests-id="no-rows-in-table"> - There are no capabilities to display - </div> - <div data-ng-repeat-start="capability in filteredCapabilitiesList | orderBy:capabilitiesSortTableDefined.sortByField:capabilitiesSortTableDefined.reverse track by $index" - class="flex-container data-row" - data-ng-class="{'selected': capability.selected, 'editable-row': capability.isCreatedManually}" - data-ng-click="capability.isCreatedManually && onEditCapability(capability)" - data-tests-id="capabilities-table-row"> - - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}}"> - <span class="sprite-new arrow-up-small hand" - data-ng-class="{'hideme': !capability.properties.length, 'opened': capability.selected}" - data-ng-click="capability.selected = !capability.selected; $event.stopPropagation();"></span> - <span data-tests-id="{{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}}" - class="name-col" data-ng-class="{'opened': capability.selected}"> - {{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}} - </span> - </div> - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{capability.type}}"> - <span data-tests-id="{{capability.type}}">{{capability.type && cutToscaTypePrefix(capability.type, 'capabilities.')}}</span> - </div> - - <div class="table-col-general flex-item text description-col"> - <div data-tests-id="{{capability.description}}" class="multiline-ellipsis" - ellipsis="capability.description" max-chars="60">{{capability.description}} - </div> - </div> - - <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{capability.validSourceTypes.join(',')}}"> - <span data-tests-id="{{capability.validSourceTypes.join(',')}}">{{capability.validSourceTypes.join(',')}}</span> - </div> - - <div class="table-col-general flex-item text ellipsis-text occurrences-col" tooltips - tooltip-content="{{capability.minOccurrences}} - {{capability.maxOccurrences}}"> - <span data-tests-id="{{capability.minOccurrences}} - {{capability.maxOccurrences}}">{{capability.minOccurrences}} - {{capability.maxOccurrences}}</span> - </div> - - <div class="table-col-general flex-item text other-col" data-tests-id="delete-cap" - data-ng-class="{'disabled': isReadonly()}"> - <svg-icon name="trash-o" class="trash-icon" size="small" - data-ng-if="capability.isCreatedManually && !isReadonly()" - data-ng-click="onDeleteCap($event, capability)"></svg-icon> - </div> - </div> - <div data-ng-repeat-end data-ng-if="capability.selected" class="item-opened properties-section"> - <p class="properties-title">Properties</p> - <div class="table-container-flex properties-table"> - <div class="table" data-ng-class="{'view-mode': true}"> - <div class="head flex-container"> - <div class="table-header head-row hand flex-item" - data-ng-repeat="header in capabilityPropertiesTableHeadersList track by $index" - data-ng-click="sort(header.property, propertiesSortTableDefined, false)"> - {{header.title}} - <span data-ng-if="propertiesSortTableDefined.sortByField === header.property" - class="table-header-sort-arrow" - data-ng-class="{'down': propertiesSortTableDefined.reverse, 'up':!propertiesSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <div data-ng-repeat="property in capability.properties | orderBy:propertiesSortTableDefined.sortByField:propertiesSortTableDefined.reverse track by $index" - data-tests-id="propertyRow" - class="flex-container data-row"> - <div class="table-col-general flex-item text" - data-tests-id="{{property.name}}" - tooltips tooltip-content="{{property.name}}"> - {{property.name}} - </div> - <div class="table-col-general flex-item text" - data-tests-id="{{property.type}}" - tooltips tooltip-content="{{property.type}}"> - {{property.type}} - </div> - <div class="table-col-general flex-item text" - data-tests-id="{{property.schema.property.type}}" - tooltips tooltip-content="{{property.schema.property.type}}"> - {{property.schema.property.type}} - </div> - <div class="table-col-general flex-item text" - tooltips tooltip-content="{{property.description}}" - data-tests-id="{{property.description}}"> - {{property.description}} - </div> - </div> - </div> - - </div> - </div> - </div> - </perfect-scrollbar> - </div> - - </div> - </div> -</div> - diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view-model.ts deleted file mode 100644 index 14b45cbdf3..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view-model.ts +++ /dev/null @@ -1,471 +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========================================================= - */ - -/** - * Created by rcohen on 9/22/2016. - */ -'use strict'; -import * as _ from "lodash"; -import {ComponentRef} from '@angular/core'; -import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; -import {ModalsHandler, ResourceType} from "app/utils"; -import {ComponentType} from "app/utils/constants"; -import { - Capability, PropertyModel, Requirement, Resource, - RelationshipTypesMap, NodeTypesMap, CapabilityTypesMap -} from "app/models"; -import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; -import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service"; -import {ToscaTypesServiceNg2} from "app/ng2/services/tosca-types.service"; -import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; -import {ModalService} from 'app/ng2/services/modal.service'; -import {RequirementsEditorComponent} from 'app/ng2/pages/req-and-capabilities-editor/requirements-editor/requirements-editor.component'; -import {CapabilitiesEditorComponent} from 'app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component'; -import {ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"; -import {IModalConfig} from "sdc-ui/lib/angular/modals/models/modal-config"; -import {ModalButtonComponent} from "sdc-ui/lib/angular/components"; - -export class SortTableDefined { - reverse:boolean; - sortByField:string; -} - -class RequirementUI extends Requirement { - isCreatedManually: boolean; - - constructor(input: Requirement, componentUniqueId: string) { - super(input); - this.isCreatedManually = input.ownerId === componentUniqueId; - } -} -class CapabilityUI extends Capability { - isCreatedManually: boolean; - - constructor(input: Capability, componentUniqueId: string) { - super(input); - this.isCreatedManually = input.ownerId === componentUniqueId; - } -} - -interface IReqAndCapabilitiesViewModelScope extends IWorkspaceViewModelScope { - requirementsTableHeadersList:Array<any>; - editableRequirementsTableHeadersList: Array<any>; - capabilitiesTableHeadersList:Array<any>; - editableCapabilitiesTableHeadersList: Array<any>; - capabilityPropertiesTableHeadersList:Array<any>; - requirementsSortTableDefined:SortTableDefined; - capabilitiesSortTableDefined:SortTableDefined; - propertiesSortTableDefined:SortTableDefined; - requirements: Array<RequirementUI>; - filteredRequirementsList: Array<RequirementUI>; - capabilities: Array<CapabilityUI>; - filteredCapabilitiesList: Array<CapabilityUI>; - mode:string; - filteredProperties:Array<Array<PropertyModel>>; - searchText:string; - isEditable: boolean; - modalInstance: ComponentRef<ModalComponent>; - filter: {txt: string; show: boolean}; - - sort(sortBy: string, sortByTableDefined: SortTableDefined, autoCollapseCapabilitiesRows: boolean): void; - sortByIsCreatedManually(arrToSort: Array<RequirementUI|CapabilityUI>): Array<any>; - updateProperty(property:PropertyModel, indexInFilteredProperties:number):void; - allCapabilitiesSelected(selected:boolean):void; - onAddBtnClicked(): void; - onEditRequirement(req: RequirementUI): void; - onEditCapability(cap: CapabilityUI): void; - onDeleteReq(event, req: RequirementUI): void; - onDeleteCap(event, cap: CapabilityUI): void; - onFilter(): void; - isListEmpty(): boolean; - onSwitchTab(): void; - onSearchIconClick(): void; - cutToscaTypePrefix(valToCut: string, textToStartCut: string): string; - isReadonly(): boolean; -} - -export class ReqAndCapabilitiesViewModel { - - static '$inject' = [ - '$scope', - '$filter', - 'ModalsHandler', - 'ComponentServiceNg2', - 'ToscaTypesServiceNg2', - 'ModalServiceNg2', - 'ModalServiceSdcUI' - ]; - - - constructor(private $scope:IReqAndCapabilitiesViewModelScope, - private $filter:ng.IFilterService, - private ModalsHandler:ModalsHandler, - private ComponentServiceNg2: ComponentServiceNg2, - private ToscaTypesServiceNg2: ToscaTypesServiceNg2, - private ModalServiceNg2: ModalService, - private ModalServiceSdcUI: ModalServiceSdcUI) { - - this.initCapabilitiesAndRequirements(); - this.fetchCapabilitiesRelatedData(); - } - - private initCapabilitiesAndRequirements = (): void => { - - this.$scope.isEditable = this.getIsEditableByComponentType(); - this.$scope.isLoading = true; - this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: ComponentGenericResponse) => { - this.$scope.component.capabilities = response.capabilities; - this.$scope.component.requirements = response.requirements; - this.initScope(); - this.$scope.isLoading = false; - }, () => { - this.$scope.isLoading = false; - }); - - } - - private openEditPropertyModal = (property:PropertyModel, indexInFilteredProperties:number):void => { - //...because there is not be api - _.forEach(this.$scope.filteredProperties[indexInFilteredProperties], (prop:PropertyModel)=> { - prop.readonly = true; - }); - this.ModalsHandler.openEditPropertyModal(property, this.$scope.component, this.$scope.filteredProperties[indexInFilteredProperties], false, "component", this.$scope.component.uniqueId).then(() => { - - }); - }; - - private initScope = (currentMode = 'requirements'): void => { - this.$scope.isReadonly = (): boolean => { - return this.$scope.isViewMode() || !this.$scope.isDesigner(); - }; - this.$scope.filter = {txt: '', show: false}; - this.$scope.requirementsSortTableDefined = { - reverse: false, - sortByField: this.$scope.isEditable ? 'other' : 'name' - }; - this.$scope.capabilitiesSortTableDefined = { - reverse: false, - sortByField: this.$scope.isEditable ? 'other' : 'name' - }; - this.$scope.propertiesSortTableDefined = { - reverse: false, - sortByField: 'name' - }; - - this.$scope.setValidState(true); - this.$scope.requirementsTableHeadersList = [ - {title: 'Name', property: 'name'}, - {title: 'Capability', property: 'capability'}, - {title: 'Node', property: 'node'}, - {title: 'Relationship', property: 'relationship'}, - {title: 'Connected To', property: ''}, - {title: 'Occurrences', property: ''} - ]; - this.$scope.capabilitiesTableHeadersList = [ - {title: 'Name', property: 'name'}, - {title: 'Type', property: 'type'}, - {title: 'Description', property: ''}, - {title: 'Valid Source', property: ''}, - {title: 'Occurrences', property: ''} - ]; - this.$scope.editableRequirementsTableHeadersList = [ - {title: 'Name', property: 'name'}, - {title: 'Capability', property: 'capability'}, - {title: 'Node', property: 'node'}, - {title: 'Relationship', property: 'relationship'}, - {title: 'Occurrences', property: 'occurrences'}, - {title: '●●●', property: 'other'} - ]; - this.$scope.editableCapabilitiesTableHeadersList = [ - {title: 'Name', property: 'name'}, - {title: 'Type', property: 'type'}, - {title: 'Description', property: 'description'}, - {title: 'Valid Sources', property: 'valid-sources'}, - {title: 'Occurrences', property: 'occurrences'}, - {title: '●●●', property: 'other'} - ]; - this.$scope.capabilityPropertiesTableHeadersList = [ - {title: 'Name', property: 'name'}, - {title: 'Type', property: 'type'}, - {title: 'Schema', property: 'schema.property.type'}, - {title: 'Description', property: 'description'}, - ]; - this.$scope.filteredProperties = []; - - this.$scope.mode = currentMode; - this.$scope.requirements = []; - _.forEach(this.$scope.component.requirements, (req:Array<Requirement>, capName)=> { - let reqUIList: Array<RequirementUI> = _.map(req, reqObj => new RequirementUI(reqObj, this.$scope.component.uniqueId)); - this.$scope.requirements = this.$scope.requirements.concat(reqUIList); - }); - this.$scope.filteredRequirementsList = this.$scope.requirements; - - this.$scope.capabilities = []; - _.forEach(this.$scope.component.capabilities, (cap:Array<Capability>, capName)=> { - let capUIList: Array<CapabilityUI> = _.map(cap, capObj => new CapabilityUI(capObj, this.$scope.component.uniqueId)); - this.$scope.capabilities = this.$scope.capabilities.concat(capUIList); - }); - - this.$scope.sortByIsCreatedManually = (arrToSort: Array<RequirementUI|CapabilityUI>): Array<any> => { - return arrToSort.sort((elem1: RequirementUI|CapabilityUI, elem2: RequirementUI|CapabilityUI) => +elem2.isCreatedManually - (+elem1.isCreatedManually)); - }; - this.$scope.filteredCapabilitiesList = this.$scope.sortByIsCreatedManually(this.$scope.capabilities); - this.$scope.filteredRequirementsList = this.$scope.sortByIsCreatedManually(this.$scope.requirements); - - this.$scope.sort = (sortBy: string, sortByTableDefined: SortTableDefined, autoCollapseCapabilitiesRows: boolean): void => { - sortByTableDefined.reverse = (sortByTableDefined.sortByField === sortBy) ? !sortByTableDefined.reverse : false; - sortByTableDefined.sortByField = sortBy; - if (autoCollapseCapabilitiesRows) { - this.$scope.allCapabilitiesSelected(false); - } - }; - - this.$scope.updateProperty = (property:PropertyModel, indexInFilteredProperties:number):void => { - this.openEditPropertyModal(property, indexInFilteredProperties); - }; - - this.$scope.allCapabilitiesSelected = (selected:boolean):void => { - _.forEach(this.$scope.capabilities, (cap:Capability)=> { - cap.selected = selected; - }); - }; - this.$scope.onAddBtnClicked = (): void => { - switch (this.$scope.mode) { - case 'requirements': - this.openRequirementsModal(); - break; - case 'capabilities': - this.openCapabilitiesModal(); - break; - } - }; - this.$scope.onEditRequirement = (req: RequirementUI): void => { - this.openRequirementsModal(req); - }; - this.$scope.onEditCapability = (cap: CapabilityUI): void => { - this.openCapabilitiesModal(cap); - }; - this.$scope.onDeleteReq = (event: Event, req: RequirementUI): void => { - event.stopPropagation(); - this.ModalServiceSdcUI.openAlertModal('Delete Requirement', - `Are you sure you want to delete requirement: ${req.name}?`, 'OK', () => this.deleteRequirement(req), 'Cancel'); - }; - this.$scope.onDeleteCap = (event: Event, cap: CapabilityUI): void => { - event.stopPropagation(); - this.ModalServiceSdcUI.openAlertModal('Delete Capability', - `Are you sure you want to delete capability: ${cap.name}?`, 'OK', () => this.deleteCapability(cap), 'Cancel'); - }; - this.$scope.onSearchIconClick = (): void => { - this.$scope.filter.show = !!this.$scope.filter.txt || !this.$scope.filter.show; - }; - this.$scope.onFilter = (): void => { - switch (this.$scope.mode) { - case 'requirements': - this.$scope.filteredRequirementsList = _.filter(this.$scope.requirements, req => req.name.includes(this.$scope.filter.txt)); - break; - case 'capabilities': - this.$scope.filteredCapabilitiesList = _.filter(this.$scope.capabilities, cap => cap.name.includes(this.$scope.filter.txt)); - break; - } - }; - this.$scope.isListEmpty = (): boolean => { - switch (this.$scope.mode) { - case 'requirements': - return this.$scope.requirements.length === 0; - case 'capabilities': - return this.$scope.capabilities.length === 0; - } - }; - this.$scope.onSwitchTab = (): void => { - this.$scope.mode = this.$scope.mode === 'requirements' ? 'capabilities' : 'requirements'; - this.$scope.filter.txt = ''; - this.$scope.filter.show = false; - this.$scope.filteredRequirementsList = this.$scope.requirements; - this.$scope.filteredCapabilitiesList = this.$scope.capabilities; - }; - this.$scope.cutToscaTypePrefix = (valToCut: string, textToStartCut: string): string => { - let index = valToCut.indexOf(textToStartCut); - return index !== -1 ? valToCut.substr(index + textToStartCut.length) : valToCut; - }; - }; - - private getIsEditableByComponentType() { - if (this.$scope.componentType === ComponentType.SERVICE) { - return true; - } - if (this.$scope.component.isResource()) { - let componentAsResource: Resource = <Resource>this.$scope.component; - return componentAsResource.resourceType === ResourceType.VF || - componentAsResource.resourceType === ResourceType.PNF; - } - return false; - }; - - private fetchCapabilitiesRelatedData() { - if (this.$scope.isEditable) { - this.$scope.capabilityTypesList = []; - this.ToscaTypesServiceNg2.fetchCapabilityTypes().subscribe((result: CapabilityTypesMap) => { - _.forEach(result, capabilityType => this.$scope.capabilityTypesList.push(capabilityType)); - }); - this.$scope.nodeTypesList = []; - this.ToscaTypesServiceNg2.fetchNodeTypes().subscribe((result: NodeTypesMap) => { - _.forEach(result, nodeType => this.$scope.nodeTypesList.push(nodeType)); - }); - this.$scope.relationshipTypesList = []; - this.ToscaTypesServiceNg2.fetchRelationshipTypes().subscribe((result: RelationshipTypesMap) => { - _.forEach(result, relshipType => this.$scope.relationshipTypesList.push(relshipType)); - }); - } - } - - private openRequirementsModal(req?: RequirementUI) { - let modalConfig: IModalConfig = { - size: 'md', - title: (req ? 'Update' : 'Add') + ' Requirement', - type: 'custom', - buttons: [ - { - id: 'saveButton', - text: (req ? 'Update' : 'Create'), - size: "'x-small'", - callback: () => this.createOrUpdateRequirement(), - closeModal: true - }, - {text: "Cancel", size: "'x-small'", closeModal: true}] - }; - let modalInputs = { - requirement: req, - relationshipTypesList: this.$scope.relationshipTypesList, - nodeTypesList: this.$scope.nodeTypesList, - capabilityTypesList: this.$scope.capabilityTypesList, - isReadonly: this.$scope.isViewMode() || !this.$scope.isDesigner(), - validityChangedCallback: this.getDisabled - }; - - this.ModalServiceSdcUI.openCustomModal(modalConfig, RequirementsEditorComponent, {input: modalInputs}); - } - - private openCapabilitiesModal(cap?: CapabilityUI) { - let modalConfig: IModalConfig = { - size: 'md', - title: (cap ? 'Update' : 'Add') + ' Capability', - type: 'custom', - buttons: [ - { - id: 'saveButton', - text: (cap ? 'Update' : 'Create'), - size: "'x-small'", - callback: () => this.createOrUpdateCapability(), - closeModal: true - }, - {text: "Cancel", size: "'x-small'", closeModal: true}] - }; - let modalInputs = { - capability: cap, - capabilityTypesList: this.$scope.capabilityTypesList, - isReadonly: this.$scope.isViewMode() || !this.$scope.isDesigner(), - validityChangedCallback: this.getDisabled - }; - - this.ModalServiceSdcUI.openCustomModal(modalConfig, CapabilitiesEditorComponent, {input: modalInputs}); - } - - getDisabled = (shouldEnable: boolean): void => { - let saveButton: ModalButtonComponent = this.ModalServiceSdcUI.getCurrentInstance().getButtonById('saveButton'); - saveButton.disabled = this.$scope.isViewMode() || !this.$scope.isDesigner() || !shouldEnable; - }; - - private createOrUpdateRequirement() { - let requirement = this.ModalServiceSdcUI.getCurrentInstance().innerModalContent.instance.requirementData; - this.$scope.isLoading = true; - if (!requirement.uniqueId) { - this.ComponentServiceNg2.createRequirement(this.$scope.component, requirement).subscribe(result => { - this.$scope.requirements.unshift(new RequirementUI(result[0], this.$scope.component.uniqueId)); - this.$scope.isLoading = false; - }, () => { - this.$scope.isLoading = false; - }); - } - else { - this.ComponentServiceNg2.updateRequirement(this.$scope.component, requirement).subscribe(result => { - let index = this.$scope.requirements.findIndex(req => result[0].uniqueId === req.uniqueId); - this.$scope.requirements[index] = new RequirementUI(result[0], this.$scope.component.uniqueId); - this.$scope.isLoading = false; - this.$scope.$apply(); - }, () => { - this.$scope.isLoading = false; - }); - } - } - - private createOrUpdateCapability() { - let capability = this.ModalServiceSdcUI.getCurrentInstance().innerModalContent.instance.capabilityData; - this.$scope.isLoading = true; - if (!capability.uniqueId) { - this.ComponentServiceNg2.createCapability(this.$scope.component, capability).subscribe(result => { - this.$scope.capabilities.unshift(new CapabilityUI(result[0], this.$scope.component.uniqueId)); - this.$scope.isLoading = false; - }, () => { - this.$scope.isLoading = false; - }); - } - else { - this.ComponentServiceNg2.updateCapability(this.$scope.component, capability).subscribe(result => { - let index = this.$scope.capabilities.findIndex(cap => result[0].uniqueId === cap.uniqueId); - this.$scope.capabilities[index] = new CapabilityUI(result[0], this.$scope.component.uniqueId); - this.$scope.isLoading = false; - this.$scope.$apply(); - }, () => { - this.$scope.isLoading = false; - }); - } - } - - private deleteRequirement(req) { - this.$scope.isLoading = true; - this.ComponentServiceNg2.deleteRequirement(this.$scope.component, req.uniqueId).subscribe(() => { - this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.$scope.componentType, this.$scope.component.uniqueId).subscribe(response => { - this.$scope.component.requirements = response.requirements; - this.initScope('requirements'); - this.$scope.isLoading = false; - }, () => { - this.$scope.isLoading = false; - }); - }, () => { - this.$scope.isLoading = false; - }); - } - - private deleteCapability(cap) { - this.$scope.isLoading = true; - this.ComponentServiceNg2.deleteCapability(this.$scope.component, cap.uniqueId).subscribe(() => { - this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.$scope.componentType, this.$scope.component.uniqueId).subscribe(response => { - this.$scope.component.capabilities = response.capabilities; - this.initScope('capabilities'); - this.$scope.isLoading = false; - }, () => { - this.$scope.isLoading = false; - }); - }, () => { - this.$scope.isLoading = false; - }); - } -} - diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view.html b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view.html deleted file mode 100644 index c661afe0ba..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view.html +++ /dev/null @@ -1,159 +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. ---> - -<div class="workspace-req-and-cap"> - <div class="tabs"> - <button data-tests-id="req-tab" data-ng-click="mode='requirements';filterTerms='';" class="tlv-btn" data-ng-class="{'selected':mode=='requirements'}">Requirements({{requirements.length||'0'}})</button> - <button data-tests-id="cap-tab" data-ng-click="mode='capabilities';filterTerms='';" class="tlv-btn" data-ng-class="{'selected':mode=='capabilities'}">Capabilities({{capabilities.length||'0'}})</button> - </div> - <div class="expand-collapse-buttons" data-ng-if="mode=='capabilities'"> - <span class="sprite-new expand-all" data-ng-click="allCapabilitiesSelected(true)"></span> - <span class="sprite-new collapse-all" data-ng-click="allCapabilitiesSelected(false)"></span> - </div> - <div class="search"> - <input id="search-box" data-tests-id="search-box" type="search" placeholder="Search" data-ng-model-options="{debounce: 200}" data-ng-model="filterTerms"/> - <div class="search-icon-container"> - <span class="search-icon sprite-new search-white-icon"></span> - </div> - </div> - <div class="table-container-flex requirements-table" data-ng-if="mode=='requirements'"> - <div class="table" data-ng-class="{'view-mode': isViewMode()}"> - <div class="head flex-container"> - <div class="table-header head-row hand flex-item" data-ng-repeat="header in requirementsTableHeadersList track by $index" data-ng-click="sort(header.property, requirementsSortTableDefined)">{{header.title}} - <span data-ng-if="requirementsSortTableDefined.sortByField === header.property" class="table-header-sort-arrow" data-ng-class="{'down': requirementsSortTableDefined.reverse, 'up':!requirementsSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> - <div data-ng-if="requirements.length === 0" class="no-row-text"> - There are no requirements to display - - </div> - <div data-ng-repeat="req in requirements | orderBy:requirementsSortTableDefined.sortByField:requirementsSortTableDefined.reverse | filter: {filterTerm:filterTerms} track by $index" - class="flex-container data-row" data-tests-id="reqRow"> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{req.name}}"> - <span data-tests-id="{{req.name}}">{{req.name}}</span> - </div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{req.capability}}"> - <span data-tests-id="{{req.capability}}">{{req.capability.substring("tosca.capabilities.".length)}}</span> - </div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{req.node}}"> - <span data-tests-id="{{req.node}}">{{req.node.substring("tosca.nodes.".length)}}</span> - </div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{req.relationship}}"> - <span data-tests-id="{{req.relationship}}">{{req.relationship.substring("tosca.relationships.".length)}}</span> - </div> - <div class="table-col-general flex-item text" data-tests-id="{{}}" data-ng-bind=""></div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{req.minOccurrences}},{{req.maxOccurrences}}"> - <span data-tests-id="{{req.minOccurrences}},{{req.maxOccurrences}}">{{req.minOccurrences}},{{req.maxOccurrences}}</span> - </div> - </div> - </perfect-scrollbar> - </div> - - </div> - </div> - <div class="table-container-flex capabilities-table" data-ng-if="mode=='capabilities'"> - <div class="table" data-ng-class="{'view-mode': isViewMode()}"> - <div class="head flex-container"> - <div class="table-header head-row hand flex-item" data-ng-repeat="header in capabilitiesTableHeadersList track by $index" data-ng-click="sort(header.property, capabilitiesSortTableDefined)">{{header.title}} - <span data-ng-if="capabilitiesSortTableDefined.sortByField === header.property" class="table-header-sort-arrow" data-ng-class="{'down': capabilitiesSortTableDefined.reverse, 'up':!capabilitiesSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> - <div data-ng-if="capabilities.length === 0" class="no-row-text"> - There are no capabilities to display - - </div> - <div data-ng-repeat-start="capability in capabilities | orderBy:capabilitiesSortTableDefined.sortByField:capabilitiesSortTableDefined.reverse | filter: {filterTerm:filterTerms} track by $index" - class="flex-container data-row" data-ng-class="{'selected': capability.selected}" - data-ng-click="capability.selected = !capability.selected" data-tests-id="capabilities-table-row"> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{capability.name}}"> - <span class="sprite-new arrow-up-small" data-ng-class="{'opened': capability.selected}"></span> - <span data-tests-id="{{capability.name}}">{{capability.name}}</span> - </div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{capability.type}}"> - <span data-tests-id="{{capability.type}}">{{capability.type.replace("tosca.capabilities.","")}}</span> - </div> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{capability.description}}"> - <span data-tests-id="{{capability.description}}">{{capability.description}}</span> - </div> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{capability.validSourceTypes.join(',')}}"> - <span data-tests-id="{{capability.validSourceTypes.join(',')}}">{{capability.validSourceTypes.join(',')}}</span> - </div> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{capability.minOccurrences}},{{capability.maxOccurrences}}"> - <span data-tests-id="{{capability.minOccurrences}},{{capability.maxOccurrences}}">{{capability.minOccurrences}},{{capability.maxOccurrences}}</span> - </div> - </div> - <div data-ng-repeat-end="" data-ng-if="capability.selected" class="item-opened"> - <p class="properties-title">Properties</p> - <div class="table-container-flex properties-table"> - <div class="table" data-ng-class="{'view-mode': isViewMode()}"> - <div class="head flex-container"> - <div class="table-header head-row hand flex-item" data-ng-repeat="header in capabilityPropertiesTableHeadersList track by $index" data-ng-click="sort(header.property, propertiesSortTableDefined)">{{header.title}} - <span data-ng-if="propertiesSortTableDefined.sortByField === header.property" class="table-header-sort-arrow" data-ng-class="{'down': propertiesSortTableDefined.reverse, 'up':!propertiesSortTableDefined.reverse}"> </span> - </div> - </div> - - <div class="body"> - <div data-ng-if="capability.properties.length === 0" class="no-row-text"> - There are no properties to display - </div> - <div data-ng-repeat="property in filteredProperties[$parent.$index]=(capability.properties | orderBy:propertiesSortTableDefined.sortByField:propertiesSortTableDefined.reverse) track by $index" - data-tests-id="propertyRow" - class="flex-container data-row"> - - <div class="table-col-general flex-item text" tooltips tooltip-content="{{property.name}}"> - <a data-tests-id="{{property.name}}" - data-ng-click="updateProperty(property, $parent.$index); $event.stopPropagation();" - data-ng-class="{'disabled': isViewMode()}">{{property.name}}</a> - - </div> - - <div class="table-col-general flex-item text" - data-tests-id="{{property.type}}" - tooltips tooltip-content="{{property.type}}" - data-ng-bind="property.type"> - </div> - <div class="table-col-general flex-item text" - data-tests-id="{{property.schema.property.type}}" - tooltips tooltip-content="{{property.schema.property.type}}" - data-ng-bind="property.schema.property.type"> - </div> - <div class="table-col-general flex-item text" tooltips tooltip-content="{{property.description}}"> - <span data-tests-id="{{property.description}}" data-ng-bind="property.description"></span> - </div> - </div> - </div> - - </div> - </div> - </div> - </perfect-scrollbar> - </div> - - </div> - </div> -</div> - diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less deleted file mode 100644 index 928f6719c6..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less +++ /dev/null @@ -1,418 +0,0 @@ -.workspace-req-and-cap { - - width: 93%; - display: inline-block; - - .tabs{ - float: left; - position: relative; - top: 6px; - button{ - float: left; - width: 233px; - height: 38px; - background-color: @tlv_color_t; - border: 1px solid @main_color_o; - color: black; - &:nth-child(1){ - border-radius: 10px 0 0 0; - } - &:nth-child(2){ - border-radius: 0 10px 0 0; - } - &.selected{ - background-color: @main_color_a; - border: 1px solid @main_color_a; - color: white; - } - } - } - .search{ - margin-bottom: 12px; - float: right; - ::-webkit-input-placeholder { - font-style: italic; - } - :-moz-placeholder { - font-style: italic; - } - ::-moz-placeholder { - font-style: italic; - } - :-ms-input-placeholder { - font-style: italic; - } - #search-box{ - -webkit-border-radius: 2px 0 0 2px; - -moz-border-radius: 2px 0 0 2px; - border-radius: 2px 0 0 2px; - width: 213px; - height: 32px; - line-height: 32px; - border: 1px solid @main_color_o; - text-indent: 10px; - float: left; - } - .search-icon-container{ - background-color: @main_color_a; - height: 32px; - width: 32px; - border-radius: 0 2px 2px 0; - float: left; - .search-icon{ - position: relative; - top: 9px; - } - } - } - .add-button { - color: @main_color_a; - } - .add-button, .expand-collapse-buttons { - float: right; - margin-left: 11px; - margin-top: 10px; - &, span { - .hand; - } - } - - - - .table{ - height:490px; - margin-bottom: 0; - } - - .arrow-up-small{ - &.opened{ - .arrow-up-small-hover; - } - } - - .item-opened{ - background-color: @tlv_color_t; - } - - .properties-title{ - margin:0; - font-weight: bold; - } - - .table-container-flex { - margin-top: 10px; - - .text{ - overflow: hidden; - text-overflow: ellipsis; - display: inline-block; - white-space: nowrap; - } - - .editable-table-data { - max-height: 430px; - } - - .data-row { - &:not(.editable-row) { - background: @tlv_color_t; - color: @main_color_n; - } - &.editable-row { - cursor: pointer; - } - .sprite-new.delete-icon { - visibility: hidden; - } - &:hover { - .sprite-new.delete-icon { - visibility: visible; - } - } - } - - &.requirements-table{ - border-top: 4px solid @main_color_a; - .flex-item:nth-child(1) { - flex-grow: 20; - } - - .flex-item:nth-child(2) { - flex-grow: 20; - } - - .flex-item:nth-child(3) { - flex-grow: 20; - } - - .flex-item:nth-child(4) { - flex-grow: 20; - } - - .flex-item:nth-child(5) { - flex-grow: 20; - } - - .flex-item:nth-child(6) { - flex-grow: 20; - } - } - - &.capabilities-table{ - border-top: 4px solid @main_color_a; - .selected{ - .flex-item:nth-child(1) { - border-left: 4px solid @main_color_a; - padding-right: 11px; - } - } - .flex-item:nth-child(1) { - flex-grow: 10; - } - - .flex-item:nth-child(2) { - flex-grow: 10; - } - - .flex-item:nth-child(3) { - flex-grow: 10; - } - - .flex-item:nth-child(4) { - flex-grow: 10; - } - - .flex-item:nth-child(5) { - flex-grow: 10; - } - - } - - &.properties-table{ - .table{ - height: auto; - } - - .flex-item:nth-child(1) { - flex-grow: 15; - a{ - .hand - } - } - - .flex-item:nth-child(2) { - flex-grow: 6; - } - - .flex-item:nth-child(3) { - flex-grow: 6; - } - - .flex-item:nth-child(4) { - flex-grow: 20; - - } - } - - } - -} - -.workspace-req-and-cap-editable { - .tabs-header { - display: flex; - justify-content: space-between; - border-bottom: 1px solid @main_color_o; - .req-and-cap-tabs { - display: flex; - .tab { - font-family: @font-opensans-regular; - font-size: 22px; - padding: 5px; - .hand; - &:first-of-type { - margin-right: 35px; - } - &.selected { - color: @main_color_a; - border-bottom: 2px solid @main_color_a; - } - } - } - .buttons-in-right { - display: flex; - .search { - display: flex; - height: min-content; - margin-top: 10px; - padding-right: 11px; - border-right: 1px solid @main_color_o; - #search-box { - border: none; - border-bottom: 1px solid @main_color_o; - text-indent: 10px; - &:focus { - outline: none; - } - } - .search-icon-container { - margin-top: 3px; - padding-top: 4px; - } - - } - .add-button-icon-and-label { - font-size: 14px; - margin-left: 11px; - margin-top: 10px; - padding-top: 5px; - /deep/ svg-icon { - vertical-align: bottom; - } - &:hover { - &:not(.disabled) { - cursor: pointer; - color: @sdcui_color_light-blue; - } - } - } - } - } - .add-button-icon-and-label { - .icon-label-txt { - text-transform: uppercase; - font-family: @font-opensans-medium; - color: @main_color_a; - &:hover { - &:not(.disabled) { - color: @sdcui_color_light-blue; - } - } - } - } - .empty-list-container { - width: 100%; - display: flex; - justify-content: center; - - .empty-list-add-btn { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border: 1px solid @main_color_o; - margin-top: 50px; - height: 229px; - width: 480px; - &.disabled { - pointer-events: none; - } - &:hover { - &:not(.disabled) { - border: 1px solid @main_color_a; - cursor: pointer; - } - } - .icon-label-txt { - margin-top: 15px; - font-size: 16px; - } - } - } - .table-container-flex .table { - .head .head-row { - text-align: left; - &.description { - flex: 2; - } - &.other { - flex: 0.25; - text-align: center; - } - &.occurrences { - flex: 0.75; - } - } - .body .data-row { - border-bottom: none; - border-top: @main_color_o solid 1px; - .ellipsis-text { - overflow: hidden; - text-overflow: ellipsis; - } - &:not(.editable-row) { - background-color: @tlv_color_t; - cursor: default; - color: @main_color_n; - } - &.editable-row { - cursor: pointer; - .table-col-general:hover { - color: @main_color_b; - } - } - &.selected { - background-color: @tlv_color_v; - .name-col { - color: @main_color_a; - } - .sprite-new.arrow-up-small { - background-position: -858px -137px; - margin-bottom: 2px; - } - } - .description-col { - flex: 2; - } - .occurrences-col { - flex: 0.75; - } - .other-col { - display: flex; - justify-content: center; - align-items: center; - flex: 0.25; - .trash-icon { - visibility: hidden; - } - } - &:hover { - .trash-icon { - visibility: visible; - } - } - .multiline-ellipsis { - line-height: 1.5em; - padding: 1px 0 1px 0; - /deep/ .ellipsis-directive-more-less { - float: none; - margin-left: 5px; - color: @main_color_a; - } - } - } - } - - .item-opened.properties-section { - border: 4px solid @tlv_color_v !important; - max-height: 263px; - overflow: auto; - .properties-title { - .s_10; - margin-top: 10px; - } - .properties-table { - &.table-container-flex { - margin-top: 18px; - } - .table { - .head { - border-bottom: 1px solid @main_color_o; - } - .head, .table-col-general { - background-color: @main_color_p; - } - } - } - } -}
\ No newline at end of file |