diff options
Diffstat (limited to 'catalog-ui/src/app/view-models/workspace')
23 files changed, 237 insertions, 87 deletions
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.ts b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.ts index 5d22d65f52..452224a829 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {Activity} from "app/models"; import {ActivityLogService} from "app/services"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts index 5236259f30..46c2d2edf9 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts @@ -18,14 +18,18 @@ * ============LICENSE_END========================================================= */ 'use strict'; +import * as _ from "lodash"; import {Component, ComponentInstance, IAppMenu} from "app/models"; import {SharingService, CacheService, EventListenerService, LeftPaletteLoaderService} from "app/services"; import {ModalsHandler, GRAPH_EVENTS, ComponentFactory, ChangeLifecycleStateHandler, MenuHandler, EVENTS} from "app/utils"; import {IWorkspaceViewModelScope} from "../../workspace-view-model"; -import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; import {Resource} from "app/models/components/resource"; -import {ResourceType,ComponentType} from "../../../../utils/constants"; +import {ResourceType,ComponentType} from "app/utils/constants"; +import {ComponentServiceFactoryNg2} from "app/ng2/services/component-services/component.service.factory"; +import {ServiceGenericResponse} from "app/ng2/services/responses/service-generic-response"; +import {Service} from "app/models/components/service"; + export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { @@ -39,6 +43,8 @@ export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { version:string; isViewOnly:boolean; isLoadingRightPanel:boolean; + disabledTabs:boolean; + openVersionChangeModal(pathsToDelete:string[]):ng.IPromise<any>; onComponentInstanceVersionChange(component:Component); isComponentInstanceSelected():boolean; updateSelectedComponent():void @@ -49,6 +55,7 @@ export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { printScreen():void; isPNF():boolean; isConfiguration():boolean; + preventMoveTab(state: boolean):void; cacheComponentsInstancesFullData:Component; } @@ -70,7 +77,7 @@ export class CompositionViewModel { 'LeftPaletteLoaderService', 'ModalsHandler', 'EventListenerService', - 'ComponentServiceNg2' + 'ComponentServiceFactoryNg2' ]; constructor(private $scope:ICompositionViewModelScope, @@ -87,7 +94,7 @@ export class CompositionViewModel { private LeftPaletteLoaderService:LeftPaletteLoaderService, private ModalsHandler:ModalsHandler, private eventListenerService:EventListenerService, - private ComponentServiceNg2: ComponentServiceNg2) { + private ComponentServiceFactoryNg2: ComponentServiceFactoryNg2) { this.$scope.setValidState(true); this.initScope(); @@ -99,9 +106,14 @@ export class CompositionViewModel { private initGraphData = ():void => { if(!this.$scope.component.componentInstances || !this.$scope.component.componentInstancesRelations ) { this.$scope.isLoading = true; - this.ComponentServiceNg2.getComponentInstancesAndRelation(this.$scope.component).subscribe((response:ComponentGenericResponse) => { + let service = this.ComponentServiceFactoryNg2.getComponentService(this.$scope.component); + service.getComponentCompositionData(this.$scope.component).subscribe((response:ComponentGenericResponse) => { + if (this.$scope.component.isService()) { + (<Service> this.$scope.component).forwardingPaths = (<ServiceGenericResponse>response).forwardingPaths; + } this.$scope.component.componentInstances = response.componentInstances; this.$scope.component.componentInstancesRelations = response.componentInstancesRelations; + this.$scope.component.policies = response.policies; this.$scope.isLoading = false; this.initComponent(); this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED); @@ -116,17 +128,15 @@ export class CompositionViewModel { private cacheComponentsInstancesFullData:Array<Component>; private initComponent = ():void => { - this.$scope.currentComponent = this.$scope.component; this.$scope.selectedComponent = this.$scope.currentComponent; this.updateUuidMap(); this.$scope.isViewOnly = this.$scope.isViewMode(); }; - private registerGraphEvents = (scope:ICompositionViewModelScope):void => { + private registerGraphEvents = (scope:ICompositionViewModelScope):void => { this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, scope.setSelectedInstance); this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, scope.onBackgroundClick); - }; private openUpdateComponentInstanceNameModal = ():void => { @@ -136,7 +146,7 @@ export class CompositionViewModel { }; private removeSelectedComponentInstance = ():void => { - this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_MULTIPLE_COMPONENTS); + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.$scope.currentComponent.selectedInstance) this.$scope.currentComponent.selectedInstance = null; this.$scope.selectedComponent = this.$scope.currentComponent; }; @@ -151,7 +161,6 @@ export class CompositionViewModel { }; private initScope = ():void => { - this.$scope.sharingService = this.sharingService; this.$scope.sdcMenu = this.sdcMenu; this.$scope.isLoading = false; @@ -231,20 +240,60 @@ export class CompositionViewModel { }; this.$scope.deleteSelectedComponentInstance = ():void => { - let state = "deleteInstance"; - let onOk = ():void => { - this.removeSelectedComponentInstance(); - //this.$scope.graphApi.deleteSelectedNodes(); - }; - let title:string = this.$scope.sdcMenu.alertMessages[state].title; - let message:string = this.$scope.sdcMenu.alertMessages[state].message.format([this.$scope.currentComponent.selectedInstance.name]); - this.ModalsHandler.openAlertModal(title, message).then(onOk); + const {currentComponent} = this.$scope; + const {title, message} = this.$scope.sdcMenu.alertMessages['deleteInstance']; + let modalText = message.format([currentComponent.selectedInstance.name]); + + if (currentComponent.isService()) { + const {forwardingPaths} = (<Service>currentComponent); + const instanceId = currentComponent.selectedInstance.uniqueId; + + const relatedPaths = _.filter(forwardingPaths, forwardingPath => { + const pathElements = forwardingPath.pathElements.listToscaDataDefinition; + return pathElements.find(path => path.fromNode === instanceId || path.toNode === instanceId); + }); + + if (relatedPaths.length) { + const pathNames = _.map(relatedPaths, path => path.name).join(', '); + modalText += `<p>The following service paths will be erased: ${pathNames}</p>`; + } + } + + this.ModalsHandler.openAlertModal(title, modalText).then(this.removeSelectedComponentInstance); + }; + + this.$scope.openVersionChangeModal = (pathsToDelete:string[]):ng.IPromise<any> => { + const {currentComponent} = this.$scope; + const {forwardingPaths} = <Service>currentComponent; + + const relatedPaths = _.filter(forwardingPaths, path => + _.find(pathsToDelete, id => + path.uniqueId === id + ) + ).map(path => path.name); + const pathNames = _.join(relatedPaths, ', ') || 'none'; + + const {title, message} = this.$scope.sdcMenu.alertMessages['upgradeInstance']; + return this.ModalsHandler.openConfirmationModal(title, message.format([pathNames]), false); }; this.$scope.onComponentInstanceVersionChange = (component:Component):void => { - this.$scope.currentComponent = component; - this.$scope.setComponent(this.$scope.currentComponent); - this.$scope.updateSelectedComponent(); + let onChange = () => { + this.$scope.currentComponent = component; + this.$scope.setComponent(this.$scope.currentComponent); + this.$scope.updateSelectedComponent(); + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_VERSION_CHANGED, this.$scope.currentComponent); + }; + + if (component.isService()) { + const service = this.ComponentServiceFactoryNg2.getComponentService(component); + service.getComponentCompositionData(component).subscribe((response:ServiceGenericResponse) => { + (<Service>component).forwardingPaths = response.forwardingPaths; + onChange(); + }); + } else { + onChange(); + } }; this.$scope.isPNF = (): boolean => { @@ -255,6 +304,10 @@ export class CompositionViewModel { return this.$scope.selectedComponent.isResource() && (<Resource>this.$scope.selectedComponent).resourceType === ResourceType.CONFIGURATION; }; + this.$scope.preventMoveTab = (state: boolean): void => { + this.$scope.disabledTabs = state; + }; + this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, this.$scope.reload); } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html index bfb2865348..fceb73b882 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html @@ -5,6 +5,8 @@ is-view-only="isViewOnly" is-loading="isLoading"></palette> + <ng2-palette-popup-panel></ng2-palette-popup-panel> + <composition-graph component="currentComponent" data-tests-id="canvas" is-view-only="isViewOnly" with-sidebar="displayDesignerRightSidebar"></composition-graph> </div> @@ -46,7 +48,8 @@ <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.details" tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Information" - data-tests-id="information-tab"> + data-tests-id="information-tab" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new info"></div> </button> <!--<button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active"--> @@ -58,32 +61,38 @@ data-ui-sref="workspace.composition.deployment" tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Deployment Artifacts" data-tests-id="deployment-artifact-tab" - data-ng-if="!isPNF() && !isConfiguration() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())"> + data-ng-if="!isPNF() && !isConfiguration() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new deployment-artifacts"></div> </button> <button tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="{{selectedComponent.isResource() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()) ? 'Properties and Attributes': 'Inputs'}}" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.properties" - data-tests-id="properties-and-attributes-tab"> + data-tests-id="properties-and-attributes-tab" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new" ng-class="selectedComponent.isResource() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()) ? 'properties': 'inputs'"></div> </button> <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.artifacts" data-ng-if="!isConfiguration() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" - tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Information Artifacts"> + tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Information Artifacts" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new information-artifacts"></div> </button> <button data-ng-if="!selectedComponent.isService() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" ui-sref="workspace.composition.relations" tooltips tooltip-class="tooltip-custom tab-tooltip tooltip-rightside" - tooltip-content="Requirements and Capabilities"> + data-tests-id="requirements-and-capabilities" + tooltip-content="Requirements and Capabilities" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new relations"></div> </button> <button data-ng-if="selectedComponent.isService() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" ui-sref="workspace.composition.api" data-tests-id="tab-api" - tooltips tooltip-class="tooltip-custom tab-tooltip tooltip-rightside" tooltip-content="API"> + tooltips tooltip-class="tooltip-custom tab-tooltip tooltip-rightside" tooltip-content="API" + data-ng-class="{'disabled': disabledTabs}"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new api"></div> </button> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less index 624ed03431..f351450e6d 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less @@ -1,3 +1,33 @@ + .i-sdc-designer-leftbar-section-popup-panel { + position: absolute; + display: inline-block; + background-color: white; + border: solid 1px #d2d2d2; + border-top: solid 3px #13a7df; + width: 140px; + height: 40px; + z-index: 10000; + } + + .i-sdc-designer-leftbar-section-popup-panel-group { + padding-left: 8px; + padding-top: 8px; + } + + .i-sdc-designer-leftbar-section-popup-panel-plus { + border-radius: 50%; + color: white; + background-color: #13a7df; + width: 20px; + text-align: center; + display: inline-block; + cursor: pointer; + } + + .i-sdc-designer-leftbar-section-popup-panel-title { + padding-left: 10px; + display: inline-block; + } .composition{ .sdc-workspace-container{ @@ -791,7 +821,16 @@ .g_1; line-height: 18px; } - + + .service-path-buttons { + margin-top: 12px; + position: absolute; + right: 70px; + top: 53px; + &.with-sidebar { + right: 380px; + } + } //Canvas search menu .w-sdc-search-menu { position:absolute; @@ -815,8 +854,8 @@ padding:2px 50px 2px 10px; transition:all 0.4s; } - .clear-search-x { - top: 17px + .search-bar-container { + position:relative; } &:not(:hover):not(.autocomplete-visible):not(.active){ diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts index b80b63cac9..627d20528e 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import { ArtifactModel, Service, @@ -131,6 +132,7 @@ export class ResourceArtifactsViewModel { this.$scope.allowDeleteAndUpdateArtifactMap[artifact.artifactLabel] = this.allowDeleteAndUpdateArtifact(artifact); }); this.$scope.isLoading = false; + this.$scope.preventMoveTab(false); }; @@ -213,6 +215,7 @@ export class ResourceArtifactsViewModel { }; this.$scope.isLoading = true; + this.$scope.preventMoveTab(true); if (this.$scope.isComponentInstanceSelected()) { this.$scope.component.getComponentInstanceArtifactsByGroupType(this.$scope.component.selectedInstance.uniqueId, this.convertToArtifactUrl(this.$scope.artifactType)).then(onGetInstanceArtifactsSuccess, onError); } else { diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts index 0d8d17ec73..6e3258f69b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts @@ -19,11 +19,15 @@ */ 'use strict'; +import * as _ from "lodash"; import {Component} from "app/models"; import {GRAPH_EVENTS} from "app/utils"; import {LeftPaletteLoaderService, EventListenerService} from "app/services"; import {ICompositionViewModelScope} from "../../composition-view-model"; import {LeftPaletteComponent} from "../../../../../../models/components/displayComponent"; +import {ComponentServiceFactoryNg2} from "app/ng2/services/component-services/component.service.factory"; +import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service'; +import {Service} from "app/models/components/service"; export interface IEditResourceVersion { allVersions:any; @@ -45,13 +49,16 @@ export class DetailsViewModel { static '$inject' = [ '$scope', 'LeftPaletteLoaderService', - 'EventListenerService' - + 'EventListenerService', + 'ComponentServiceFactoryNg2', + 'ServiceServiceNg2' ]; constructor(private $scope:IDetailsViewModelScope, private LeftPaletteLoaderService:LeftPaletteLoaderService, - private eventListenerService:EventListenerService) { + private eventListenerService:EventListenerService, + private ComponentServiceFactoryNg2: ComponentServiceFactoryNg2, + private serviceService: ServiceServiceNg2) { this.initScope(); } @@ -112,22 +119,43 @@ export class DetailsViewModel { this.$scope.isLoading = true; this.$scope.$parent.isLoading = true; - let onSuccess = (component:Component)=> { + let service = <Service>this.$scope.currentComponent; + let {changeVersion} = this.$scope.editResourceVersion; + let componentUid:string = this.$scope.editResourceVersion.allVersions[changeVersion]; + + let onCancel = (error:any) => { this.$scope.isLoading = false; this.$scope.$parent.isLoading = false; - this.$scope.onComponentInstanceVersionChange(component); + this.$scope.editResourceVersion.changeVersion = this.$scope.currentComponent.selectedInstance.componentVersion; - this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_VERSION_CHANGED, this.$scope.currentComponent); + if (error) { + console.log(error); + } }; - let onFailed = (error:any)=> { - this.$scope.isLoading = false; - this.$scope.$parent.isLoading = false; - console.log(error); + let onUpdate = () => { + let onSuccess = (component:Component) => { + this.$scope.isLoading = false; + this.$scope.$parent.isLoading = false; + this.$scope.onComponentInstanceVersionChange(component); + }; + + this.$scope.currentComponent.changeComponentInstanceVersion(componentUid).then(onSuccess, onCancel); }; - let componentUid:string = this.$scope.editResourceVersion.allVersions[this.$scope.editResourceVersion.changeVersion]; - this.$scope.currentComponent.changeComponentInstanceVersion(componentUid).then(onSuccess, onFailed); + this.serviceService.checkComponentInstanceVersionChange(service, componentUid).subscribe((pathsToDelete:string[]) => { + if (pathsToDelete && pathsToDelete.length) { + this.$scope.isLoading = false; + this.$scope.$parent.isLoading = false; + this.$scope.$parent.openVersionChangeModal(pathsToDelete).then(() => { + this.$scope.isLoading = true; + this.$scope.$parent.isLoading = true; + onUpdate(); + }, onCancel); + } else { + onUpdate(); + } + }, onCancel); }; } } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html index 5020c73df4..033c4668f3 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html @@ -26,7 +26,7 @@ data-ng-if="!isComponentInstanceSelected()" data-tests-id="rightTab_version" data-ng-bind="selectedComponent.version"></span> <ng-form name="editForm" data-ng-if="isComponentInstanceSelected()"> - <select data-ng-model="editResourceVersion.changeVersion" name="changeVersion" data-tests-id="changeVersion" data-ng-disabled="$parent.isViewOnly" + <select data-ng-model="editResourceVersion.changeVersion" name="changeVersion" data-tests-id="changeVersion" data-ng-disabled="$parent.isViewOnly || selectedComponent.uniqueId != editResourceVersion.allVersions[editResourceVersion.changeVersion]" class="i-sdc-designer-sidebar-section-content-item-value i-sdc-form-select" data-ng-class="{'minor': (editResourceVersion.changeVersion)%1}" data-ng-change="changeResourceVersion()"> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model.ts index 99bbd8d7ac..efd5cfd84d 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import { AttributeModel, AttributesGroup, diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view-model.ts index 4c53edf6bd..ce44aaff50 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {ICompositionViewModelScope} from "../../composition-view-model"; import {CapabilitiesGroup, Requirement, RequirementsGroup} from "app/models"; import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model.ts index 86bc478048..c652da4eab 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model.ts @@ -20,6 +20,7 @@ //@require "./*.html" 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {ArtifactModel, ArtifactGroupModel, Resource} from "app/models"; import {ArtifactsUtils, ModalsHandler, ValidationUtils} from "app/utils"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model.ts index 5ffae64689..eab06f28e8 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {Distribution, DistributionComponent, ExportExcel} from "app/models"; interface IDistributionStatusModalViewModelScope { diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view-model.ts index 663361cd85..47ec1fd9e3 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {Distribution, DistributionComponent, Service} from "app/models"; import {ModalsHandler, Dictionary} from "app/utils"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view.html b/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view.html index 710336af15..f32e7c7fdf 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view.html @@ -5,6 +5,7 @@ <div class="header-spacer"></div> <div class="top-search"> <input type="text" + style="width: auto;" class="search-text" data-tests-id="searchTextbox" placeholder="Search" diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts index 6060130191..b03d7c4d7c 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {ModalsHandler, ValidationUtils, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, DEFAULT_ICON, ResourceType, ComponentState} from "app/utils"; import {CacheService, EventListenerService, ProgressService, OnboardingService} from "app/services"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html index e3eb903a36..36976c610e 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html @@ -28,7 +28,6 @@ name="componentName" data-ng-init="isCreateMode() && validateName(true)" data-ng-maxlength="50" - maxlength="50" data-ng-model="component.name" type="text" data-required @@ -117,7 +116,6 @@ data-ng-model="component.description" data-ng-model-options="{ debounce: 500 }" data-ng-pattern="validation.commentValidationPattern" - maxlength="1024" data-tests-id="description"></textarea> <!-- placeholder="Description here..." --> @@ -178,10 +176,11 @@ data-ng-pattern="validation.contactIdValidationPattern" data-ng-model-options="{ debounce: 500 }" data-tests-id="contactId" - maxlength="50" + data-ng-maxlength="50" /> <div class="input-error" data-ng-show="validateField(editForm.contactId)"> + <span ng-show="editForm.contactId.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span> <span ng-show="editForm.contactId.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_REQUIRED"></span> <span ng-show="editForm.contactId.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_NOT_VALID"></span> </div> @@ -196,7 +195,7 @@ data-ng-model="component.projectCode" data-ng-class="{'view-mode': isViewMode()}" data-ng-model-options="{ debounce: 500 }" - maxlength="50" + data-ng-maxlength="50" data-required name="projectCode" data-ng-pattern="validation.projectCodeValidationPattern" @@ -204,6 +203,7 @@ /> <div class="input-error" data-ng-show="validateField(editForm.projectCode)"> + <span ng-show="editForm.contactId.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span> <span ng-show="editForm.projectCode.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_REQUIRED"></span> <span ng-show="editForm.projectCode.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_NOT_VALID"></span> </div> @@ -222,7 +222,6 @@ name="vendorName" data-ng-change="onVendorNameChange(oldValue)" data-ng-pattern="validation.VendorNameValidationPattern" - maxlength="60" data-ng-disabled="component.isAlreadyCertified() || (component.isCsarComponent() && component.vendorName && component.vendorName!=='')" data-tests-id="vendorName" /> @@ -250,7 +249,6 @@ data-required name="vendorRelease" data-ng-pattern="validation.VendorReleaseValidationPattern" - maxlength="25" data-ng-disabled="component.isCsarComponent() && component.vendorRelease && component.vendorRelease!==''" data-tests-id="vendorRelease" /> @@ -275,7 +273,6 @@ data-ng-maxlength="65" name="resourceVendorModelNumber" data-ng-pattern="validation.VendorModelNumberValidationPattern" - maxlength="65" data-tests-id="resourceVendorModelNumber" /> @@ -312,10 +309,9 @@ <div ng-if="component.isService()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.namingPolicy)}"> <label class="i-sdc-form-label">Naming policy</label> <input class="i-sdc-form-input" - name="fullName" + name="namingPolicy" data-ng-class="{'view-mode': isViewMode() || !component.ecompGeneratedNaming}" data-ng-maxlength="100" - maxlength="100" data-ng-model="component.namingPolicy" type="text" data-ng-model-options="{ debounce: 500 }" @@ -345,10 +341,9 @@ data-tests-id="serviceType" data-ng-maxlength="256" data-ng-pattern="validation.ServiceTypeAndRoleValidationPattern" - maxlength="256" /> <div class="input-error" data-ng-show="validateField(editForm.serviceType)"> - <span ng-show="editForm.serviceType.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> + <span ng-show="editForm.serviceType.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span> <span ng-show="editForm.serviceType.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> </div> </div> @@ -367,10 +362,9 @@ data-tests-id="serviceRole" data-ng-maxlength="256" data-ng-pattern="validation.ServiceTypeAndRoleValidationPattern" - maxlength="256" /> <div class="input-error" data-ng-show="validateField(editForm.serviceRole)"> - <span ng-show="editForm.serviceRole.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> + <span ng-show="editForm.serviceRole.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span> <span ng-show="editForm.serviceRole.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> </div> </div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view-model.ts index b2fd4d68c0..47a96fb385 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {ModalsHandler} from "app/utils"; import {SharingService} from "app/services"; import {IAppConfigurtaion, ArtifactModel, IFileDownload} from "app/models"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/inputs/resource-input/resource-inputs-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/inputs/resource-input/resource-inputs-view-model.ts index 2e871a5f8d..2a7cd3dd65 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/inputs/resource-input/resource-inputs-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/inputs/resource-input/resource-inputs-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {ComponentInstance, InstancesInputsOrPropertiesMapData, Resource, PropertyModel, InputModel} from "app/models"; import {ModalsHandler} from "app/utils"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/inputs/service-input/service-inputs-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/inputs/service-input/service-inputs-view-model.ts index 00f3347b74..bdbc0a4334 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/inputs/service-input/service-inputs-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/inputs/service-input/service-inputs-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {ComponentInstance, InstancesInputsOrPropertiesMapData, Service, IAppMenu, InputModel, PropertyModel, InputPropertyBase} from "app/models"; import {DataTypesService} from "app/services"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view-model.ts index 488e4c774d..af11e1cf9a 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view-model.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {VendorModel} from "app/view-models/workspace/tabs/management-workflow/management-workflow-view-model"; import {ResourceType, ArtifactType} from "app/utils"; 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 index b6cbf65cf0..f63ab1ccbc 100644 --- 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 @@ -22,6 +22,7 @@ * Created by rcohen on 9/22/2016. */ 'use strict'; +import * as _ from "lodash"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {ModalsHandler} from "app/utils"; import {Capability, PropertyModel, Requirement} from "app/models"; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model.ts index 77b5ab74eb..a1f8152cea 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model.ts @@ -19,10 +19,12 @@ */ 'use strict'; +import * as _ from "lodash"; import {ArtifactModel, IFileDownload} from "app/models"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response"; import {ComponentServiceNg2} from "../../../../ng2/services/component-services/component.service"; + export interface IToscaArtifactsScope extends IWorkspaceViewModelScope { artifacts:Array<ArtifactModel>; tableHeadersList:Array<any>; diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts index ca34d6fdc4..01b3aa3b22 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts @@ -7,9 +7,9 @@ * 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. @@ -22,6 +22,7 @@ * Created by obarda on 3/30/2016. */ 'use strict'; +import * as _ from "lodash"; import {IUserProperties, IAppMenu, Resource, Component, Plugin, PluginsConfiguration, PluginDisplayOptions} from "app/models"; import { WorkspaceMode, ComponentFactory, ChangeLifecycleStateHandler, Role, ComponentState, MenuItemGroup, MenuHandler, @@ -50,6 +51,7 @@ export interface IWorkspaceViewModelScope extends ng.IScope { isNew:boolean; isFromImport:boolean; isValidForm:boolean; + isActiveTopBar:boolean; mode:WorkspaceMode; breadcrumbsModel:Array<MenuItemGroup>; sdcMenu:IAppMenu; @@ -197,6 +199,7 @@ export class WorkspaceViewModel { this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1); this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT; this.$scope.progressService = this.progressService; + this.$scope.isActiveTopBar = true; this.$scope.getComponent = ():Component => { return this.$scope.component; @@ -267,7 +270,7 @@ export class WorkspaceViewModel { this.$scope.onVersionChanged = (selectedId:string):void => { if (this.$state.current.data && this.$state.current.data.unsavedChanges) { this.$scope.changeVersion.selectedVersion = _.find(this.$scope.versionsList, (versionObj)=> { - return versionObj.versionId === this.$scope.component.uniqueId; + return versionObj.versionId === this.$scope.component.uniqueId; }); } this.$scope.isLoading = true; @@ -323,13 +326,15 @@ export class WorkspaceViewModel { this.showSuccessNotificationMessage(); this.progressService.deleteProgressValue(this.$scope.component.uniqueId); - //update components for breadcrumbs + + // Update the components list for breadcrumbs this.components.unshift(component); + this.$state.go(States.WORKSPACE_GENERAL, { id: component.uniqueId, type: component.componentType.toLowerCase(), components: this.components - }); + }, { inherit: false }); deferred.resolve(true); }; @@ -347,17 +352,20 @@ export class WorkspaceViewModel { return item === component.name }); - // Update the components + // Update the components list for breadcrumbs + const bcIdx = this.MenuHandler.findBreadcrumbComponentIndex(this.components, component); + if (bcIdx !== -1) { + this.components[bcIdx] = component; + this.initBreadcrumbs(); // re-calculate breadcrumbs + } + + // Update the component this.$scope.component = component; this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component); - //update components for breadcrumbs - this.components.unshift(component); - // Enable left tags this.$scope.enabledTabs(); - if (this.$state.current.data) { this.$state.current.data.unsavedChanges = false; } @@ -469,11 +477,11 @@ export class WorkspaceViewModel { } //when checking out a minor version uuid remains - let bcComponent:Component = _.find(this.components, (item) => { + const bcIdx = _.findIndex(this.components, (item) => { return item.uuid === component.uuid; }); - if (bcComponent) { - this.components[this.components.indexOf(bcComponent)] = component; + if (bcIdx !== -1) { + this.components[bcIdx] = component; } else { //when checking out a major(certified) version this.components.unshift(component); @@ -681,7 +689,7 @@ export class WorkspaceViewModel { }); this.$scope.getTabTitle = ():string => { - return this.$scope.leftBarTabs.menuItems.find((menuItem:MenuItem)=>{ + return this.$scope.leftBarTabs.menuItems.find((menuItem:MenuItem) => { return menuItem.state == this.$scope.$state.current.name; }).text; }; @@ -690,6 +698,10 @@ export class WorkspaceViewModel { this.$state.go(this.$state.current.name,{id:component.uniqueId},{reload:true}); }; + this.$scope.$on('setWorkspaceTopBarActive', (event:ng.IAngularEvent, isActive:boolean) => { + this.$scope.isActiveTopBar = isActive; + }); + }; private initAfterScope = ():void => { @@ -718,9 +730,9 @@ export class WorkspaceViewModel { return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]); }; - private updateMenuItemByRole = (menuItems:Array<any>, role:string) : Array<any> => { - let tempMenuItems:Array<any> = new Array<any>(); - menuItems.forEach((item:any) => { + private updateMenuItemByRole = (menuItems:Array<MenuItem>, role:string) => { + let tempMenuItems:Array<MenuItem> = new Array<MenuItem>(); + menuItems.forEach((item:MenuItem) => { //remove item if role is disabled if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) { tempMenuItems.push(item); @@ -810,6 +822,4 @@ export class WorkspaceViewModel { }); }; -} - - +}
\ No newline at end of file diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view.html b/catalog-ui/src/app/view-models/workspace/workspace-view.html index d724b8d058..0f686b1d64 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view.html +++ b/catalog-ui/src/app/view-models/workspace/workspace-view.html @@ -1,13 +1,12 @@ <div class="sdc-workspace-container"> <loader data-display="isLoading"></loader> <div class="w-sdc-main-container"> - <div class="w-sdc-left-sidebar" data-ng-if="!isComposition"> <div class="menu-header" tooltips tooltip-content="{{menuComponentTitle}}"> {{menuComponentTitle}} </div> - <div class="i-sdc-designer-sidebar-section-content-item" ng-class="{'selected': isSelected(menuItem)}" ng-repeat="menuItem in leftBarTabs.menuItems track by $index"> - <div class="expand-collapse-menu-box-item-text" ng-click="menuItem.callback()" ng-class="{'disabled': menuItem.isDisabled }" data-tests-id="{{menuItem.text}}LeftSideMenu">{{menuItem.text}}</div> + <div class="i-sdc-designer-sidebar-section-content-item" ng-class="{'selected': menuItem.state == $state.current.name}" ng-repeat="menuItem in leftBarTabs.menuItems track by $index"> + <div class="expand-collapse-menu-box-item-text" ng-click="onMenuItemPressed(menuItem.state)" ng-class="{'disabled': menuItem.isDisabled }" data-tests-id="{{menuItem.text}}LeftSideMenu">{{menuItem.text}}</div> </div> </div> @@ -18,7 +17,7 @@ <div class="version-container"> <span data-ng-if="!isCreateMode() && !component.isLatestVersion()" class="not-latest"></span> - <select class="version-selector" data-ng-if="!isCreateMode()" data-tests-id="versionHeader" data-ng-model="changeVersion.selectedVersion" + <select class="version-selector" data-ng-if="!isCreateMode()" data-tests-id="versionHeader" data-ng-model="changeVersion.selectedVersion" data-ng-class="{'disabled': !isActiveTopBar}" ng-options="'V'+version.versionNumber for version in versionsList" data-ng-change="onVersionChanged(changeVersion.selectedVersion.versionId)"> </select> </div> @@ -35,10 +34,10 @@ <div class="sdc-workspace-top-bar-buttons"> - <span ng-if="!isCreateMode() && !component.isLatestVersion() && !showChangeStateButton()">Switch to the <a ng-click="getLatestVersion()">latest version</a></span> + <span ng-if="!isCreateMode() && !component.isLatestVersion() && !showChangeStateButton()" [disabled]="!isActiveTopBar">Switch to the <a ng-click="getLatestVersion()">latest version</a></span> <button ng-if="isDesigner() && !isCreateMode()" - data-ng-class="{'disabled' :!isValidForm || isDisableMode() || isViewMode()}" + data-ng-class="{'disabled' :!isValidForm || isDisableMode() || isViewMode() || !isActiveTopBar}" ng-click="save()" class="tlv-btn blue" data-tests-id="create/save" @@ -48,22 +47,22 @@ <button ng-repeat="(key,button) in changeLifecycleStateButtons" ng-click="changeLifecycleState(key)" ng-if="showChangeStateButton() && key != 'deleteVersion'" - data-ng-disabled="isCreateMode() || button.disabled || disabledButtons || !isValidForm" + data-ng-disabled="isCreateMode() || button.disabled || disabledButtons || !isValidForm || !isActiveTopBar" class="change-lifecycle-state-btn tlv-btn" ng-class="$first ? 'outline green' : 'grey'" data-tests-id="{{button.text | testsId}}"> {{button.text}} </button> - <button ng-if="!isViewMode() && isCreateMode()" data-ng-disabled="!isValidForm || isDisableMode() || isLoading" ng-click="save()" class="tlv-btn outline green" data-tests-id="create/save">Create</button> + <button ng-if="!isViewMode() && isCreateMode()" data-ng-disabled="!isValidForm || isDisableMode() || isLoading || !isActiveTopBar" ng-click="save()" class="tlv-btn outline green" data-tests-id="create/save">Create</button> <span data-ng-if="isDesigner() && !isCreateMode() && component.lifecycleState === 'NOT_CERTIFIED_CHECKOUT'" sdc-smart-tooltip="" - data-ng-class="{'disabled' : !isValidForm || isDisableMode() || isViewMode()}" ng-click="changeLifecycleState('deleteVersion')" + data-ng-class="{'disabled' : !isValidForm || isDisableMode() || isViewMode() || !isActiveTopBar}" ng-click="changeLifecycleState('deleteVersion')" class="sprite-new delete-btn" data-tests-id="delete_version" sdc-smart-tooltip="">Delete</span> - <span data-ng-if="isDesigner()" data-ng-class="{'disabled' :isDisableMode() || isViewMode()}" ng-click="revert()" class="sprite-new revert-btn" data-tests-id="revert" + <span data-ng-if="isDesigner()" data-ng-class="{'disabled' :isDisableMode() || isViewMode() || !isActiveTopBar}" ng-click="revert()" class="sprite-new revert-btn" data-tests-id="revert" data-ng-show="showFullIcons()" sdc-smart-tooltip="">Revert</span> - + <span class="delimiter"></span> <span class="sprite-new x-btn" data-ng-click="goToBreadcrumbHome()" sdc-smart-tooltip="">Close</span> |