Catalog alignment
Issue-ID: SDC-2724
Signed-off-by: ys9693 <ys9693@att.com>
Change-Id: I52b4aacb58cbd432ca0e1ff7ff1f7dd52099c6fe
diff --git a/catalog-ui/src/app/_favicon.png b/catalog-ui/src/app/_favicon.png
deleted file mode 100644
index 6e9f04d..0000000
--- a/catalog-ui/src/app/_favicon.png
+++ /dev/null
Binary files differ
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts
index a147f8c..f2ad73893 100644
--- a/catalog-ui/src/app/app.ts
+++ b/catalog-ui/src/app/app.ts
@@ -20,8 +20,6 @@
'use strict';
-//import 'restangular';
-//import 'angular-ui-router';
import * as _ from "lodash";
import "reflect-metadata";
import 'ng-infinite-scroll';
@@ -30,34 +28,22 @@
import './modules/directive-module.ts';
import './modules/service-module';
import './modules/view-model-module.ts';
-import {SdcUiComponentsNg1Module} from 'sdc-ui/lib/angular';
-
+import {SdcUiCommon, SdcUiComponents, SdcUiServices} from 'onap-ui-angular';
import {
- DataTypesService,
- LeftPaletteLoaderService,
- EcompHeaderService,
+ AngularJSBridge,
CookieService,
- ConfigurationUiService,
- CacheService,
- SdcVersionService,
- ICategoryResourceClass,
- EntityService
+ DataTypesService,
+ EcompHeaderService,
+ LeftPaletteLoaderService
} from "./services";
-import { UserService } from "./ng2/services/user.service";
-import {forwardRef} from '@angular/core';
-import {UpgradeAdapter} from '@angular/upgrade';
-import {CHANGE_COMPONENT_CSAR_VERSION_FLAG, States, PREVIOUS_CSAR_COMPONENT} from "./utils";
-import {IAppConfigurtaion, IAppMenu, IMainCategory, Resource, IHostedApplication} from "./models";
+import {CacheService, CatalogService, HomeService} from "./services-ng2";
+import {AuthenticationService} from "app/ng2/services/authentication.service";
+import {CHANGE_COMPONENT_CSAR_VERSION_FLAG, PREVIOUS_CSAR_COMPONENT, States} from "./utils";
+import {IAppConfigurtaion, IAppMenu, IHostedApplication, Resource} from "./models";
import {ComponentFactory} from "./utils/component-factory";
-import {ModalsHandler} from "./utils/modals-handler";
-import {downgradeComponent} from "@angular/upgrade/static";
-
-import {AppModule} from './ng2/app.module';
import {Component} from "./models/components/component";
-import {ComponentServiceNg2} from "./ng2/services/component-services/component.service";
-import {ComponentMetadata} from "./models/component-metadata";
-import {Categories} from "./models/categories";
import {IUserProperties} from "./models/user";
+import {WorkspaceService} from "./ng2/pages/workspace/workspace.service";
let moduleName:string = 'sdcApp';
let viewModelsModuleName:string = 'Sdc.ViewModels';
@@ -100,7 +86,6 @@
'angular-clipboard',
'angularResizable',
'infinite-scroll',
- SdcUiComponentsNg1Module.name,
viewModelsModuleName,
directivesModuleName,
servicesModuleName,
@@ -181,47 +166,40 @@
$translateProvider.preferredLanguage('en_US');
$httpProvider.interceptors.push('Sdc.Services.HeaderInterceptor');
- $httpProvider.interceptors.push('Sdc.Services.HttpErrorInterceptor');
- $urlRouterProvider.otherwise('welcome');
+ $urlRouterProvider.otherwise('dashboard');
$stateProvider.state(
'dashboard', {
url: '/dashboard?show&folder&filter.term&filter.status&filter.distributed',
- templateUrl: "./view-models/dashboard/dashboard-view.html",
- controller: viewModelsModuleName + '.DashboardViewModel',
- }
+ template: '<home-page></home-page>',
+ permissions: ['DESIGNER']
+ },
+
);
- $stateProvider.state(
- 'welcome', {
- url: '/welcome',
- templateUrl: "./view-models/welcome/welcome-view.html",
- controller: viewModelsModuleName + '.WelcomeViewModel'
- }
- );
- let componentsParam:Array<any> = ['$stateParams', 'Sdc.Services.EntityService', 'Sdc.Services.CacheService', ($stateParams:any, EntityService:EntityService, cacheService:CacheService) => {
+ let componentsParam:Array<any> = ['$stateParams', 'HomeService', 'CatalogService', 'Sdc.Services.CacheService', ($stateParams:any, HomeService:HomeService, CatalogService:CatalogService, cacheService:CacheService) => {
if (cacheService.get('breadcrumbsComponentsState') === $stateParams.previousState) {
const breadcrumbsComponents = cacheService.get('breadcrumbsComponents');
if (breadcrumbsComponents) {
return breadcrumbsComponents;
}
} else {
- let breadcrumbsComponentsPromise;
+ let breadcrumbsComponentsObservable;
if ($stateParams.previousState === 'dashboard') {
- breadcrumbsComponentsPromise = EntityService.getAllComponents(true);
+ breadcrumbsComponentsObservable = HomeService.getAllComponents(true);
} else if ($stateParams.previousState === 'catalog') {
- breadcrumbsComponentsPromise = EntityService.getCatalog();
+ breadcrumbsComponentsObservable = CatalogService.getCatalog();
} else {
cacheService.remove('breadcrumbsComponentsState');
cacheService.remove('breadcrumbsComponents');
return [];
}
- breadcrumbsComponentsPromise.then((components) => {
+ breadcrumbsComponentsObservable.subscribe((components) => {
cacheService.set('breadcrumbsComponentsState', $stateParams.previousState);
cacheService.set('breadcrumbsComponents', components);
});
- return breadcrumbsComponentsPromise;
+ return breadcrumbsComponentsObservable;
}
}];
@@ -246,19 +224,20 @@
templateUrl: './view-models/workspace/workspace-view.html',
controller: viewModelsModuleName + '.WorkspaceViewModel',
resolve: {
- injectComponent: ['$stateParams', 'ComponentFactory', 'Sdc.Services.CacheService', 'ComponentServiceNg2', function ($stateParams, ComponentFactory:ComponentFactory, cacheService:CacheService, ComponentServiceNg2:ComponentServiceNg2) {
+ injectComponent: ['$stateParams', 'ComponentFactory', 'workspaceService', 'Sdc.Services.CacheService', function ($stateParams, ComponentFactory:ComponentFactory, workspaceService:WorkspaceService, cacheService: CacheService) {
if ($stateParams.id && $stateParams.id.length) { //need to check length in case ID is an empty string
return ComponentFactory.getComponentWithMetadataFromServer($stateParams.type.toUpperCase(), $stateParams.id).then(
(component:Component)=> {
- if ($stateParams.componentCsar && component.isResource()){
- if((<Resource>component).csarVersion != $stateParams.componentCsar.csarVersion) {
- cacheService.set(PREVIOUS_CSAR_COMPONENT, angular.copy(component));
+ if ($stateParams.componentCsar && component.isResource()){
+ if((<Resource>component).csarVersion != $stateParams.componentCsar.csarVersion) {
+ cacheService.set(PREVIOUS_CSAR_COMPONENT, angular.copy(component));
+ }
+ component = ComponentFactory.updateComponentFromCsar($stateParams.componentCsar, <Resource>component);
}
- component = ComponentFactory.updateComponentFromCsar($stateParams.componentCsar, <Resource>component);
- }
- return component;
- });
+ workspaceService.setComponentMetadata(component.componentMetadata);
+ return component;
+ });
} else if ($stateParams.componentCsar && $stateParams.componentCsar.csarUUID) {
return $stateParams.componentCsar;
} else {
@@ -288,36 +267,12 @@
}
);
- $stateProvider.state(
- States.WORKSPACE_ACTIVITY_LOG, {
- url: 'activity_log',
- parent: 'workspace',
- controller: viewModelsModuleName + '.ActivityLogViewModel',
- templateUrl: './view-models/workspace/tabs/activity-log/activity-log.html',
- }
- );
-
- $stateProvider.state(
- States.WORKSPACE_DEPLOYMENT_ARTIFACTS, {
- url: 'deployment_artifacts',
- parent: 'workspace',
- controller: viewModelsModuleName + '.DeploymentArtifactsViewModel',
- templateUrl: './view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view.html',
- data: {
- bodyClass: 'deployment_artifacts'
- }
- }
- );
$stateProvider.state(
States.WORKSPACE_INFORMATION_ARTIFACTS, {
url: 'information_artifacts',
parent: 'workspace',
- controller: viewModelsModuleName + '.InformationArtifactsViewModel',
- templateUrl: './view-models/workspace/tabs/information-artifacts/information-artifacts-view.html',
- data: {
- bodyClass: 'information_artifacts'
- }
+ template:'<information-artifact-page></information-artifact-page>'
}
);
@@ -325,11 +280,16 @@
States.WORKSPACE_TOSCA_ARTIFACTS, {
url: 'tosca_artifacts',
parent: 'workspace',
- controller: viewModelsModuleName + '.ToscaArtifactsViewModel',
- templateUrl: './view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view.html',
- data: {
- bodyClass: 'tosca_artifacts'
- }
+ template:'<tosca-artifact-page></tosca-artifact-page>'
+ }
+ );
+
+
+ $stateProvider.state(
+ States.WORKSPACE_DEPLOYMENT_ARTIFACTS, {
+ url: 'deployment_artifacts',
+ parent: 'workspace',
+ template:'<deployment-artifact-page></deployment-artifact-page>'
}
);
@@ -368,11 +328,7 @@
States.WORKSPACE_ATTRIBUTES, {
url: 'attributes',
parent: 'workspace',
- controller: viewModelsModuleName + '.AttributesViewModel',
- templateUrl: './view-models/workspace/tabs/attributes/attributes-view.html',
- data: {
- bodyClass: 'attributes'
- }
+ template: '<attributes></attributes>',
}
);
@@ -380,20 +336,17 @@
States.WORKSPACE_REQUIREMENTS_AND_CAPABILITIES, {
url: 'req_and_capabilities',
parent: 'workspace',
- controller: viewModelsModuleName + '.ReqAndCapabilitiesViewModel',
- templateUrl: './view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view.html',
+ template: '<req-and-capabilities></req-and-capabilities>',
data: {
bodyClass: 'attributes'
}
}
);
-
$stateProvider.state(
States.WORKSPACE_REQUIREMENTS_AND_CAPABILITIES_EDITABLE, {
url: 'req_and_capabilities_editable',
parent: 'workspace',
- controller: viewModelsModuleName + '.ReqAndCapabilitiesViewModel',
- templateUrl: './view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html',
+ template: '<req-and-capabilities></req-and-capabilities>',
data: {
bodyClass: 'attributes'
}
@@ -419,44 +372,50 @@
}
);
- $stateProvider.state(
- States.WORKSPACE_DISTRIBUTION, {
- parent: 'workspace',
- url: 'distribution',
- templateUrl: './view-models/workspace/tabs/distribution/distribution-view.html',
- controller: viewModelsModuleName + '.DistributionViewModel'
- }
- );
$stateProvider.state(
States.WORKSPACE_COMPOSITION, {
url: 'composition/',
+ params: {'component': null},
parent: 'workspace',
- controller: viewModelsModuleName + '.CompositionViewModel',
- templateUrl: './view-models/workspace/tabs/composition/composition-view.html',
+ template: '<composition-page></composition-page>',
+ resolve: {
+ componentData: ['injectComponent', '$stateParams', function (injectComponent:Component, $stateParams) {
+ //injectComponent.componentService = null; // this is for not passing the service so no one will use old api and start using new api
+ $stateParams.component = injectComponent;
+ return injectComponent;
+ }],
+ },
data: {
bodyClass: 'composition'
}
}
);
- // $stateProvider.state(
- // States.WORKSPACE_NG2, {
- // url: 'ng2/',
- // component: downgradeComponent({component: NG2Example2Component}), //viewModelsModuleName + '.NG2Example',
- // templateUrl: './ng2/view-ng2/ng2.example2/ng2.example2.component.html'
- // }
- // );
+ $stateProvider.state(
+ States.WORKSPACE_ACTIVITY_LOG, {
+ url: 'activity_log/',
+ parent: 'workspace',
+ template: '<activity-log></activity-log>',
+ }
+
+ );
+
+ $stateProvider.state(
+ States.WORKSPACE_DISTRIBUTION, {
+ url: 'distribution',
+ parent: 'workspace',
+ template: '<distribution></distribution>',
+ }
+
+ );
$stateProvider.state(
States.WORKSPACE_DEPLOYMENT, {
url: 'deployment/',
parent: 'workspace',
- templateUrl: './view-models/workspace/tabs/deployment/deployment-view.html',
- controller: viewModelsModuleName + '.DeploymentViewModel',
- data: {
- bodyClass: 'composition'
- }
+ template: '<deployment-page></deployment-page>',
+
}
);
@@ -464,85 +423,61 @@
'workspace.composition.details', {
url: 'details',
parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/details/details-view.html',
- controller: viewModelsModuleName + '.DetailsViewModel'
+ resolve: {
+ componentData: ['injectComponent', '$stateParams', function (injectComponent:Component, $stateParams) {
+ $stateParams.component = injectComponent;
+ return injectComponent;
+ }],
+ }
+
}
);
$stateProvider.state(
'workspace.composition.properties', {
url: 'properties',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view.html',
- controller: viewModelsModuleName + '.ResourcePropertiesViewModel'
+ parent: 'workspace.composition'
}
);
$stateProvider.state(
'workspace.composition.artifacts', {
url: 'artifacts',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html',
- controller: viewModelsModuleName + '.ResourceArtifactsViewModel'
+ parent: 'workspace.composition'
+
}
);
$stateProvider.state(
'workspace.composition.relations', {
url: 'relations',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/relations/relations-view.html',
- controller: viewModelsModuleName + '.RelationsViewModel'
+ parent: 'workspace.composition'
}
);
$stateProvider.state(
'workspace.composition.structure', {
url: 'structure',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/structure/structure-view.html',
- controller: viewModelsModuleName + '.StructureViewModel'
+ parent: 'workspace.composition'
}
);
$stateProvider.state(
'workspace.composition.lifecycle', {
url: 'lifecycle',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html',
- controller: viewModelsModuleName + '.ResourceArtifactsViewModel'
+ parent: 'workspace.composition'
}
);
$stateProvider.state(
'workspace.composition.api', {
url: 'api',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html',
- controller: viewModelsModuleName + '.ResourceArtifactsViewModel'
+ parent: 'workspace.composition'
}
);
$stateProvider.state(
'workspace.composition.deployment', {
url: 'deployment',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html',
- controller: viewModelsModuleName + '.ResourceArtifactsViewModel'
- }
- );
- $stateProvider.state(
- 'workspace.composition.consumption', {
- url: 'consumption',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html',
- controller: viewModelsModuleName + '.ServiceConsumptionViewModel'
- }
- );
- $stateProvider.state(
- 'workspace.composition.dependencies', {
- url: 'dependencies',
- parent: 'workspace.composition',
- templateUrl: './view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view.html',
- controller: viewModelsModuleName + '.ServiceDependenciesViewModel'
+ parent: 'workspace.composition'
}
);
@@ -562,9 +497,14 @@
'workspace.plugins', {
url: 'plugins/*path',
parent: 'workspace',
- params: {'queryParams': null},
- templateUrl: './view-models/workspace/tabs/plugins/plugins-context-view.html',
- controller: viewModelsModuleName + '.PluginsContextViewModel'
+ template: '<plugin-context-view></plugin-context-view>',
+ resolve: {
+ componentData: ['injectComponent', '$stateParams', function (injectComponent:Component, $stateParams) {
+ $stateParams.component = injectComponent;
+ return injectComponent;
+ }],
+ }
+
}
);
@@ -581,15 +521,14 @@
'onboardVendor', {
url: '/onboardVendor',
templateUrl: './view-models/onboard-vendor/onboard-vendor-view.html',
- controller: viewModelsModuleName + '.OnboardVendorViewModel'//,
+ controller: viewModelsModuleName + '.OnboardVendorViewModel'
}
);
$stateProvider.state(
'plugins', {
url: '/plugins/*path',
- templateUrl: './view-models/plugins/plugins-tab-view.html',
- controller: viewModelsModuleName + '.PluginsTabViewModel'
+ template: '<plugin-tab-view></plugin-tab-view>'
}
);
@@ -609,11 +548,10 @@
$stateProvider.state(
'catalog', {
url: '/catalog?filter.components&filter.resourceSubTypes&filter.categories&filter.statuses&filter.order&filter.term&filter.active',
- templateUrl: './view-models/catalog/catalog-view.html',
- controller: viewModelsModuleName + '.CatalogViewModel',
+ template: '<catalog-page></catalog-page>',
resolve: {
- auth: ["$q", "UserServiceNg2", ($q:any, userService:UserService) => {
- let userInfo:IUserProperties = userService.getLoggedinUser();
+ auth: ["$q", "AuthenticationServiceNg2", ($q:any, authService:AuthenticationService) => {
+ let userInfo:IUserProperties = authService.getLoggedinUser();
if (userInfo) {
return $q.when(userInfo);
} else {
@@ -625,14 +563,6 @@
);
$stateProvider.state(
- 'support', {
- url: '/support',
- templateUrl: './view-models/support/support-view.html',
- controller: viewModelsModuleName + '.SupportViewModel'
- }
- );
-
- $stateProvider.state(
'error-403', {
url: '/error-403',
templateUrl: "./view-models/modals/error-modal/error-403-view.html",
@@ -661,7 +591,6 @@
ng1appModule.value('ServiceTypeAndRoleValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,256}$/);
ng1appModule.value('ContactIdValidationPattern', /^[\s\w-]{1,50}$/);
ng1appModule.value('UserIdValidationPattern', /^[\s\w-]{1,50}$/);
-ng1appModule.value('ProjectCodeValidationPattern', /^[\s\w-]{5,50}$/);
ng1appModule.value('LabelValidationPattern', /^[\sa-zA-Z0-9+-]{1,25}$/);
ng1appModule.value('UrlValidationPattern', /^(https?|ftp):\/\/(((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([A-Za-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([A-Za-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/);
ng1appModule.value('IntegerValidationPattern', /^(([-+]?\d+)|([-+]?0x[0-9a-fA-F]+))$/);
@@ -680,93 +609,42 @@
'$http',
'Sdc.Services.CacheService',
'Sdc.Services.CookieService',
- 'Sdc.Services.ConfigurationUiService',
- 'UserServiceNg2',
- 'Sdc.Services.CategoryResourceService',
- 'Sdc.Services.SdcVersionService',
+ 'AuthenticationServiceNg2',
'$state',
'$rootScope',
'$location',
'sdcMenu',
- 'ModalsHandler',
'Sdc.Services.EcompHeaderService',
'LeftPaletteLoaderService',
'Sdc.Services.DataTypesService',
'AngularJSBridge',
'$templateCache',
+ 'ModalServiceSdcUI',
($http:ng.IHttpService,
cacheService:CacheService,
cookieService:CookieService,
- ConfigurationUi:ConfigurationUiService,
- userService:UserService,
- categoryResourceService:ICategoryResourceClass,
- sdcVersionService:SdcVersionService,
+ authService:AuthenticationService,
$state:ng.ui.IStateService,
$rootScope:ng.IRootScopeService,
$location:ng.ILocationService,
sdcMenu:IAppMenu,
- ModalsHandler:ModalsHandler,
ecompHeaderService:EcompHeaderService,
LeftPaletteLoaderService:LeftPaletteLoaderService,
DataTypesService:DataTypesService,
AngularJSBridge,
- $templateCache:ng.ITemplateCacheService):void => {
+ $templateCache:ng.ITemplateCacheService,
+ ModalServiceSdcUI:SdcUiServices.ModalService):void => {
$templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html'));
$templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html'));
- //handle cache data - version
- let initAsdcVersion:Function = ():void => {
-
- let onFailed = (response) => {
- console.info('onFailed initAsdcVersion', response);
- cacheService.set('version', 'N/A');
- };
-
- let onSuccess = (version:any) => {
- let tmpVerArray = version.version.split(".");
- let ver = tmpVerArray[0] + "." + tmpVerArray[1] + "." + tmpVerArray[2];
- cacheService.set('version', ver);
- };
-
- sdcVersionService.getVersion().then(onSuccess, onFailed);
-
- };
-
- let initEcompMenu:Function = (user):void => {
- ecompHeaderService.getMenuItems(user.userId).then((data)=> {
- $rootScope['menuItems'] = data;
- });
- };
-
- let initConfigurationUi:Function = ():void => {
- ConfigurationUi
- .getConfigurationUi()
- .then((configurationUi:any) => {
- cacheService.set('UIConfiguration', configurationUi);
- });
- };
-
- let initCategories:Function = ():void => {
- let onError = ():void => {
- console.log('Failed to init categories');
- };
-
- categoryResourceService.getAllCategories((categories: Categories):void => {
- cacheService.set('serviceCategories', categories.serviceCategories);
- cacheService.set('resourceCategories', categories.resourceCategories);
- }, onError);
- };
// Add hosted applications to sdcConfig
sdcConfig.hostedApplications = hostedApplications;
//handle http config
$http.defaults.withCredentials = true;
- $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
+ // $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
$http.defaults.headers.common[cookieService.getUserIdSuffix()] = cookieService.getUserId();
- initAsdcVersion();
- initConfigurationUi();
- // initLeftPalette();
DataTypesService.initDataTypes();
//handle stateChangeStart
@@ -794,41 +672,44 @@
};
let onNavigateOut:Function = (toState, toParams):void => {
- let onOk = ():void => {
+ let onOk:Function = ():void => {
$state.current.data.unsavedChanges = false;
$state.go(toState.name, toParams);
};
let data = sdcMenu.alertMessages.exitWithoutSaving;
+ const okButton = {
+ testId: "OK",
+ text: sdcMenu.alertMessages.okButton,
+ type: SdcUiCommon.ButtonType.warning,
+ callback: onOk,
+ closeModal: true
+ } as SdcUiComponents.ModalButtonComponent;
//open notify to user if changes are not saved
- ModalsHandler.openAlertModal(data.title, data.message).then(onOk);
+ ModalServiceSdcUI.openWarningModal(data.title,
+ data.message,
+ 'navigate-modal',
+ [okButton]);
};
let onStateChangeStart:Function = (event, toState, toParams, fromState, fromParams):void => {
console.info((new Date()).getTime());
console.info('$stateChangeStart', toState.name);
+ if (toState.name !== 'error-403' && !authService.getLoggedinUser()) {
- if (toState.name !== 'error-403' && !userService.getLoggedinUser()) {
- if (toState.name !== 'welcome') {
- event.preventDefault();
- }
- userService.authorize().subscribe((userInfo:IUserProperties) => {
+ authService.authenticate().subscribe((userInfo:IUserProperties) => {
if (!doesUserHasAccess(toState, userInfo)) {
$state.go('error-403');
console.info('User has no permissions');
return;
}
- userService.setLoggedinUser(userInfo);
- cacheService.set('user', userInfo);
- initCategories();
- // initEcompMenu(userInfo);
+ authService.setLoggedinUser(userInfo);
setTimeout(function () {
removeLoader();
- // initCategories();
- if (userService.getLoggedinUser().role === 'ADMIN') {
+ if (authService.getLoggedinUser().role === 'ADMIN') {
// toState.name = "adminDashboard";
$state.go("adminDashboard", toParams);
return;
@@ -850,16 +731,25 @@
$state.go('error-403');
});
}
- else if (userService.getLoggedinUser()) {
- if (!doesUserHasAccess(toState, userService.getLoggedinUser())) {
+ else if (authService.getLoggedinUser()) {
+ let user:IUserProperties = authService.getLoggedinUser();
+ if(!cacheService.contains('user')){
+ cacheService.set('user', user);
+ }
+
+ if (!doesUserHasAccess(toState, authService.getLoggedinUser())) {
event.preventDefault();
$state.go('error-403');
console.info('User has no permissions');
}
- if (toState.name === "welcome") {
- $state.go("dashboard");
+
+ if (authService.getLoggedinUser().role === 'ADMIN') {
+ // toState.name = "adminDashboard";
+ $state.go("adminDashboard", toParams);
+ return;
}
+
//if form is dirty and not save - notify to user
if (fromState.data && fromState.data.unsavedChanges && fromParams.id != toParams.id) {
event.preventDefault();
@@ -920,7 +810,6 @@
onStateChangeSuccess(event, toState, toParams, fromState, fromParams);
});
};
-
registerStateChangeStartWatcher();
}]);
diff --git a/catalog-ui/src/app/directives/clicked-outside/clicked-outside-directive.ts b/catalog-ui/src/app/directives/clicked-outside/clicked-outside-directive.ts
index 94f4643..adec51f 100644
--- a/catalog-ui/src/app/directives/clicked-outside/clicked-outside-directive.ts
+++ b/catalog-ui/src/app/directives/clicked-outside/clicked-outside-directive.ts
@@ -67,12 +67,12 @@
if (!container) {
let clickedOutsideContainerSelector:string = clickedOutsideModel.getClickedOutsideContainerSelector();
if (!angular.isUndefined(clickedOutsideContainerSelector) && clickedOutsideContainerSelector !== '') {
- container = element.parents(clickedOutsideContainerSelector + ':first')[0];
+ container = <HTMLElement>element.parents(clickedOutsideContainerSelector + ':first')[0];
if (!container) {
- container = element[0];
+ container = <HTMLElement>element[0];
}
} else {
- container = element[0];
+ container = <HTMLElement>element[0];
}
}
return container;
@@ -85,7 +85,7 @@
if (targetDomElementJq.hasClass('tooltip') || targetDomElementJq.parents('.tooltip:first').length) {
return;
}
- let targetDomElement:HTMLElement = targetDomElementJq[0];
+ let targetDomElement:HTMLElement = <HTMLElement>targetDomElementJq[0];
if (!containerDomElement.contains(targetDomElement)) {
scope.$apply(() => {
let onClickedOutsideGetter:Function = clickedOutsideModel.getOnClickedOutsideGetter();
diff --git a/catalog-ui/src/app/directives/download-artifact/download-artifact.ts b/catalog-ui/src/app/directives/download-artifact/download-artifact.ts
index deeb1f5..8f7735d 100644
--- a/catalog-ui/src/app/directives/download-artifact/download-artifact.ts
+++ b/catalog-ui/src/app/directives/download-artifact/download-artifact.ts
@@ -20,7 +20,8 @@
'use strict';
import {IFileDownload, Component, ArtifactModel} from "app/models";
-import {EventListenerService, CacheService} from "app/services";
+import {EventListenerService} from "app/services";
+import {CacheService} from "app/services-ng2";
import {EVENTS, FileUtils} from "app/utils";
export class DOWNLOAD_CSS_CLASSES {
diff --git a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts
index 76bc169..eb9e71f 100644
--- a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts
+++ b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts
@@ -23,6 +23,7 @@
import {IAppConfigurtaion, User, IUser} from "app/models";
import {IUserProperties} from "../../models/user";
import {UserService} from "../../ng2/services/user.service";
+import { AuthenticationService } from "../../ng2/services/authentication.service";
export class MenuItem {
menuId:number;
@@ -57,7 +58,8 @@
constructor(private $http:ng.IHttpService,
private sdcConfig:IAppConfigurtaion,
- private userService:UserService) {
+ private userService:UserService,
+ private authService:AuthenticationService) {
}
@@ -92,7 +94,7 @@
let initUser = ():void => {
let defaultUserId:string;
- let userInfo:IUserProperties = this.userService.getLoggedinUser();
+ let userInfo:IUserProperties = this.authService.getLoggedinUser();
if (!userInfo) {
defaultUserId = this.$http.defaults.headers.common[this.sdcConfig.cookie.userIdSuffix];
this.userService.getUser(defaultUserId).subscribe((defaultUserInfo):void => {
@@ -137,8 +139,9 @@
public static factory = ($http:ng.IHttpService,
sdcConfig:IAppConfigurtaion,
- userService:UserService)=> {
- return new EcompHeaderDirective($http, sdcConfig, userService);
+ userService:UserService,
+ authService:AuthenticationService)=> {
+ return new EcompHeaderDirective($http, sdcConfig, userService, authService);
};
}
@@ -231,7 +234,7 @@
};
}
-EcompHeaderDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2'];
+EcompHeaderDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2', 'AuthenticationServiceNg2'];
diff --git a/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.html b/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.html
index d59c44d..156192d 100644
--- a/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.html
+++ b/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.html
@@ -18,8 +18,8 @@
{{actualText}}
<span class="ellipsis-directive-more-less"
- data-ng-click="onMoreLessClick($event)"
- data-ng-hide="ellipsis.length <= maxChars"
- data-tests-id="ellipsis-more-less">
+ data-ng-click="onMoreLessClick($event)"
+ data-ng-hide="ellipsis.length <= maxChars"
+ data-tests-id="ellipsis-more-less">
{{actualText ? (collapsed ? "More" : "Less") : ""}}
</span>
diff --git a/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.ts b/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.ts
index 21e074a..be7547c 100644
--- a/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.ts
+++ b/catalog-ui/src/app/directives/ellipsis/ellipsis-directive.ts
@@ -23,7 +23,6 @@
ellipsis:string;
maxChars:number;
toggleText():void;
- onMoreLessClick(event): void;
collapsed:boolean;
actualText:string;
diff --git a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.html b/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.html
deleted file mode 100644
index b07668d..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-
-<div class="assetPopover" ng-class="assetPopoverObj.menuSide" ng-style="{left: assetPopoverObj.menuPosition.x, top: assetPopoverObj.menuPosition.y}">
- <div class="display-name-tooltip" >{{assetPopoverObj.displayName}}</div>
-
- <div class="assetMenu">
- <!--<div class="sprite-new expand-asset-icon" uib-tooltip="Open" tooltip-class="uib-custom-tooltip" tooltip-placement="{{tooltipSide}}"></div>-->
- <div class="sprite-new view-info-icon" uib-tooltip="Information" tooltip-class="uib-custom-tooltip" tooltip-placement="{{assetPopoverObj.menuSide}}"></div>
- <div class="sprite-new cp-icon" uib-tooltip="Connection Points" tooltip-class="uib-custom-tooltip" tooltip-placement="{{assetPopoverObj.menuSide}}"></div>
- <div class="sprite-new vl-icon" uib-tooltip="Links" tooltip-class="uib-custom-tooltip" tooltip-placement="{{assetPopoverObj.menuSide}}"></div>
- <div class="sprite-new trash-icon" uib-tooltip="Delete" tooltip-class="uib-custom-tooltip" tooltip-placement="{{assetPopoverObj.menuSide}}" ng-click="deleteAsset()" data-ng-class="{'disabled-icon': assetPopoverObj.isViewOnly}"></div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.less b/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.less
deleted file mode 100644
index 1a113e5..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.less
+++ /dev/null
@@ -1,64 +0,0 @@
-.assetPopover {
- font-family: @font-opensans-regular;
- font-size: 13px;
- width:230px;
- padding:0 15px;
- position:absolute;
- display:flex;
- flex-direction:column;
- align-items:flex-start;
-
- &.left {
- align-items:flex-end;
-
- .uib-custom-tooltip {
- margin-left:-10px;
- }
- }
-
- .display-name-tooltip {
-
- border:solid 1px @main_color_p;
- color: @main_color_p;
- padding:5px 10px;
- width:200px;
- margin-bottom:10px;
- border-radius: 2px;
- background-color: rgba(80, 99, 113, 0.8);
- box-shadow: 0px 3px 7.44px 0.56px rgba(0, 0, 0, 0.33);
- }
-
- .uib-custom-tooltip {
- margin-left:20px;
- font-family: @font-opensans-regular;
- font-size: 13px;
- }
-
- .assetMenu {
-
- border-radius: 2px;
- border: solid 1px @main_color_p;
- background-color: rgba(234, 234, 234, 0.7);
- box-shadow: 0px 3px 7.44px 0.56px rgba(0, 0, 0, 0.33);
- display:flex;
- flex-direction: column;
- justify-content: center;
- align-items:center;
-
- .sprite-new {
- border-bottom:solid 1px #CCC;
- &:hover:not(.disabled-icon) {
- .hand;
- }
- &:active:not(.disabled-icon) {
- background-color: @main_color_a;
- border-bottom-color: @main_color_a;
- }
- &.trash-icon {
- border-bottom: none;
- }
- }
-
-
- }
-}
diff --git a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.ts b/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.ts
deleted file mode 100644
index ad3197c..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/asset-popover/asset-popover.ts
+++ /dev/null
@@ -1,55 +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=========================================================
- */
-
-'use strict';
-import {AssetPopoverObj} from "app/models";
-
-export interface IAssetPopoverScope extends ng.IScope {
- assetPopoverObj:AssetPopoverObj;
- deleteAsset:Function;
-}
-
-export class AssetPopoverDirective implements ng.IDirective {
-
- constructor() {
- }
-
- scope = {
- assetPopoverObj: '=',
- deleteAsset: '&'
- };
-
- restrict = 'E';
- replace = true;
- template = ():string => {
- return require('app/directives/graphs-v2/asset-popover/asset-popover.html');
- };
-
- link = (scope:IAssetPopoverScope, element:JQuery, $attr:ng.IAttributes) => {
-
- };
-
- public static factory = ()=> {
- return new AssetPopoverDirective();
- };
-}
-
-AssetPopoverDirective.factory.$inject = [];
-
diff --git a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts b/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts
deleted file mode 100644
index 81d4150..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts
+++ /dev/null
@@ -1,487 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import {CommonNodeBase, CompositionCiLinkBase, RelationshipModel, Relationship, CompositionCiNodeBase, NodesFactory, LinksFactory} from "app/models";
-import {GraphUIObjects} from "app/utils";
-import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-import {Requirement, Capability} from "app/models";
-/**
- * Created by obarda on 12/21/2016.
- */
-export class CommonGraphUtils {
-
- constructor(private NodesFactory:NodesFactory, private LinksFactory:LinksFactory) {
-
- }
-
- public safeApply = (scope:ng.IScope, fn:any) => { //todo remove to general utils
- let phase = scope.$root.$$phase;
- if (phase == '$apply' || phase == '$digest') {
- if (fn && (typeof(fn) === 'function')) {
- fn();
- }
- } else {
- scope.$apply(fn);
- }
- };
-
- /**
- * Draw node on the graph
- * @param cy
- * @param compositionGraphNode
- * @param position
- * @returns {CollectionElements}
- */
- public addNodeToGraph(cy:Cy.Instance, compositionGraphNode:CommonNodeBase, position?:Cy.Position):Cy.CollectionElements {
-
- let node = cy.add(<Cy.ElementDefinition> {
- group: 'nodes',
- position: position,
- data: compositionGraphNode,
- classes: compositionGraphNode.classes
- });
-
- if(!node.data().isUcpe) { //ucpe should not have tooltip
- this.initNodeTooltip(node);
- }
- return node;
- };
-
- /**
- * The function will create a component instance node by the componentInstance position.
- * If the node is UCPE the function will create all cp lan&wan for the ucpe
- * @param cy
- * @param compositionGraphNode
- * @returns {Cy.CollectionElements}
- */
- public addComponentInstanceNodeToGraph(cy:Cy.Instance, compositionGraphNode:CompositionCiNodeBase):Cy.CollectionElements {
-
- let nodePosition = {
- x: +compositionGraphNode.componentInstance.posX,
- y: +compositionGraphNode.componentInstance.posY
- };
-
- let node = this.addNodeToGraph(cy, compositionGraphNode, nodePosition);
- if (compositionGraphNode.isUcpe) {
- this.createUcpeCpNodes(cy, node);
- }
- return node;
- };
-
- /**
- * This function will create CP_WAN & CP_LAN for the UCPE. this is a special node on the group that will behave like ports on the ucpe
- * @param cy
- * @param ucpeGraphNode
- */
- private createUcpeCpNodes(cy:Cy.Instance, ucpeGraphNode:Cy.CollectionNodes):void {
-
- let requirementsArray:Array<any> = ucpeGraphNode.data().componentInstance.requirements["tosca.capabilities.Node"];
- //show only LAN or WAN requirements
- requirementsArray = _.reject(requirementsArray, (requirement:any) => {
- let name:string = requirement.ownerName.toLowerCase();
- return name.indexOf('lan') === -1 && name.indexOf('wan') === -1;
- });
- requirementsArray.sort(function (a, b) {
- let nameA = a.ownerName.toLowerCase().match(/[^ ]+/)[0];
- let nameB = b.ownerName.toLowerCase().match(/[^ ]+/)[0];
- let numA = _.last(a.ownerName.toLowerCase().split(' '));
- let numB = _.last(b.ownerName.toLowerCase().split(' '));
-
- if (nameA === nameB) return numA > numB ? 1 : -1;
- return nameA < nameB ? 1 : -1;
- });
- let position = angular.copy(ucpeGraphNode.boundingbox());
- //add CP nodes to group
- let topCps:number = 0;
- for (let i = 0; i < requirementsArray.length; i++) {
-
- let cpNode = this.NodesFactory.createUcpeCpNode(angular.copy(ucpeGraphNode.data().componentInstance));
- cpNode.componentInstance.capabilities = requirementsArray[i];
- cpNode.id = requirementsArray[i].ownerId;
- cpNode.group = ucpeGraphNode.data().componentInstance.uniqueId;
- cpNode.name = requirementsArray[i].ownerName; //for tooltip
- cpNode.displayName = requirementsArray[i].ownerName;
- cpNode.displayName = cpNode.displayName.length > 5 ? cpNode.displayName.substring(0, 5) + '...' : cpNode.displayName;
-
-
- if (cpNode.name.toLowerCase().indexOf('lan') > -1) {
- cpNode.textPosition = "top";
- cpNode.componentInstance.posX = position.x1 + (i * 90) - (topCps * 90) + 53;
- cpNode.componentInstance.posY = position.y1 + 400 + 27;
- } else {
- cpNode.textPosition = "bottom";
- cpNode.componentInstance.posX = position.x1 + (topCps * 90) + 53;
- cpNode.componentInstance.posY = position.y1 + 27;
- topCps++;
- }
- let cyCpNode = this.addComponentInstanceNodeToGraph(cy, cpNode);
- cyCpNode.lock();
- }
- };
-
- /**
- * Returns relation source and target nodes.
- * @param nodes - all nodes in graph in order to find the edge connecting the two nodes
- * @param fromNodeId
- * @param toNodeId
- * @returns [source, target] array of source node and target node.
- */
- public getRelationNodes(nodes:Cy.CollectionNodes, fromNodeId:string, toNodeId:string) {
- return [
- _.find(nodes, (node:Cy.CollectionFirst) => node.data().id === fromNodeId),
- _.find(nodes, (node:Cy.CollectionFirst) => node.data().id === toNodeId)
- ];
- }
-
- /**
- * Add link to graph - only draw the link
- * @param cy
- * @param link
- * @param getRelationRequirementCapability
- */
- public insertLinkToGraph = (cy:Cy.Instance, link:CompositionCiLinkBase, getRelationRequirementCapability:Function) => {
- const relationNodes = this.getRelationNodes(cy.nodes(), link.source, link.target);
- const sourceNode:CompositionCiNodeBase = relationNodes[0] && relationNodes[0].data();
- const targetNode:CompositionCiNodeBase = relationNodes[1] && relationNodes[1].data();
- if ((sourceNode && !sourceNode.certified) || (targetNode && !targetNode.certified)) {
- link.classes = 'not-certified-link';
- }
- let linkElement = cy.add({
- group: 'edges',
- data: link,
- classes: link.classes
- });
- const getLinkRequirementCapability = () =>
- getRelationRequirementCapability(link.relation.relationships[0], sourceNode.componentInstance, targetNode.componentInstance);
- this.initLinkTooltip(linkElement, link.relation.relationships[0], getLinkRequirementCapability);
- };
-
- /**
- * Add service path link to graph - only draw the link
- * @param cy
- * @param link
- */
- public insertServicePathLinkToGraph = (cy:Cy.Instance, link:CompositionCiServicePathLink) => {
- let linkElement = cy.add({
- group: 'edges',
- data: link,
- classes: link.classes
- });
- this.initServicePathTooltip(linkElement, link);
- };
-
- /**
- * Returns function for the link tooltip content
- * @param {Relationship} linkRelation
- * @param {Requirement} requirement
- * @param {Capability} capability
- * @returns {() => string}
- * @private
- */
- private _getLinkTooltipContent(linkRelation:Relationship, requirement?:Requirement, capability?:Capability):string {
- return '<div class="line">' +
- '<span class="req-cap-label">R: </span>' +
- '<span>' + (requirement ? requirement.getTitle() : linkRelation.relation.requirement) + '</span>' +
- '</div>' +
- '<div class="line">' +
- '<div class="sprite-new link-tooltip-arrow"></div>' +
- '<span class="req-cap-label">C: </span>' +
- '<span>' + (capability ? capability.getTitle() : linkRelation.relation.capability) + '</span>' +
- '</div>';
- }
-
- /**
- * This function will init qtip tooltip on the link
- * @param linkElement - the link we want the tooltip to apply on,
- * @param link
- * @param getLinkRequirementCapability
- * link - the link obj
- */
- public initLinkTooltip(linkElement:Cy.CollectionElements, link:Relationship, getLinkRequirementCapability:Function) {
- const content = () => this._getLinkTooltipContent(link); // base tooltip content without owner names
- const render = (event, api) => {
- // on render (called once at first show), get the link requirement and capability and change to full tooltip content (with owner names)
- getLinkRequirementCapability().then((linkReqCap) => {
- const fullContent = () => this._getLinkTooltipContent(link, linkReqCap.requirement, linkReqCap.capability);
- api.set('content.text', fullContent);
- });
- };
- linkElement.qtip(this.prepareInitTooltipData({content, events: {render}}));
- };
-
- /**
- *
- * @param linkElement
- * @param link
- */
- public initServicePathTooltip(linkElement:Cy.CollectionElements, link:CompositionCiServicePathLink) {
- let content = function () {
- return '<div class="line">' +
- '<div>'+link.pathName+'</div>' +
- '</div>';
- };
- linkElement.qtip(this.prepareInitTooltipData({content}));
- };
-
- private prepareInitTooltipData(options?:Object) {
- return _.merge({
- position: {
- my: 'top center',
- at: 'bottom center',
- adjust: {x:0, y:0},
- effect: false
- },
- style: {
- classes: 'qtip-dark qtip-rounded qtip-custom link-qtip',
- tip: {
- width: 16,
- height: 8
- }
- },
- show: {
- event: 'mouseover',
- delay: 1000
- },
- hide: {event: 'mouseout mousedown'},
- includeLabels: true,
- events: {}
- }, options);
- }
-
- /**
- * go over the relations and draw links on the graph
- * @param cy
- * @param instancesRelations
- * @param getRelationRequirementCapability - function to get requirement and capability of a relation
- */
- public initGraphLinks(cy:Cy.Instance, instancesRelations:Array<RelationshipModel>, getRelationRequirementCapability:Function) {
-
- if (instancesRelations) {
- _.forEach(instancesRelations, (relationshipModel:RelationshipModel) => {
- _.forEach(relationshipModel.relationships, (relationship:Relationship) => {
- let linkToCreate = this.LinksFactory.createGraphLink(cy, relationshipModel, relationship);
- this.insertLinkToGraph(cy, linkToCreate, getRelationRequirementCapability);
- });
- });
- }
- }
-
- /**
- * Determine which nodes are in the UCPE and set child data for them.
- * @param cy
- */
- public initUcpeChildren(cy:Cy.Instance) {
- let ucpe:Cy.CollectionNodes = cy.nodes('[?isUcpe]'); // Get ucpe on graph if exist
- _.each(cy.edges('.ucpe-host-link'), (link)=> {
-
- let ucpeChild:Cy.CollectionNodes = (link.source().id() == ucpe.id()) ? link.target() : link.source();
- this.initUcpeChildData(ucpeChild, ucpe);
-
- //vls dont have ucpe-host-link connection, so need to find them and iterate separately
- let connectedVLs = ucpeChild.connectedEdges().connectedNodes('.vl-node');
- _.forEach(connectedVLs, (vl)=> { //all connected vls must be UCPE children because not allowed to connect to a VL outside of the UCPE
- this.initUcpeChildData(vl, ucpe);
- });
- });
- }
-
- /**
- * Set properties for nodes contained by the UCPE
- * @param childNode- node contained in UCPE
- * @param ucpe- ucpe container node
- */
- public initUcpeChildData(childNode:Cy.CollectionNodes, ucpe:Cy.CollectionNodes) {
-
- if (!childNode.data('isInsideGroup')) {
- this.updateUcpeChildPosition(childNode, ucpe);
- childNode.data({isInsideGroup: true});
- }
-
- }
-
- /**
- * Updates UCPE child node offset, which allows child nodes to be dragged in synchronization with ucpe
- * @param childNode- node contained in UCPE
- * @param ucpe- ucpe container node
- */
- public updateUcpeChildPosition(childNode:Cy.CollectionNodes, ucpe:Cy.CollectionNodes) {
- let childPos:Cy.Position = childNode.relativePosition();
- let ucpePos:Cy.Position = ucpe.relativePosition();
- let offset:Cy.Position = {
- x: childPos.x - ucpePos.x,
- y: childPos.y - ucpePos.y
- };
- childNode.data("ucpeOffset", offset);
- }
-
- /**
- * Removes ucpe-child properties from the node
- * @param childNode- node being removed from UCPE
- */
- public removeUcpeChildData(childNode:Cy.CollectionNodes) {
- childNode.removeData("ucpeOffset");
- childNode.data({isInsideGroup: false});
-
- }
-
-
- public HTMLCoordsToCytoscapeCoords(cytoscapeBoundingBox:Cy.Extent, mousePos:Cy.Position):Cy.Position {
- return {x: mousePos.x + cytoscapeBoundingBox.x1, y: mousePos.y + cytoscapeBoundingBox.y1}
- };
-
-
- public getCytoscapeNodePosition = (cy:Cy.Instance, event:IDragDropEvent):Cy.Position => {
- let targetOffset = $(event.target).offset();
- let x = (event.pageX - targetOffset.left) / cy.zoom();
- let y = (event.pageY - targetOffset.top) / cy.zoom();
-
- return this.HTMLCoordsToCytoscapeCoords(cy.extent(), {
- x: x,
- y: y
- });
- };
-
-
- public getNodePosition(node:Cy.CollectionFirstNode):Cy.Position {
- let nodePosition = node.relativePoint();
- if (node.data().isUcpe) { //UCPEs use bounding box and not relative point.
- nodePosition = {x: node.boundingbox().x1, y: node.boundingbox().y1};
- }
-
- return nodePosition;
- }
-
- /**
- * Generic function that can be used for any html elements overlaid on canvas
- * Returns the html position of a node on canvas, including left palette and header offsets. Option to pass in additional offset to add to return position.
- * @param node
- * @param additionalOffset
- * @returns {Cy.Position}
-
- public getNodePositionWithOffset = (node:Cy.CollectionFirstNode, additionalOffset?:Cy.Position): Cy.Position => {
- if(!additionalOffset) additionalOffset = {x: 0, y:0};
-
- let nodePosition = node.renderedPosition();
- let posWithOffset:Cy.Position = {
- x: nodePosition.x + GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET + additionalOffset.x,
- y: nodePosition.y + GraphUIObjects.COMPOSITION_HEADER_OFFSET + additionalOffset.y
- };
- return posWithOffset;
- };*/
-
- /**
- * return true/false if first node contains in second - this used in order to verify is node is entirely inside ucpe
- * @param firstBox
- * @param secondBox
- * @returns {boolean}
- */
- public isFirstBoxContainsInSecondBox(firstBox:Cy.BoundingBox, secondBox:Cy.BoundingBox) {
-
- return firstBox.x1 > secondBox.x1 && firstBox.x2 < secondBox.x2 && firstBox.y1 > secondBox.y1 && firstBox.y2 < secondBox.y2;
-
- };
-
-
- /**
- * Check if node node bounds position is inside any ucpe on graph, and return the ucpe
- * @param {diagram} the diagram.
- * @param {nodeActualBounds} the actual bound position of the node.
- * @return the ucpe if found else return null
- */
- public isInUcpe = (cy:Cy.Instance, nodeBounds:Cy.BoundingBox):Cy.CollectionElements => {
-
- let ucpeNodes = cy.nodes('[?isUcpe]').filterFn((ucpeNode) => {
- return this.isFirstBoxContainsInSecondBox(nodeBounds, ucpeNode.boundingbox());
- });
- return ucpeNodes;
- };
-
- /**
- *
- * @param cy
- * @param node
- * @returns {Array}
- */
- public getLinkableNodes(cy:Cy.Instance, node:Cy.CollectionFirstNode):Array<CompositionCiNodeBase> {
- let compatibleNodes = [];
- _.each(cy.nodes(), (tempNode)=> {
- if (this.nodeLocationsCompatible(cy, node, tempNode)) {
- compatibleNodes.push(tempNode.data());
- }
- });
- return compatibleNodes;
- }
-
- /**
- * Checks whether node locations are compatible in reference to UCPEs.
- * Returns true if both nodes are in UCPE or both nodes out, or one node is UCPEpart.
- * @param node1
- * @param node2
- */
- public nodeLocationsCompatible(cy:Cy.Instance, node1:Cy.CollectionFirstNode, node2:Cy.CollectionFirstNode) {
-
- let ucpe = cy.nodes('[?isUcpe]');
- if(!ucpe.length){ return true; }
- if(node1.data().isUcpePart || node2.data().isUcpePart) { return true; }
-
- return (this.isFirstBoxContainsInSecondBox(node1.boundingbox(), ucpe.boundingbox()) == this.isFirstBoxContainsInSecondBox(node2.boundingbox(), ucpe.boundingbox()));
-
- }
-
- /**
- * This function will init qtip tooltip on the node
- * @param node - the node we want the tooltip to apply on
- */
- public initNodeTooltip(node:Cy.CollectionNodes) {
-
- let opts = {
- content: function () {
- return this.data('name');
- },
- position: {
- my: 'top center',
- at: 'bottom center',
- adjust: {x:0, y:-5}
- },
- style: {
- classes: 'qtip-dark qtip-rounded qtip-custom',
- tip: {
- width: 16,
- height: 8
- }
- },
- show: {
- event: 'mouseover',
- delay: 1000
- },
- hide: {event: 'mouseout mousedown'},
- includeLabels: true
- };
-
- if (node.data().isUcpePart){ //fix tooltip positioning for UCPE-cps
- opts.position.adjust = {x:0, y:20};
- }
-
- node.qtip(opts);
- };
-}
-
-CommonGraphUtils.$inject = ['NodesFactory', 'LinksFactory'];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
deleted file mode 100644
index e6c2fb3..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
+++ /dev/null
@@ -1,947 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import {
- Match,
- LinkMenu,
- ComponentInstance,
- LeftPaletteComponent,
- Relationship,
- Component,
- Service,
- ConnectRelationModel,
- CompositionCiNodeBase,
- CompositionCiNodeVl,
- ModalModel,
- ButtonModel,
- NodesFactory,
- Point
-} from "app/models";
-import { ComponentInstanceFactory, ComponentFactory, GRAPH_EVENTS, GraphColors, DEPENDENCY_EVENTS } from "app/utils";
-import { EventListenerService, LoaderService } from "app/services";
-import { CompositionGraphLinkUtils } from "./utils/composition-graph-links-utils";
-import { CompositionGraphGeneralUtils } from "./utils/composition-graph-general-utils";
-import { CompositionGraphNodesUtils } from "./utils/composition-graph-nodes-utils";
-import { CommonGraphUtils } from "../common/common-graph-utils";
-import { MatchCapabilitiesRequirementsUtils } from "./utils/match-capability-requierment-utils";
-import { CompositionGraphPaletteUtils } from "./utils/composition-graph-palette-utils";
-import { ComponentInstanceNodesStyle } from "../common/style/component-instances-nodes-style";
-import { CytoscapeEdgeEditation } from 'third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js';
-import { ComponentServiceNg2 } from "../../../ng2/services/component-services/component.service";
-import { ComponentGenericResponse } from "../../../ng2/services/responses/component-generic-response";
-import { ModalService } from "../../../ng2/services/modal.service";
-import { ConnectionWizardService } from "../../../ng2/pages/connection-wizard/connection-wizard.service";
-import { StepModel } from "../../../models/wizard-step";
-import { FromNodeStepComponent } from "app/ng2/pages/connection-wizard/from-node-step/from-node-step.component";
-import { PropertiesStepComponent } from "app/ng2/pages/connection-wizard/properties-step/properties-step.component";
-import { ToNodeStepComponent } from "app/ng2/pages/connection-wizard/to-node-step/to-node-step.component";
-import { ConnectionWizardHeaderComponent } from "app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component";
-import { ConnectionPropertiesViewComponent } from "../../../ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component";
-import { ComponentInstanceServiceNg2 } from "../../../ng2/services/component-instance-services/component-instance.service";
-import { EVENTS } from "../../../utils/constants";
-import { PropertyBEModel } from "../../../models/properties-inputs/property-be-model";
-import { ForwardingPath } from "app/models/forwarding-path";
-import { ServicePathGraphUtils } from "./utils/composition-graph-service-path-utils";
-import { CompositionCiServicePathLink } from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-import {
- ZoneInstance, ZoneInstanceMode, ZoneInstanceType,
- ZoneInstanceAssignmentType
-} from "app/models/graph/zones/zone-instance";
-
-import { Zone } from "app/models/graph/zones/zone";
-import { CompositionGraphZoneUtils } from "./utils/composition-graph-zone-utils";
-import { UIZoneInstanceObject } from "../../../models/ui-models/ui-zone-instance-object";
-import { GroupInstance } from "../../../models/graph/zones/group-instance";
-import { PolicyInstance } from "../../../models/graph/zones/policy-instance";
-
-
-export interface ICompositionGraphScope extends ng.IScope {
-
- component: Component;
- isLoading: boolean;
- isViewOnly: boolean;
- withSidebar: boolean;
-
- //zones
- newZoneInstance;
- zoneTagMode: string;
- activeZoneInstance: ZoneInstance;
- zones: Array<Zone>;
- zoneMinimizeToggle(zoneType: ZoneInstanceType): void;
- zoneInstanceTagged(taggedInstance: ZoneInstance): void;
- zoneBackgroundClicked() :void;
- zoneInstanceModeChanged(newMode: ZoneInstanceMode, instance: ZoneInstance, zoneId: ZoneInstanceType);
- unsetActiveZoneInstance(): void;
- clickOutsideZoneInstance(): void;
- zoneAssignmentSaveStart(): void;
- zoneAssignmentSaveComplete(success: boolean): void;
-
- // Link menu - create link menu
- relationMenuDirectiveObj: ConnectRelationModel;
- isLinkMenuOpen: boolean;
- createLinkFromMenu: (chosenMatch: Match, vl: Component) => void;
- saveChangedCapabilityProperties: () => Promise<PropertyBEModel[]>;
-
- //modify link menu - for now only delete menu
- relationMenuTimeout: ng.IPromise<any>;
- linkMenuObject: LinkMenu;
- isOnDrag: boolean;
-
- //left palette functions callbacks
- dropCallback(event: JQueryEventObject, ui: any): void;
- beforeDropCallback(event: IDragDropEvent): void;
- verifyDrop(event: JQueryEventObject, ui: any): void;
-
- //Links menus
- viewRelation(link: Cy.CollectionEdges): void;
- deleteRelation(link: Cy.CollectionEdges): void;
- hideRelationMenu();
-
- //search,zoom in/out/all
- componentInstanceNames: Array<string>; //id, name
- zoom(zoomIn: boolean): void;
- zoomAllWithoutSidebar(): void;
- getAutoCompleteValues(searchTerm: string): void;
- highlightSearchMatches(searchTerm: string): void;
-
- canvasMenuProps: any;
-
- createOrUpdateServicePath(data: any): void;
- deletePathsOnCy(): void;
- drawPathOnCy(data: ForwardingPath): void;
- selectedPathId: string;
-}
-
-export class CompositionGraph implements ng.IDirective {
- private _cy: Cy.Instance;
- private _currentlyCLickedNodePosition: Cy.Position;
- private dragElement: JQuery;
- private dragComponent: ComponentInstance;
-
- constructor(private $q: ng.IQService,
- private $log: ng.ILogService,
- private $timeout: ng.ITimeoutService,
- private NodesFactory: NodesFactory,
- private CompositionGraphLinkUtils: CompositionGraphLinkUtils,
- private GeneralGraphUtils: CompositionGraphGeneralUtils,
- private ComponentInstanceFactory: ComponentInstanceFactory,
- private NodesGraphUtils: CompositionGraphNodesUtils,
- private eventListenerService: EventListenerService,
- private ComponentFactory: ComponentFactory,
- private LoaderService: LoaderService,
- private commonGraphUtils: CommonGraphUtils,
- private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
- private CompositionGraphPaletteUtils: CompositionGraphPaletteUtils,
- private compositionGraphZoneUtils: CompositionGraphZoneUtils,
- private ComponentServiceNg2: ComponentServiceNg2,
- private ModalServiceNg2: ModalService,
- private ConnectionWizardServiceNg2: ConnectionWizardService,
- private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2,
- private servicePathGraphUtils: ServicePathGraphUtils) {
-
- }
-
- restrict = 'E';
- template = require('./composition-graph.html');
- scope = {
- component: '=',
- isViewOnly: '=',
- withSidebar: '='
- };
-
- link = (scope: ICompositionGraphScope, el: JQuery) => {
- this.loadGraph(scope, el);
-
- if (!scope.component.groupInstances || !scope.component.policies) {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED, () => {
- this.loadGraphData(scope);
- });
- } else {
- this.loadGraphData(scope);
- }
-
-
- scope.$on('$destroy', () => {
- this._cy.destroy();
- _.forEach(GRAPH_EVENTS, (event) => {
- this.eventListenerService.unRegisterObserver(event);
- });
- this.eventListenerService.unRegisterObserver(EVENTS.SHOW_LOADER_EVENT + 'composition-graph');
- this.eventListenerService.unRegisterObserver(EVENTS.HIDE_LOADER_EVENT + 'composition-graph');
- this.eventListenerService.unRegisterObserver(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE);
- });
-
- };
-
- private loadGraphData = (scope: ICompositionGraphScope) => {
- this.initGraphNodes(scope.component.componentInstances, scope.isViewOnly);
- this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations, scope.component.getRelationRequirementCapability.bind(scope.component));
- this.commonGraphUtils.initUcpeChildren(this._cy);
- this.compositionGraphZoneUtils.initZoneInstances(scope.zones, scope.component);
- setTimeout(() => {//Need settimeout so that angular canvas changes will take effect before resize & center
- this.GeneralGraphUtils.zoomAllWithMax(this._cy, 1);
- });
- }
-
- private loadGraph = (scope: ICompositionGraphScope, el: JQuery) => {
- let graphEl = el.find('.sdc-composition-graph-wrapper');
- this.initGraph(graphEl, scope.isViewOnly);
- this.initDropZone(scope);
- this.initZones(scope);
- this.registerCytoscapeGraphEvents(scope);
- this.registerCustomEvents(scope, el);
- this.initViewMode(scope.isViewOnly);
- };
-
- private initGraph(graphEl: JQuery, isViewOnly: boolean) {
-
- this._cy = cytoscape({
- container: graphEl,
- style: ComponentInstanceNodesStyle.getCompositionGraphStyle(),
- zoomingEnabled: true,
- maxZoom: 1.2,
- minZoom: .1,
- userZoomingEnabled: false,
- userPanningEnabled: true,
- selectionType: 'single',
- boxSelectionEnabled: true,
- autolock: isViewOnly,
- autoungrabify: isViewOnly
- });
- }
-
- private initViewMode(isViewOnly: boolean) {
-
- if (isViewOnly) {
- //remove event listeners
- this._cy.off('drag');
- this._cy.off('handlemouseout');
- this._cy.off('handlemouseover');
- this._cy.off('canvasredraw');
- this._cy.off('handletagclick')
- this._cy.edges().unselectify();
- }
- };
-
- private registerCustomEvents(scope: ICompositionGraphScope, el: JQuery) {
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, (groupInstance: GroupInstance) => {
- this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(scope.zones, groupInstance);
- this.GeneralGraphUtils.showGroupUpdateSuccess();
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, (policyInstance: PolicyInstance) => {
- this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(scope.zones, policyInstance);
- this.GeneralGraphUtils.showPolicyUpdateSuccess();
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, (leftPaletteComponent: LeftPaletteComponent) => {
- if (scope.isOnDrag) {
- return;
- }
-
- this.$log.info(`composition-graph::registerEventServiceEvents:: palette hover on component: ${leftPaletteComponent.uniqueId}`);
-
- let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes());
- let nodesLinks = this.GeneralGraphUtils.getAllCompositionCiLinks(this._cy);
-
- if (this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(leftPaletteComponent.uniqueId)) {
- let cacheComponent = this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(leftPaletteComponent.uniqueId);
- let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(cacheComponent, nodesData, nodesLinks);
-
- this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy);
- this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy);
-
- return;
- }
-
- //----------------------- ORIT TO FIX------------------------//
-
- this.ComponentServiceNg2.getCapabilitiesAndRequirements(leftPaletteComponent.componentType, leftPaletteComponent.uniqueId).subscribe((response: ComponentGenericResponse) => {
-
- let component = this.ComponentFactory.createEmptyComponent(leftPaletteComponent.componentType);
- component.uniqueId = component.uniqueId;
- component.capabilities = response.capabilities;
- component.requirements = response.requirements;
- this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, component);
- });
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ADD_ZONE_INSTANCE_FROM_PALETTE, (component: Component, paletteComponent: LeftPaletteComponent, startPosition: Point) => {
-
- let zoneType: ZoneInstanceType = this.compositionGraphZoneUtils.getZoneTypeForPaletteComponent(paletteComponent.categoryType);
- this.compositionGraphZoneUtils.showZone(scope.zones[zoneType]);
-
- this.LoaderService.showLoader('composition-graph');
- this.compositionGraphZoneUtils.createZoneInstanceFromLeftPalette(zoneType, component, paletteComponent.type).subscribe((zoneInstance: ZoneInstance) => {
- this.LoaderService.hideLoader('composition-graph');
- this.compositionGraphZoneUtils.addInstanceToZone(scope.zones[zoneInstance.type], zoneInstance, true);
- this.compositionGraphZoneUtils.createPaletteToZoneAnimation(startPosition, zoneType, zoneInstance);
- }, (error) => {
- this.LoaderService.hideLoader('composition-graph');
- });
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT, () => {
-
- this._cy.emit('hidehandles');
- this.matchCapabilitiesRequirementsUtils.resetFadedNodes(this._cy);
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, (dragElement, dragComponent) => {
-
- this.dragElement = dragElement;
- this.dragComponent = this.ComponentInstanceFactory.createComponentInstanceFromComponent(dragComponent);
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, (event: IDragDropEvent) => {
- this.CompositionGraphPaletteUtils.onComponentDrag(this._cy, event, this.dragElement, this.dragComponent);
-
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, (component: ComponentInstance) => {
-
- let selectedNode = this._cy.getElementById(component.uniqueId);
- selectedNode.data().componentInstance.name = component.name;
- selectedNode.data('name', component.name); //used for tooltip
- selectedNode.data('displayName', selectedNode.data().getDisplayName()); //abbreviated
-
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, (componentInstance: ComponentInstance) => {
- let nodeToDelete = this._cy.getElementById(componentInstance.uniqueId);
- this.NodesGraphUtils.deleteNode(this._cy, scope.component, nodeToDelete);
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE, (deletedInstance: UIZoneInstanceObject) => {
-
- if (deletedInstance.type === ZoneInstanceType.POLICY) {
- scope.component.policies = scope.component.policies.filter(policy => policy.uniqueId !== deletedInstance.uniqueId);
- } else if (deletedInstance.type === ZoneInstanceType.GROUP) {
- scope.component.groupInstances = scope.component.groupInstances.filter(group => group.uniqueId !== deletedInstance.uniqueId);
- }
- //remove it from zones
- scope.zones[deletedInstance.type].removeInstance(deletedInstance.uniqueId);
- if (deletedInstance.type === ZoneInstanceType.GROUP && !_.isEmpty(scope.zones[ZoneInstanceType.POLICY])) {
- this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(deletedInstance.uniqueId, [scope.zones[ZoneInstanceType.POLICY]], ZoneInstanceAssignmentType.GROUPS);
- }
- this.eventListenerService.notifyObservers(EVENTS.UPDATE_PANEL);
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, (componentInstanceId: string) => {
- if (!_.isEmpty(scope.zones)) {
- this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(componentInstanceId, scope.zones, ZoneInstanceAssignmentType.COMPONENT_INSTANCES);
- }
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_EDGE, (releaseLoading: boolean, linksToDelete: Cy.CollectionEdges) => {
- this.CompositionGraphLinkUtils.deleteLink(this._cy, scope.component, releaseLoading, linksToDelete);
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_INSERT_NODE_TO_UCPE, (node: Cy.CollectionNodes, ucpe: Cy.CollectionNodes, updateExistingNode: boolean) => {
-
- this.commonGraphUtils.initUcpeChildData(node, ucpe);
- //check if item is a VL, and if so, skip adding the binding to ucpe
- if (!(node.data() instanceof CompositionCiNodeVl)) {
- this.CompositionGraphLinkUtils.createVfToUcpeLink(scope.component, this._cy, ucpe.data(), node.data()); //create link from the node to the ucpe
- }
-
- if (updateExistingNode) {
- let vlsPendingDeletion: Cy.CollectionNodes = this.NodesGraphUtils.deleteNodeVLsUponMoveToOrFromUCPE(scope.component, node.cy(), node); //delete connected VLs that no longer have 2 links
- this.CompositionGraphLinkUtils.deleteLinksWhenNodeMovedFromOrToUCPE(scope.component, node.cy(), node, vlsPendingDeletion); //delete all connected links if needed
- this.GeneralGraphUtils.pushUpdateComponentInstanceActionToQueue(scope.component, true, node.data().componentInstance); //update componentInstance position
- }
-
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_REMOVE_NODE_FROM_UCPE, (node: Cy.CollectionNodes, ucpe: Cy.CollectionNodes) => {
- this.commonGraphUtils.removeUcpeChildData(node);
- let vlsPendingDeletion: Cy.CollectionNodes = this.NodesGraphUtils.deleteNodeVLsUponMoveToOrFromUCPE(scope.component, node.cy(), node);
- this.CompositionGraphLinkUtils.deleteLinksWhenNodeMovedFromOrToUCPE(scope.component, node.cy(), node, vlsPendingDeletion); //delete all connected links if needed
- this.GeneralGraphUtils.pushUpdateComponentInstanceActionToQueue(scope.component, true, node.data().componentInstance); //update componentInstance position
- });
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_VERSION_CHANGED, (component: Component) => {
- scope.component = component;
- this._cy.elements().remove();
- this.loadGraphData(scope);
- });
-
- this.eventListenerService.registerObserverCallback(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, (ischecked: boolean) => {
- if (ischecked) {
- this._cy.$('node:selected').addClass('dependent');
- } else {
- // due to defect in cytoscape, just changing the class does not replace the icon, and i need to revert to original icon with no markings.
- this._cy.$('node:selected').removeClass('dependent');
- this._cy.$('node:selected').style({'background-image': this._cy.$('node:selected').data('originalImg')});
- }
- });
-
- scope.zoom = (zoomIn: boolean): void => {
- let currentZoom: number = this._cy.zoom();
- if (zoomIn) {
- this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom + .1);
- } else {
- this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom - .1);
- }
- }
-
-
- scope.zoomAllWithoutSidebar = () => {
- scope.withSidebar = false;
- setTimeout(() => { //wait for sidebar changes to take effect before zooming
- this.GeneralGraphUtils.zoomAll(this._cy);
- });
- };
-
- scope.getAutoCompleteValues = (searchTerm: string) => {
- if (searchTerm.length > 1) { //US requirement: only display search results after 2nd letter typed.
- let nodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
- scope.componentInstanceNames = _.map(nodes, node => node.data('name'));
- } else {
- scope.componentInstanceNames = [];
- }
- };
-
- scope.highlightSearchMatches = (searchTerm: string) => {
- this.NodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm);
- let matchingNodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
- this.GeneralGraphUtils.zoomAll(this._cy, matchingNodes);
- };
-
- scope.saveChangedCapabilityProperties = (): Promise<PropertyBEModel[]> => {
- return new Promise<PropertyBEModel[]>((resolve) => {
- const capabilityPropertiesBE: PropertyBEModel[] = this.ConnectionWizardServiceNg2.changedCapabilityProperties.map((prop) => {
- prop.value = prop.getJSONValue();
- const propBE = new PropertyBEModel(prop);
- propBE.parentUniqueId = this.ConnectionWizardServiceNg2.selectedMatch.relationship.relation.capabilityOwnerId;
- return propBE;
- });
- if (capabilityPropertiesBE.length > 0) {
- // if there are capability properties to update, then first update capability properties and then resolve promise
- this.ComponentInstanceServiceNg2
- .updateInstanceCapabilityProperties(
- scope.component,
- this.ConnectionWizardServiceNg2.selectedMatch.toNode,
- this.ConnectionWizardServiceNg2.selectedMatch.capability,
- capabilityPropertiesBE
- )
- .subscribe((response) => {
- console.log("Update resource instance capability properties response: ", response);
- this.ConnectionWizardServiceNg2.changedCapabilityProperties = [];
- resolve(capabilityPropertiesBE);
- });
- } else {
- // no capability properties to update, immediately resolve promise
- resolve(capabilityPropertiesBE);
- }
- });
- };
-
- scope.createLinkFromMenu = (): void => {
- scope.isLinkMenuOpen = false;
-
- scope.saveChangedCapabilityProperties().then(() => {
- //create link:
- this.CompositionGraphLinkUtils
- .createLinkFromMenu(this._cy, this.ConnectionWizardServiceNg2.selectedMatch, scope.component);
- });
- };
-
- scope.hideRelationMenu = () => {
- this.commonGraphUtils.safeApply(scope, () => {
- delete scope.canvasMenuProps;
- this.$timeout.cancel(scope.relationMenuTimeout);
- });
- };
-
- scope.createOrUpdateServicePath = (data: any) => {
- this.servicePathGraphUtils.createOrUpdateServicePath(scope, data);
- };
- scope.deletePathsOnCy = () => {
- this.servicePathGraphUtils.deletePathsFromGraph(this._cy, <Service>scope.component);
- };
- scope.drawPathOnCy = (data: ForwardingPath) => {
- this.servicePathGraphUtils.drawPath(this._cy, data, <Service>scope.component);
- };
-
- scope.viewRelation = (link: Cy.CollectionEdges) => {
- scope.hideRelationMenu();
-
- const linkData = link.data();
- const sourceNode: CompositionCiNodeBase = link.source().data();
- const targetNode: CompositionCiNodeBase = link.target().data();
- const relationship: Relationship = linkData.relation.relationships[0];
-
- scope.component.getRelationRequirementCapability(relationship, sourceNode.componentInstance, targetNode.componentInstance).then((objReqCap) => {
- const capability = objReqCap.capability;
- const requirement = objReqCap.requirement;
-
- this.ConnectionWizardServiceNg2.currentComponent = scope.component;
- this.ConnectionWizardServiceNg2.connectRelationModel = new ConnectRelationModel(sourceNode, targetNode, []);
- this.ConnectionWizardServiceNg2.selectedMatch = new Match(requirement, capability, true, linkData.source, linkData.target);
- this.ConnectionWizardServiceNg2.selectedMatch.relationship = relationship;
-
- const title = `Connection Properties`;
- const saveButton: ButtonModel = new ButtonModel('Save', 'blue', () => {
- scope.saveChangedCapabilityProperties().then(() => {
- this.ModalServiceNg2.closeCurrentModal();
- })
- });
- const cancelButton: ButtonModel = new ButtonModel('Cancel', 'white', () => {
- this.ModalServiceNg2.closeCurrentModal();
- });
- const modal = new ModalModel('xl', title, '', [saveButton, cancelButton]);
- const modalInstance = this.ModalServiceNg2.createCustomModal(modal);
- this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
- modalInstance.instance.open();
-
- new Promise((resolve) => {
- if (!this.ConnectionWizardServiceNg2.selectedMatch.capability.properties) {
- this.ComponentInstanceServiceNg2.getInstanceCapabilityProperties(scope.component, linkData.target, capability)
- .subscribe(() => {
- resolve();
- }, (error) => {
- });
- } else {
- resolve();
- }
- }).then(() => {
- this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
- })
-
- }, (error) => {
- });
- };
-
- scope.deleteRelation = (link: Cy.CollectionEdges) => {
- scope.hideRelationMenu();
-
- //if multiple edges selected, delete the VL itself so edges get deleted automatically
- if (this._cy.$('edge:selected').length > 1) {
- this.NodesGraphUtils.deleteNode(this._cy, scope.component, this._cy.$('node:selected'));
- } else {
- this.CompositionGraphLinkUtils.deleteLink(this._cy, scope.component, true, link);
- }
- };
- }
-
- private registerCytoscapeGraphEvents(scope: ICompositionGraphScope) {
-
- this._cy.on('addedgemouseup', (event, data) => {
- scope.relationMenuDirectiveObj = this.CompositionGraphLinkUtils.onLinkDrawn(this._cy, data.source, data.target);
- if (scope.relationMenuDirectiveObj != null) {
- this.ConnectionWizardServiceNg2.setRelationMenuDirectiveObj(scope.relationMenuDirectiveObj);
- this.ConnectionWizardServiceNg2.currentComponent = scope.component;
- //TODO: init with the selected values
- this.ConnectionWizardServiceNg2.selectedMatch = null;
-
- let steps: Array<StepModel> = [];
- let fromNodeName: string = scope.relationMenuDirectiveObj.fromNode.componentInstance.name;
- let toNodeName: string = scope.relationMenuDirectiveObj.toNode.componentInstance.name;
- steps.push(new StepModel(fromNodeName, FromNodeStepComponent));
- steps.push(new StepModel(toNodeName, ToNodeStepComponent));
- steps.push(new StepModel('Properties', PropertiesStepComponent));
- let wizardTitle = 'Connect: ' + fromNodeName + ' to ' + toNodeName;
- let modalInstance = this.ModalServiceNg2.createMultiStepsWizard(wizardTitle, steps, scope.createLinkFromMenu, ConnectionWizardHeaderComponent);
- modalInstance.instance.open();
- }
- });
- this._cy.on('tapstart', 'node', (event: Cy.EventObject) => {
- scope.isOnDrag = true;
- this._currentlyCLickedNodePosition = angular.copy(event.cyTarget[0].position()); //update node position on drag
- if (event.cyTarget.data().isUcpe) {
- this._cy.nodes('.ucpe-cp').unlock();
- event.cyTarget.style('opacity', 0.5);
- }
- });
-
- this._cy.on('drag', 'node', (event: Cy.EventObject) => {
-
- if (event.cyTarget.data().isDraggable) {
- event.cyTarget.style({ 'overlay-opacity': 0.24 });
- if (this.GeneralGraphUtils.isValidDrop(this._cy, event.cyTarget)) {
- event.cyTarget.style({ 'overlay-color': GraphColors.NODE_BACKGROUND_COLOR });
- } else {
- event.cyTarget.style({ 'overlay-color': GraphColors.NODE_OVERLAPPING_BACKGROUND_COLOR });
- }
- }
-
- if (event.cyTarget.data().isUcpe) {
- let pos = event.cyTarget.position();
-
- this._cy.nodes('[?isInsideGroup]').positions((i, node) => {
- return {
- x: pos.x + node.data("ucpeOffset").x,
- y: pos.y + node.data("ucpeOffset").y
- }
- });
- }
- });
-
- this._cy.on('handlemouseover', (event, payload) => {
-
- if (payload.node.grabbed() || this._cy.scratch('_edge_editation_highlights') === true) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes
- return;
- }
-
- if (scope.zoneTagMode) {
- scope.zoneTagMode = scope.zones[scope.activeZoneInstance.type].getHoverTagModeId();
- return;
- }
-
- let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes());
- let nodesLinks = this.GeneralGraphUtils.getAllCompositionCiLinks(this._cy);
-
- let linkableNodes = this.commonGraphUtils.getLinkableNodes(this._cy, payload.node);
- let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(payload.node.data().componentInstance, linkableNodes, nodesLinks);
- this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy);
- this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data());
-
- this._cy.scratch()._edge_editation_highlights = true;
- });
-
- this._cy.on('handlemouseout', () => {
- if (scope.zoneTagMode) {
- scope.zoneTagMode = scope.zones[scope.activeZoneInstance.type].getTagModeId();
- return;
- }
- if (this._cy.scratch('_edge_editation_highlights') === true) {
- this._cy.removeScratch('_edge_editation_highlights');
- this._cy.emit('hidehandles');
- this.matchCapabilitiesRequirementsUtils.resetFadedNodes(this._cy);
- }
- });
-
-
- this._cy.on('tapend', (event: Cy.EventObject) => {
- scope.isOnDrag = false;
- if (scope.zoneTagMode) {
- return;
- }
- if (event.cyTarget === this._cy) { //On Background clicked
- if (this._cy.$('node:selected').length === 0) { //if the background click but not dragged
- if (scope.activeZoneInstance) {
- scope.unsetActiveZoneInstance();
- }
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
- }
- scope.hideRelationMenu();
- }
-
- else if (event.cyTarget.isEdge()) { //On Edge clicked
- this.CompositionGraphLinkUtils.handleLinkClick(this._cy, event);
- if (event.cyTarget.data().type === CompositionCiServicePathLink.LINK_TYPE) {
- return;
- }
- this.openModifyLinkMenu(scope, this.CompositionGraphLinkUtils.getModifyLinkMenu(event.cyTarget[0], event), 6000);
- }
-
- else { //On Node clicked
-
- this._cy.nodes(':grabbed').style({ 'overlay-opacity': 0 });
-
- let isUcpe: boolean = event.cyTarget.data().isUcpe;
- let newPosition = event.cyTarget[0].position();
- //node position changed (drop after drag event) - we need to update position
- if (this._currentlyCLickedNodePosition.x !== newPosition.x || this._currentlyCLickedNodePosition.y !== newPosition.y) {
- let nodesMoved: Cy.CollectionNodes = this._cy.$(':grabbed');
- if (isUcpe) {
- nodesMoved = nodesMoved.add(this._cy.nodes('[?isInsideGroup]:free')); //'child' nodes will not be recognized as "grabbed" elements within cytoscape. manually add them to collection of nodes moved.
- }
- this.NodesGraphUtils.onNodesPositionChanged(this._cy, scope.component, nodesMoved);
- } else {
- this.$log.debug('composition-graph::onNodeSelectedEvent:: fired');
- if (scope.activeZoneInstance) {
- scope.unsetActiveZoneInstance();
- }
- scope.$apply(() => {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_NODE_SELECTED, event.cyTarget.data().componentInstance);
- });
- }
-
- if (isUcpe) {
- this._cy.nodes('.ucpe-cp').lock();
- event.cyTarget.style('opacity', 1);
- }
-
- }
- });
-
- this._cy.on('boxselect', 'node', (event: Cy.EventObject) => {
- scope.unsetActiveZoneInstance();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_NODE_SELECTED, event.cyTarget.data().componentInstance);
- });
-
- this._cy.on('canvasredraw', (event: Cy.EventObject) => {
- if (scope.zoneTagMode) {
- this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, scope.activeZoneInstance);
- }
- });
-
- this._cy.on('handletagclick', (event: Cy.EventObject, eventData: any) => {
- this.compositionGraphZoneUtils.handleTagClick(this._cy, scope.activeZoneInstance, eventData.nodeId);
-
-
- });
- }
-
- private openModifyLinkMenu = (scope: ICompositionGraphScope, linkMenuObject: LinkMenu, timeOutInMilliseconds?: number) => {
- scope.hideRelationMenu();
- this.$timeout(() => {
- scope.canvasMenuProps = {
- open: true,
- styleClass: 'w-sdc-canvas-menu-list',
- items: [],
- position: {
- x: `${linkMenuObject.position.x}px`,
- y: `${linkMenuObject.position.y}px`
- }
- };
-
- if (this._cy.$('edge:selected').length === 1) {
- scope.canvasMenuProps.items.push({
- contents: 'View',
- styleClass: 'w-sdc-canvas-menu-item-view',
- action: () => {
- scope.viewRelation(<Cy.CollectionEdges>linkMenuObject.link);
- }
- });
- }
- if (!scope.isViewOnly) {
- scope.canvasMenuProps.items.push({
- contents: 'Delete',
- styleClass: 'w-sdc-canvas-menu-item-delete',
- action: () => {
- scope.deleteRelation(<Cy.CollectionEdges>linkMenuObject.link);
- }
- });
- }
- scope.relationMenuTimeout = this.$timeout(() => {
- scope.hideRelationMenu();
- }, timeOutInMilliseconds ? timeOutInMilliseconds : 6000);
- });
- };
-
- private initGraphNodes(componentInstances: ComponentInstance[], isViewOnly: boolean) {
-
-
- setTimeout(() => {
- let handles = new CytoscapeEdgeEditation;
- handles.init(this._cy);
- if (!isViewOnly) { //Init nodes handle extension - enable dynamic links
- handles.initNodeEvents();
- handles.registerHandle(ComponentInstanceNodesStyle.getAddEdgeHandle());
- }
- handles.registerHandle(ComponentInstanceNodesStyle.getTagHandle());
- handles.registerHandle(ComponentInstanceNodesStyle.getTaggedPolicyHandle());
- handles.registerHandle(ComponentInstanceNodesStyle.getTaggedGroupHandle());
- }, 0);
-
-
- _.each(componentInstances, (instance) => {
- let compositionGraphNode: CompositionCiNodeBase = this.NodesFactory.createNode(instance);
- this.commonGraphUtils.addComponentInstanceNodeToGraph(this._cy, compositionGraphNode);
- });
- }
-
-
- private initDropZone(scope: ICompositionGraphScope) {
-
- if (scope.isViewOnly) {
- return;
- }
- scope.dropCallback = (event: IDragDropEvent) => {
- this.$log.debug(`composition-graph::dropCallback:: fired`);
- this.CompositionGraphPaletteUtils.addNodeFromPalette(this._cy, event, scope.component);
- };
-
- scope.verifyDrop = (event: JQueryEventObject) => {
-
- if (!this.dragElement || this.dragElement.hasClass('red')) {
- return false;
- }
- return true;
- };
-
- scope.beforeDropCallback = (event: IDragDropEvent): ng.IPromise<void> => {
- let deferred: ng.IDeferred<void> = this.$q.defer<void>();
- if (this.dragElement.hasClass('red')) {
- deferred.reject();
- } else {
- deferred.resolve();
- }
-
- return deferred.promise;
- }
- }
-
-
- private initZones = (scope: ICompositionGraphScope): void => {
- scope.zones = this.compositionGraphZoneUtils.createCompositionZones();
-
-
- scope.zoneMinimizeToggle = (zoneType: ZoneInstanceType): void => {
- scope.zones[zoneType].minimized = !scope.zones[zoneType].minimized;
- };
-
- scope.zoneInstanceModeChanged = (newMode: ZoneInstanceMode, instance: ZoneInstance, zoneId: ZoneInstanceType): void => {
- if (scope.zoneTagMode) { //we're in tag mode.
- if (instance == scope.activeZoneInstance && newMode == ZoneInstanceMode.NONE) { //we want to turn tag mode off.
- scope.zoneTagMode = null;
- scope.activeZoneInstance.mode = ZoneInstanceMode.SELECTED;
- this.compositionGraphZoneUtils.endCyTagMode(this._cy);
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_END, instance);
-
- }
- } else {
- if (instance != scope.activeZoneInstance || (instance == scope.activeZoneInstance && newMode > ZoneInstanceMode.HOVER)) { //when active zone instance gets hover/none,dont actually change mode, just show/hide indications
- instance.mode = newMode;
- }
-
- if (newMode == ZoneInstanceMode.NONE) {
- this.compositionGraphZoneUtils.hideZoneTagIndications(this._cy);
- if (scope.zones[ZoneInstanceType.GROUP]) {
- this.compositionGraphZoneUtils.hideGroupZoneIndications(scope.zones[ZoneInstanceType.GROUP].instances);
- }
- }
- if (newMode >= ZoneInstanceMode.HOVER) {
- this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, instance);
- if (instance.type == ZoneInstanceType.POLICY && scope.zones[ZoneInstanceType.GROUP]) {
- this.compositionGraphZoneUtils.showGroupZoneIndications(scope.zones[ZoneInstanceType.GROUP].instances, instance);
- }
- }
- if (newMode >= ZoneInstanceMode.SELECTED) {
- this._cy.$('node:selected').unselect();
- if (scope.activeZoneInstance && scope.activeZoneInstance != instance && newMode >= ZoneInstanceMode.SELECTED) {
- scope.activeZoneInstance.mode = ZoneInstanceMode.NONE;
- }
- scope.activeZoneInstance = instance;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, instance);
- }
- if (newMode == ZoneInstanceMode.TAG) {
- this.compositionGraphZoneUtils.startCyTagMode(this._cy);
- scope.zoneTagMode = scope.zones[zoneId].getTagModeId();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_START, zoneId);
- }
- }
- };
-
- scope.zoneInstanceTagged = (taggedInstance: ZoneInstance) => {
- scope.activeZoneInstance.addOrRemoveAssignment(taggedInstance.instanceData.uniqueId, ZoneInstanceAssignmentType.GROUPS);
- let newHandle: string = this.compositionGraphZoneUtils.getCorrectHandleForNode(taggedInstance.instanceData.uniqueId, scope.activeZoneInstance);
- taggedInstance.showHandle(newHandle);
- }
-
- scope.zoneBackgroundClicked = (): void => {
- if (!scope.zoneTagMode && scope.activeZoneInstance) {
- scope.unsetActiveZoneInstance();
- }
- };
-
- scope.zoneAssignmentSaveStart = () => {
- this.LoaderService.showLoader('composition-graph');
- }
-
- scope.zoneAssignmentSaveComplete = (success: boolean) => {
- this.LoaderService.hideLoader('composition-graph');
- if (!success) {
- this.GeneralGraphUtils.showUpdateFailure();
- }
- };
-
- scope.unsetActiveZoneInstance = (): void => {
- if (scope.activeZoneInstance) {
- scope.activeZoneInstance.mode = ZoneInstanceMode.NONE;
- scope.activeZoneInstance = null;
- scope.zoneTagMode = null;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
- }
- };
- };
-
-
- public static factory = ($q,
- $log,
- $timeout,
- NodesFactory,
- LinksGraphUtils,
- GeneralGraphUtils,
- ComponentInstanceFactory,
- NodesGraphUtils,
- EventListenerService,
- ComponentFactory,
- LoaderService,
- CommonGraphUtils,
- MatchCapabilitiesRequirementsUtils,
- CompositionGraphPaletteUtils,
- CompositionGraphZoneUtils,
- ComponentServiceNg2,
- ModalService,
- ConnectionWizardService,
- ComponentInstanceServiceNg2,
- ServicePathGraphUtils) => {
- return new CompositionGraph(
- $q,
- $log,
- $timeout,
- NodesFactory,
- LinksGraphUtils,
- GeneralGraphUtils,
- ComponentInstanceFactory,
- NodesGraphUtils,
- EventListenerService,
- ComponentFactory,
- LoaderService,
- CommonGraphUtils,
- MatchCapabilitiesRequirementsUtils,
- CompositionGraphPaletteUtils,
- CompositionGraphZoneUtils,
- ComponentServiceNg2,
- ModalService,
- ConnectionWizardService,
- ComponentInstanceServiceNg2,
- ServicePathGraphUtils);
- }
-}
-
-CompositionGraph.factory.$inject = [
- '$q',
- '$log',
- '$timeout',
- 'NodesFactory',
- 'CompositionGraphLinkUtils',
- 'CompositionGraphGeneralUtils',
- 'ComponentInstanceFactory',
- 'CompositionGraphNodesUtils',
- 'EventListenerService',
- 'ComponentFactory',
- 'LoaderService',
- 'CommonGraphUtils',
- 'MatchCapabilitiesRequirementsUtils',
- 'CompositionGraphPaletteUtils',
- 'CompositionGraphZoneUtils',
- 'ComponentServiceNg2',
- 'ModalServiceNg2',
- 'ConnectionWizardServiceNg2',
- 'ComponentInstanceServiceNg2',
- 'ServicePathGraphUtils'
-];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
deleted file mode 100644
index b473f44..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
+++ /dev/null
@@ -1,67 +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.
- -->
-
-
-<loader display="isLoading" loader-type="composition-graph"></loader>
-<div class="sdc-composition-graph-wrapper {{zoneTagMode}}" ng-class="{'with-sidebar': withSidebar, 'view-only':isViewOnly}"
- data-drop="!zoneTagMode"
- data-jqyoui-options="{accept: verifyDrop}"
- data-jqyoui-droppable="{onDrop:'dropCallback', beforeDrop: 'beforeDropCallback'}">
-</div>
-
-<!-- <relation-menu relation-menu-directive-obj="relationMenuDirectiveObj" is-link-menu-open="isLinkMenuOpen"
- create-relation="createLinkFromMenu" cancel="cancelRelationMenu()"></relation-menu> -->
-
-<menu-list-ng2 [props]="canvasMenuProps"></menu-list-ng2>
-
- <div class="w-sdc-search-menu" data-ng-class="{'with-sidebar': withSidebar}">
-
- <ng2-service-path-selector
- ng-if="component.isService()"
- [service]="component"
- [draw-path]="drawPathOnCy"
- [delete-paths]="deletePathsOnCy"
- [selected-path-id]="selectedPathId">
- </ng2-service-path-selector>
- <ng2-service-path
- ng-if="component.isService()"
- [service]="component"
- [on-create]="createOrUpdateServicePath"
- [is-view-only]="isViewOnly">
- </ng2-service-path>
- <ng2-search-with-autocomplete
- [search-placeholder]="'Type to search'"
- [auto-complete-values]="componentInstanceNames"
- (search-changed)="getAutoCompleteValues($event)"
- (search-button-clicked)="highlightSearchMatches($event)"
- [search-bar-class]="'composition-search'">
- </ng2-search-with-autocomplete>
- <div class="zoom-icons sprite-new canvas-fit-all" data-ng-click="zoomAllWithoutSidebar()"></div>
- <div class="zoom-icons sprite-new zoom-plus" data-ng-click="zoom(true)"></div>
- <div class="zoom-icons sprite-new zoom-minus" data-ng-click="zoom(false)"></div>
- </div>
-<!--<asset-popover ng-if="assetPopoverOpen" asset-popover-obj="assetPopoverObj" delete-asset="deleteNode(assetPopoverObj.nodeId)"></asset-popover>-->
-<div class="sdc-canvas-zones__wrapper {{zoneTagMode}}" data-ng-class="{'with-sidebar': withSidebar}">
- <ng2-zone-container data-ng-repeat="zone in zones" [title]="zone.title" [type]="zone.type" [count]="zone.instances.length"
- [visible]="zone.visible" [minimized]="zone.minimized" (minimize)="zoneMinimizeToggle(zone.type)" (background-click)="zoneBackgroundClicked()">
- <ng2-zone-instance
- data-ng-repeat="instance in zone.instances" [hidden]="instance.hidden"
- [zone-instance]="instance" [default-icon-text]="zone.defaultIconText" [is-active]="activeZoneInstance == instance" [active-instance-mode]="activeZoneInstance && activeZoneInstance.mode"
- [is-view-only]="isViewOnly" [force-save]="instance.forceSave" (mode-change)="zoneInstanceModeChanged($event.newMode, $event.instance, zone.type)" (tag-handle-click)="zoneInstanceTagged($event)"
- (assignment-save-start)="zoneAssignmentSaveStart()" (assignment-save-complete)="zoneAssignmentSaveComplete($event)">
- </ng2-zone-instance>
- </ng2-zone-container>
-</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less
deleted file mode 100644
index 7124a4b..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less
+++ /dev/null
@@ -1,50 +0,0 @@
-composition-graph {
- display: block;
- height:100%;
- width: 100%;
-
- .sdc-composition-graph-wrapper{
- height:100%;
- width: 100%;
-
- &.with-sidebar {
- width: calc(~'100% - 300px');
- }
- }
-
- .view-only{
- background-color:rgb(248, 248, 248);
- }
-
- .sdc-canvas-zones__wrapper {
- position: absolute;
- bottom: 10px;
- right: 12px;
- display:flex;
- transition: right 0.2s;
-
- &.with-sidebar {
- right:310px;
- }
-
- ng2-zone-container {
- display:flex;
- margin-left: 10px;
- }
- }
-
-
- .group-tagging {
- cursor: url("../../../../assets/styles/images/canvas-tagging-icons/group_1.svg"), pointer;
- }
- .group-tagging-hover {
- cursor: url("../../../../assets/styles/images/canvas-tagging-icons/group_2.svg"), pointer;
- }
- .policy-tagging {
- cursor: url("../../../../assets/styles/images/canvas-tagging-icons/policy_1.svg"), pointer;
- }
- .policy-tagging-hover {
- cursor: url("../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer;
- }
-
-}
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
deleted file mode 100644
index 329af56..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
+++ /dev/null
@@ -1,323 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import {ComponentInstance, Component, Match, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models";
-import {QueueUtils, Dictionary, GraphUIObjects} from "app/utils";
-import {LoaderService} from "app/services";
-import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
-import {CommonGraphUtils} from "../../common/common-graph-utils";
-
-
-export class CompositionGraphGeneralUtils {
-
- public componentRequirementsAndCapabilitiesCaching = new Dictionary<string, Component>();
- protected static graphUtilsUpdateQueue:QueueUtils;
-
- constructor(private $q:ng.IQService,
- private LoaderService:LoaderService,
- private commonGraphUtils:CommonGraphUtils,
- private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils,
- private Notification:any) {
- CompositionGraphGeneralUtils.graphUtilsUpdateQueue = new QueueUtils(this.$q);
- }
-
-
- /**
- * Get the offset for the link creation Menu
- * @param point
- * @returns {Cy.Position}
- */
- public calcMenuOffset:Function = (point:Cy.Position):Cy.Position => {
- point.x = point.x + 60;
- point.y = point.y + 105;
- return point;
- };
-
- /**
- * return the top left position of the link menu
- * @param cy
- * @param targetNodePosition
- * @returns {Cy.Position}
- */
- public getLinkMenuPosition = (cy:Cy.Instance, targetNodePosition:Cy.Position) => {
- let menuPosition:Cy.Position = this.calcMenuOffset(targetNodePosition); //get the link mid point
- if ($(document.body).height() < menuPosition.y + GraphUIObjects.LINK_MENU_HEIGHT + $(document.getElementsByClassName('sdc-composition-graph-wrapper')).offset().top) { // if position menu is overflow bottom
- menuPosition.y = $(document.body).height() - GraphUIObjects.TOP_HEADER_HEIGHT - GraphUIObjects.LINK_MENU_HEIGHT;
- }
- return menuPosition;
- };
-
-
- public zoomGraphTo = (cy:Cy.Instance, zoomLevel: number):void => {
- let zy = cy.height() / 2;
- let zx = cy.width() / 2;
- cy.zoom({
- level: zoomLevel,
- renderedPosition: { x: zx, y: zy }
- });
- }
-
-
- //saves the current zoom, and then sets a temporary maximum zoom for zoomAll, and then reverts to old value
- public zoomAllWithMax = (cy:Cy.Instance, maxZoom:number):void => {
-
- let oldMaxZoom:number = cy.maxZoom();
-
- cy.maxZoom(maxZoom);
- this.zoomAll(cy);
- cy.maxZoom(oldMaxZoom);
-
- };
-
-
- //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph
- public zoomAll = (cy:Cy.Instance, nodes?:Cy.CollectionNodes):void => {
-
- if (!nodes || !nodes.length) {
- nodes = cy.nodes();
- }
-
- cy.resize();
- cy.animate({
- fit: { eles: nodes, padding: 20 },
- center: { eles: nodes }
- }, { duration: 400 });
- };
-
- /**
- * will return true/false if two nodes overlapping
- *
- * @param graph node
- */
- private isNodesOverlapping(node:Cy.CollectionFirstNode, draggedNode:Cy.CollectionFirstNode):boolean {
-
- let nodeBoundingBox:Cy.BoundingBox = node.renderedBoundingBox();
- let secondNodeBoundingBox:Cy.BoundingBox = draggedNode.renderedBoundingBox();
-
- return this.isBBoxOverlapping(nodeBoundingBox, secondNodeBoundingBox);
- }
-
- /**
- * Checks whether the bounding boxes of two nodes are overlapping on any side
- * @param nodeOneBBox
- * @param nodeTwoBBox
- * @returns {boolean}
- */
- private isBBoxOverlapping(nodeOneBBox:Cy.BoundingBox, nodeTwoBBox:Cy.BoundingBox) {
- return (((nodeOneBBox.x1 < nodeTwoBBox.x1 && nodeOneBBox.x2 > nodeTwoBBox.x1) ||
- (nodeOneBBox.x1 < nodeTwoBBox.x2 && nodeOneBBox.x2 > nodeTwoBBox.x2) ||
- (nodeTwoBBox.x1 < nodeOneBBox.x1 && nodeTwoBBox.x2 > nodeOneBBox.x2)) &&
- ((nodeOneBBox.y1 < nodeTwoBBox.y1 && nodeOneBBox.y2 > nodeTwoBBox.y1) ||
- (nodeOneBBox.y1 < nodeTwoBBox.y2 && nodeOneBBox.y2 > nodeTwoBBox.y2) ||
- (nodeTwoBBox.y1 < nodeOneBBox.y1 && nodeTwoBBox.y2 > nodeOneBBox.y2)))
- }
-
-
- /**
- * Checks whether a specific component instance can be hosted on the UCPE instance
- * @param cy - Cytoscape instance
- * @param fromUcpeInstance
- * @param toComponentInstance
- * @returns {Match}
- */
- public canBeHostedOn(cy:Cy.Instance, fromUcpeInstance:ComponentInstance, toComponentInstance:ComponentInstance):Match {
-
- let matches:Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromUcpeInstance, toComponentInstance, this.getAllCompositionCiLinks(cy));
- let hostedOnMatch:Match = _.find(matches, (match:Match) => {
- return match.requirement.capability.toLowerCase() === 'tosca.capabilities.container';
- });
-
- return hostedOnMatch;
- };
-
-
- /**
- * Checks whether node can be dropped into UCPE
- * @param cy
- * @param nodeToInsert
- * @param ucpeNode
- * @returns {boolean}
- */
- private isValidDropInsideUCPE(cy:Cy.Instance, nodeToInsert:ComponentInstance, ucpeNode:ComponentInstance):boolean {
-
- let hostedOnMatch:Match = this.canBeHostedOn(cy, ucpeNode, nodeToInsert);
- let result:boolean = !angular.isUndefined(hostedOnMatch) || nodeToInsert.isVl(); //group validation
- return result;
-
- };
-
-
- /**
- * For drops from palette, checks whether the node can be dropped. If node is being held over another node, check if capable of hosting
- * @param cy
- * @param pseudoNodeBBox
- * @param paletteComponentInstance
- * @returns {boolean}
- */
- public isPaletteDropValid(cy:Cy.Instance, pseudoNodeBBox:Cy.BoundingBox, paletteComponentInstance:ComponentInstance) {
-
- let componentIsUCPE:boolean = (paletteComponentInstance.capabilities && paletteComponentInstance.capabilities['tosca.capabilities.Container'] && paletteComponentInstance.name.toLowerCase().indexOf('ucpe') > -1);
-
- if (componentIsUCPE && cy.nodes('[?isUcpe]').length > 0) { //second UCPE not allowed
- return false;
- }
-
- let illegalOverlappingNodes = _.filter(cy.nodes("[isSdcElement]"), (graphNode:Cy.CollectionFirstNode) => {
-
- if (this.isBBoxOverlapping(pseudoNodeBBox, graphNode.renderedBoundingBox())) {
- if (!componentIsUCPE && graphNode.data().isUcpe) {
- return !this.isValidDropInsideUCPE(cy, paletteComponentInstance, graphNode.data().componentInstance); //if this is valid insert into ucpe, we return false - no illegal overlapping nodes
- }
- return true;
- }
-
- return false;
- });
-
- return illegalOverlappingNodes.length === 0;
- }
-
- /**
- * will return true/false if a drop of a single node is valid
- *
- * @param graph node
- */
- public isValidDrop(cy:Cy.Instance, draggedNode:Cy.CollectionFirstNode):boolean {
-
- let illegalOverlappingNodes = _.filter(cy.nodes("[isSdcElement]"), (graphNode:Cy.CollectionFirstNode) => { //all sdc nodes, removing child nodes (childe node allways collaps
-
- if (draggedNode.data().isUcpe && (graphNode.isChild() || graphNode.data().isInsideGroup)) { //ucpe cps always inside ucpe, no overlapping
- return false;
- }
- if (draggedNode.data().isInsideGroup && (!draggedNode.active() || graphNode.data().isUcpe)) {
- return false;
- }
-
- if (!draggedNode.data().isUcpe && !(draggedNode.data() instanceof CompositionCiNodeUcpeCp) && graphNode.data().isUcpe) { //case we are dragging a node into UCPE
- let isEntirelyInUCPE:boolean = this.commonGraphUtils.isFirstBoxContainsInSecondBox(draggedNode.renderedBoundingBox(), graphNode.renderedBoundingBox());
- if (isEntirelyInUCPE) {
- if (this.isValidDropInsideUCPE(cy, draggedNode.data().componentInstance, graphNode.data().componentInstance)) { //if this is valid insert into ucpe, we return false - no illegal overlapping nodes
- return false;
- }
- }
- }
- return graphNode.data().id !== draggedNode.data().id && this.isNodesOverlapping(draggedNode, graphNode);
-
- });
- // return false;
- return illegalOverlappingNodes.length === 0;
- };
-
- /**
- * will return true/false if the move of the nodes is valid (no node overlapping and verifying if insert into UCPE is valid)
- *
- * @param nodesArray - the selected drags nodes
- */
- public isGroupValidDrop(cy:Cy.Instance, nodesArray:Cy.CollectionNodes):boolean {
- let filterDraggedNodes = nodesArray.filter('[?isDraggable]');
- let isValidDrop = _.every(filterDraggedNodes, (node:Cy.CollectionFirstNode) => {
- return this.isValidDrop(cy, node);
-
- });
- return isValidDrop;
- };
-
- /**
- * get all links in diagram
- * @param cy
- * @returns {any[]|boolean[]}
- */
- public getAllCompositionCiLinks = (cy:Cy.Instance):Array<CompositionCiLinkBase> => {
- return _.map(cy.edges("[isSdcElement]"), (edge:Cy.CollectionEdges) => {
- return edge.data();
- });
- };
-
-
- public showPolicyUpdateSuccess = () => {
- this.Notification.success({
- message: "Policy Updated",
- title: "Success"
- });
- }
-
- public showGroupUpdateSuccess = () => {
- this.Notification.success({
- message: "Group Updated",
- title: "Success"
- });
- }
-
- public showUpdateFailure = () => {
- this.Notification.error({
- message: "Update Failed",
- title: "Error"
- });
- };
-
- /**
- * Get Graph Utils server queue
- * @returns {QueueUtils}
- */
- public getGraphUtilsServerUpdateQueue():QueueUtils {
- return CompositionGraphGeneralUtils.graphUtilsUpdateQueue;
- }
- ;
-
- /**
- *
- * @param blockAction - true/false if this is a block action
- * @param instances
- * @param component
- */
- public pushMultipleUpdateComponentInstancesRequestToQueue = (blockAction:boolean, instances:Array<ComponentInstance>, component:Component):void => {
- if (blockAction) {
- this.getGraphUtilsServerUpdateQueue().addBlockingUIAction(
- () => component.updateMultipleComponentInstances(instances)
- );
- } else {
- this.getGraphUtilsServerUpdateQueue().addNonBlockingUIAction(
- () => component.updateMultipleComponentInstances(instances),
- () => this.LoaderService.hideLoader('composition-graph'));
- }
- };
-
- /**
- * this function will update component instance data
- * @param blockAction - true/false if this is a block action
- * @param updatedInstance
- */
- public pushUpdateComponentInstanceActionToQueue = (component:Component, blockAction:boolean, updatedInstance:ComponentInstance):void => {
-
- if (blockAction) {
- this.LoaderService.showLoader('composition-graph');
- this.getGraphUtilsServerUpdateQueue().addBlockingUIAction(
- () => component.updateComponentInstance(updatedInstance)
- );
- } else {
- this.getGraphUtilsServerUpdateQueue().addNonBlockingUIAction(
- () => component.updateComponentInstance(updatedInstance),
- () => this.LoaderService.hideLoader('composition-graph'));
- }
- };
-}
-
-CompositionGraphGeneralUtils.$inject = ['$q', 'LoaderService', 'CommonGraphUtils', 'MatchCapabilitiesRequirementsUtils', 'Notification'];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts
deleted file mode 100644
index 705367c..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts
+++ /dev/null
@@ -1,301 +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 obarda on 6/28/2016.
- */
-import * as _ from "lodash";
-import {GraphUIObjects} from "app/utils";
-import {LoaderService} from "app/services";
-import {
- NodeUcpe,
- CompositionCiNodeVf,
- Match,
- CompositionCiNodeBase,
- RelationshipModel,
- ConnectRelationModel,
- LinksFactory,
- Component,
- LinkMenu,
- Point,
- CompositionCiLinkBase
-} from "app/models";
-import {CommonGraphUtils} from "../../common/common-graph-utils";
-import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils";
-import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
-import {CompositionCiServicePathLink} from "../../../../models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-
-export class CompositionGraphLinkUtils {
-
- constructor(private linksFactory:LinksFactory,
- private loaderService:LoaderService,
- private generalGraphUtils:CompositionGraphGeneralUtils,
- private commonGraphUtils:CommonGraphUtils,
- private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils) {
- }
-
-
- /**
- * Delete the link on server and then remove it from graph
- * @param component
- * @param releaseLoading - true/false release the loader when finished
- * @param link - the link to delete
- */
- public deleteLink = (cy:Cy.Instance, component:Component, releaseLoading:boolean, link:Cy.CollectionEdges) => {
-
- this.loaderService.showLoader('composition-graph');
- let onSuccessDeleteRelation = (response) => {
- cy.remove(link);
- };
-
- if (!releaseLoading) {
- this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIAction(
- () => component.deleteRelation(link.data().relation).then(onSuccessDeleteRelation)
- );
- } else {
- this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
- () => component.deleteRelation(link.data().relation).then(onSuccessDeleteRelation),
- () => this.loaderService.hideLoader('composition-graph'));
- }
- };
-
- /**
- * create the link on server and than draw it on graph
- * @param link - the link to create
- * @param cy
- * @param component
- */
- public createLink = (link:CompositionCiLinkBase, cy:Cy.Instance, component:Component):void => {
-
- this.loaderService.showLoader('composition-graph');
-
- let onSuccess:(response:RelationshipModel) => void = (relation:RelationshipModel) => {
- link.setRelation(relation);
- this.commonGraphUtils.insertLinkToGraph(cy, link, component.getRelationRequirementCapability.bind(component));
- };
-
- link.updateLinkDirection();
-
- this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
- () => component.createRelation(link.relation).then(onSuccess),
- () => this.loaderService.hideLoader('composition-graph')
- );
- };
-
- private createSimpleLink = (match:Match, cy:Cy.Instance, component:Component):void => {
- let newRelation:RelationshipModel = match.matchToRelationModel();
- let linkObg:CompositionCiLinkBase = this.linksFactory.createGraphLink(cy, newRelation, newRelation.relationships[0]);
- this.createLink(linkObg, cy, component);
- };
-
- public createLinkFromMenu = (cy:Cy.Instance, chosenMatch:Match, component:Component):void => {
-
- if (chosenMatch) {
- if (chosenMatch && chosenMatch instanceof Match) {
- this.createSimpleLink(chosenMatch, cy, component);
- }
- }
- };
-
-
- /**
- * Filters the matches for UCPE links so that shown requirements and capabilites are only related to the selected ucpe-cp
- * @param fromNode
- * @param toNode
- * @param matchesArray
- * @returns {Array<MatchBase>}
- */
- public filterUcpeLinks(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, matchesArray:Array<Match>):any {
-
- let matchLink:Array<Match>;
-
- if (fromNode.isUcpePart) {
- matchLink = _.filter(matchesArray, (match:Match) => {
- return match.isOwner(fromNode.id);
- });
- }
-
- if (toNode.isUcpePart) {
- matchLink = _.filter(matchesArray, (match:Match) => {
- return match.isOwner(toNode.id);
- });
- }
- return matchLink ? matchLink : matchesArray;
- }
-
-
- /**
- * open the connect link menu if the link drawn is valid - match requirements & capabilities
- * @param cy
- * @param fromNode
- * @param toNode
- * @returns {any}
- */
- public onLinkDrawn(cy:Cy.Instance, fromNode:Cy.CollectionFirstNode, toNode:Cy.CollectionFirstNode):ConnectRelationModel {
-
- if (!this.commonGraphUtils.nodeLocationsCompatible(cy, fromNode, toNode)) {
- return null;
- }
- let linkModel:Array<CompositionCiLinkBase> = this.generalGraphUtils.getAllCompositionCiLinks(cy);
-
- let possibleRelations:Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromNode.data().componentInstance,
- toNode.data().componentInstance, linkModel);
-
- //filter relations found to limit to specific ucpe-cp
- possibleRelations = this.filterUcpeLinks(fromNode.data(), toNode.data(), possibleRelations);
-
- //if found possibleRelations between the nodes we create relation menu directive and open the link menu
- if (possibleRelations.length) {
- // let menuPosition = this.generalGraphUtils.getLinkMenuPosition(cy, toNode.renderedPoint());
- return new ConnectRelationModel(fromNode.data(), toNode.data(), possibleRelations);
- }
- return null;
- };
-
-
- /**
- * when we drag instance in to UCPE or out of UCPE - get all links we need to delete - one node in ucpe and one node outside of ucpe
- * @param node - the node we dragged into or out of the ucpe
- */
- public deleteLinksWhenNodeMovedFromOrToUCPE(component:Component, cy:Cy.Instance, nodeMoved:Cy.CollectionNodes, vlsPendingDeletion?:Cy.CollectionNodes):void {
-
-
- let linksToDelete:Cy.CollectionElements = cy.collection();
- _.forEach(nodeMoved.neighborhood('node'), (neighborNode)=> {
-
- if (neighborNode.data().isUcpePart) { //existing connections to ucpe or ucpe-cp - we want to delete even though nodeLocationsCompatible will technically return true
- linksToDelete = linksToDelete.add(nodeMoved.edgesWith(neighborNode)); // This will delete the ucpe-host-link, or the vl-ucpe-link if nodeMoved is vl
- } else if (!this.commonGraphUtils.nodeLocationsCompatible(cy, nodeMoved, neighborNode)) { //connection to regular node or vl - check if locations are compatible
- if (!vlsPendingDeletion || !vlsPendingDeletion.intersect(neighborNode).length) { //Check if this is a link to a VL pending deletion, to prevent double deletion of between the node moved and vl
- linksToDelete = linksToDelete.add(nodeMoved.edgesWith(neighborNode));
- }
- }
- });
-
- linksToDelete.each((i, link)=> {
- this.deleteLink(cy, component, false, link);
- });
-
- };
-
- /**
- * Creates a hostedOn link between a VF and UCPE
- * @param component
- * @param cy
- * @param ucpeNode
- * @param vfNode
- */
- public createVfToUcpeLink = (component:Component, cy:Cy.Instance, ucpeNode:NodeUcpe, vfNode:CompositionCiNodeVf):void => {
- let hostedOnMatch:Match = this.generalGraphUtils.canBeHostedOn(cy, ucpeNode.componentInstance, vfNode.componentInstance);
- /* create relation */
- let newRelation = new RelationshipModel();
- newRelation.fromNode = ucpeNode.id;
- newRelation.toNode = vfNode.id;
-
- let link:CompositionCiLinkBase = this.linksFactory.createUcpeHostLink(newRelation);
- link.relation = hostedOnMatch.matchToRelationModel();
- this.createLink(link, cy, component);
- };
-
- private handlePathLink(cy:Cy.Instance, event:Cy.EventObject) {
- let linkData = event.cyTarget.data();
- let selectedPathId = linkData.pathId;
- let pathEdges = cy.collection(`[pathId='${selectedPathId}']`);
- if (pathEdges.length > 1) {
- setTimeout(() => {
- pathEdges.select();
- }, 0);
- }
- }
-
- private handleVLLink(event:Cy.EventObject) {
- let vl:Cy.CollectionNodes = event.cyTarget[0].target('.vl-node');
- let connectedEdges:Cy.CollectionEdges = vl.connectedEdges(`[type!="${CompositionCiServicePathLink.LINK_TYPE}"]`);
- if (vl.length && connectedEdges.length > 1) {
- setTimeout(() => {
- vl.select();
- connectedEdges.select();
- }, 0);
- }
- }
-
-
- /**
- * Handles click event on links.
- * If one edge selected: do nothing.
- * Two or more edges: first click - select all, secondary click - select single.
- * @param cy
- * @param event
- */
- public handleLinkClick(cy:Cy.Instance, event:Cy.EventObject) {
- if (cy.$('edge:selected').length > 1 && event.cyTarget[0].selected()) {
- cy.$(':selected').unselect();
- } else {
- if (event.cyTarget[0].data().type === CompositionCiServicePathLink.LINK_TYPE) {
- this.handlePathLink(cy, event);
- }
- else {
- this.handleVLLink(event);
- }
- }
- }
-
-
- /**
- * Calculates the position for the menu that modifies an existing link
- * @param event
- * @param elementWidth
- * @param elementHeight
- * @returns {Point}
- */
- public calculateLinkMenuPosition(event, elementWidth, elementHeight):Point {
- let point:Point = new Point(event.originalEvent.clientX, event.originalEvent.clientY);
- if (event.originalEvent.view.screen.height - elementHeight < point.y) {
- point.y = event.originalEvent.view.screen.height - elementHeight;
- }
- if (event.originalEvent.view.screen.width - elementWidth < point.x) {
- point.x = event.originalEvent.view.screen.width - elementWidth;
- }
- return point;
- };
-
-
- /**
- * Gets the menu that is displayed when you click an existing link.
- * @param link
- * @param event
- * @returns {LinkMenu}
- */
- public getModifyLinkMenu(link:Cy.CollectionFirstEdge, event:Cy.EventObject):LinkMenu {
- let point:Point = this.calculateLinkMenuPosition(event, GraphUIObjects.MENU_LINK_VL_WIDTH_OFFSET, GraphUIObjects.MENU_LINK_VL_HEIGHT_OFFSET);
- let menu:LinkMenu = new LinkMenu(point, true, link);
- return menu;
- };
-
-}
-
-
-CompositionGraphLinkUtils.$inject = [
- 'LinksFactory',
- 'LoaderService',
- 'CompositionGraphGeneralUtils',
- 'CommonGraphUtils',
- 'MatchCapabilitiesRequirementsUtils'
-];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
deleted file mode 100644
index c6c732b..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
+++ /dev/null
@@ -1,277 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, NodesFactory, ComponentInstance, CompositionCiNodeVl, IAppMenu, AssetPopoverObj, Service } from "app/models";
-import { EventListenerService, LoaderService } from "app/services";
-import { GRAPH_EVENTS, ModalsHandler, GraphUIObjects } from "app/utils";
-import { CompositionGraphGeneralUtils } from "./composition-graph-general-utils";
-import { CommonGraphUtils } from "../../common/common-graph-utils";
-import { CompositionCiServicePathLink } from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-import { ServiceGenericResponse } from "app/ng2/services/responses/service-generic-response";
-import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
-/**
- * Created by obarda on 11/9/2016.
- */
-export class CompositionGraphNodesUtils {
- constructor(private NodesFactory: NodesFactory, private $log: ng.ILogService,
- private GeneralGraphUtils: CompositionGraphGeneralUtils,
- private commonGraphUtils: CommonGraphUtils,
- private eventListenerService: EventListenerService,
- private loaderService: LoaderService,
- private serviceService: ServiceServiceNg2) {
-
- }
-
- /**
- * Returns component instances for all nodes passed in
- * @param nodes - Cy nodes
- * @returns {any[]}
- */
- public getAllNodesData(nodes: Cy.CollectionNodes) {
- return _.map(nodes, (node: Cy.CollectionFirstNode) => {
- return node.data();
- })
- };
-
-
- public highlightMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string) => {
-
- cy.batch(() => {
- cy.nodes("[name !@^= '" + nameToMatch + "']").style({ 'background-image-opacity': 0.4 });
- cy.nodes("[name @^= '" + nameToMatch + "']").style({ 'background-image-opacity': 1 });
- })
-
- }
-
- //Returns all nodes whose name starts with searchTerm
- public getMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string): Cy.CollectionNodes => {
- return cy.nodes("[name @^= '" + nameToMatch + "']");
- };
-
- /**
- * Deletes component instances on server and then removes it from the graph as well
- * @param cy
- * @param component
- * @param nodeToDelete
- */
- public deleteNode(cy: Cy.Instance, component: Component, nodeToDelete: Cy.CollectionNodes): void {
-
- this.loaderService.showLoader('composition-graph');
- let onSuccess: (response: ComponentInstance) => void = (response: ComponentInstance) => {
- console.info('onSuccess', response);
-
- //if node to delete is a UCPE, remove all children (except UCPE-CPs) and remove their "hostedOn" links
- if (nodeToDelete.data().isUcpe) {
- _.each(cy.nodes('[?isInsideGroup]'), (node) => {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_REMOVE_NODE_FROM_UCPE, node, nodeToDelete);
- });
- }
-
- //check whether the node is connected to any VLs that only have one other connection. If so, delete that VL as well
- if (!(nodeToDelete.data() instanceof CompositionCiNodeVl)) {
- let connectedVls: Array<Cy.CollectionFirstNode> = this.getConnectedVlToNode(nodeToDelete);
- this.handleConnectedVlsToDelete(connectedVls);
- }
-
- // check whether there is a service path going through this node, and if so clean it from the graph.
- let nodeId = nodeToDelete.data().id;
- let connectedPathLinks = cy.collection(`[type="${CompositionCiServicePathLink.LINK_TYPE}"][source="${nodeId}"], [type="${CompositionCiServicePathLink.LINK_TYPE}"][target="${nodeId}"]`);
- _.forEach(connectedPathLinks, (link, key) => {
- cy.remove(`[pathId="${link.data().pathId}"]`);
- });
-
- // update service path list
- this.serviceService.getComponentCompositionData(component).subscribe((response: ServiceGenericResponse) => {
- (<Service>component).forwardingPaths = response.forwardingPaths;
- });
-
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, nodeId);
-
- //update UI
- cy.remove(nodeToDelete);
- };
-
- let onFailed: (response: any) => void = (response: any) => {
- console.info('onFailed', response);
- };
-
-
- this.GeneralGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
- () => component.deleteComponentInstance(nodeToDelete.data().componentInstance.uniqueId).then(onSuccess, onFailed),
- () => this.loaderService.hideLoader('composition-graph')
- );
-
- };
-
- /**
- * Finds all VLs connected to a single node
- * @param node
- * @returns {Array<Cy.CollectionFirstNode>}
- */
- public getConnectedVlToNode = (node: Cy.CollectionNodes): Array<Cy.CollectionFirstNode> => {
- let connectedVls: Array<Cy.CollectionFirstNode> = new Array<Cy.CollectionFirstNode>();
- _.forEach(node.connectedEdges().connectedNodes(), (node: Cy.CollectionFirstNode) => {
- if (node.data() instanceof CompositionCiNodeVl) {
- connectedVls.push(node);
- }
- });
- return connectedVls;
- };
-
-
- /**
- * Delete all VLs that have only two connected nodes (this function is called when deleting a node)
- * @param connectedVls
- */
- public handleConnectedVlsToDelete = (connectedVls: Array<Cy.CollectionFirstNode>) => {
- _.forEach(connectedVls, (vlToDelete: Cy.CollectionNodes) => {
-
- if (vlToDelete.connectedEdges().length === 2) { // if vl connected only to 2 nodes need to delete the vl
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, vlToDelete.data().componentInstance);
- }
- });
- };
-
-
- /**
- * This function is called when moving a node in or out of UCPE.
- * Deletes all connected VLs that have less than 2 valid connections remaining after the move
- * Returns the collection of vls that are in the process of deletion (async) to prevent duplicate calls while deletion is in progress
- * @param component
- * @param cy
- * @param node - node that was moved in/out of ucpe
- */
- public deleteNodeVLsUponMoveToOrFromUCPE = (component: Component, cy: Cy.Instance, node: Cy.CollectionNodes): Cy.CollectionNodes => {
- if (node.data() instanceof CompositionCiNodeVl) {
- return;
- }
-
- let connectedVLsToDelete: Cy.CollectionNodes = cy.collection();
- _.forEach(node.neighborhood('node'), (connectedNode) => {
-
- //Find all neighboring nodes that are VLs
- if (connectedNode.data() instanceof CompositionCiNodeVl) {
-
- //check VL's neighbors to see if it has 2 or more nodes whose location is compatible with VL (regardless of whether VL is in or out of UCPE)
- let compatibleNodeCount = 0;
- let vlNeighborhood = connectedNode.neighborhood('node');
- _.forEach(vlNeighborhood, (vlNeighborNode) => {
- if (this.commonGraphUtils.nodeLocationsCompatible(cy, connectedNode, vlNeighborNode)) {
- compatibleNodeCount++;
- }
- });
-
- if (compatibleNodeCount < 2) {
- connectedVLsToDelete = connectedVLsToDelete.add(connectedNode);
- }
- }
- });
-
- connectedVLsToDelete.each((i, vlToDelete: Cy.CollectionNodes) => {
- this.deleteNode(cy, component, vlToDelete);
- });
- return connectedVLsToDelete;
- };
-
- /**
- * This function will update nodes position. if the new position is into or out of ucpe, the node will trigger the ucpe events
- * @param cy
- * @param component
- * @param nodesMoved - the node/multiple nodes now moved by the user
- */
- public onNodesPositionChanged = (cy: Cy.Instance, component: Component, nodesMoved: Cy.CollectionNodes): void => {
-
- if (nodesMoved.length === 0) {
- return;
- }
-
- let isValidMove: boolean = this.GeneralGraphUtils.isGroupValidDrop(cy, nodesMoved);
- if (isValidMove) {
-
- this.$log.debug(`composition-graph::ValidDrop:: updating node position`);
- let instancesToUpdateInNonBlockingAction: Array<ComponentInstance> = new Array<ComponentInstance>();
-
- _.each(nodesMoved, (node: Cy.CollectionFirstNode) => { //update all nodes new position
-
- if (node.data().isUcpePart && !node.data().isUcpe) {
- return;
- }//No need to update UCPE-CPs
-
- //update position
- let newPosition: Cy.Position = this.commonGraphUtils.getNodePosition(node);
- node.data().componentInstance.updatePosition(newPosition.x, newPosition.y);
-
- //check if node moved to or from UCPE
- let ucpe = this.commonGraphUtils.isInUcpe(node.cy(), node.boundingbox());
- if (node.data().isInsideGroup || ucpe.length) {
- this.handleUcpeChildMove(node, ucpe, instancesToUpdateInNonBlockingAction);
- } else {
- instancesToUpdateInNonBlockingAction.push(node.data().componentInstance);
- }
-
- });
-
- if (instancesToUpdateInNonBlockingAction.length > 0) {
- this.GeneralGraphUtils.pushMultipleUpdateComponentInstancesRequestToQueue(false, instancesToUpdateInNonBlockingAction, component);
- }
- } else {
- this.$log.debug(`composition-graph::notValidDrop:: node return to latest position`);
- //reset nodes position
- nodesMoved.positions((i, node) => {
- return {
- x: +node.data().componentInstance.posX,
- y: +node.data().componentInstance.posY
- };
- })
- }
-
- this.GeneralGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(() => {
- }, () => {
- this.loaderService.hideLoader('composition-graph');
- });
-
- };
-
- /**
- * Checks whether the node has been added or removed from UCPE and triggers appropriate events
- * @param node - node moved
- * @param ucpeContainer - UCPE container that the node has been moved to. When moving a node out of ucpe, param will be empty
- * @param instancesToUpdateInNonBlockingAction
- */
- public handleUcpeChildMove(node: Cy.CollectionFirstNode, ucpeContainer: Cy.CollectionElements, instancesToUpdateInNonBlockingAction: Array<ComponentInstance>) {
-
- if (node.data().isInsideGroup) {
- if (ucpeContainer.length) { //moving node within UCPE. Simply update position
- this.commonGraphUtils.updateUcpeChildPosition(<Cy.CollectionNodes>node, ucpeContainer);
- instancesToUpdateInNonBlockingAction.push(node.data().componentInstance);
- } else { //removing node from UCPE. Notify observers
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_REMOVE_NODE_FROM_UCPE, node, ucpeContainer);
- }
- } else if (!node.data().isInsideGroup && ucpeContainer.length && !node.data().isUcpePart) { //adding node to UCPE
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_INSERT_NODE_TO_UCPE, node, ucpeContainer, true);
- }
- }
-
-}
-
-
-CompositionGraphNodesUtils.$inject = ['NodesFactory', '$log', 'CompositionGraphGeneralUtils', 'CommonGraphUtils', 'EventListenerService', 'LoaderService', 'ServiceServiceNg2' /*, 'sdcMenu', 'ModalsHandler'*/]
-
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-palette-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-palette-utils.ts
deleted file mode 100644
index 10d0d42..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-palette-utils.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import { EventListenerService, LoaderService } from "app/services";
-import { CapabilitiesGroup, NodesFactory, ComponentInstance, Component, CompositionCiNodeBase, RequirementsGroup } from "app/models";
-import { ComponentFactory, ComponentInstanceFactory, GRAPH_EVENTS, GraphUIObjects } from "app/utils";
-import { CompositionGraphGeneralUtils } from "./composition-graph-general-utils";
-import { CommonGraphUtils } from "../../common/common-graph-utils";
-import 'sdc-angular-dragdrop';
-import { LeftPaletteComponent } from "../../../../models/components/displayComponent";
-
-export class CompositionGraphPaletteUtils {
-
- constructor(private ComponentFactory: ComponentFactory,
- private $filter: ng.IFilterService,
- private loaderService: LoaderService,
- private generalGraphUtils: CompositionGraphGeneralUtils,
- private componentInstanceFactory: ComponentInstanceFactory,
- private nodesFactory: NodesFactory,
- private commonGraphUtils: CommonGraphUtils,
- private eventListenerService: EventListenerService) {
- }
-
- /**
- * Calculate the dragged element (html element) position on canvas
- * @param cy
- * @param event
- * @param position
- * @returns {Cy.BoundingBox}
- * @private
- */
- private _getNodeBBox(cy: Cy.Instance, event: IDragDropEvent, position?: Cy.Position) {
- let bbox = <Cy.BoundingBox>{};
- if (!position) {
- position = this.commonGraphUtils.getCytoscapeNodePosition(cy, event);
- }
- let cushionWidth: number = 40;
- let cushionHeight: number = 40;
-
- bbox.x1 = position.x - cushionWidth / 2;
- bbox.y1 = position.y - cushionHeight / 2;
- bbox.x2 = position.x + cushionWidth / 2;
- bbox.y2 = position.y + cushionHeight / 2;
- return bbox;
- }
-
- /**
- * Create the component instance, update data from parent component in the left palette and notify on_insert_to_ucpe if component was dragg into ucpe
- * @param cy
- * @param fullComponent
- * @param event
- * @param component
- */
- private _createComponentInstanceOnGraphFromPaletteComponent(cy: Cy.Instance, fullComponent: LeftPaletteComponent, event: IDragDropEvent, component: Component) {
-
- let componentInstanceToCreate: ComponentInstance = this.componentInstanceFactory.createComponentInstanceFromComponent(fullComponent);
- let cytoscapePosition: Cy.Position = this.commonGraphUtils.getCytoscapeNodePosition(cy, event);
-
- componentInstanceToCreate.posX = cytoscapePosition.x;
- componentInstanceToCreate.posY = cytoscapePosition.y;
-
-
- let onFailedCreatingInstance: (error: any) => void = (error: any) => {
- this.loaderService.hideLoader('composition-graph');
- };
-
- //on success - update node data
- let onSuccessCreatingInstance = (createInstance: ComponentInstance): void => {
-
- this.loaderService.hideLoader('composition-graph');
-
- createInstance.name = this.$filter('resourceName')(createInstance.name);
- createInstance.requirements = new RequirementsGroup(createInstance.requirements);
- createInstance.capabilities = new CapabilitiesGroup(createInstance.capabilities);
- createInstance.componentVersion = fullComponent.version;
- createInstance.icon = fullComponent.icon;
- createInstance.setInstanceRC();
-
- let newNode: CompositionCiNodeBase = this.nodesFactory.createNode(createInstance);
- let cyNode: Cy.CollectionNodes = this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, newNode);
-
- //check if node was dropped into a UCPE
- let ucpe: Cy.CollectionElements = this.commonGraphUtils.isInUcpe(cy, cyNode.boundingbox());
- if (ucpe.length > 0) {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_INSERT_NODE_TO_UCPE, cyNode, ucpe, false);
- }
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE);
-
- };
-
- this.loaderService.showLoader('composition-graph');
-
- // Create the component instance on server
- this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIAction(() => {
- component.createComponentInstance(componentInstanceToCreate).then(onSuccessCreatingInstance, onFailedCreatingInstance);
- });
- }
-
- /**
- * Thid function applay red/green background when component dragged from palette
- * @param cy
- * @param event
- * @param dragElement
- * @param dragComponent
- */
- public onComponentDrag(cy: Cy.Instance, event: IDragDropEvent, dragElement: JQuery, dragComponent: ComponentInstance) {
-
- if (event.clientX < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || event.clientY < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
- dragElement.removeClass('red');
- return;
- }
-
- let offsetPosition = {
- x: event.clientX - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
- y: event.clientY - GraphUIObjects.DIAGRAM_HEADER_OFFSET
- };
- let bbox = this._getNodeBBox(cy, event, offsetPosition);
-
- if (this.generalGraphUtils.isPaletteDropValid(cy, bbox, dragComponent)) {
- dragElement.removeClass('red');
- } else {
- dragElement.addClass('red');
- }
- }
-
- /**
- * This function is called when after dropping node on canvas
- * Check if the capability & requirements fulfilled and if not get from server
- * @param cy
- * @param event
- * @param component
- */
- public addNodeFromPalette(cy: Cy.Instance, event: IDragDropEvent, component: Component) {
- this.loaderService.showLoader('composition-graph');
-
- let draggedComponent: LeftPaletteComponent = event.dataTransfer.component;
-
- if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(draggedComponent.uniqueId)) {
- let fullComponent = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(draggedComponent.uniqueId);
- draggedComponent.capabilities = fullComponent.capabilities;
- draggedComponent.requirements = fullComponent.requirements;
- this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, event, component);
-
- } else {
-
- this.ComponentFactory.getComponentFromServer(draggedComponent.getComponentSubType(), draggedComponent.uniqueId)
- .then((fullComponent: Component) => {
- draggedComponent.capabilities = fullComponent.capabilities;
- draggedComponent.requirements = fullComponent.requirements;
- this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, event, component);
- });
- }
- }
-}
-
-
-CompositionGraphPaletteUtils.$inject = [
- 'ComponentFactory',
- '$filter',
- 'LoaderService',
- 'CompositionGraphGeneralUtils',
- 'ComponentInstanceFactory',
- 'NodesFactory',
- 'CommonGraphUtils',
- 'EventListenerService'
-];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts
deleted file mode 100644
index 48befef..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { LoaderService } from "app/services";
-import { CompositionGraphGeneralUtils } from "./composition-graph-general-utils";
-import { ICompositionGraphScope } from "../composition-graph.directive";
-import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
-import { Service } from "../../../../models/components/service";
-import { ForwardingPath } from "app/models/forwarding-path";
-import { ForwardingPathLink } from "app/models/forwarding-path-link";
-import { CompositionCiServicePathLink } from "../../../../models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-import { CommonGraphUtils } from "app/directives/graphs-v2/common/common-graph-utils";
-
-export class ServicePathGraphUtils {
-
- constructor(
- private loaderService: LoaderService,
- private generalGraphUtils: CompositionGraphGeneralUtils,
- private serviceService: ServiceServiceNg2,
- private commonGraphUtils: CommonGraphUtils
- ) { }
-
- public deletePathsFromGraph(cy: Cy.Instance, service: Service) {
- cy.remove(`[type="${CompositionCiServicePathLink.LINK_TYPE}"]`);
- }
-
- public drawPath(cy: Cy.Instance, forwardingPath: ForwardingPath, service: Service) {
- let pathElements = forwardingPath.pathElements.listToscaDataDefinition;
-
- _.forEach(pathElements, (link: ForwardingPathLink) => {
- let data: CompositionCiServicePathLink = new CompositionCiServicePathLink(link);
- data.source = _.find(
- service.componentInstances,
- instance => instance.name === data.forwardingPathLink.fromNode
- ).uniqueId;
- data.target = _.find(
- service.componentInstances,
- instance => instance.name === data.forwardingPathLink.toNode
- ).uniqueId;
- data.pathId = forwardingPath.uniqueId;
- data.pathName = forwardingPath.name;
- this.commonGraphUtils.insertServicePathLinkToGraph(cy, data);
- });
- }
-
- public createOrUpdateServicePath = (scope: ICompositionGraphScope, path: any): void => {
- let service = <Service>scope.component;
- this.loaderService.showLoader('composition-graph');
-
- let onSuccess: (response: ForwardingPath) => void = (response: ForwardingPath) => {
-
- service.forwardingPaths[response.uniqueId] = response;
- scope.selectedPathId = response.uniqueId;
- };
-
- this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
- () => this.serviceService.createOrUpdateServicePath(service, path).subscribe(onSuccess),
- () => this.loaderService.hideLoader('composition-graph')
- );
- };
-}
-
-ServicePathGraphUtils.$inject = [
- 'LoaderService',
- 'CompositionGraphGeneralUtils',
- 'ServiceServiceNg2',
- 'CommonGraphUtils'
-];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts
deleted file mode 100644
index aa19910..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import {
- Requirement, CompositionCiLinkBase, CapabilitiesGroup, RequirementsGroup, Match,
- CompositionCiNodeBase, Component, Capability
-} from "app/models";
-import { ComponentInstance } from "../../../../models/componentsInstances/componentInstance";
-/**
- * Created by obarda on 1/1/2017.
- */
-
-export class MatchCapabilitiesRequirementsUtils {
-
- /**
- * Shows + icon in corner of each node passed in
- * @param filteredNodesData
- * @param cy
- */
- public highlightMatchingComponents(filteredNodesData, cy: Cy.Instance) {
- _.each(filteredNodesData, (data: any) => {
- let node = cy.getElementById(data.id);
- cy.emit('showhandle', [node]);
- });
- }
-
- /**
- * Adds opacity to each node that cannot be linked to hovered node
- * @param filteredNodesData
- * @param nodesData
- * @param cy
- * @param hoveredNodeData
- */
- public fadeNonMachingComponents(filteredNodesData, nodesData, cy: Cy.Instance, hoveredNodeData?) {
- let fadeNodes = _.xorWith(nodesData, filteredNodesData, (node1, node2) => {
- return node1.id === node2.id;
- });
- if (hoveredNodeData) {
- _.remove(fadeNodes, hoveredNodeData);
- }
- cy.batch(() => {
- _.each(fadeNodes, (node) => {
- cy.getElementById(node.id).style({ 'background-image-opacity': 0.4 });
- });
- })
- }
-
- /**
- * Resets all nodes to regular opacity
- * @param cy
- */
- public resetFadedNodes(cy: Cy.Instance) {
- cy.batch(() => {
- cy.nodes().style({ 'background-image-opacity': 1 });
- })
- }
-
- private static isRequirementFulfilled(fromNodeId: string, requirement: any, links: Array<CompositionCiLinkBase>): boolean {
- if (requirement.maxOccurrences === 'UNBOUNDED') {
- return false;
- }
- let linksWithThisReq: Array<CompositionCiLinkBase> = _.filter(links, {
- 'relation': {
- 'fromNode': fromNodeId,
- 'relationships': [{
- 'relation': {
- 'requirementOwnerId': requirement.ownerId,
- 'requirement': requirement.name,
- 'relationship': {
- 'type': requirement.capability
- }
-
- }
- }]
- }
- });
- return linksWithThisReq.length == requirement.maxOccurrences;
- };
-
- private static isMatch(requirement: Requirement, capability: Capability): boolean {
- if (capability.type === requirement.capability) {
- if (requirement.node) {
- if (_.includes(capability.capabilitySources, requirement.node)) {
- return true;
- }
- } else {
- return true;
- }
- }
- return false;
- };
-
- public getMatchedRequirementsCapabilities(fromComponentInstance: ComponentInstance,
- toComponentInstance: ComponentInstance,
- links: Array<CompositionCiLinkBase>): Array<Match> {
- let fromToMatches: Array<Match> = this.getMatches(fromComponentInstance.requirements,
- toComponentInstance.capabilities,
- links,
- fromComponentInstance.uniqueId,
- toComponentInstance.uniqueId, true);
- let toFromMatches: Array<Match> = this.getMatches(toComponentInstance.requirements,
- fromComponentInstance.capabilities,
- links,
- fromComponentInstance.uniqueId,
- toComponentInstance.uniqueId, false);
-
- return fromToMatches.concat(toFromMatches);
- }
-
- /***** REFACTORED FUNCTIONS START HERE *****/
-
- public getMatches(requirements: RequirementsGroup, capabilities: CapabilitiesGroup, links: Array<CompositionCiLinkBase>,
- fromId: string, toId: string, isFromTo: boolean): Array<Match> {
- let matches: Array<Match> = [];
- let unfulfilledReqs = this.getUnfulfilledRequirements(fromId, requirements, links);
- _.forEach(unfulfilledReqs, (req) => {
- _.forEach(_.flatten(_.values(capabilities)), (capability: Capability) => {
- if (MatchCapabilitiesRequirementsUtils.isMatch(req, capability)) {
- if (isFromTo) {
- matches.push(new Match(req, capability, isFromTo, fromId, toId));
- } else {
- matches.push(new Match(req, capability, isFromTo, toId, fromId));
- }
- }
- });
- });
- return matches;
- }
-
- public getUnfulfilledRequirements = (fromNodeId: string, requirements: RequirementsGroup, links: Array<CompositionCiLinkBase>): Array<Requirement> => {
-
- let requirementArray: Array<Requirement> = [];
- _.forEach(_.flatten(_.values(requirements)), (requirement: Requirement) => {
- if (requirement.name !== 'dependency' && requirement.parentName !== 'dependency' && !MatchCapabilitiesRequirementsUtils.isRequirementFulfilled(fromNodeId, requirement, links)) {
- requirementArray.push(requirement);
- }
- });
- return requirementArray;
- };
-
-
- /**
- * Returns true if there is a match between the capabilities and requirements that are passed in
- * @param requirements
- * @param capabilities
- * @returns {boolean}
- */
- public containsMatch = (requirements: Array<Requirement>, capabilities: CapabilitiesGroup): boolean => {
- return _.some(requirements, (req: Requirement) => {
- return _.some(_.flatten(_.values(capabilities)), (capability: Capability) => {
- return MatchCapabilitiesRequirementsUtils.isMatch(req, capability);
- });
- });
- };
-
- /**
- * Returns array of nodes that can connect to the component.
- * In order to connect, one of the following conditions must be met:
- * 1. component has an unfulfilled requirement that matches a node's capabilities
- * 2. node has an unfulfilled requirement that matches the component's capabilities
- * 3. vl is passed in which has the capability to fulfill requirement from component and requirement on node.
- */
- public findMatchingNodes(component: Component, nodeDataArray: Array<CompositionCiNodeBase>,
- links: Array<CompositionCiLinkBase>): Array<any> //TODO allow for VL array and TEST
- {
- let componentRequirements: Array<Requirement> = this.getUnfulfilledRequirements(component.uniqueId, component.requirements, links);
- return _.filter(nodeDataArray, (node: any) => {
- if (node && node.componentInstance) {
-
- //Check if component has an unfulfilled requirement that can be met by one of nodes's capabilities (#1)
- if (componentRequirements.length && node.category !== 'groupCp' && this.containsMatch(componentRequirements, node.componentInstance.capabilities)) {
- return true;
-
- } else { //Check if node has unfulfilled requirement that can be filled by component (#2)
- let nodeRequirements: Array<Requirement> = this.getUnfulfilledRequirements(node.componentInstance.uniqueId, node.componentInstance.requirements, links);
- if (!nodeRequirements.length) return false;
- if (this.containsMatch(nodeRequirements, component.capabilities)) {
- return true;
- }
- }
- }
- });
- }
-}
-
-MatchCapabilitiesRequirementsUtils.$inject = [];
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
deleted file mode 100644
index 159a1c8..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Module, NodesFactory, ComponentInstance } from "app/models";
-import { ComponentInstanceFactory } from "app/utils";
-import { DeploymentGraphGeneralUtils } from "./deployment-utils/deployment-graph-general-utils";
-import { CommonGraphUtils } from "../common/common-graph-utils";
-import { ComponentInstanceNodesStyle } from "../common/style/component-instances-nodes-style";
-import { ModulesNodesStyle } from "../common/style/module-node-style";
-import { GRAPH_EVENTS } from "app/utils";
-import { EventListenerService } from "app/services";
-import '@bardit/cytoscape-expand-collapse';
-import { AngularJSBridge } from "../../../services/angular-js-bridge-service";
-
-interface IDeploymentGraphScope extends ng.IScope {
- component: Component;
-}
-
-export class DeploymentGraph implements ng.IDirective {
- private _cy: Cy.Instance;
-
- constructor(private NodesFactory: NodesFactory,
- private commonGraphUtils: CommonGraphUtils,
- private deploymentGraphGeneralUtils: DeploymentGraphGeneralUtils,
- private ComponentInstanceFactory: ComponentInstanceFactory,
- private eventListenerService: EventListenerService) {
- }
-
- restrict = 'E';
- template = require('./deployment-graph.html');
- scope = {
- component: '=',
- isViewOnly: '='
- };
-
- link = (scope: IDeploymentGraphScope, el: JQuery) => {
-
- if (scope.component.isResource()) {
- if (scope.component.componentInstances && scope.component.componentInstancesRelations && scope.component.modules) {
- this.loadGraph(scope, el);
- } else {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED, () => {
- this.loadGraph(scope, el);
- });
- }
- }
- };
-
- public initGraphNodes = (cy: Cy.Instance, component: Component): void => {
- if (component.modules) { // Init module nodes
- _.each(component.modules, (groupModule: Module) => {
- let moduleNode = this.NodesFactory.createModuleNode(groupModule);
- this.commonGraphUtils.addNodeToGraph(cy, moduleNode);
-
- });
- }
- _.each(component.componentInstances, (instance: ComponentInstance) => { // Init component instance nodes
- let componentInstanceNode = this.NodesFactory.createNode(instance);
- componentInstanceNode.parent = this.deploymentGraphGeneralUtils.findInstanceModule(component.modules, instance.uniqueId);
- if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module
- this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, componentInstanceNode);
- }
- });
-
- // This is a special functionality to pass the cytoscape default behavior - we can't create Parent module node without children's
- // so we must add an empty dummy child node
- _.each(this._cy.nodes('[?isGroup]'), (moduleNode: Cy.CollectionFirstNode) => {
- if (!moduleNode.isParent()) {
- let dummyInstance = this.ComponentInstanceFactory.createEmptyComponentInstance();
- let componentInstanceNode = this.NodesFactory.createNode(dummyInstance);
- componentInstanceNode.parent = moduleNode.id();
- let dummyNode = this.commonGraphUtils.addNodeToGraph(cy, componentInstanceNode, moduleNode.position());
- dummyNode.addClass('dummy-node');
- }
- })
- };
-
- private registerGraphEvents() {
-
- this._cy.on('afterExpand', (event) => {
- event.cyTarget.qtip({});
- });
-
- this._cy.on('afterCollapse', (event) => {
- this.commonGraphUtils.initNodeTooltip(event.cyTarget);
- });
- }
-
- private loadGraph = (scope: IDeploymentGraphScope, el: JQuery) => {
-
- let graphEl = el.find('.sdc-deployment-graph-wrapper');
- const imagePath = AngularJSBridge.getAngularConfig().imagesPath;
- this._cy = cytoscape({
- container: graphEl,
- style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()),
- zoomingEnabled: false,
- selectionType: 'single',
-
- });
-
- //adding expand collapse extension
- this._cy.expandCollapse({
- layoutBy: {
- name: "grid",
- animate: true,
- randomize: false,
- fit: true
- },
- fisheye: false,
- undoable: false,
- expandCollapseCueSize: 18,
- expandCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'closeModule.png',
- collapseCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'openModule.png',
- expandCollapseCueSensitivity: 2,
- cueOffset: -20
- });
-
- this.initGraphNodes(this._cy, scope.component); //creating instances nodes
- this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations, scope.component.getRelationRequirementCapability.bind(scope.component));
- this._cy.collapseAll();
- this.registerGraphEvents();
-
- scope.$on('$destroy', () => {
- this._cy.destroy();
- _.forEach(GRAPH_EVENTS, (event) => {
- this.eventListenerService.unRegisterObserver(event);
- });
- });
-
- };
-
- public static factory = (NodesFactory: NodesFactory, CommonGraphUtils: CommonGraphUtils, DeploymentGraphGeneralUtils: DeploymentGraphGeneralUtils, ComponentInstanceFactory: ComponentInstanceFactory, EventListenerService: EventListenerService) => {
- return new DeploymentGraph(NodesFactory, CommonGraphUtils, DeploymentGraphGeneralUtils, ComponentInstanceFactory, EventListenerService)
- }
-}
-
-DeploymentGraph.factory.$inject = ['NodesFactory', 'CommonGraphUtils', 'DeploymentGraphGeneralUtils', 'ComponentInstanceFactory', 'EventListenerService'];
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.html b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.html
deleted file mode 100644
index 1bca4bb..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.html
+++ /dev/null
@@ -1,19 +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="sdc-deployment-graph-wrapper" ng-class="{'view-only':isViewOnly}">
-</div>
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.less b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.less
deleted file mode 100644
index f83ee8a..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.less
+++ /dev/null
@@ -1,14 +0,0 @@
-deployment-graph {
- display: block;
- height:100%;
- width: 100%;
-
- .sdc-deployment-graph-wrapper {
- height:100%;
- width: 100%;
- }
-
- .view-only{
- background-color:rgb(248, 248, 248);
- }
-}
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts
deleted file mode 100644
index 5d0f38f..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Module } from "app/models";
-/**
- * Created by obarda on 12/21/2016.
- */
-
-export class DeploymentGraphGeneralUtils {
-
- constructor() {
-
- }
-
- public findInstanceModule = (groupsArray: Array<Module>, componentInstanceId: string): string => {
- let parentGroup: Module = _.find(groupsArray, (group: Module) => {
- return _.find((<any>Object).values(group.members), (member: string) => {
- return member === componentInstanceId;
- });
- });
- return parentGroup ? parentGroup.uniqueId : "";
- };
-}
-
-DeploymentGraphGeneralUtils.$inject = [];
diff --git a/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts b/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts
deleted file mode 100644
index 19c86a2..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts
+++ /dev/null
@@ -1,86 +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=========================================================
- */
-
-export interface ICanvasImage {
- src: string;
- width: number
- height: number;
- x: number;
- y: number;
-}
-
-'use strict';
-export class ImageCreatorService {
- static '$inject' = ['$q'];
- private _canvas: HTMLCanvasElement;
-
- constructor(private $q: ng.IQService) {
- this._canvas = <HTMLCanvasElement>$('<canvas>')[0];
- this._canvas.setAttribute('style', 'display:none');
-
- let body = document.getElementsByTagName('body')[0];
- body.appendChild(this._canvas);
- }
-
- /**
- * Create an image composed of different image layers
- * @param canvasImages
- * @param canvasWidth
- * @param canvasHeight
- * returns a PROMISE
- */
- getMultiLayerBase64Image(canvasImages: ICanvasImage[], canvasWidth?: number, canvasHeight?: number): ng.IPromise<string> {
- const deferred = this.$q.defer<string>();
-
- if (canvasImages && canvasImages.length === 0) {
- return null;
- }
-
- //If only width was set, use it for height, otherwise use first canvasImage height
- canvasHeight = canvasHeight || canvasImages[0].height;
- canvasWidth = canvasWidth || canvasImages[0].width;
-
- const images = [];
- let imagesLoaded = 0;
- const onImageLoaded = () => {
- imagesLoaded++;
- if (imagesLoaded < canvasImages.length) {
- return;
- }
- this._canvas.setAttribute('width', canvasWidth.toString());
- this._canvas.setAttribute('height', canvasHeight.toString());
- const canvasCtx = this._canvas.getContext('2d');
- canvasCtx.clearRect(0, 0, this._canvas.width, this._canvas.height);
- images.forEach((image, index) => {
- const canvasImage = canvasImages[index];
- canvasCtx.drawImage(image, canvasImage.x, canvasImage.y, canvasImage.width, canvasImage.height);
- });
- let base64Image = this._canvas.toDataURL();
- deferred.resolve(base64Image);
- };
- canvasImages.forEach(canvasImage => {
- let image = new Image();
- image.onload = onImageLoaded;
- image.src = canvasImage.src;
- images.push(image);
- });
- return deferred.promise;
- }
-}
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts b/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts
deleted file mode 100644
index 26c0426..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-interface IDragDropEvent extends JQueryEventObject {
- dataTransfer: any;
- toElement: {
- naturalWidth: number;
- naturalHeight: number;
- }
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
deleted file mode 100644
index 01ddb14..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
+++ /dev/null
@@ -1,338 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-import * as _ from "lodash";
-import { Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance, Point } from "app/models";
-import { CompositionGraphGeneralUtils } from "../composition-graph/utils/composition-graph-general-utils";
-import { EventListenerService } from "app/services";
-import { ResourceType, GRAPH_EVENTS, EVENTS, ComponentInstanceFactory, ModalsHandler } from "app/utils";
-import 'sdc-angular-dragdrop';
-import { LeftPaletteLoaderService } from "../../../services/components/utils/composition-left-palette-service";
-import { Resource } from "app/models/components/resource";
-import { ComponentType } from "app/utils/constants";
-import { LeftPaletteMetadataTypes } from "../../../models/components/displayComponent";
-import { IDirectiveLinkFn, IScope } from "angular";
-
-
-interface IPaletteScope extends IScope {
- components: Array<LeftPaletteComponent>;
- currentComponent: Component;
- model: any;
- displaySortedCategories: any;
- expandedSection: string;
- dragElement: JQuery;
- dragbleNode: {
- event: JQueryEventObject,
- components: LeftPaletteComponent,
- ui: any
- }
-
- addInstanceClick: () => void; // added code
- onPopupMouseOver: () => void // added code
- onPopupMouseOut: () => void // added code
-
- sectionClick: (section: string) => void;
- searchComponents: (searchText: string) => void;
- onMouseOver: (displayComponent: LeftPaletteComponent, elem: HTMLElement) => void;
- onMouseOut: (displayComponent: LeftPaletteComponent) => void;
-
- dragStartCallback: (event: JQueryEventObject, ui, displayComponent: LeftPaletteComponent) => void;
- dragStopCallback: () => void;
- onDragCallback: (event: JQueryEventObject) => void;
-
- setElementTemplate: (e: JQueryEventObject) => void;
-
- isOnDrag: boolean;
- isDragable: boolean;
- isLoading: boolean;
- isViewOnly: boolean;
-}
-
-export class Palette implements ng.IDirective {
- constructor(private $log: ng.ILogService,
- private LeftPaletteLoaderService: LeftPaletteLoaderService,
- private sdcConfig,
- private ComponentFactory,
- private ComponentInstanceFactory: ComponentInstanceFactory,
- private NodesFactory: NodesFactory,
- private CompositionGraphGeneralUtils: CompositionGraphGeneralUtils,
- private EventListenerService: EventListenerService,
- private sdcMenu: IAppMenu,
- private ModalsHandler: ModalsHandler
- ) {
- }
-
- private fetchingComponentFromServer: boolean = false;
- private nodeHtmlSubstitute: JQuery;
-
- scope = {
- currentComponent: '=',
- isViewOnly: '=',
- isLoading: '='
- };
- restrict = 'E';
- template = require('./palette.html');
-
- link: IDirectiveLinkFn = (scope: IPaletteScope, el: JQuery) => {
- this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent);
- this.nodeHtmlSubstitute = $('<div class="node-substitute"><span></span><img /></div>');
- el.append(this.nodeHtmlSubstitute);
- this.registerEventListenerForLeftPalette(scope);
-
- this.initComponents(scope);
- this.initEvents(scope);
- this.initDragEvents(scope);
- this._initExpandedSection(scope, '');
- el.on('$destroy', () => {
- //remove listener of download event
- this.unRegisterEventListenerForLeftPalette(scope);
- });
- };
-
-
- private registerEventListenerForLeftPalette = (scope: IPaletteScope): void => {
- this.EventListenerService.registerObserverCallback(EVENTS.LEFT_PALETTE_UPDATE_EVENT, () => {
- this.updateLeftPanelDisplay(scope);
- });
- };
-
- private unRegisterEventListenerForLeftPalette = (scope: IPaletteScope): void => {
- this.EventListenerService.unRegisterObserver(EVENTS.LEFT_PALETTE_UPDATE_EVENT);
- };
-
- private leftPanelResourceFilter(resourcesNotAbstract: Array<LeftPaletteComponent>, resourceFilterTypes: Array<string>): Array<LeftPaletteComponent> {
- let filterResources = _.filter(resourcesNotAbstract, (component) => {
- return resourceFilterTypes.indexOf(component.getComponentSubType()) > -1;
- });
- return filterResources;
- }
-
- private initLeftPanel(leftPanelComponents: Array<LeftPaletteComponent>, resourceFilterTypes: Array<string>): LeftPanelModel {
- let leftPanelModel = new LeftPanelModel();
-
- if (resourceFilterTypes && resourceFilterTypes.length) {
- leftPanelComponents = this.leftPanelResourceFilter(leftPanelComponents, resourceFilterTypes);
- }
- leftPanelModel.numberOfElements = leftPanelComponents && leftPanelComponents.length || 0;
-
- if (leftPanelComponents && leftPanelComponents.length) {
-
- let categories: any = _.groupBy(leftPanelComponents, 'mainCategory');
- for (let category in categories)
- categories[category] = _.groupBy(categories[category], 'subCategory');
-
- leftPanelModel.sortedCategories = categories;
- }
- return leftPanelModel;
- }
-
-
- private initEvents(scope: IPaletteScope) {
- scope.sectionClick = (section: string) => {
- if (section === scope.expandedSection) {
- scope.expandedSection = '';
- return;
- }
- scope.expandedSection = section;
- };
-
- scope.onMouseOver = (displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => {
- if (this.isGroupOrPolicy(displayComponent)) {
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, scope.currentComponent, displayComponent, sectionElem);
- } else {
- if (scope.isOnDrag) {
- return;
- }
- scope.isOnDrag = true;
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent);
- this.$log.debug('palette::onMouseOver:: fired');
- }
-
- };
-
- scope.onMouseOut = (displayComponent: LeftPaletteComponent) => {
- if (this.isGroupOrPolicy(displayComponent)) {
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL);
- } else {
- scope.isOnDrag = false;
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT);
- }
- };
- }
-
- private isGroupOrPolicy(component: LeftPaletteComponent): boolean {
- if (component &&
- (component.categoryType === LeftPaletteMetadataTypes.Group ||
- component.categoryType === LeftPaletteMetadataTypes.Policy)) {
- return true;
- }
- return false;
- }
-
- private initComponents(scope: IPaletteScope) {
- scope.searchComponents = (searchText: any): void => {
- scope.displaySortedCategories = this._searchComponents(searchText, scope.model.sortedCategories);
- this._initExpandedSection(scope, searchText);
- };
-
- scope.isDragable = scope.currentComponent.isComplex();
- this.updateLeftPanelDisplay(scope);
- }
-
- private updateLeftPanelDisplay(scope: IPaletteScope) {
- let entityType: string = scope.currentComponent.componentType.toLowerCase();
- let resourceFilterTypes: Array<string> = this.sdcConfig.resourceTypesFilter[entityType];
- scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent);
- //remove the container component from the list
- let componentTempToDisplay = angular.copy(scope.components);
- componentTempToDisplay = _.remove(componentTempToDisplay, function (leftPalettecomponent) {
- return leftPalettecomponent.invariantUUID !== scope.currentComponent.invariantUUID;
- });
- scope.model = this.initLeftPanel(componentTempToDisplay, resourceFilterTypes);
- scope.displaySortedCategories = angular.copy(scope.model.sortedCategories);
- };
-
- private _initExpandedSection(scope: IPaletteScope, searchText: string): void {
- if (searchText == '') {
- let isContainingCategory: boolean = false;
- let categoryToExpand: string;
- if (scope.currentComponent && scope.currentComponent.categories && scope.currentComponent.categories[0]) {
- categoryToExpand = this.sdcMenu.categoriesDictionary[scope.currentComponent.categories[0].name];
- for (let category in scope.model.sortedCategories) {
- if (categoryToExpand == category) {
- isContainingCategory = true;
- break;
- }
- }
- }
- isContainingCategory ? scope.expandedSection = categoryToExpand : scope.expandedSection = 'Generic';
- }
- else {
- scope.expandedSection = Object.keys(scope.displaySortedCategories).sort()[0];
- }
- };
-
- private initDragEvents(scope: IPaletteScope) {
- scope.dragStartCallback = (event: IDragDropEvent, ui, displayComponent: LeftPaletteComponent): void => {
- if (scope.isLoading || !scope.isDragable || scope.isViewOnly || this.isGroupOrPolicy(displayComponent)) {
- return;
- }
-
- let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (componentFullData: LeftPaletteComponent) => {
- return displayComponent.uniqueId === componentFullData.uniqueId;
- });
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, scope.dragElement, component);
-
- scope.isOnDrag = true;
-
- // this.graphUtils.showMatchingNodes(component, myDiagram, scope.sdcConfig.imagesPath);
- // document.addEventListener('mousemove', moveOnDocument);
- event.dataTransfer.component = component;
- };
-
- scope.dragStopCallback = () => {
- scope.isOnDrag = false;
- };
-
- scope.onDragCallback = (event: IDragDropEvent): void => {
- this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, event);
- };
- scope.setElementTemplate = (e) => {
- let dragComponent: LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent),
- (fullComponent: LeftPaletteComponent) => {
- return (<any>angular.element(e.currentTarget).scope()).component.uniqueId === fullComponent.uniqueId;
- });
- let componentInstance: ComponentInstance = this.ComponentInstanceFactory.createComponentInstanceFromComponent(dragComponent);
- let node: CompositionCiNodeBase = this.NodesFactory.createNode(componentInstance);
-
- // myDiagram.dragFromPalette = node;
- this.nodeHtmlSubstitute.find("img").attr('src', node.img);
- scope.dragElement = this.nodeHtmlSubstitute.clone().show();
-
- return scope.dragElement;
- };
- }
-
- private _searchComponents = (searchText: string, categories: any): void => {
- let displaySortedCategories = angular.copy(categories);
- if (searchText != '') {
- angular.forEach(categories, function (category: any, categoryKey) {
-
- angular.forEach(category, function (subcategory: Array<LeftPaletteComponent>, subcategoryKey) {
- let filteredResources = [];
- angular.forEach(subcategory, function (component: LeftPaletteComponent) {
-
- let resourceFilterTerm: string = component.searchFilterTerms.toLowerCase();
- if (resourceFilterTerm.indexOf(searchText.toLowerCase()) >= 0) {
- filteredResources.push(component);
- }
- });
- if (filteredResources.length > 0) {
- displaySortedCategories[categoryKey][subcategoryKey] = filteredResources;
- }
- else {
- delete displaySortedCategories[categoryKey][subcategoryKey];
- }
- });
- if (!(Object.keys(displaySortedCategories[categoryKey]).length > 0)) {
- delete displaySortedCategories[categoryKey];
- }
-
- });
- }
- return displaySortedCategories;
- };
-
- public static factory = ($log,
- LeftPaletteLoaderService,
- sdcConfig,
- ComponentFactory,
- ComponentInstanceFactory,
- NodesFactory,
- CompositionGraphGeneralUtils,
- EventListenerService,
- sdcMenu,
- ModalsHandler
- ) => {
- return new Palette($log,
- LeftPaletteLoaderService,
- sdcConfig,
- ComponentFactory,
- ComponentInstanceFactory,
- NodesFactory,
- CompositionGraphGeneralUtils,
- EventListenerService,
- sdcMenu,
- ModalsHandler
- );
- };
-}
-
-Palette.factory.$inject = [
- '$log',
- 'LeftPaletteLoaderService',
- 'sdcConfig',
- 'ComponentFactory',
- 'ComponentInstanceFactory',
- 'NodesFactory',
- 'CompositionGraphGeneralUtils',
- 'EventListenerService',
- 'sdcMenu',
- 'ModalsHandler'
-];
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
deleted file mode 100644
index 1fed027..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
+++ /dev/null
@@ -1,76 +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="w-sdc-designer-leftbar">
- <div class="w-sdc-designer-leftbar-title">Elements <span class="w-sdc-designer-leftbar-title-count">{{model.numberOfElements}}</span>
- </div>
-
- <div class="w-sdc-designer-leftbar-search">
- <input type="text" class="w-sdc-designer-leftbar-search-input" placeholder="Search..."
- data-ng-model="searchText" data-ng-change="searchComponents(searchText)"
- ng-model-options="{ debounce: 500 }" data-tests-id="searchAsset"/>
- <span class="w-sdc-search-icon leftbar" data-ng-class="{'cancel':searchText, 'magnification':!searchText}"
- data-ng-click="searchText=''; searchComponents('',categories)"></span>
- </div>
- <div class="i-sdc-designer-leftbar-section"
- data-ng-repeat="(entityCategory, objCategory) in displaySortedCategories track by $index"
- data-ng-class="{'expanded': expandedSection.indexOf(entityCategory) !== -1}">
- <div class="i-sdc-designer-leftbar-section-title pointer" data-ng-click="sectionClick(entityCategory)"
- data-tests-id="leftbar-section-title-{{entityCategory}}">
- {{entityCategory}}
- <div class="i-sdc-designer-leftbar-section-title-icon"></div>
- </div>
- <div class="i-sdc-designer-leftbar-section-content"
- data-ng-repeat="(subCategory, components) in objCategory track by $index">
- <div class="i-sdc-designer-leftbar-section-content-subcat i-sdc-designer-leftbar-section-content-item">
- {{subCategory}}
- </div>
- <div class="i-sdc-designer-leftbar-section-content-item"
- data-ng-class="{'default-pointer': isViewOnly}"
- data-ng-mouseover="!isViewOnly && onMouseOver(component, $event.currentTarget)"
- data-ng-mouseleave="!isViewOnly && onMouseOut(component)"
- data-drag="!isViewOnly && component.isDraggable"
- data-jqyoui-options="{revert: 'invalid', helper:setElementTemplate, appendTo:'body', cursorAt: {left:38, top: 38}, cursor:'move'}"
- jqyoui-draggable="{index:{{$index}},animate:true,onStart:'dragStartCallback(component)',onStop:'dragStopCallback()', onDrag:'onDragCallback()'}"
- data-ng-repeat="component in components | orderBy: 'displayName' track by $index"
- data-tests-id={{component.displayName}}>
- <div class="i-sdc-designer-leftbar-section-content-item-icon-ph">
- <div class="medium small {{component.iconClass}}"
- data-tests-id="leftbar-section-content-item-{{component.displayName}}">
- <div class="{{component.certifiedIconClass}}" uib-tooltip="Not certified"
- tooltip-class="uib-custom-tooltip" tooltip-placement="bottom" tooltip-popup-delay="700">
- </div>
- </div>
- </div>
- <div class="i-sdc-designer-leftbar-section-content-item-info">
- <span class="i-sdc-designer-leftbar-section-content-item-info-title"
- uib-tooltip="{{component.displayName}}" tooltip-class="uib-custom-tooltip"
- tooltip-placement="bottom" tooltip-popup-delay="700">
- {{component.displayName}}</span>
- <div class="i-sdc-designer-leftbar-section-content-item-info-text">
- V.{{component.version}}
- </div>
- <div class="i-sdc-designer-leftbar-section-content-item-info-text"
- uib-tooltip="{{component.type}}" tooltip-class="uib-custom-tooltip"
- tooltip-placement="top" tooltip-popup-delay="700"> Type:
- {{component.componentSubType}}
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.less b/catalog-ui/src/app/directives/graphs-v2/palette/palette.less
deleted file mode 100644
index 85657a4..0000000
--- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.less
+++ /dev/null
@@ -1,92 +0,0 @@
-.drag-icon-border{
- border: 7px solid red;
- border-radius: 500px;
- -webkit-border-radius: 500px;
- -moz-border-radius: 500px;
- width: 53px;
- height: 53px;
-}
-
-.drag-icon-circle{
- width: 60px;
- height: 60px;
- -webkit-border-radius: 50%;
- -moz-border-radius: 50%;
- border-radius: 50%;
- position: relative;
-
-}
-
-
-@green-shadow: rgba(29, 154, 149, 0.3);
-@red-shadow: rgba(218, 31, 61, 0.3);
-.drag-icon-circle .sprite-resource-icons {
- position: absolute;
- top: 10px;
- left: 10px;
-}
-
-.drag-icon-circle.red {
- background: @red-shadow;
-}
-
-.drag-icon-circle.green {
- background: @green-shadow;
-}
-
-
-.node-substitute {
- display: none;
- position: absolute;
- z-index: 9999;
- height: 80px;
- width: 80px;
- border-radius: 50%;
- text-align: center;
-
- span {
- display: inline-block;
- vertical-align: middle;
- height: 100%;
- }
-
- img {
- height: 40px;
- width: 40px;
- box-shadow: 0 0 0 10px @green-shadow;
- border-radius: 50%;
-
- -webkit-user-drag: none;
- -moz-user-drag: none;
- user-drag: none;
- }
- &.red img {
- box-shadow: 0 0 0 10px @red-shadow;
- }
- &.bounce img {
- -moz-animation:bounceOut 0.3s linear;
- -webkit-animation:bounceOut 0.3s linear;
- animation:bounceOut 0.3s linear;
- }
-}
-
-@keyframes bounceOut {
- 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
- 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
- 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
- 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
-}
-
-@-moz-keyframes bounceOut {
- 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
- 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
- 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
- 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
-}
-
-@-webkit-keyframes bounceOut {
- 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
- 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
- 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
- 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
-}
diff --git a/catalog-ui/src/app/directives/loader/loader-directive.html b/catalog-ui/src/app/directives/loader/loader-directive.html
index 3842721..abac670 100644
--- a/catalog-ui/src/app/directives/loader/loader-directive.html
+++ b/catalog-ui/src/app/directives/loader/loader-directive.html
@@ -13,9 +13,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+ <div data-ng-if="display" data-tests-id="loader">
-
-<div data-ng-if="display" data-tests-id="tlv-loader">
<div class="tlv-loader-back " data-ng-class="{'tlv-loader-relative':relative}"></div>
<div class="tlv-loader {{size}}"></div>
</div>
diff --git a/catalog-ui/src/app/directives/print-graph-screen/print-graph-screen.ts b/catalog-ui/src/app/directives/print-graph-screen/print-graph-screen.ts
new file mode 100644
index 0000000..30b8c24
--- /dev/null
+++ b/catalog-ui/src/app/directives/print-graph-screen/print-graph-screen.ts
@@ -0,0 +1,209 @@
+/*-
+ * ============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=========================================================
+ */
+
+'use strict';
+import {IAppMenu, Component, IAppConfigurtaion} from "app/models";
+import {UrlToBase64Service} from "app/services";
+
+export interface IPrintGraphScreenScope extends ng.IScope {
+ entity:Component;
+}
+
+
+export class PrintGraphScreenDirective implements ng.IDirective {
+
+ constructor(private $filter:ng.IFilterService,
+ private sdcMenu:IAppMenu,
+ private sdcConfig:IAppConfigurtaion,
+ private urlToBase64Service:UrlToBase64Service) {
+ }
+
+ scope = {
+ entity: '='
+ };
+ restrict = 'A';
+ link = (scope:IPrintGraphScreenScope, element:any) => {
+
+
+ element.bind('click', function () {
+ printScreen();
+ });
+
+
+ let printScreen = ():void => {
+ //
+ // let pdf :any = new jsPDF('landscape', 'mm', 'a4');
+ // pdf.setProperties({
+ // title: scope.entity.name,
+ // subject: 'Design Snapshot for ' + scope.entity.name,
+ // author: scope.entity.creatorFullName,
+ // keywords: scope.entity.tags.join(', '),
+ // creator: scope.entity.creatorFullName
+ // });
+ //
+ // // A4 measures is 210 × 297 millimeters
+ // let pdfWidth :number = 297,
+ // pdfHeight :number = 210,
+ // leftColumnWidth :number = 80;
+ //
+ // //left bar background
+ // pdf.setDrawColor(0);
+ // pdf.setFillColor(248, 249, 251);
+ // pdf.rect(0, 0, leftColumnWidth, pdfHeight, 'F');
+ //
+ // //entity name
+ // pdf.setFontSize(12);
+ // pdf.setTextColor(38, 61, 77);
+ // let splitTitle :any = pdf.splitTextToSize(scope.entity.name, 50);
+ // pdf.text(22, 15 - (splitTitle.length - 1) * 2, splitTitle);
+ //
+ // //line
+ // pdf.setLineWidth(0.2);
+ // pdf.setDrawColor(208, 209, 213);
+ // pdf.line(0, 28, leftColumnWidth, 28);
+ //
+ //
+ // pdf.setFontSize(10);
+ // let properties :any = getPdfProperties();
+ //
+ // let topOffset :number = 39, lines;
+ // properties.forEach( (item:any) => {
+ // if (!item.value) {
+ // return;
+ // }
+ // if (item.title === 'Description:') {
+ // topOffset += 5;
+ // }
+ //
+ // pdf.setTextColor(38, 61, 77);
+ // pdf.text(5, topOffset, item.title);
+ // pdf.setTextColor(102, 102, 102);
+ // lines = pdf.splitTextToSize(item.value, 49);
+ // pdf.text(5 + item.offset, topOffset, lines[0]);
+ // if (lines.length > 1) {
+ // lines = pdf.splitTextToSize(item.value.substring(lines[0].length + 1), 65);
+ // if (lines.length > 8) {
+ // lines = lines.slice(0, 7);
+ // lines[lines.length - 1] += '...';
+ // }
+ // pdf.text(5, topOffset + 4, lines);
+ // topOffset += 4 * (lines.length);
+ // }
+ //
+ // topOffset += 6;
+ // });
+ //
+ //
+ // //another background in case the text was too long
+ // let declarationLineOffset :number = 176;
+ // pdf.setDrawColor(0);
+ // pdf.setFillColor(248, 249, 251);
+ // pdf.rect(0, declarationLineOffset, leftColumnWidth, pdfHeight - declarationLineOffset, 'F');
+ // //line
+ // pdf.setLineWidth(0.2);
+ // pdf.setDrawColor(208, 209, 213);
+ // pdf.line(0, declarationLineOffset, leftColumnWidth, declarationLineOffset);
+ //
+ // //declaration
+ // pdf.setFontSize(10.5);
+ // pdf.setTextColor(38, 61, 77);
+ // pdf.text(5, 185, 'Declaration');
+ // pdf.setFontSize(9);
+ // pdf.setTextColor(102, 102, 102);
+ // pdf.setFontType('bold');
+ // pdf.text(5, 190, this.$filter('translate')('PDF_FILE_DECLARATION_BOLD'));
+ // pdf.setFontType('normal');
+ // pdf.text(5, 194, pdf.splitTextToSize(this.$filter('translate')('PDF_FILE_DECLARATION'), 65));
+ //
+ // //entity icon
+ // let self = this;
+ // let addEntityIcon:Function = () => {
+ // let iconPath:string = self.sdcConfig.imagesPath + '/styles/images/';
+ // if (scope.entity.isService()) {
+ // iconPath += 'service-icons/' + scope.entity.icon + '.png';
+ // } else {
+ // iconPath += 'resource-icons/' + scope.entity.icon + '.png';
+ // }
+ // self.urlToBase64Service.downloadUrl(iconPath, (base64string:string):void => {
+ // if (base64string) {
+ // pdf.addImage(base64string, 'JPEG', 5, 7, 15, 15);
+ // }
+ // pdf.save(scope.entity.name + '.pdf');
+ // });
+ // };
+ //
+ // //actual snapshop of canvas
+ // let diagramDiv :any = document.getElementById('myDiagram');
+ // let diagram :go.Diagram = go.Diagram.fromDiv(diagramDiv), canvasImg = new Image();
+ // diagram.startTransaction('print screen');
+ // let canvasImgBase64:any = diagram.makeImageData({
+ // //scale: 1,
+ // size: new go.Size(pdfHeight * 5, NaN),
+ // background: 'white',
+ // type: 'image/jpeg'
+ // });
+ // diagramDiv.firstElementChild.toDataURL();
+ // diagram.commitTransaction('print screen');
+ //
+ // canvasImg.onload = () => {
+ // if (canvasImg.height > 0) {
+ // let canvasImgRatio:number = Math.min((pdfWidth - leftColumnWidth - 15) / canvasImg.width, pdfHeight / canvasImg.height);
+ // let canvasImgWidth:number = canvasImg.width * canvasImgRatio,
+ // canvasImgHeight:number = canvasImg.height * canvasImgRatio;
+ // let canvasImgOffset:number = (pdfHeight - canvasImgHeight) / 2;
+ // pdf.addImage(canvasImg, 'JPEG', leftColumnWidth, canvasImgOffset, canvasImgWidth, canvasImgHeight);
+ //
+ // addEntityIcon();
+ // }
+ // };
+ //
+ // if(canvasImg.src === 'data:,') { //empty canvas
+ // addEntityIcon();
+ // } else {
+ // canvasImg.src = canvasImgBase64;
+ // }
+ };
+
+
+ let getPdfProperties = ():Array<any> => {
+ // return [
+ // {title: this.$filter('translate')('GENERAL_LABEL_TYPE'), value: scope.entity.getComponentSubType(), offset: 10},
+ // {title: this.$filter('translate')('GENERAL_LABEL_VERSION'), value: scope.entity.version, offset: 15},
+ // {title: this.$filter('translate')('GENERAL_LABEL_CATEGORY'), value: scope.entity.categories.length ? scope.entity.categories[0].name : '', offset: 16},
+ // {title: this.$filter('translate')('GENERAL_LABEL_CREATION_DATE'), value: this.$filter('date')(scope.entity.creationDate, 'MM/dd/yyyy'), offset: 24},
+ // {title: this.$filter('translate')('GENERAL_LABEL_AUTHOR'), value: scope.entity.creatorFullName, offset: 13},
+ // {title: this.$filter('translate')('GENERAL_LABEL_CONTACT_ID'), value: scope.entity.contactId, offset: 41},
+ // {title: this.$filter('translate')('GENERAL_LABEL_STATUS'), value: (<any>this.sdcMenu).LifeCycleStatuses[scope.entity.lifecycleState].text, offset: 13},
+ // {title: this.$filter('translate')('GENERAL_LABEL_DESCRIPTION'), value: scope.entity.description, offset: 20},
+ // {title: this.$filter('translate')('GENERAL_LABEL_TAGS'), value: scope.entity.tags.join(', '), offset: 10}
+ // ];
+ return null;
+ };
+
+
+ };
+
+ public static factory = ($filter:ng.IFilterService, sdcMenu:IAppMenu, sdcConfig:IAppConfigurtaion, urlToBase64Service:UrlToBase64Service)=> {
+ return new PrintGraphScreenDirective($filter, sdcMenu, sdcConfig, urlToBase64Service);
+ };
+
+}
+
+PrintGraphScreenDirective.factory.$inject = ['$filter', 'sdcMenu', 'sdcConfig', 'Sdc.Services.UrlToBase64Service'];
diff --git a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html
index 25e1891..7929191 100644
--- a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html
+++ b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html
@@ -13,8 +13,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
+
+
<div class="data-type-fields-structure">
<div class="open-close">
<div class="open-close-button" data-ng-class="{'expand':expand,'collapse':!expand}" data-ng-click="expandAndCollapse()"></div>
@@ -30,71 +30,89 @@
</div>
</div>
<!--<div class="property-value">-->
- <div data-ng-if="dataTypesService.isDataTypeForDataTypePropertyType(property)" class="inner-structure">
- <fields-structure value-obj-ref="(valueObjRef[property.name])"
- type-name="property.type"
- parent-form-obj="parentFormObj"
- fields-prefix-name="fieldsPrefixName+property.name"
- read-only="readOnly"
- default-value="{{currentTypeDefaultValue[property.name]}}">
+ <div data-ng-if="dataTypesService.isDataTypeForDataTypePropertyType(property)" class="inner-structure">
+ <fields-structure value-obj-ref="(valueObjRef[property.name])"
+ type-name="property.type"
+ parent-form-obj="parentFormObj"
+ fields-prefix-name="fieldsPrefixName+property.name"
+ read-only="readOnly"
+ default-value="{{currentTypeDefaultValue[property.name]}}">
- </fields-structure>
- </div>
- <div data-ng-if="!dataTypesService.isDataTypeForDataTypePropertyType(property)" ng-switch="property.type">
- <div ng-switch-when="map">
- <type-map value-obj-ref="valueObjRef[property.name]"
- schema-property="property.schema.property"
- parent-form-obj="parentFormObj"
- fields-prefix-name="fieldsPrefixName+property.name"
- read-only="readOnly"
- default-value="{{currentTypeDefaultValue[property.name]}}"
- types="types"></type-map>
- </div>
- <div ng-switch-when="list">
- <type-list value-obj-ref="valueObjRef[property.name]"
+ </fields-structure>
+ </div>
+ <div data-ng-if="!dataTypesService.isDataTypeForDataTypePropertyType(property)" ng-switch="property.type">
+ <div ng-switch-when="map">
+ <type-map value-obj-ref="valueObjRef[property.name]"
schema-property="property.schema.property"
parent-form-obj="parentFormObj"
fields-prefix-name="fieldsPrefixName+property.name"
read-only="readOnly"
default-value="{{currentTypeDefaultValue[property.name]}}"
- types="types"></type-list>
- </div>
- <div ng-switch-default class="primitive-value-field">
- <div class="i-sdc-form-item" data-ng-class="{error:(parentFormObj[fieldsPrefixName+property.name].$dirty && parentFormObj[fieldsPrefixName+property.name].$invalid)}">
- <input class="i-sdc-form-input"
- data-tests-id="{{fieldsPrefixName+property.name}}"
- ng-if="!((property.simpleType||property.type) == 'boolean')"
- data-ng-maxlength="100"
- data-ng-readonly="readOnly"
- maxlength="{{(property.simpleType||property.type) == 'integer'? 10 : 100}}"
- data-ng-model="valueObjRef[property.name]"
- type="text"
- name="{{fieldsPrefixName+property.name}}"
- data-ng-pattern="getValidationPattern((property.simpleType||property.type))"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-change="inputOnValueChange(property)"
- autofocus />
- <select class="i-sdc-form-select"
- data-tests-id="{{fieldsPrefixName+property.name}}"
- ng-if="(property.simpleType||property.type) == 'boolean'"
- data-ng-disabled="readOnly"
- name="{{fieldsPrefixName+property.name}}"
- data-ng-change="onValueChange(property.name,'boolean')"
- data-ng-model="valueObjRef[property.name]"
- data-ng-options="option.v as option.n for option in [{ n: '', v: undefined }, { n: 'false', v: false }, { n: 'true', v: true }]">
- </select>
+ types="types"></type-map>
+ </div>
+ <div ng-switch-when="list">
+ <type-list value-obj-ref="valueObjRef[property.name]"
+ schema-property="property.schema.property"
+ parent-form-obj="parentFormObj"
+ fields-prefix-name="fieldsPrefixName+property.name"
+ read-only="readOnly"
+ default-value="{{currentTypeDefaultValue[property.name]}}"
+ types="types"></type-list>
+ </div>
+ <div ng-switch-default class="primitive-value-field">
+ <div class="i-sdc-form-item" data-ng-class="{error:(parentFormObj[fieldsPrefixName+property.name].$dirty && parentFormObj[fieldsPrefixName+property.name].$invalid)}">
+ <!-- Has Constraints -->
- <div class="input-error" data-ng-show="parentFormObj[fieldsPrefixName+property.name].$dirty && parentFormObj[fieldsPrefixName+property.name].$invalid">
- <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
- <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
- <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.customValidation" translate="PROPERTY_EDIT_MAP_UNIQUE_KEYS"></span>
- </div>
+ <!--<select class="i-sdc-form-select"-->
+ <!--ng-if="(property.constraints)"-->
+ <!--data-ng-disabled="readOnly"-->
+ <!--name="{{fieldsPrefixName+property.name}}"-->
+ <!--data-ng-change="onValueChange(property.name,'constraintsChange')"-->
+ <!--data-ng-model="valueObjRef[property.name]"-->
+ <!-->-->
+ <!--<!– Get the default value in case exist –>-->
+ <!--<option value = "{{valueObjRef[property.name]}}" name = "{{valueObjRef[property.name]}}" hidden selected>-->
+ <!--{{valueObjRef[property.name]}}-->
+ <!--</option> -->
+ <!--<!– add all constratint to Select list –>-->
+ <!--<option ng-repeat='value in property.constraints[0].validValues' value="{{value}}" >-->
+ <!--{{value}}-->
+ <!--</option> -->
+ <!--</select>-->
+ <!-- Input without constraints -->
+ <input class="i-sdc-form-input"
+ data-tests-id="{{fieldsPrefixName+property.name}}"
+ ng-if="!((property.simpleType||property.type) == 'boolean')"
+ data-ng-maxlength="100"
+ data-ng-readonly="readOnly"
+ maxlength="{{(property.simpleType||property.type) == 'integer'? 10 : 100}}"
+ data-ng-model="valueObjRef[property.name]"
+ type="text"
+ name="{{fieldsPrefixName+property.name}}"
+ data-ng-pattern="getValidationPattern((property.simpleType||property.type))"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-change="inputOnValueChange(property)"
+ autofocus
+ />
+ <select class="i-sdc-form-select"
+ data-tests-id="{{fieldsPrefixName+property.name}}"
+ ng-if="(property.simpleType||property.type) == 'boolean'"
+ data-ng-disabled="readOnly"
+ name="{{fieldsPrefixName+property.name}}"
+ data-ng-change="onValueChange(property.name,'boolean')"
+ data-ng-model="valueObjRef[property.name]"
+ data-ng-options="option.v as option.n for option in [{ n: '', v: undefined }, { n: 'false', v: false }, { n: 'true', v: true }]">
+ </select>
+
+ <div class="input-error" data-ng-show="parentFormObj[fieldsPrefixName+property.name].$dirty && parentFormObj[fieldsPrefixName+property.name].$invalid">
+ <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
+ <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
+ <span ng-show="parentFormObj[fieldsPrefixName+property.name].$error.customValidation" translate="PROPERTY_EDIT_MAP_UNIQUE_KEYS"></span>
</div>
</div>
</div>
+ </div>
<!--</div>-->
</div>
</div>
-
-
diff --git a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts
index eed209d..ff23445 100644
--- a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts
+++ b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts
@@ -42,6 +42,7 @@
expand:boolean;
expanded:boolean;
dataTypesService:DataTypesService;
+ constraints:string[];
expandAndCollapse():void;
getValidationPattern(type:string):RegExp;
@@ -53,11 +54,15 @@
export class DataTypeFieldsStructureDirective implements ng.IDirective {
+
+
constructor(private DataTypesService:DataTypesService,
private PropertyNameValidationPattern:RegExp,
private ValidationUtils:ValidationUtils) {
}
+ constraints: string[];
+
scope = {
valueObjRef: '=',
typeName: '=',
@@ -67,6 +72,7 @@
defaultValue: '@',
// types: '=',
expandByDefault: '='
+
};
restrict = 'E';
@@ -93,6 +99,7 @@
return defaultValue;
};
+
private initDataOnScope = (scope:any, $attr:any):void => {
scope.dataTypesService = this.DataTypesService;
scope.dataTypeProperties = this.DataTypesService.getFirsLevelOfDataTypeProperties(scope.typeName);
@@ -149,7 +156,7 @@
return !value || this.ValidationUtils.validateIntRange(value);
};
- scope.onValueChange = (propertyName:string, type:string):void => {
+ scope.onValueChange = (propertyName:string, type:string,):void => {
scope.valueObjRef[propertyName] = !angular.isUndefined(scope.valueObjRef[propertyName]) ? scope.valueObjRef[propertyName] : scope.currentTypeDefaultValue[propertyName];
if (scope.valueObjRef[propertyName] && type != 'string') {
scope.valueObjRef[propertyName] = JSON.parse(scope.valueObjRef[propertyName]);
@@ -157,7 +164,10 @@
};
scope.inputOnValueChange = (property:any) => {
-
+ if (property.constraints){
+ // this.constraints = property.constraints[0].validValues;
+ }
+
let value = !scope.parentFormObj[scope.fieldsPrefixName + property.name].$error.pattern
&& ('integer' == property.type && scope.parentFormObj[scope.fieldsPrefixName + property.name].$setValidity('pattern', scope.validateIntRange(scope.valueObjRef[property.name]))
|| scope.onValueChange(property.name, (property.simpleType || property.type)));
diff --git a/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.html b/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.html
index 2363f57..661514f 100644
--- a/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.html
+++ b/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.html
@@ -20,7 +20,7 @@
<div class="i-sdc-form-item list-new-item" data-ng-class="{error:(parentFormObj['listNewItem'+fieldsPrefixName].$dirty && parentFormObj['listNewItem'+fieldsPrefixName].$invalid)}">
<input class="i-sdc-form-input"
data-tests-id="listNewItem{{fieldsPrefixName}}"
- ng-if="!((schemaProperty.simpleType||schemaProperty.type) == 'boolean')"
+ ng-if="!constraints && !((schemaProperty.simpleType||schemaProperty.type) == 'boolean')"
data-ng-disabled="readOnly"
data-ng-model="listNewItem.value"
type="text"
@@ -34,13 +34,32 @@
autofocus />
<select class="i-sdc-form-select"
data-tests-id="listNewItem{{fieldsPrefixName}}"
- ng-if="(schemaProperty.simpleType||schemaProperty.type) == 'boolean'"
+ ng-if="!constraints && (schemaProperty.simpleType||schemaProperty.type) == 'boolean'"
data-ng-disabled="readOnly"
name="listNewItem{{fieldsPrefixName}}"
data-ng-model="listNewItem.value">
<option value="true">true</option>
<option value="false">false</option>
</select>
+
+
+ <select class="i-sdc-form-select"
+ data-tests-id="constraints"
+ ng-if="constraints"
+ data-ng-disabled="readOnly"
+ data-ng-model="listNewItem.value">
+ <!-- Get the default value in case exist -->
+ <option value = "{{listNewItem.value}" name = "{{listNewItem.value}}" hidden selected>
+ {{listNewItem.value}}
+ </option>
+ <!-- add all constratint to Select list -->
+ <option ng-repeat='value in constraints' value="{{value}}" name="{{value}}">
+ {{value}}
+ </option>
+
+
+ </select>
+
<div class="input-error" data-ng-show="parentFormObj['listNewItem'+fieldsPrefixName].$dirty && parentFormObj['listNewItem'+fieldsPrefixName].$invalid">
<span ng-show="parentFormObj['listNewItem'+fieldsPrefixName].$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
<span ng-show="parentFormObj['listNewItem'+fieldsPrefixName].$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '{{maxLength}}' }"></span>
diff --git a/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.ts b/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.ts
index f2288cf..997e28d 100644
--- a/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.ts
+++ b/catalog-ui/src/app/directives/property-types/type-list/type-list-directive.ts
@@ -37,6 +37,8 @@
listDefaultValue:any;
listNewItem:any;
maxLength:number;
+
+ constraints:string[];
getValidationPattern(type:string):RegExp;
validateIntRange(value:string):boolean;
@@ -49,7 +51,7 @@
constructor(private DataTypesService:DataTypesService,
private PropertyNameValidationPattern:RegExp,
- private ValidationUtils:ValidationUtils) {
+ private ValidationUtils:ValidationUtils) {
}
scope = {
@@ -59,7 +61,8 @@
fieldsPrefixName: '=',//prefix for form fields names
readOnly: '=',//is form read only
defaultValue: '@',//this list default value
- maxLength: '='
+ maxLength: '=',
+ constraints: '='
};
restrict = 'E';
diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html
index aa03cec..55a414e 100644
--- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html
+++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html
@@ -41,8 +41,9 @@
</div>
<div data-ng-if="!isSchemaTypeDataType" class="i-sdc-form-item map-item-field" data-ng-class="{error:(parentFormObj['mapValue'+fieldsPrefixName+$index].$dirty && parentFormObj['mapValue'+fieldsPrefixName+$index].$invalid)}">
<label class="i-sdc-form-label required">Value</label>
+
<input class="i-sdc-form-input"
- ng-if="!((schemaProperty.simpleType||schemaProperty.type) == 'boolean')"
+ ng-if="!constraints && !((schemaProperty.simpleType||schemaProperty.type) == 'boolean')"
data-ng-readonly="readOnly"
data-ng-model="valueObjRef[mapKeys[$index]]"
type="text"
@@ -57,7 +58,7 @@
autofocus />
<select class="i-sdc-form-select"
data-tests-id="mapValue{{fieldsPrefixName}}{{$index}}"
- ng-if="(schemaProperty.simpleType||schemaProperty.type) == 'boolean'"
+ ng-if="!constraints && (schemaProperty.simpleType||schemaProperty.type) == 'boolean'"
data-ng-disabled="readOnly"
name="mapValue{{fieldsPrefixName}}{{$index}}"
data-ng-model="valueObjRef[mapKeys[$index]]"
@@ -65,6 +66,24 @@
<option value="true">true</option>
<option value="false">false</option>
</select>
+
+
+ <select class="i-sdc-form-select"
+ data-tests-id="constraints"
+ ng-if="constraints"
+ data-ng-disabled="readOnly"
+ data-ng-model="valueObjRef[mapKeys[$index]]">
+
+ <!-- Get the saved value for the relevant key -->
+ <option ng-if = "valueObjRef[mapKeys[$index]]" value = "{{valueObjRef[mapKeys[$index]]}}" name = "{{valueObjRef[mapKeys[$index]]}}" hidden selected>
+ {{valueObjRef[mapKeys[$index]]}}
+ </option>
+ <!-- add all constratint to Select list -->
+ <option ng-repeat='value in constraints' value="{{value}}" name="{{value}}">
+ {{value}}
+ </option>
+ </select>
+
<div class="input-error" data-ng-show="parentFormObj['mapValue'+fieldsPrefixName+$index].$dirty && parentFormObj['mapValue'+fieldsPrefixName+$index].$invalid">
<span ng-show="parentFormObj['mapValue'+fieldsPrefixName+$index].$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Value' }"></span>
<span ng-show="parentFormObj['mapValue'+fieldsPrefixName+$index].$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts
index 5718cdd..080c13b 100644
--- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts
+++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts
@@ -39,6 +39,7 @@
readOnly:boolean;
mapDefaultValue:any;
maxLength:number;
+ constraints:string[];
getValidationPattern(type:string):RegExp;
validateIntRange(value:string):boolean;
@@ -65,7 +66,9 @@
fieldsPrefixName: '=',//prefix for form fields names
readOnly: '=',//is form read only
defaultValue: '@',//this map default value
- maxLength: '='
+ maxLength: '=',
+ constraints: '='
+
};
restrict = 'E';
diff --git a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.html b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.html
index fbcbb39..f6bd1ca 100644
--- a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.html
+++ b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.html
@@ -90,6 +90,7 @@
data-ng-model="valueObjRef[property.name]"
data-ng-options="option.v as option.n for option in [{ n: '', v: undefined }, { n: 'false', v: false }, { n: 'true', v: true }]">
</select>
+
</div>
</div>
diff --git a/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts b/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts
index 1367906..0200e3d 100644
--- a/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts
+++ b/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts
@@ -21,6 +21,7 @@
'use strict';
import {User, IUser, IAppConfigurtaion, IUserProperties} from "app/models";
import { UserService } from "../../ng2/services/user.service";
+import { AuthenticationService } from "app/ng2/services/authentication.service";
export interface IUserHeaderDetailsScope extends ng.IScope {
iconUrl:string;
user:IUser;
@@ -29,7 +30,7 @@
export class UserHeaderDetailsDirective implements ng.IDirective {
- constructor(private $http:ng.IHttpService, private sdcConfig:IAppConfigurtaion, private userService:UserService) {
+ constructor(private $http:ng.IHttpService, private sdcConfig:IAppConfigurtaion, private userService:UserService, private authService: AuthenticationService) {
}
scope = {
@@ -46,7 +47,7 @@
scope.initUser = ():void => {
let defaultUserId:string;
- let userInfo:IUserProperties = this.userService.getLoggedinUser();
+ let userInfo:IUserProperties = this.authService.getLoggedinUser();
if (!userInfo) {
defaultUserId = this.$http.defaults.headers.common[this.sdcConfig.cookie.userIdSuffix];
this.userService.getUser(defaultUserId).subscribe((defaultUserInfo):void => {
@@ -59,10 +60,10 @@
scope.initUser();
};
- public static factory = ($http:ng.IHttpService, sdcConfig:IAppConfigurtaion, userService:UserService)=> {
- return new UserHeaderDetailsDirective($http, sdcConfig, userService);
+ public static factory = ($http:ng.IHttpService, sdcConfig:IAppConfigurtaion, userService:UserService, authService:AuthenticationService)=> {
+ return new UserHeaderDetailsDirective($http, sdcConfig, userService, authService);
};
}
-UserHeaderDetailsDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2'];
+UserHeaderDetailsDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2', 'AuthenticationServiceNg2'];
diff --git a/catalog-ui/src/app/directives/utils/expand-collapse/expand-collapse.ts b/catalog-ui/src/app/directives/utils/expand-collapse/expand-collapse.ts
index 878de11..5874308 100644
--- a/catalog-ui/src/app/directives/utils/expand-collapse/expand-collapse.ts
+++ b/catalog-ui/src/app/directives/utils/expand-collapse/expand-collapse.ts
@@ -70,7 +70,7 @@
$elem.addClass('expanded');
scope.collapsed = false;
- let element = $(scope.expandedSelector)[0];
+ let element = <HTMLElement>$(scope.expandedSelector)[0];
let prevWidth = element.style.height;
element.style.height = 'auto';
let endWidth = getComputedStyle(element).height;
@@ -92,7 +92,7 @@
$elem.removeClass('expanded');
scope.collapsed = true;
- let element = $(scope.expandedSelector)[0];
+ let element = <HTMLElement>$(scope.expandedSelector)[0];
element.style.height = getComputedStyle(element).height;
element.style.transition = 'height .5s ease-in-out';
element.offsetHeight; // force repaint
diff --git a/catalog-ui/src/app/directives/utils/smart-tooltip/smart-tooltip.ts b/catalog-ui/src/app/directives/utils/smart-tooltip/smart-tooltip.ts
index 098134a..0c84af9 100644
--- a/catalog-ui/src/app/directives/utils/smart-tooltip/smart-tooltip.ts
+++ b/catalog-ui/src/app/directives/utils/smart-tooltip/smart-tooltip.ts
@@ -43,7 +43,7 @@
}
$elem.bind('mouseenter', () => {
- if ($elem[0].offsetWidth < $elem[0].scrollWidth && !$elem.attr('tooltips')) {
+ if ((<HTMLElement>$elem[0]).offsetWidth < $elem[0].scrollWidth && !$elem.attr('tooltips')) {
$attrs.$set('tooltips', 'tooltips');
if ($attrs['sdcSmartTooltip'] && $attrs['sdcSmartTooltip'].length > 0) {
$elem.attr('tooltip-content', $attrs['sdcSmartTooltip']);
diff --git a/catalog-ui/src/app/filters/category-type-filter.ts b/catalog-ui/src/app/filters/category-type-filter.ts
index 763b4a9..d02c0b9 100644
--- a/catalog-ui/src/app/filters/category-type-filter.ts
+++ b/catalog-ui/src/app/filters/category-type-filter.ts
@@ -20,7 +20,8 @@
import * as _ from "lodash";
import {ComponentType} from "../utils/constants";
-import {CacheService} from "../services/cache-service";
+import {CacheService} from "app/services-ng2";
+
export class CategoryTypeFilter {
static $inject = ['Sdc.Services.CacheService'];
diff --git a/catalog-ui/src/app/filters/resource-type-filter.ts b/catalog-ui/src/app/filters/resource-type-filter.ts
index 51bf071..ca61ee1 100644
--- a/catalog-ui/src/app/filters/resource-type-filter.ts
+++ b/catalog-ui/src/app/filters/resource-type-filter.ts
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-import {CacheService} from "../services/cache-service";
+import {CacheService} from "app/services-ng2";
export class ResourceTypeFilter {
static '$inject' = ['Sdc.Services.CacheService'];
diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts
index ad1da27..91fa4a7 100644
--- a/catalog-ui/src/app/models.ts
+++ b/catalog-ui/src/app/models.ts
@@ -44,6 +44,8 @@
export * from './models/componentsInstances/serviceProxyInstance';
export * from './models/graph/zones/group-instance';
export * from './models/graph/zones/policy-instance';
+export * from './models/graph/zones/zone';
+export * from './models/graph/zones/zone-instance';
export * from './models/csar-component';
//export * from './models/data-type-properties';
export * from './models/properties-inputs/property-be-model';
@@ -108,15 +110,19 @@
export * from './models/user';
export * from './models/validate';
export * from './models/component-metadata';
+export * from './models/components-array';
export * from './models/modal';
export * from './models/button';
export * from './models/wizard-step';
export * from './models/radio-button';
export * from './models/filter-properties-assignment-data';
export * from './models/properties-inputs/input-be-model';
+export * from './models/catalogSelector';
+export * from './models/componentsInstances/fullComponentInstance';
+export * from './models/catalogSelector';
+export * from './models/componentsInstances/fullComponentInstance';
export * from './models/service-instance-properties-and-interfaces';
export * from './models/relationship-types';
export * from './models/tosca-presentation';
export * from './models/node-types';
-export * from './models/capability-types';
-
+export * from './models/capability-types';
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/activity.ts b/catalog-ui/src/app/models/activity.ts
index 5d37e0f..768ef0a 100644
--- a/catalog-ui/src/app/models/activity.ts
+++ b/catalog-ui/src/app/models/activity.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.
@@ -18,30 +18,13 @@
* ============LICENSE_END=========================================================
*/
-/**
- * Created by obarda on 19/11/2015.
- */
'use strict';
/*this is in uppercase because of the server response*/
-export class Activity {
- TIMESTAMP:string;
- ACTION:string;
- MODIFIER:string;
- STATUS:string;
- DESC:string;
- COMMENT:string;
- //custom data
- public dateFormat:string;
-
- constructor() {
- }
-
- public toJSON = ():any => {
- this.dateFormat = undefined;
- return this;
- };
-
+export interface Activity {
+ TIMESTAMP: string;
+ ACTION: string;
+ MODIFIER: string;
+ STATUS: string;
+ COMMENT: string;
}
-
-
diff --git a/catalog-ui/src/app/models/app-config.ts b/catalog-ui/src/app/models/app-config.ts
index 4754cba..a31c31f 100644
--- a/catalog-ui/src/app/models/app-config.ts
+++ b/catalog-ui/src/app/models/app-config.ts
@@ -3,7 +3,6 @@
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nokia. 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.
@@ -20,225 +19,214 @@
*/
'use strict';
+// tslint:disable-next-line:interface-name
export interface IApi {
- baseUrl:string;
+ baseUrl: string;
- //***** NEW API *******//
- GET_component:string;
- PUT_component:string;
- GET_component_validate_name:string;
- POST_changeLifecycleState:string;
- component_api_root:string;
- //*********//
-
- GET_user:string;
- GET_user_authorize:string;
- GET_all_users:string;
+ GET_SDC_Setup_Data: string;
+ GET_component: string;
+ PUT_component: string;
+ GET_component_validate_name: string;
+ POST_changeLifecycleState: string;
+ component_api_root: string;
+ GET_user: string;
+ GET_user_authorize: string;
+ GET_all_users: string;
POST_create_user;
DELETE_delete_user;
POST_edit_user_role;
- GET_resource:string;
- GET_resources_latestversion_notabstract:string;
- GET_resources_certified_not_abstract:string;
- GET_resources_certified_abstract:string;
- PUT_resource:string;
- GET_resource_property:string;
- GET_resource_artifact:string;
- GET_download_instance_artifact:string;
- POST_instance_artifact:string;
- GET_resource_additional_information:string;
- GET_service_artifact:string;
- GET_resource_interface_artifact:string;
- GET_resource_api_artifact:string;
- GET_resource_validate_name:string;
- GET_resource_artifact_types:string;
- GET_activity_log:string;
- GET_configuration_ui:string;
- GET_plugins_configuration:string;
- GET_plugin_online_state:string;
- GET_service:string;
- GET_ecomp_menu_items:string;
- GET_service_validate_name:string;
- GET_service_distributions:string;
- GET_service_distributions_components:string;
- POST_service_distribution_deploy:string;
- GET_element:string;
- GET_catalog:string;
- GET_resource_category:string;
- GET_service_category:string;
- resource_instance:string;
- GET_resource_instance_property:string;
- GET_relationship:string;
- GET_lifecycle_state_resource:string;
- GET_lifecycle_state_CHECKIN:string;
- GET_lifecycle_state_CERTIFICATIONREQUEST:string;
- GET_lifecycle_state_UNDOCHECKOUT:string;
- root:string;
- no_proxy_root:string;
- PUT_service:string;
- GET_download_artifact:string;
- GET_SDC_Version:string;
- GET_categories:string;
- POST_category:string;
- POST_subcategory:string;
- POST_change_instance_version:string;
- GET_requirements_capabilities:string;
- GET_onboarding:string;
- GET_component_from_csar_uuid:string;
- POST_GAB_Search:string;
- kibana:string;
- services_api_root:string;
+ GET_resource: string;
+ GET_resources_latestversion_notabstract: string;
+ GET_resources_certified_not_abstract: string;
+ GET_resources_certified_abstract: string;
+ PUT_resource: string;
+ GET_resource_property: string;
+ GET_resource_artifact: string;
+ GET_download_instance_artifact: string;
+ POST_instance_artifact: string;
+ GET_resource_additional_information: string;
+ GET_service_artifact: string;
+ GET_resource_interface_artifact: string;
+ GET_resource_api_artifact: string;
+ GET_resource_validate_name: string;
+ GET_resource_artifact_types: string;
+ GET_activity_log: string;
+ GET_configuration_ui: string;
+ GET_plugins_configuration: string;
+ GET_plugin_online_state: string;
+ GET_service: string;
+ GET_ecomp_menu_items: string;
+ GET_service_validate_name: string;
+ GET_service_distributions: string;
+ GET_service_distributions_components: string;
+ POST_service_distribution_deploy: string;
+ GET_element: string;
+ GET_catalog: string;
+ GET_resource_category: string;
+ GET_service_category: string;
+ resource_instance: string;
+ GET_resource_instance_property: string;
+ GET_relationship: string;
+ GET_lifecycle_state_resource: string;
+ GET_lifecycle_state_CHECKIN: string;
+ GET_lifecycle_state_UNDOCHECKOUT: string;
+ root: string;
+ no_proxy_root: string;
+ PUT_service: string;
+ GET_download_artifact: string;
+ GET_SDC_Version: string;
+ GET_categories: string;
+ POST_category: string;
+ POST_subcategory: string;
+ POST_change_instance_version: string;
+ GET_requirements_capabilities: string;
+ GET_onboarding: string;
+ GET_component_from_csar_uuid: string;
+ POST_GAB_Search: string;
+ kibana: string;
+ services_api_root: string;
+ uicache_root: string;
+ GET_uicache_catalog: string;
+ GET_uicache_left_palette: string;
}
+// tslint:disable-next-line:interface-name
export interface ILogConfig {
- minLogLevel:string;
- prefix:string;
+ minLogLevel: string;
+ prefix: string;
}
+// tslint:disable-next-line:interface-name
export interface ICookie {
- junctionName:string;
- prefix:string;
- userIdSuffix:string;
- userFirstName:string;
- userLastName:string;
- userEmail:string;
-}
-export interface IUserTypes {
- admin:any;
- designer:any;
- tester:any;
+ junctionName: string;
+ prefix: string;
+ userIdSuffix: string;
+ userFirstName: string;
+ userLastName: string;
+ userEmail: string;
}
+// tslint:disable-next-line:interface-name
export interface IConfigStatuses {
- inDesign:IConfigStatus;
- readyForCertification:IConfigStatus;
- inCertification:IConfigStatus;
- certified:IConfigStatus;
- distributed:IConfigStatus;
+ inDesign: IConfigStatus;
+ certified: IConfigStatus;
+ distributed: IConfigStatus;
}
+// tslint:disable-next-line:interface-name
export interface IConfigStatus {
- name:string;
- values:Array<string>;
+ name: string;
+ values: string[];
}
+// tslint:disable-next-line:interface-name
export interface IConfigRoles {
- ADMIN:IConfigRole;
- DESIGNER:IConfigRole;
- TESTER:IConfigRole;
- OPS:IConfigRole;
- GOVERNOR:IConfigRole;
+ ADMIN: IConfigRole;
+ DESIGNER: IConfigRole;
}
+// tslint:disable-next-line:interface-name
export interface IConfigRole {
- changeLifecycleStateButtons:any;
+ changeLifecycleStateButtons: any;
}
-export interface IConfigState {
- NOT_CERTIFIED_CHECKOUT:Array<IConfigDistribution>;
- NOT_CERTIFIED_CHECKIN:Array<IConfigDistribution>;
- READY_FOR_CERTIFICATION:Array<IConfigDistribution>;
- CERTIFICATION_IN_PROGRESS:Array<IConfigDistribution>;
- CERTIFIED:Array<IConfigDistribution>;
-}
-
-export interface IConfigDistribution {
- DISTRIBUTION_NOT_APPROVED:Array<ConfigMenuItem>;
- DISTRIBUTION_APPROVED:Array<ConfigMenuItem>;
- DISTRIBUTED:Array<ConfigMenuItem>;
- DISTRIBUTION_REJECTED:Array<ConfigMenuItem>;
-}
-
+// tslint:disable-next-line:interface-name
export interface IConfirmationMessage {
- showComment:boolean;
- title:string;
- message:string;
+ showComment: boolean;
+ title: string;
+ message: string;
}
+// tslint:disable-next-line:interface-name
export interface IConfirmationMessages {
- checkin:IConfirmationMessage;
- checkout:IConfirmationMessage;
- certify:IConfirmationMessage;
- failCertification:IConfirmationMessage;
- certificationRequest:IConfirmationMessage;
- approve:IConfirmationMessage;
- reject:IConfirmationMessage;
+ checkin: IConfirmationMessage;
+ checkout: IConfirmationMessage;
+ certify: IConfirmationMessage;
+ failCertification: IConfirmationMessage;
+ certificationRequest: IConfirmationMessage;
+ approve: IConfirmationMessage;
+ reject: IConfirmationMessage;
}
+// tslint:disable-next-line:interface-name
export interface IAlertMessage {
- title:string;
- message:string;
+ title: string;
+ message: string;
}
+// tslint:disable-next-line:interface-name
export interface IAlertMessages {
- deleteInstance:IAlertMessage;
- exitWithoutSaving:IConfirmationMessage;
+ deleteInstance: IAlertMessage;
+ exitWithoutSaving: IConfirmationMessage;
+ okButton: string;
}
class ConfigMenuItem {
- text:string;
- action:string;
- url:string;
- disable:boolean = false;
+ text: string;
+ action: string;
+ url: string;
+ disable = false;
}
+// tslint:disable-next-line:interface-name
export interface IAppConfigurtaion {
- environment:string;
- api:IApi;
- hostedApplications:Array<IHostedApplication>;
- resourceTypesFilter:IResourceTypesFilter;
- logConfig:ILogConfig;
- cookie:ICookie;
- imagesPath:string;
- toscaFileExtension:string;
- csarFileExtension:string;
- testers:Array<ITester>
- tutorial:any;
- roles:Array<string>;
- cpEndPointInstances:Array<string>;
- openSource:boolean;
- showOutlook:boolean;
- validationConfigPath:string;
+ environment: string;
+ api: IApi;
+ hostedApplications: IHostedApplication[];
+ resourceTypesFilter: IResourceTypesFilter;
+ logConfig: ILogConfig;
+ cookie: ICookie;
+ imagesPath: string;
+ toscaFileExtension: string;
+ csarFileExtension: string;
+ testers: ITester[];
+ tutorial: any;
+ roles: string[];
+ cpEndPointInstances: string[];
+ openSource: boolean;
+ showOutlook: boolean;
+ validationConfigPath: string;
}
+// tslint:disable-next-line:interface-name
export interface IResourceTypesFilter {
- resource:Array<string>;
+ resource: string[];
}
+// tslint:disable-next-line:interface-name
export interface IHostedApplication {
- moduleName:string;
- navTitle:string;
- defaultState:string;
- exists?:boolean;
- state:IHostedApplicationState;
+ moduleName: string;
+ navTitle: string;
+ defaultState: string;
+ exists?: boolean;
+ state: IHostedApplicationState;
}
+// tslint:disable-next-line:interface-name
export interface IHostedApplicationState {
- name:string;
- url:string;
- relativeHtmlPath:string;
- controllerName:string;
+ name: string;
+ url: string;
+ relativeHtmlPath: string;
+ controllerName: string;
}
+// tslint:disable-next-line:interface-name
export interface ITester {
- email:string;
+ email: string;
}
-export interface IComponentType {
- RESOURCE:any;
- SERVICE:any;
-}
-
+// tslint:disable-next-line:interface-name
export interface IAppMenu {
- roles:IConfigRoles;
- confirmationMessages:IConfirmationMessages;
- alertMessages:IAlertMessages;
- statuses:IConfigStatuses;
- catalogMenuItem:any;
- categoriesDictionary:any;
- canvas_buttons:Object;
- component_workspace_menu_option:any;
- LifeCycleStatuses:any;
- DistributionStatuses:any;
- ChangeLifecycleStateButton:any;
+ roles: IConfigRoles;
+ confirmationMessages: IConfirmationMessages;
+ alertMessages: IAlertMessages;
+ statuses: IConfigStatuses;
+ catalogMenuItem: any;
+ categoriesDictionary: any;
+ // tslint:disable-next-line:ban-types
+ canvas_buttons: Object;
+ component_workspace_menu_option: any;
+ LifeCycleStatuses: any;
+ DistributionStatuses: any;
+ ChangeLifecycleStateButton: any;
}
diff --git a/catalog-ui/src/app/models/artifacts.ts b/catalog-ui/src/app/models/artifacts.ts
index 27c0dd6..7b93470 100644
--- a/catalog-ui/src/app/models/artifacts.ts
+++ b/catalog-ui/src/app/models/artifacts.ts
@@ -69,11 +69,13 @@
apiUrl:string;
heatParameters:Array<HeatParameterModel>;
generatedFromId:string;
+ isFromCsar: boolean;
//custom properties
selected:boolean;
originalDescription:string;
envArtifact:ArtifactModel;
+ allowDeleteAndUpdate: boolean;
constructor(artifact?:ArtifactModel) {
if (artifact) {
@@ -97,10 +99,11 @@
this["Content-MD5"] = artifact["Content-MD5"];
this.artifactChecksum = artifact.artifactChecksum;
this.apiUrl = artifact.apiUrl;
- this.heatParameters = _.sortBy(artifact.heatParameters, 'name');
+ this.heatParameters = _.sortBy(_.cloneDeep(artifact.heatParameters), 'name');
this.generatedFromId = artifact.generatedFromId;
this.selected = artifact.selected ? artifact.selected : false;
this.originalDescription = artifact.description;
+ this.isFromCsar = artifact.isFromCsar;
}
}
@@ -120,6 +123,7 @@
this.selected = undefined;
this.originalDescription = undefined;
this.envArtifact = undefined;
+ this.allowDeleteAndUpdate = undefined;
return this;
};
}
diff --git a/catalog-ui/src/app/models/aschema-property.ts b/catalog-ui/src/app/models/aschema-property.ts
index 5e99b33..b0d22d7 100644
--- a/catalog-ui/src/app/models/aschema-property.ts
+++ b/catalog-ui/src/app/models/aschema-property.ts
@@ -22,36 +22,36 @@
* Created by osonsino on 16/05/2016.
*/
'use strict';
-import { PROPERTY_DATA } from "app/utils";
+import { PROPERTY_DATA } from 'app/utils/constants';
export class SchemaPropertyGroupModel {
- property:SchemaProperty;
+ property: SchemaProperty;
- constructor(schemaProperty?:SchemaProperty) {
+ constructor(schemaProperty?: SchemaProperty) {
this.property = schemaProperty;
}
}
export class SchemaProperty {
- type:string;
- required:boolean;
- definition:boolean;
- description:string;
- password:boolean;
- //custom properties
- simpleType:string;
+ type: string;
+ required: boolean;
+ definition: boolean;
+ description: string;
+ password: boolean;
+ // custom properties
+ simpleType: string;
isSimpleType: boolean;
isDataType: boolean;
- private _derivedFromSimpleTypeName:string;
- get derivedFromSimpleTypeName():string {
+ private _derivedFromSimpleTypeName: string;
+ get derivedFromSimpleTypeName(): string {
return this._derivedFromSimpleTypeName;
}
- set derivedFromSimpleTypeName(derivedFromSimpleTypeName:string) {
+ set derivedFromSimpleTypeName(derivedFromSimpleTypeName: string) {
this._derivedFromSimpleTypeName = derivedFromSimpleTypeName;
}
- constructor(schemaProperty?:SchemaProperty) {
+ constructor(schemaProperty?: SchemaProperty) {
if (schemaProperty) {
this.type = schemaProperty.type;
this.required = schemaProperty.required;
@@ -60,17 +60,15 @@
this.password = schemaProperty.password;
this.simpleType = schemaProperty.simpleType;
this.isSimpleType = (-1 < PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type));
- this.isDataType = PROPERTY_DATA.TYPES.indexOf(this.type) == -1;
+ this.isDataType = PROPERTY_DATA.TYPES.indexOf(this.type) === -1;
}
}
- public toJSON = ():any => {
+ public toJSON = (): any => {
this.simpleType = undefined;
this.isSimpleType = undefined;
this.isDataType = undefined;
this._derivedFromSimpleTypeName = undefined;
return this;
- };
+ }
}
-
-
diff --git a/catalog-ui/src/app/models/attributes.ts b/catalog-ui/src/app/models/attributes.ts
index 9e5828a..80af540 100644
--- a/catalog-ui/src/app/models/attributes.ts
+++ b/catalog-ui/src/app/models/attributes.ts
@@ -88,6 +88,9 @@
this.resourceInstanceUniqueId = attribute.resourceInstanceUniqueId;
this.readonly = attribute.readonly;
this.valueUniqueUid = attribute.valueUniqueUid;
+ } else {
+ this.defaultValue = '';
+ this.hidden = false;
}
if (!this.schema || !this.schema.property) {
@@ -100,7 +103,7 @@
this.convertValueToView();
}
- public convertToServerObject:Function = ():string => {
+ public convertToServerObject():string {
if (this.defaultValue && this.type === 'map') {
this.defaultValue = '{' + this.defaultValue + '}';
}
diff --git a/catalog-ui/src/app/models/capability.ts b/catalog-ui/src/app/models/capability.ts
index 4a4f821..f365dc4 100644
--- a/catalog-ui/src/app/models/capability.ts
+++ b/catalog-ui/src/app/models/capability.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,30 +22,23 @@
* Created by obarda on 4/20/2016.
*/
'use strict';
-import * as _ from "lodash";
-import {PropertyModel} from "./properties";
-import {Requirement} from "./requirement";
+import * as _ from 'lodash';
+import { PropertyModel } from './properties';
-export interface RequirementCapabilityModel{};
-//this is an object contains keys, when each key has matching array.
+export interface RequirementCapabilityModel {}
+
+// this is an object contains keys, when each key has matching array.
// for example: key = tosca.capabilities.network.Linkable and the match array is array of capabilities objects
export class CapabilitiesGroup {
- constructor(capabilityGroupObj?:CapabilitiesGroup) {
- _.forEach(capabilityGroupObj, (capabilitiesArrayObj:Array<Capability>, instance) => {
+ constructor(capabilityGroupObj?: CapabilitiesGroup) {
+ _.forEach(capabilityGroupObj, (capabilitiesArrayObj: Capability[], instance) => {
this[instance] = [];
- _.forEach(capabilitiesArrayObj, (capability:Capability):void => {
+ _.forEach(capabilitiesArrayObj, (capability: Capability): void => {
this[instance].push(new Capability(capability));
});
});
}
-
- public findValueByKey(keySubstring:string):Array<Capability> {
- let key:string = _.find(Object.keys(this), (key)=> {
- return _.includes(key.toLowerCase(), keySubstring);
- });
- return this[key];
- }
-
+
public static getFlattenedCapabilities(capabilitiesGroup: CapabilitiesGroup): Array<Capability> {
return _.reduce(
_.toArray(capabilitiesGroup),
@@ -54,29 +47,30 @@
}
}
-export class Capability implements RequirementCapabilityModel{
+export class Capability implements RequirementCapabilityModel {
- //server data
- name:string;
- ownerId:string;
- ownerName:string;
- type:string;
- uniqueId:string;
- capabilitySources:Array<String>;
- leftOccurrences:string;
- minOccurrences: number;
- maxOccurrences:string;
- description:string;
- validSourceTypes:Array<string>;
- properties:Array<PropertyModel>;
- //custom
- selected:boolean;
- filterTerm:string;
+ // server data
+ name: string;
+ ownerId: string;
+ ownerName: string;
+ type: string;
+ uniqueId: string;
+ capabilitySources: string[];
+ leftOccurrences: string;
+ minOccurrences: string | number;
+ maxOccurrences: string;
+ description: string;
+ validSourceTypes: string[];
+ properties: PropertyModel[];
- constructor(capability?:Capability) {
+ // custom
+ selected: boolean;
+ filterTerm: string;
+
+ constructor(capability?: Capability) {
if (capability) {
- //server data
+ // server data
this.name = capability.name;
this.ownerId = capability.ownerId;
this.ownerName = capability.ownerName;
@@ -95,41 +89,50 @@
}
}
- public getTitle():string {
+ public getTitle(): string {
return this.ownerName + ': ' + this.name;
}
- public getFullTitle():string {
- let maxOccurrences:string = this.maxOccurrences === 'UNBOUNDED' ? '∞' : this.maxOccurrences;
+ public getFullTitle(): string {
+ const maxOccurrences: string = this.maxOccurrences === 'UNBOUNDED' ? '∞' : this.maxOccurrences;
return this.getTitle() + ': [' + this.minOccurrences + ', ' + maxOccurrences + ']';
}
- public toJSON = ():any => {
+ public toJSON = (): any => {
this.selected = undefined;
this.filterTerm = undefined;
return this;
- };
-
- private initFilterTerm = ():void => {
- this.filterTerm = this.name + " " +
- (this.type ? (this.type.replace("tosca.capabilities.", "") + " " ) : "") +
- (this.description || "") + " " +
- (this.ownerName || "") + " " +
- (this.validSourceTypes ? (this.validSourceTypes.join(',') + " ") : "") +
- this.minOccurrences + "," + this.maxOccurrences;
- if (this.properties && this.properties.length) {
- _.forEach(this.properties, (prop:PropertyModel)=> {
- this.filterTerm += " " + prop.name +
- " " + (prop.description || "") +
- " " + prop.type +
- (prop.schema && prop.schema.property ? (" " + prop.schema.property.type) : "");
- });
- }
}
public isFulfilled() {
return parseInt(this.leftOccurrences) === 0;
}
+
+ private initFilterTerm = (): void => {
+ this.filterTerm = this.name + ' ' +
+ (this.type ? (this.type.replace('tosca.capabilities.', '') + ' ' ) : '') +
+ (this.description || '') + ' ' +
+ (this.ownerName || '') + ' ' +
+ (this.validSourceTypes ? (this.validSourceTypes.join(',') + ' ') : '') +
+ this.minOccurrences + ',' + this.maxOccurrences;
+ if (this.properties && this.properties.length) {
+ _.forEach(this.properties, (prop: PropertyModel) => {
+ this.filterTerm += ' ' + prop.name +
+ ' ' + (prop.description || '') +
+ ' ' + prop.type +
+ (prop.schema && prop.schema.property ? (' ' + prop.schema.property.type) : '');
+ });
+ }
+ }
+}
+
+export class CapabilityUI extends Capability {
+ isCreatedManually: boolean;
+
+ constructor(input: Capability, componentUniqueId: string) {
+ super(input);
+ this.isCreatedManually = input.ownerId === componentUniqueId;
+ }
}
diff --git a/catalog-ui/src/app/models/component-metadata.ts b/catalog-ui/src/app/models/component-metadata.ts
index 0f0a30d..8a4b257 100644
--- a/catalog-ui/src/app/models/component-metadata.ts
+++ b/catalog-ui/src/app/models/component-metadata.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.
@@ -18,65 +18,135 @@
* ============LICENSE_END=========================================================
*/
-import {IMainCategory} from "./category";
+import { CapabilitiesGroup, RequirementsGroup } from 'app/models';
+import { ComponentType } from 'app/utils';
+import { IMainCategory } from './category';
/**
* Created by obarda on 4/18/2017.
*/
-export class ComponentMetadata {
+export interface IComponentMetadata {
- public abstract:string;
- public uniqueId:string;
- public uuid:string;
- public invariantUUID:string;
- public name:string;
- public version:string;
- public creationDate:number;
- public lastUpdateDate:number;
- public description:string;
- public lifecycleState:string;
- public tags:Array<string>;
- public icon:string;
- public contactId:string;
- public allVersions:any;
- public creatorUserId:string;
- public creatorFullName:string;
- public lastUpdaterUserId:string;
- public lastUpdaterFullName:string;
- public componentType:string;
- public categories:Array<IMainCategory>;
- public highestVersion:boolean;
- public normalizedName:string;
- public systemName:string;
- public archived:boolean;
+ abstract: string;
+ uniqueId: string;
+ uuid: string;
+ invariantUUID: string;
+ name: string;
+ version: string;
+ creationDate: number;
+ lastUpdateDate: number;
+ description: string;
+ lifecycleState: string;
+ tags: string[];
+ icon: string;
+ contactId: string;
+ allVersions: any;
+ creatorUserId: string;
+ creatorFullName: string;
+ lastUpdaterUserId: string;
+ lastUpdaterFullName: string;
+ componentType: string;
+ categories: IMainCategory[];
+ highestVersion: boolean;
+ normalizedName: string;
+ systemName: string;
+ archived: boolean;
+ vspArchived: boolean;
+ selectedCategory: string;
+ filterTerm: string;
+
+ // Resource only
+ resourceType: string;
+ csarUUID: string;
+ csarVersion: string;
+ derivedList: string[];
+ vendorName: string;
+ vendorRelease: string;
+ derivedFrom: string[];
+ resourceVendorModelNumber: string;
+ csarPackageType: string;
+ packageId: string;
+ iconSprite: string;
+
+ // Service only
+ serviceFunction: string;
+ distributionStatus: string;
+ ecompGeneratedNaming: boolean;
+ namingPolicy: string;
+ serviceType: string;
+ serviceRole: string;
+ environmentContext: string;
+ instantiationType: string;
+
+ // backend lifecycleState
+ state: string;
+
+ capabilities: CapabilitiesGroup;
+ requirements: RequirementsGroup;
+
+}
+
+export class ComponentMetadata implements IComponentMetadata {
+
+ public abstract: string;
+ public uniqueId: string;
+ public uuid: string;
+ public invariantUUID: string;
+ public name: string;
+ public version: string;
+ public creationDate: number;
+ public lastUpdateDate: number;
+ public description: string;
+ public lifecycleState: string;
+ public tags: string[];
+ public icon: string;
+ public contactId: string;
+ public allVersions: any;
+ public creatorUserId: string;
+ public creatorFullName: string;
+ public lastUpdaterUserId: string;
+ public lastUpdaterFullName: string;
+ public componentType: string;
+ public categories: IMainCategory[];
+ public highestVersion: boolean;
+ public normalizedName: string;
+ public systemName: string;
+ public archived: boolean;
public vspArchived: boolean;
public toscaResourceName: string;
+ public selectedCategory: string;
+ public filterTerm: string;
- //Resource only
+ // Resource only
public resourceType: string;
- public csarUUID:string;
- public csarVersion:string;
+ public csarUUID: string;
+ public csarVersion: string;
public derivedList: string[];
- public vendorName:string;
- public vendorRelease:string;
- public derivedFrom: Array<string>;
- public resourceVendorModelNumber:string;
+ public vendorName: string;
+ public vendorRelease: string;
+ public derivedFrom: string[];
+ public resourceVendorModelNumber: string;
+ public csarPackageType: string;
+ public packageId: string;
+ public iconSprite: string;
- //Service only
- public projectCode:string;
- public distributionStatus:string;
+ // Service only
+ public serviceFunction: string;
+ public distributionStatus: string;
public ecompGeneratedNaming: boolean;
public namingPolicy: string;
- public serviceType:string;
- public serviceRole:string;
- public environmentContext:string;
- public instantiationType:string;
+ public serviceType: string;
+ public serviceRole: string;
+ public environmentContext: string;
+ public instantiationType: string;
+ // backend lifecycleState
+ public state: string;
+ // requirements
+ public capabilities;
+ public requirements;
- //backend lifecycleState
- public state:string;
-
- deserialize (response): ComponentMetadata {
+ deserialize(response): ComponentMetadata {
this.abstract = response.abstract;
this.uniqueId = response.uniqueId;
this.uuid = response.uuid;
@@ -104,7 +174,7 @@
this.derivedList = response.derivedList;
this.normalizedName = response.normalizedName;
this.systemName = response.systemName;
- this.projectCode = response.projectCode;
+ this.serviceFunction = response.serviceFunction;
this.resourceType = response.resourceType;
this.csarUUID = response.csarUUID;
this.csarVersion = response.csarVersion;
@@ -120,7 +190,16 @@
this.instantiationType = response.instantiationType;
this.vspArchived = response.vspArchived;
this.toscaResourceName = response.toscaResourceName;
+ this.capabilities = response.capabilities;
+ this.requirements = response.requirements;
return this;
}
+ public isService = (): boolean => {
+ return this.componentType === ComponentType.SERVICE;
+ }
+
+ public getTypeUrl(): string {
+ return this.componentType === ComponentType.RESOURCE ? 'resources/' : 'services/';
+ }
}
diff --git a/catalog-ui/src/app/models/components-array.ts b/catalog-ui/src/app/models/components-array.ts
new file mode 100644
index 0000000..17f67b6
--- /dev/null
+++ b/catalog-ui/src/app/models/components-array.ts
@@ -0,0 +1,7 @@
+import {Service} from "./components/service";
+import {Resource} from "./components/resource";
+
+export interface IComponentsArray {
+ services:Array<Service>;
+ resources:Array<Resource>;
+}
diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts
index 8f0fa33..b76d29c 100644
--- a/catalog-ui/src/app/models/components/component.ts
+++ b/catalog-ui/src/app/models/components/component.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.
@@ -48,67 +48,33 @@
createComponentOnServer():ng.IPromise<Component>;
changeLifecycleState(state:string, commentObj:AsdcComment):ng.IPromise<Component>;
validateName(newName:string):ng.IPromise<IValidate>;
- updateRequirementsCapabilities():ng.IPromise<any>;
//Artifacts API
addOrUpdateArtifact(artifact:ArtifactModel):ng.IPromise<ArtifactModel>;
- updateMultipleArtifacts(artifacts:Array<ArtifactModel>):ng.IPromise<any>;
deleteArtifact(artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel>;
downloadInstanceArtifact(artifactId:string):ng.IPromise<IFileDownload>;
downloadArtifact(artifactId:string):ng.IPromise<IFileDownload>;
- getArtifactByGroupType(artifactGroupType:string):ng.IPromise<ArtifactGroupModel>;
-
//Property API
addOrUpdateProperty(property:PropertyModel):ng.IPromise<PropertyModel>;
deleteProperty(propertyId:string):ng.IPromise<PropertyModel>;
- updateInstanceProperties(componentInstanceId:string, properties:PropertyModel[]):ng.IPromise<PropertyModel[]>;
//Attribute API
deleteAttribute(attributeId:string):ng.IPromise<AttributeModel>;
addOrUpdateAttribute(attribute:AttributeModel):ng.IPromise<AttributeModel>;
- updateInstanceAttribute(attribute:AttributeModel):ng.IPromise<AttributeModel>;
-
-
-
-
- //Component Instance API
- createComponentInstance(componentInstance:ComponentInstance):ng.IPromise<ComponentInstance>;
- deleteComponentInstance(componentInstanceId:string):ng.IPromise<ComponentInstance>;
- addOrUpdateInstanceArtifact(artifact:ArtifactModel):ng.IPromise<ArtifactModel>;
- deleteInstanceArtifact(artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel>;
- uploadInstanceEnvFile(artifact:ArtifactModel):ng.IPromise<ArtifactModel>;
- checkComponentInstanceVersionChange(componentUid:string):ng.IPromise<any>;
- changeComponentInstanceVersion(componentUid:string):ng.IPromise<Component>;
- updateComponentInstance(componentInstance:ComponentInstance):ng.IPromise<ComponentInstance>;
- updateMultipleComponentInstances(instances:Array<ComponentInstance>):ng.IPromise<Array<ComponentInstance>>;
-
- //Inputs API
- getComponentInstanceInputProperties(componentInstanceId:string, inputId:string):ng.IPromise<Array<PropertyModel>>
- getComponentInstanceProperties(componentInstanceId:string):ng.IPromise<Array<PropertyModel>>
- getComponentInputs(componentId:string):ng.IPromise<Array<InputModel>>;
-
- createRelation(link:RelationshipModel):ng.IPromise<RelationshipModel>;
- deleteRelation(link:RelationshipModel):ng.IPromise<RelationshipModel>;
- fetchRelation(linkId:string):ng.IPromise<RelationshipModel>;
-
//Modules
getModuleForDisplay(moduleId:string):ng.IPromise<DisplayModule>;
getModuleInstanceForDisplay(componentInstanceId:string, moduleId:string):ng.IPromise<DisplayModule>;
updateGroupMetadata(group:Module):ng.IPromise<Module>;
-
//---------------------------------------------- HELP FUNCTIONS ----------------------------------------------------//
-
-
getComponentSubType():string;
isAlreadyCertified():boolean;
isService():boolean;
isResource():boolean;
isComplex():boolean;
- getAdditionalInformation():Array<AdditionalInformationModel>;
getAllVersionsAsSortedArray():Array<any>;
getStatus(sdcMenu:IAppMenu):string;
}
@@ -161,7 +127,6 @@
public interfaces:any;
public normalizedName:string;
public systemName:string;
- public projectCode:string;
public policies:Array<PolicyInstance>;
public groupInstances:Array<GroupInstance>
public modules:Array<Module>;
@@ -176,6 +141,7 @@
public showMenu:boolean;
public archived:boolean;
public vspArchived: boolean;
+ public componentMetadata: ComponentMetadata;
constructor(componentService:IComponentService, protected $q:ng.IQService, component?:Component) {
if (component) {
@@ -220,7 +186,6 @@
this.interfaces = component.interfaces;
this.normalizedName = component.normalizedName;
this.systemName = component.systemName;
- this.projectCode = component.projectCode;
this.inputs = component.inputs;
this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
this.properties = CommonUtils.initProperties(component.properties, this.uniqueId);
@@ -243,11 +208,6 @@
this.uniqueId = uniqueId;
};
- public setSelectedInstance = (componentInstance:ComponentInstance):void => {
- this.selectedInstance = componentInstance;
- };
-
-
//------------------------------------------ API Calls ----------------------------------------------------------------//
public changeLifecycleState = (state:string, commentObj:AsdcComment):ng.IPromise<Component> => {
let deferred = this.$q.defer<Component>();
@@ -302,23 +262,6 @@
return deferred.promise;
};
- public updateMultipleArtifacts = (artifacts:Array<ArtifactModel>):ng.IPromise<any>=> {
- let deferred = this.$q.defer();
- let onSuccess = (response:any):void => {
- deferred.resolve(response);
- };
- let onError = (error:any):void => {
- deferred.reject(error);
- };
- let q = new QueueUtils(this.$q);
-
- _.forEach(artifacts, (artifact)=> {
- q.addBlockingUIAction(()=> this.addOrUpdateArtifact(artifact).then(onSuccess, onError));
- });
- return deferred.promise;
- };
-
-
public deleteArtifact = (artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel> => {
let deferred = this.$q.defer<ArtifactModel>();
let onSuccess = (artifactObj:ArtifactModel):void => {
@@ -336,32 +279,6 @@
return deferred.promise;
};
- public getArtifactByGroupType = (artifactGroupType:string):ng.IPromise<ArtifactGroupModel> => {
-
- let deferred = this.$q.defer<ArtifactGroupModel>();
- let onSuccess = (response:ArtifactGroupModel):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getArtifactByGroupType(this.uniqueId, artifactGroupType).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public getComponentInstanceArtifactsByGroupType = (componentInstanceId:string, artifactGroupType:string):ng.IPromise<ArtifactGroupModel> => {
-
- let deferred = this.$q.defer<ArtifactGroupModel>();
- let onSuccess = (response:ArtifactGroupModel):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInstanceArtifactsByGroupType(this.uniqueId, componentInstanceId, artifactGroupType).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
public addOrUpdateProperty = (property:PropertyModel):ng.IPromise<PropertyModel> => {
let deferred = this.$q.defer<PropertyModel>();
@@ -446,348 +363,10 @@
return deferred.promise;
};
-
- public updateInstancePropertiesSuccess = (newProperties:PropertyModel[]):void => {
- newProperties.forEach((newProperty) => {
- // find exist instance property in parent component for update the new value ( find bu uniqueId & path)
- let existProperty: PropertyModel = <PropertyModel>_.find(this.componentInstancesProperties[newProperty.resourceInstanceUniqueId], {
- uniqueId: newProperty.uniqueId,
- path: newProperty.path
- });
- let index = this.componentInstancesProperties[newProperty.resourceInstanceUniqueId].indexOf(existProperty);
- this.componentInstancesProperties[newProperty.resourceInstanceUniqueId][index] = newProperty;
- });
- }
-
- public updateInstanceProperties = (componentInstanceId:string, properties:PropertyModel[]):ng.IPromise<PropertyModel[]> => {
- let deferred = this.$q.defer<PropertyModel[]>();
- let onSuccess = (newProperties:PropertyModel[]):void => {
- this.updateInstancePropertiesSuccess(newProperties);
- deferred.resolve(newProperties);
- };
- let onFailed = (error:any):void => {
- console.log('Failed to update property value');
- deferred.reject(error);
- };
- this.componentService.updateInstanceProperties(this.uniqueId, componentInstanceId, properties).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public updateInstanceAttribute = (attribute:AttributeModel):ng.IPromise<AttributeModel> => {
- let deferred = this.$q.defer<AttributeModel>();
- let onSuccess = (newAttribute:AttributeModel):void => {
- let existAttribute:AttributeModel = <AttributeModel>_.find(this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId], {uniqueId: newAttribute.uniqueId});
- let index = this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId].indexOf(existAttribute);
- this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId][index] = newAttribute;
- deferred.resolve(newAttribute);
- };
- let onFailed = (error:any):void => {
- console.log('Failed to update attribute value');
- deferred.reject(error);
- };
- this.componentService.updateInstanceAttribute(this.uniqueId, attribute).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
public downloadInstanceArtifact = (artifactId:string):ng.IPromise<IFileDownload> => {
return this.componentService.downloadInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifactId);
};
- public deleteInstanceArtifact = (artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel> => {
- let deferred = this.$q.defer<ArtifactModel>();
- let onSuccess = (artifactObj:ArtifactModel):void => {
- let newArtifact = new ArtifactModel(artifactObj);
- let artifacts = this.selectedInstance.deploymentArtifacts;
- if (newArtifact.mandatory || newArtifact.serviceApi) {//?????????
- artifacts[newArtifact.artifactLabel] = newArtifact;
- }
- else {
- delete artifacts[artifactLabel];
- }
- deferred.resolve(newArtifact);
- };
- this.componentService.deleteInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifactId, artifactLabel).then(onSuccess);
- return deferred.promise;
- };
-
- public addOrUpdateInstanceArtifact = (artifact:ArtifactModel):ng.IPromise<ArtifactModel> => {
- let deferred = this.$q.defer<ArtifactModel>();
- let onSuccess = (artifactObj:ArtifactModel):void => {
- switch (artifactObj.artifactGroupType) {
- case ArtifactGroupType.DEPLOYMENT:
- this.selectedInstance.deploymentArtifacts[artifactObj.artifactLabel] = artifactObj;
- break;
- case ArtifactGroupType.INFORMATION:
- this.selectedInstance.artifacts[artifactObj.artifactLabel] = artifactObj;
- break;
- }
- deferred.resolve(artifactObj);
- };
- let onError = (error:any):void => {
- deferred.reject(error);
- };
- if (artifact.uniqueId) {
- this.componentService.updateInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
- } else {
- this.componentService.addInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
- }
- return deferred.promise;
- };
-
- public uploadInstanceEnvFile = (artifact:ArtifactModel):ng.IPromise<ArtifactModel> => {
- let deferred = this.$q.defer<ArtifactModel>();
- let onSuccess = (artifactObj:ArtifactModel):void => {
- this.selectedInstance.deploymentArtifacts[artifactObj.artifactLabel] = artifactObj;
- deferred.resolve(artifactObj);
- };
- let onError = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.uploadInstanceEnvFile(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
- return deferred.promise;
- };
-
- //this function will update the instance version than the function call getComponent to update the current component and return the new instance version
- public changeComponentInstanceVersion = (componentUid:string):ng.IPromise<Component> => {
- let deferred = this.$q.defer<Component>();
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- let onSuccess = (componentInstance:ComponentInstance):void => {
- let onSuccess = (component:Component):void => {
- component.setSelectedInstance(componentInstance);
- deferred.resolve(component);
- };
- this.getComponent().then(onSuccess, onFailed);
- };
- this.componentService.changeResourceInstanceVersion(this.uniqueId, this.selectedInstance.uniqueId, componentUid).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public checkComponentInstanceVersionChange = (componentUid:string):ng.IPromise<any> => {
- return this.componentService.checkResourceInstanceVersionChange(this.uniqueId, this.selectedInstance.uniqueId, componentUid);
- };
-
- public createComponentInstance = (componentInstance:ComponentInstance):ng.IPromise<ComponentInstance> => {
- let deferred = this.$q.defer<ComponentInstance>();
- let onSuccess = (instance:ComponentInstance):void => {
- this.componentInstances.push(instance);
- deferred.resolve(instance);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.createComponentInstance(this.uniqueId, componentInstance).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public updateComponentInstance = (componentInstance:ComponentInstance):ng.IPromise<ComponentInstance> => {
- let deferred = this.$q.defer<ComponentInstance>();
- let onSuccess = (updatedInstance:ComponentInstance):void => {
- let componentInstance:ComponentInstance = _.find(this.componentInstances, (instance:ComponentInstance) => {
- return instance.uniqueId === updatedInstance.uniqueId;
- });
-
- let index = this.componentInstances.indexOf(componentInstance);
- this.componentInstances[index] = componentInstance;
- deferred.resolve(updatedInstance);
-
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.updateComponentInstance(this.uniqueId, componentInstance).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public updateMultipleComponentInstances = (instances:Array<ComponentInstance>):ng.IPromise<Array<ComponentInstance>> => {
- let deferred = this.$q.defer<Array<ComponentInstance>>();
- let onSuccess = (updatedInstances:Array<ComponentInstance>):void => {
- _.forEach(updatedInstances, (updatedComponentInstance) => {
- let componentInstance:ComponentInstance = _.find(this.componentInstances, (instance:ComponentInstance) => {
- return instance.uniqueId === updatedComponentInstance.uniqueId;
- });
-
- let index = this.componentInstances.indexOf(componentInstance);
- this.componentInstances[index] = componentInstance;
-
- });
- deferred.resolve(updatedInstances);
-
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.updateMultipleComponentInstances(this.uniqueId, instances).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public deleteComponentInstance = (componentInstanceId:string):ng.IPromise<ComponentInstance> => {
- let deferred = this.$q.defer<ComponentInstance>();
- let onSuccess = ():void => {
- let onSuccess = (component:Component):void => {
- this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
- this.componentInstancesProperties = new PropertiesGroup(component.componentInstancesProperties);
- this.componentInstancesAttributes = new AttributesGroup(component.componentInstancesAttributes);
- this.modules = component.modules;
- this.componentInstancesRelations = CommonUtils.initComponentInstanceRelations(component.componentInstancesRelations);
- deferred.resolve();
- };
- this.getComponent().then(onSuccess);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.deleteComponentInstance(this.uniqueId, componentInstanceId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
-
- public syncComponentByRelation(relation:RelationshipModel) {
- relation.relationships.forEach((rel) => {
- if (rel.capability) {
- const toComponentInstance:ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.toNode);
- const toComponentInstanceCapability:Capability = toComponentInstance.findCapability(
- rel.capability.type, rel.capability.uniqueId, rel.capability.ownerId, rel.capability.name);
- const isCapabilityFulfilled:boolean = rel.capability.isFulfilled();
- if (isCapabilityFulfilled && toComponentInstanceCapability) {
- // if capability is fulfilled and in component, then remove it
- console.log('Capability is fulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
- toComponentInstance.capabilities[rel.capability.type].splice(
- toComponentInstance.capabilities[rel.capability.type].findIndex((cap) => cap === toComponentInstanceCapability), 1
- )
- } else if (!isCapabilityFulfilled && !toComponentInstanceCapability) {
- // if capability is unfulfilled and not in component, then add it
- console.log('Capability is unfulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
- toComponentInstance.capabilities[rel.capability.type].push(rel.capability);
- }
- }
- if (rel.requirement) {
- const fromComponentInstance:ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.fromNode);
- const fromComponentInstanceRequirement:Requirement = fromComponentInstance.findRequirement(
- rel.requirement.capability, rel.requirement.uniqueId, rel.requirement.ownerId, rel.requirement.name);
- const isRequirementFulfilled:boolean = rel.requirement.isFulfilled();
- if (isRequirementFulfilled && fromComponentInstanceRequirement) {
- // if requirement is fulfilled and in component, then remove it
- console.log('Requirement is fulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
- fromComponentInstance.requirements[rel.requirement.capability].splice(
- fromComponentInstance.requirements[rel.requirement.capability].findIndex((req) => req === fromComponentInstanceRequirement), 1
- )
- } else if (!isRequirementFulfilled && !fromComponentInstanceRequirement) {
- // if requirement is unfulfilled and not in component, then add it
- console.log('Requirement is unfulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
- fromComponentInstance.requirements[rel.requirement.capability].push(rel.requirement);
- }
- }
- });
- }
-
- public fetchRelation = (linkId:string):ng.IPromise<RelationshipModel> => {
- let deferred = this.$q.defer<RelationshipModel>();
- let onSuccess = (relation:RelationshipModel):void => {
- this.syncComponentByRelation(relation);
- deferred.resolve(relation);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.fetchRelation(this.uniqueId, linkId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public createRelation = (relation:RelationshipModel):ng.IPromise<RelationshipModel> => {
- let deferred = this.$q.defer<RelationshipModel>();
- let onSuccess = (relation:RelationshipModel):void => {
- console.info('Link created successfully', relation);
- if (!this.componentInstancesRelations) {
- this.componentInstancesRelations = [];
- }
- this.componentInstancesRelations.push(new RelationshipModel(relation));
- this.syncComponentByRelation(relation);
- deferred.resolve(relation);
- };
- let onFailed = (error:any):void => {
- console.info('Failed to create relation', error);
- deferred.reject(error);
- };
- this.componentService.createRelation(this.uniqueId, relation).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public deleteRelation = (relation:RelationshipModel):ng.IPromise<RelationshipModel> => {
- let deferred = this.$q.defer<RelationshipModel>();
- let onSuccess = (relation:RelationshipModel):void => {
- console.log("Link Deleted In Server");
- let relationToDelete = _.find(this.componentInstancesRelations, (item) => {
- return item.fromNode === relation.fromNode && item.toNode === relation.toNode && _.some(item.relationships, (relationship)=> {
- return angular.equals(relation.relationships[0].relation, relationship.relation);
- });
- });
- let index = this.componentInstancesRelations.indexOf(relationToDelete);
- if (relationToDelete != undefined && index > -1) {
- if (relationToDelete.relationships.length == 1) {
- this.componentInstancesRelations.splice(index, 1);
- } else {
- this.componentInstancesRelations[index].relationships =
- _.reject(this.componentInstancesRelations[index].relationships, (relationship) => {
- return angular.equals(relation.relationships[0].relation, relationship.relation);
- });
- }
- } else {
- console.error("Error while deleting relation - the return delete relation from server was not found in UI")
- }
- this.syncComponentByRelation(relation);
- deferred.resolve(relation);
- };
- let onFailed = (error:any):void => {
- console.error("Failed To Delete Link");
- deferred.reject(error);
- };
- this.componentService.deleteRelation(this.uniqueId, relation).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- public getRelationRequirementCapability(relationship: Relationship, sourceNode:ComponentInstance, targetNode:ComponentInstance): Promise<{requirement:Requirement, capability:Capability}> {
- // try find the requirement and capability in the source and target component instances:
- let capability:Capability = targetNode.findCapability(undefined,
- relationship.relation.capabilityUid,
- relationship.relation.capabilityOwnerId,
- relationship.relation.capability);
- let requirement:Requirement = sourceNode.findRequirement(undefined,
- relationship.relation.requirementUid,
- relationship.relation.requirementOwnerId,
- relationship.relation.requirement);
-
- return new Promise<{requirement:Requirement, capability:Capability}>((resolve, reject) => {
- if (capability && requirement) {
- resolve({capability, requirement});
- }
- else {
- // if requirement and/or capability is missing, then fetch the full relation with its requirement and capability:
- this.fetchRelation(relationship.relation.id).then((fetchedRelation) => {
- resolve({
- capability: capability || fetchedRelation.relationships[0].capability,
- requirement: requirement || fetchedRelation.relationships[0].requirement
- });
- }, reject);
- }
- });
- }
-
- public updateRequirementsCapabilities = ():ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let onSuccess = (response:any):void => {
- this.capabilities = new CapabilitiesGroup(response.capabilities);
- this.requirements = new RequirementsGroup(response.requirements);
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getRequirementsCapabilities(this.uniqueId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
public getModuleForDisplay = (moduleId:string):ng.IPromise<DisplayModule> => {
let deferred = this.$q.defer<DisplayModule>();
@@ -814,82 +393,6 @@
return deferred.promise;
};
-
- // this function get all instances filtered by inputs and properties (optional) - if no search string insert - this function will
- // get all the instances of the component (in service only VF instances)
- public getComponentInstancesFilteredByInputsAndProperties = (searchText?:string):ng.IPromise<Array<ComponentInstance>> => {
-
- let deferred = this.$q.defer<Array<ComponentInstance>>();
- let onSuccess = (response:Array<ComponentInstance>):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInstancesFilteredByInputsAndProperties(this.uniqueId, searchText).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
-
- // get inputs for instance - Pagination function
- public getComponentInputs = ():ng.IPromise<Array<InputModel>> => {
-
- let deferred = this.$q.defer<Array<InputModel>>();
- let onSuccess = (inputsRes:Array<InputModel>):void => {
- this.inputs = inputsRes;
- deferred.resolve(inputsRes);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInputs(this.uniqueId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
-
- // get inputs instance - Pagination function
- public getComponentInstanceInputs = (componentInstanceId:string, originComponentUid:string):ng.IPromise<Array<InputModel>> => {
-
- let deferred = this.$q.defer<Array<InputModel>>();
- let onSuccess = (response:Array<InputModel>):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInstanceInputs(this.uniqueId, componentInstanceId, originComponentUid).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- // get inputs inatnce - Pagination function
- public getComponentInstanceInputProperties = (componentInstanceId:string, inputId:string):ng.IPromise<Array<PropertyModel>> => {
-
- let deferred = this.$q.defer<Array<PropertyModel>>();
- let onSuccess = (response:Array<PropertyModel>):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInstanceInputProperties(this.uniqueId, componentInstanceId, inputId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
- // get inputs inatnce - Pagination function
- public getComponentInstanceProperties = (componentInstanceId:string):ng.IPromise<Array<PropertyModel>> => {
-
- let deferred = this.$q.defer<Array<PropertyModel>>();
- let onSuccess = (response:Array<PropertyModel>):void => {
- deferred.resolve(response);
- };
- let onFailed = (error:any):void => {
- deferred.reject(error);
- };
- this.componentService.getComponentInstanceProperties(this.uniqueId, componentInstanceId).then(onSuccess, onFailed);
- return deferred.promise;
- };
-
-
public updateGroupMetadata = (module:Module):ng.IPromise<Module> => {
let deferred = this.$q.defer<Module>();
@@ -969,15 +472,6 @@
};
- public getAdditionalInformation = ():Array<AdditionalInformationModel> => {
- let additionalInformationObject:any = _.find(this.additionalInformation, (obj:any):boolean => {
- return obj.parentUniqueId == this.uniqueId;
- });
- if (additionalInformationObject) {
- return additionalInformationObject.parameters;
- }
- return [];
- };
public handleTags = ():void => {
let isContainTag = _.find(this.tags, (tag)=> {
@@ -1036,10 +530,10 @@
this.derivedList = componentMetadata.derivedList;
this.normalizedName = componentMetadata.normalizedName;
this.systemName = componentMetadata.systemName;
- this.projectCode = componentMetadata.projectCode;
this.categories = componentMetadata.categories;
this.archived = componentMetadata.archived || false;
this.vspArchived = componentMetadata.vspArchived;
+ this.componentMetadata = componentMetadata;
}
public toJSON = ():any => {
diff --git a/catalog-ui/src/app/models/components/displayComponent.ts b/catalog-ui/src/app/models/components/displayComponent.ts
index f96e0bf..4e94695 100644
--- a/catalog-ui/src/app/models/components/displayComponent.ts
+++ b/catalog-ui/src/app/models/components/displayComponent.ts
@@ -22,47 +22,42 @@
*/
'use strict';
-import {ComponentType} from "../../utils/constants";
-import {ComponentMetadata} from "../component-metadata";
-import {PolicyMetadata} from "../policy-metadata";
-import {GroupMetadata} from "../group-metadata";
-import {RequirementsGroup} from "../requirement";
-import {CapabilitiesGroup} from "../capability";
+import { ComponentType, SdcElementType } from '../../utils/constants';
+import { ComponentMetadata } from '../component-metadata';
+import { PolicyMetadata } from '../policy-metadata';
+import { GroupMetadata } from '../group-metadata';
+import { RequirementsGroup } from '../requirement';
+import { CapabilitiesGroup } from '../capability';
export enum LeftPaletteMetadataTypes {
- Component,
- Group,
- Policy
+ Component = 'COMPONENT',
+ Group = 'GROUP',
+ Policy = 'POLICY'
}
export class LeftPaletteComponent {
- uniqueId:string;
- type:string;
- displayName:string;
- version:string;
- mainCategory:string;
- subCategory:string;
- iconClass:string;
- componentSubType:string;
- searchFilterTerms:string;
- certifiedIconClass:string;
- icon:string;
- isDraggable:boolean;
- isRequirmentAndCapabilitiesLoaded:boolean;
- uuid:string;
- name:string;
- lifecycleState:string;
- allVersions:any;
- componentType:string;
- systemName:string;
-
- invariantUUID:string;
-
- capabilities:CapabilitiesGroup;
- requirements:RequirementsGroup;
-
- categoryType:LeftPaletteMetadataTypes;
+ uniqueId: string;
+ type: string;
+ version: string;
+ mainCategory: string;
+ subCategory: string;
+ componentSubType: string;
+ searchFilterTerms: string;
+ certifiedIconClass: string;
+ isDraggable: boolean;
+ uuid: string;
+ name: string;
+ lifecycleState: string;
+ allVersions: any;
+ componentType: string;
+ systemName: string;
+ invariantUUID: string;
+ capabilities: CapabilitiesGroup;
+ requirements: RequirementsGroup;
+ categoryType: LeftPaletteMetadataTypes;
+ resourceType: string;
+ icon: string;
constructor(metadataType: LeftPaletteMetadataTypes, item: ComponentMetadata | PolicyMetadata | GroupMetadata) {
if (metadataType === LeftPaletteMetadataTypes.Policy) {
@@ -81,13 +76,10 @@
}
}
- private initComponent(component:ComponentMetadata): void {
- this.categoryType = LeftPaletteMetadataTypes.Component;
+ private initComponent(component: ComponentMetadata): void {
- this.icon = component.icon;
this.version = component.version;
this.uniqueId = component.uniqueId;
- this.isRequirmentAndCapabilitiesLoaded = false;
this.uuid = component.uuid;
this.name = component.name;
this.allVersions = component.allVersions;
@@ -95,7 +87,6 @@
this.systemName = component.systemName;
this.invariantUUID = component.invariantUUID;
this.isDraggable = true;
-
if (component.categories && component.categories[0] && component.categories[0].subcategories && component.categories[0].subcategories[0]) {
this.mainCategory = component.categories[0].name;
this.subCategory = component.categories[0].subcategories[0].name;
@@ -103,75 +94,43 @@
this.mainCategory = 'Generic';
this.subCategory = 'Generic';
}
+ // this.categoryType = LeftPaletteMetadataTypes.Component;
+ // this.componentSubType = component. ? component.resourceType: ComponentType.SERVICE_PROXY;
+ this.searchFilterTerms = (this.name + ' ' + component.description + ' ' + component.tags.join(' ')).toLowerCase() + ' ' + component.version;
+ this.icon = component.icon;
+ this.certifiedIconClass = component.lifecycleState != 'CERTIFIED' ? 'non-certified' : ''; // need to fix after onap fix
- this.componentSubType = component.resourceType ? component.resourceType: 'SERVICE';
-
- this.initDisplayName(component.name);
- this.searchFilterTerms = (this.displayName + ' ' + component.description + ' ' + component.tags.join(' ')).toLowerCase() + ' ' + component.version;
- this.initIconSprite(component.icon);
- this.certifiedIconClass = component.lifecycleState != 'CERTIFIED' ? 'non-certified' : '';
- if (component.icon === 'vl' || component.icon === 'cp') {
- this.certifiedIconClass = this.certifiedIconClass + " " + 'smaller-icon';
- }
}
- private initGroup(group:GroupMetadata): void {
+ private initGroup(group: GroupMetadata): void {
this.categoryType = LeftPaletteMetadataTypes.Group;
-
this.uniqueId = group.uniqueId;
- this.displayName = group.name;
- this.mainCategory = "Groups";
- this.subCategory = "Groups";
- this.iconClass = "sprite-group-icons group";
+ this.name = group.name;
+ this.mainCategory = 'Groups';
+ this.subCategory = 'Groups';
this.version = group.version;
-
this.type = group.type;
- this.componentSubType = 'GROUP';
-
+ this.componentSubType = SdcElementType.GROUP;
+ this.icon = SdcElementType.GROUP;
this.searchFilterTerms = this.type + ' ' + group.name + ' ' + group.version;
this.isDraggable = false;
}
- private initPolicy(policy:PolicyMetadata): void {
+ private initPolicy(policy: PolicyMetadata): void {
this.categoryType = LeftPaletteMetadataTypes.Policy;
-
this.uniqueId = policy.uniqueId;
- this.displayName = policy.name;
- this.mainCategory = "Policies";
- this.subCategory = "Policies";
- this.iconClass = "sprite-policy-icons policy";
+ this.name = policy.name;
+ this.mainCategory = 'Policies';
+ this.subCategory = 'Policies';
this.version = policy.version;
-
this.type = policy.type;
- this.componentSubType = 'POLICY';
-
+ this.componentSubType = SdcElementType.POLICY;
+ this.icon = SdcElementType.POLICY;
this.searchFilterTerms = this.type + ' ' + policy.name + ' ' + policy.version;
this.isDraggable = false;
}
- public initDisplayName = (name:string):void => {
- let newName =
- _.last(_.last(_.last(_.last(_.last(_.last(_.last(_.last(name.split('tosca.nodes.'))
- .split('network.')).split('relationships.')).split('org.openecomp.')).split('resource.nfv.'))
- .split('nodes.module.')).split('cp.')).split('vl.'));
- if (newName) {
- this.displayName = newName;
- } else {
- this.displayName = name;
- }
- };
-
- public initIconSprite = (icon:string):void => {
- switch (this.componentSubType) {
- case ComponentType.SERVICE:
- this.iconClass = "sprite-services-icons " + icon;
- break;
- default:
- this.iconClass = "sprite-resource-icons " + icon;
- }
- }
-
- public getComponentSubType = ():string => {
+ public getComponentSubType = (): string => {
return this.componentSubType;
};
}
diff --git a/catalog-ui/src/app/models/components/service.ts b/catalog-ui/src/app/models/components/service.ts
index a947e81..911a432 100644
--- a/catalog-ui/src/app/models/components/service.ts
+++ b/catalog-ui/src/app/models/components/service.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.
@@ -38,6 +38,7 @@
public namingPolicy:string;
public serviceType:string;
public serviceRole:string;
+ public serviceFunction:string;
public environmentContext:string;
public instantiationType:string;
public forwardingPaths:{ [key:string]:ForwardingPath } = {};
@@ -52,6 +53,7 @@
this.namingPolicy = component.namingPolicy;
this.serviceType = component.serviceType;
this.serviceRole = component.serviceRole;
+ this.serviceFunction = component.serviceFunction;
this.instantiationType = component.instantiationType;
this.environmentContext = component.environmentContext;
if (component.categories && component.categories[0]) {
@@ -168,6 +170,7 @@
this.namingPolicy = componentMetadata.namingPolicy;
this.serviceType = componentMetadata.serviceType;
this.serviceRole = componentMetadata.serviceRole;
+ this.serviceFunction = componentMetadata.serviceFunction;
this.environmentContext = componentMetadata.environmentContext;
this.instantiationType = componentMetadata.instantiationType;
this.setComponentDisplayData();
@@ -195,6 +198,7 @@
temp.selectedCategory = undefined;
temp.modules = undefined;
temp.groupInstances = undefined;
+ temp.policies = undefined;
return temp;
};
}
diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
index f95d655..d3a99e5 100644
--- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
+++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
@@ -23,12 +23,53 @@
*/
'use strict';
import * as _ from "lodash";
-import {ArtifactGroupModel, CapabilitiesGroup,RequirementsGroup, PropertyModel, InputModel, Module} from "../../models";
-import {ResourceType,ComponentType} from "../../utils/constants";
+import {
+ ArtifactGroupModel,
+ CapabilitiesGroup,
+ RequirementsGroup,
+ PropertyModel,
+ InputModel,
+ Module
+} from "../../models";
+import {ResourceType, ComponentType} from "../../utils/constants";
import {Capability} from "../capability";
import {Requirement} from "../requirement";
-export class ComponentInstance {
+export interface IComponentInstance {
+
+ componentUid:string;
+ componentName:string;
+ posX:number;
+ posY:number;
+ componentVersion:string;
+ description:string;
+ icon:string;
+ name:string;
+ normalizedName:string;
+ originType:string;
+ deploymentArtifacts:ArtifactGroupModel;
+ artifacts:ArtifactGroupModel;
+ propertyValueCounter:number;
+ uniqueId:string;
+ creationTime:number;
+ modificationTime:number;
+ capabilities:CapabilitiesGroup;
+ requirements:RequirementsGroup;
+ customizationUUID:string;
+ sourceModelInvariant:string;
+ sourceModelName:string;
+ sourceModelUid:string;
+ sourceModelUuid:string;
+ //custom properties
+ certified:boolean;
+ iconSprite:string;
+ inputs:Array<InputModel>;
+ properties:Array<PropertyModel>;
+ groupInstances:Array<Module>;
+ invariantName:string;
+ originArchived:boolean;
+}
+export class ComponentInstance implements IComponentInstance{
public componentUid:string;
public componentName:string;
@@ -61,7 +102,7 @@
public groupInstances:Array<Module>;
public invariantName:string;
public originArchived:boolean;
- public directives: Array<string>;
+ public directives: string[];
DIRECTIVES_TYPES = {
SELECTABLE: 'selectable'
@@ -112,14 +153,18 @@
return this.originType === 'VL';
};
- public isComplex = () : boolean => {
- return this.originType === ResourceType.VF || this.originType === ResourceType.PNF || this.originType === ResourceType.CVFC || this.originType === ResourceType.CR ;
+ public isComplex = ():boolean => {
+ return this.originType === ResourceType.VF || this.originType === ResourceType.PNF || this.originType === ResourceType.CVFC || this.originType === ResourceType.CR;
}
- public isServiceProxy = () :boolean => {
+ public isServiceProxy = ():boolean => {
return this.originType === ComponentType.SERVICE_PROXY;
}
+ public getComponentUid = ():string => {
+ return this.isServiceProxy()? this.sourceModelUid : this.componentUid;
+ }
+
public setInstanceRC = ():void=> {
_.forEach(this.requirements, (requirementValue:Array<any>, requirementKey)=> {
_.forEach(requirementValue, (requirement)=> {
@@ -183,7 +228,6 @@
public get iconClass() {
return this.iconSprite + ' ' + this.icon;
}
-
public isDependent = () : boolean => {
return this.directives && this.directives.indexOf(this.DIRECTIVES_TYPES.SELECTABLE) !== -1;
}
diff --git a/catalog-ui/src/app/models/componentsInstances/fullComponentInstance.ts b/catalog-ui/src/app/models/componentsInstances/fullComponentInstance.ts
new file mode 100644
index 0000000..ce5aa1d
--- /dev/null
+++ b/catalog-ui/src/app/models/componentsInstances/fullComponentInstance.ts
@@ -0,0 +1,110 @@
+import { ComponentInstance, Component, ArtifactGroupModel, Service, Resource, IMainCategory, ArtifactModel, AttributeModel } from "app/models";
+import { ComponentType } from '../../utils/constants';
+import * as _ from 'lodash';
+
+
+export class FullComponentInstance extends ComponentInstance {
+ public contactId: string;
+ public componentType: string;
+ public interfaces:any;
+ public tags:Array<string>;
+ public version:string;
+ public allVersions:any;
+ public highestVersion:boolean;
+ public categories:Array<IMainCategory>;
+ public creationDate:number;
+ public creatorFullName:string;
+ public vendorName:string;
+ public vendorRelease:string;
+ public systemName:string;
+ public uuid:string;
+ public lifecycleState: string;
+ public archived: boolean;
+
+ public isServiceInstance: boolean;
+ public isResourceInstance: boolean;
+ public directives: string[];
+
+ DIRECTIVES_TYPES = {
+ SELECTABLE: 'selectable'
+ };
+
+ //service
+ public serviceApiArtifacts:ArtifactGroupModel;
+ public serviceType:string;
+ public serviceRole:string;
+
+ //resource
+ public csarUUID:string;
+ public isCsarComponent: boolean;
+ public csarVersion:string;
+ public csarPackageType:string;
+ public packageId:string;
+ public resourceType:string;
+ public resourceVendorModelNumber:string;
+
+ public attributes: Array<AttributeModel>;
+
+ constructor(componentInstance:ComponentInstance, originComponent:Component) {
+ super(componentInstance);
+
+ this.componentType = originComponent.componentType;
+ this.interfaces = originComponent.interfaces;
+ this.tags = [];
+ this.tags = _.clone(originComponent.tags);
+ this.version = originComponent.version;
+ this.allVersions = originComponent.allVersions;
+ this.highestVersion = originComponent.highestVersion;
+ this.categories = originComponent.categories;
+ this.creationDate = originComponent.creationDate;
+ this.creatorFullName = originComponent.creatorFullName;
+ this.vendorName = originComponent.vendorName;
+ this.vendorRelease = originComponent.vendorRelease;
+ this.contactId = originComponent.contactId;
+ this.description = originComponent.description;
+ this.systemName = originComponent.systemName;
+ this.uuid = originComponent.uuid;
+ this.lifecycleState = originComponent.lifecycleState;
+ this.archived = originComponent.archived;
+ this.attributes = originComponent.attributes;
+ this.directives = componentInstance.directives;
+
+
+ if(originComponent.componentType === ComponentType.SERVICE || originComponent.componentType === ComponentType.SERVICE_PROXY){
+ this.isServiceInstance = true;
+ this.serviceApiArtifacts = (<Service>originComponent).serviceApiArtifacts;
+ this.serviceType = (<Service>originComponent).serviceType;
+ this.serviceRole = (<Service>originComponent).serviceRole;
+ }
+ if(originComponent.componentType === ComponentType.RESOURCE) {
+ this.isResourceInstance = true;
+ this.csarUUID = (<Resource>originComponent).csarUUID;
+ this.isCsarComponent = !!this.csarUUID;
+ this.resourceType = (<Resource>originComponent).resourceType;
+ this.resourceVendorModelNumber = (<Resource>originComponent).resourceVendorModelNumber;
+ }
+ }
+
+ public isResource = ():boolean => {
+ return this.isResourceInstance;
+ }
+
+ public isService = ():boolean => {
+ return this.isServiceInstance;
+ }
+ public isDependent = () : boolean => {
+ return this.directives && this.directives.indexOf(this.DIRECTIVES_TYPES.SELECTABLE) !== -1;
+ }
+
+ public markAsDependent = () : void => {
+ this.directives.push(this.DIRECTIVES_TYPES.SELECTABLE);
+ }
+
+ public unmarkAsDependent = () : void => {
+ const index = this.directives.indexOf(this.DIRECTIVES_TYPES.SELECTABLE);
+ if(index >= 0) {
+ this.directives.splice(index, 1);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/graph/graph-links/links-factory.ts b/catalog-ui/src/app/models/graph/graph-links/links-factory.ts
index cc037a7..d690eca 100644
--- a/catalog-ui/src/app/models/graph/graph-links/links-factory.ts
+++ b/catalog-ui/src/app/models/graph/graph-links/links-factory.ts
@@ -22,60 +22,49 @@
*/
'use strict';
import * as _ from "lodash";
-import {RelationshipModel, Relationship, CompositionCiLinkBase, CompositionCiNodeBase, LinkUcpeHost, CompositionCiUcpeLink,
- CompositionCiVlUcpeLink, CompositionCiSimpleLink, ModuleCiLinkBase, ModuleCiVlLink, CompositionCiVLink} from "../../../models";
+import {
+ RelationshipModel, Relationship, CompositionCiLinkBase, CompositionCiNodeBase, LinkUcpeHost, CompositionCiUcpeLink,
+ CompositionCiVlUcpeLink, CompositionCiSimpleLink, ModuleCiLinkBase, ModuleCiVlLink, CompositionCiVLink
+} from "app/models";
+import {Injectable} from "@angular/core";
+@Injectable()
export class LinksFactory {
- constructor() {
- }
-
- public createGraphLink = (cy:Cy.Instance, relation:RelationshipModel, singleRelation:Relationship):CompositionCiLinkBase => {
-
- let newRelation:CompositionCiLinkBase;
-
- // let fromNode:CompositionCiNodeBase = cy.getElementById(relation.fromNode).data();
- // let toNode:CompositionCiNodeBase = cy.getElementById(relation.toNode).data();
- //
- // if ((relation.fromNode && fromNode.isUcpePart) || (relation.toNode && toNode.isUcpePart )) { //Link from or to node inside ucpe
- //
- // if (singleRelation && singleRelation.relationship.type && singleRelation.relationship.type == 'tosca.relationships.HostedOn') {
- // newRelation = new LinkUcpeHost(relation, singleRelation);
- // } else if (singleRelation.relationship.type && _.includes(singleRelation.relationship.type.toLowerCase(), 'link')) {
- // newRelation = new CompositionCiVlUcpeLink(relation, fromNode.isUcpePart, singleRelation);
- // } else {
- // newRelation = new CompositionCiUcpeLink(relation, fromNode.isUcpePart, singleRelation);
- // }
- // } else
- if (singleRelation.relation.relationship.type && _.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) {
- newRelation = new CompositionCiVLink(relation, singleRelation);
- } else {
- newRelation = new CompositionCiSimpleLink(relation, singleRelation);
+ constructor() {
}
- return newRelation;
- };
+ public createGraphLink = (cy:Cy.Instance, relation:RelationshipModel, singleRelation:Relationship):CompositionCiLinkBase => {
- public createUcpeHostLink = (relation:RelationshipModel):LinkUcpeHost => {
- return new LinkUcpeHost(relation);
- };
+ let newRelation:CompositionCiLinkBase;
+ if (singleRelation.relation.relationship.type && _.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) {
+ newRelation = new CompositionCiVLink(relation, singleRelation);
+ } else {
+ newRelation = new CompositionCiSimpleLink(relation, singleRelation);
+ }
- public createVLLink = (relation:RelationshipModel):CompositionCiVLink => {
- return new CompositionCiVLink(relation);
- }
+ return newRelation;
+ };
+ public createUcpeHostLink = (relation:RelationshipModel):LinkUcpeHost => {
+ return new LinkUcpeHost(relation);
+ };
- public createModuleGraphLinks = (relation:RelationshipModel, singleRelation:Relationship):ModuleCiLinkBase => {
-
- let newRelation:ModuleCiLinkBase;
-
- if (_.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) {
- newRelation = new ModuleCiVlLink(relation, singleRelation);
- } else {
- newRelation = new ModuleCiLinkBase(relation, singleRelation);
+ public createVLLink = (relation:RelationshipModel):CompositionCiVLink => {
+ return new CompositionCiVLink(relation);
}
- return newRelation;
- };
+ public createModuleGraphLinks = (relation:RelationshipModel, singleRelation:Relationship):ModuleCiLinkBase => {
+
+ let newRelation:ModuleCiLinkBase;
+
+ if (_.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) {
+ newRelation = new ModuleCiVlLink(relation, singleRelation);
+ } else {
+ newRelation = new ModuleCiLinkBase(relation, singleRelation);
+ }
+
+ return newRelation;
+ };
}
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts
index 51a0c7b..6960550 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts
@@ -20,9 +20,11 @@
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
import {CommonCINodeBase} from "../common-ci-node-base";
-import {ICanvasImage, ImageCreatorService} from "app/directives/graphs-v2/image-creator/image-creator.service";
import {ImagesUrl, GraphUIObjects} from "app/utils";
import {AngularJSBridge} from "app/services";
+import {ResourceNamePipe} from "app/ng2/pipes/resource-name.pipe";
+import {ComponentInstanceNodesStyle} from "app/ng2/pages/composition/graph/common/style/component-instances-nodes-style";
+import {ImageCreatorService, ICanvasImage} from "app/ng2/pages/composition/graph/common/image-creator.service";
export interface ICompositionCiNodeBase {
@@ -48,14 +50,16 @@
this.isUcpePart = false;
this.isInsideGroup = false;
}
-
-
+
+
protected enhanceImage(node:Cy.Collection, nodeMinSize:number, imgUrl: string):string {
+
let infoIconWidth:number = GraphUIObjects.HANDLE_SIZE;
let nodeWidth:number = node.data('imgWidth') || node.width();
+ // let uncertifiedCanvasWidth: number = nodeWidth;
let infoCanvasWidth: number = nodeWidth;
- if (nodeWidth < nodeMinSize) { //info icon will overlap too much of the node, need to expand canvas.
+ if (nodeWidth < nodeMinSize) { //uncertified icon will overlap too much of the node, need to expand canvas.
infoCanvasWidth = nodeWidth + infoIconWidth/2; //expand canvas so that only half of the icon overlaps with the node
}
@@ -66,13 +70,14 @@
{ src: imgUrl, x: 0, y: 0, width: infoIconWidth, height: infoIconWidth}
];
+
//Create the image and update the node background styles
this.imageCreator.getMultiLayerBase64Image(canvasImages, infoCanvasWidth, infoCanvasWidth).then(img => this.updateNodeStyles(node,infoCanvasWidth,img));
return this.img; // Return the referance to the image (in Base64 format)
}
-
- public setArchivedImageBgStyle(node:Cy.Collection, nodeMinSize:number):string {
+
+ public setArchivedImageBgStyle(node:Cy.Collection, nodeMinSize:number):string {
let archivedIconWidth:number = GraphUIObjects.HANDLE_SIZE;
let nodeWidth:number = node.data('imgWidth') || node.width();
let archivedCanvasWidth: number = nodeWidth;
@@ -95,13 +100,12 @@
}
protected getDisplayName():string {
- let graphResourceName = AngularJSBridge.getFilter('graphResourceName');
- let resourceName = AngularJSBridge.getFilter('resourceName');
- return graphResourceName(resourceName(this.componentInstance.name));
+ let resourceName = ResourceNamePipe.getDisplayName(this.componentInstance.name);
+ return ComponentInstanceNodesStyle.getGraphDisplayName(resourceName);
}
//TODO:: move to Base class ???
- private updateNodeStyles(node,canvasWidth,imageBase64){
+ private updateNodeStyles(node,canvasWidth,imageBase64){
this.img = imageBase64;
node.style({
'background-image': this.img,
@@ -109,7 +113,7 @@
'background-height': canvasWidth,
'background-position-x':0,
'background-position-y':0
- });
+ });
}
}
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts
index 78bcc17..cac48df 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts
@@ -20,7 +20,7 @@
import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
import {ComponentInstance, CompositionCiNodeBase} from "../../../../models";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
export class CompositionCiNodeConfiguration extends CompositionCiNodeBase {
constructor(instance:ComponentInstance,
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts
index 05a6d79..9b6a4ed 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts
@@ -20,7 +20,7 @@
import {CompositionCiNodeBase} from "./composition-ci-node-base";
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import {AngularJSBridge} from "../../../../services/angular-js-bridge-service";
import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts
index 5ef3a73..a46e0c4 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts
@@ -18,9 +18,9 @@
* ============LICENSE_END=========================================================
*/
-import {ComponentInstance, CompositionCiNodeBase} from "app/models";
-import {ImageCreatorService} from "app/directives/graphs-v2/image-creator/image-creator.service";
-import {ImagesUrl, GraphUIObjects} from "app/utils";
+import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
+import {ComponentInstance, CompositionCiNodeBase} from "../../../../models";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
export class CompositionCiNodeServiceProxy extends CompositionCiNodeBase {
private isDependent: boolean;
private originalImg: string;
@@ -50,7 +50,6 @@
}
}
-
public initUncertifiedDependentImage(node:Cy.Collection, nodeMinSize:number):string {
return this.enhanceImage(node, nodeMinSize, this.imagesPath + 'uncertified_dependent.png');
}
@@ -58,5 +57,4 @@
public initDependentImage(node:Cy.Collection, nodeMinSize:number):string {
return this.enhanceImage(node, nodeMinSize, this.imagesPath + 'dependent.png');
}
-
}
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts
index bf8facf..5b62815 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts
@@ -20,7 +20,7 @@
import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
import {ComponentInstance, CompositionCiNodeBase} from "../../../../models";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
export class CompositionCiNodeService extends CompositionCiNodeBase {
constructor(instance:ComponentInstance,
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts
index a79b183..f769e69 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts
@@ -19,7 +19,7 @@
*/
import {CompositionCiNodeCp, ComponentInstance} from "./../../../../models";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import { ImagesUrl} from "../../../../utils/constants";
export class CompositionCiNodeUcpeCp extends CompositionCiNodeCp {
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts
index d4172c0..242e968 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts
@@ -19,7 +19,7 @@
*/
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import {CompositionCiNodeBase} from "./composition-ci-node-base";
import { ImagesUrl} from "../../../../utils/constants";
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts
index 4aff85e..c5d2d9e 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts
@@ -19,7 +19,7 @@
*/
import {CompositionCiNodeBase} from "./composition-ci-node-base";
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
export class CompositionCiNodeVf extends CompositionCiNodeBase {
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts
index 5f07986..4c16661 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
import {CompositionCiNodeBase} from "./composition-ci-node-base";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
import {ImagesUrl} from "../../../../utils/constants";
diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts
index a440f09..2407593 100644
--- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts
+++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts
@@ -19,7 +19,7 @@
*/
import * as _ from "lodash";
import {ComponentInstance} from "../../../componentsInstances/componentInstance";
-import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
import {CompositionCiNodeBase} from "./composition-ci-node-base";
import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants";
diff --git a/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts b/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts
index 245f2e1..bcd2f7e 100644
--- a/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts
+++ b/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts
@@ -22,8 +22,10 @@
import {CompositionCiNodeUcpeCp, Module, ModuleNodeBase, CompositionCiNodeVf, CompositionCiNodeVl, CompositionCiNodeCp, CompositionCiNodeConfiguration,
NodeUcpe, CompositionCiNodeService,CompositionCiNodeServiceProxy, CompositionCiNodeBase, ComponentInstance} from "./../../../models";
import {ComponentType, ResourceType} from "../../../utils/constants";
-import {ImageCreatorService} from "../../../directives/graphs-v2/image-creator/image-creator.service";
+import {ImageCreatorService} from "app/ng2/pages/composition/graph/common/image-creator.service";
+import {Injectable} from "@angular/core";
+@Injectable()
export class NodesFactory {
constructor(private imageCreator:ImageCreatorService) {
@@ -54,7 +56,6 @@
};
public createModuleNode = (module:Module):ModuleNodeBase => {
-
return new ModuleNodeBase(module);
};
@@ -64,6 +65,3 @@
}
}
-NodesFactory.$inject = [
- 'ImageCreatorService'
-];
diff --git a/catalog-ui/src/app/models/graph/relationship.ts b/catalog-ui/src/app/models/graph/relationship.ts
index 8d56272..13a1bd1 100644
--- a/catalog-ui/src/app/models/graph/relationship.ts
+++ b/catalog-ui/src/app/models/graph/relationship.ts
@@ -119,4 +119,11 @@
this.capability = capability;
this.requirement = requirement;
};
+
+ public toJSON = ():any => {
+ let temp = angular.copy(this);
+ temp.capability = undefined;
+ temp.requirement = undefined;
+ return temp;
+ }
}
diff --git a/catalog-ui/src/app/models/graph/zones/group-instance.ts b/catalog-ui/src/app/models/graph/zones/group-instance.ts
index 92d850b..4001b94 100644
--- a/catalog-ui/src/app/models/graph/zones/group-instance.ts
+++ b/catalog-ui/src/app/models/graph/zones/group-instance.ts
@@ -27,24 +27,24 @@
public originArchived?:boolean;
- constructor(group:GroupInstance) {
-
- this.name = group.name;
- this.groupUUID = group.groupUUID;
- this.invariantUUID = group.invariantUUID;
- this.propertyValueCounter = group.propertyValueCounter;
- this.type = group.type;
- this.typeUid = group.typeUid;
- this.uniqueId = group.uniqueId;
- this.version = group.version;
- this.artifacts = group.artifacts;
- this.artifactsUuid = group.artifactsUuid;
- this.properties = CommonUtils.initProperties(group.properties);
- this.members = _.values(group.members);
- this.description = group.description;
- this.empty = group.empty;
- this.ownerId = group.ownerId;
-
+ constructor(group?:GroupInstance) {
+ if (group) {
+ this.name = group.name;
+ this.groupUUID = group.groupUUID;
+ this.invariantUUID = group.invariantUUID;
+ this.propertyValueCounter = group.propertyValueCounter;
+ this.type = group.type;
+ this.typeUid = group.typeUid;
+ this.uniqueId = group.uniqueId;
+ this.version = group.version;
+ this.artifacts = group.artifacts;
+ this.artifactsUuid = group.artifactsUuid;
+ this.properties = CommonUtils.initProperties(group.properties);
+ this.members = _.values(group.members);
+ this.description = group.description;
+ this.empty = group.empty;
+ this.ownerId = group.ownerId;
+ }
this.iconSprite = '';
this.icon = 'icon-group';
}
diff --git a/catalog-ui/src/app/models/graph/zones/policy-instance.ts b/catalog-ui/src/app/models/graph/zones/policy-instance.ts
index cef1705..9dd2d5f 100644
--- a/catalog-ui/src/app/models/graph/zones/policy-instance.ts
+++ b/catalog-ui/src/app/models/graph/zones/policy-instance.ts
@@ -5,6 +5,7 @@
import {ComponentInstance} from "../../componentsInstances/componentInstance";
import {TargetUiObject} from "../../ui-models/ui-target-object";
import {TargetOrMemberType} from "../../../utils/constants";
+import * as _ from 'lodash';
/* The request and response should be same model, need to fix in BE */
export class PolicyTargetsMap {
@@ -66,24 +67,25 @@
constructor(policy?:PolicyInstance) {
- this.componentName = policy.componentName;
- this.description = policy.description;
- this.empty = policy.empty;
- this.invariantName = policy.invariantName;
- this.invariantUUID = policy.invariantUUID;
- this.isFromCsar = policy.isFromCsar;
-
- this.name = policy.name;
- this.normalizedName =policy.normalizedName;
- this.type = policy.type;
- this.policyTypeUid = policy.policyTypeUid;
- this.policyUUID = policy.policyUUID;
- this.properties = CommonUtils.initProperties(policy.properties);
- this.targets = policy.targets;
- this.uniqueId = policy.uniqueId;
- this.version = policy.version;
- this.instanceUniqueId = policy.instanceUniqueId;
-
+ if(policy){
+ this.componentName = policy.componentName;
+ this.description = policy.description;
+ this.empty = policy.empty;
+ this.invariantName = policy.invariantName;
+ this.invariantUUID = policy.invariantUUID;
+ this.isFromCsar = policy.isFromCsar;
+
+ this.name = policy.name;
+ this.normalizedName =policy.normalizedName;
+ this.type = policy.type;
+ this.policyTypeUid = policy.policyTypeUid;
+ this.policyUUID = policy.policyUUID;
+ this.properties = CommonUtils.initProperties(policy.properties);
+ this.targets = policy.targets;
+ this.uniqueId = policy.uniqueId;
+ this.version = policy.version;
+ this.instanceUniqueId = policy.instanceUniqueId;
+ }
this.iconSprite = '';
this.icon = 'icon-policy';
}
diff --git a/catalog-ui/src/app/models/graph/zones/zone-instance.ts b/catalog-ui/src/app/models/graph/zones/zone-instance.ts
index fb8ec77..ee6473a 100644
--- a/catalog-ui/src/app/models/graph/zones/zone-instance.ts
+++ b/catalog-ui/src/app/models/graph/zones/zone-instance.ts
@@ -43,11 +43,11 @@
hidden:boolean;
forceSave:Subject<Function>;
- constructor(instance: PolicyInstance | GroupInstance, topologyTemplate:TopologyTemplate) {
+ constructor(instance: PolicyInstance | GroupInstance, topologyTemplateType: string, topologyTemplateId: string) {
this.instanceData = instance;
- this.parentComponentType = topologyTemplate.componentType;
- this.parentComponentID = topologyTemplate.uniqueId;
+ this.parentComponentType = topologyTemplateType;
+ this.parentComponentID = topologyTemplateId;
if (instance instanceof PolicyInstance) {
this.type = ZoneInstanceType.POLICY;
diff --git a/catalog-ui/src/app/models/heat-parameters.ts b/catalog-ui/src/app/models/heat-parameters.ts
index 153108a..a6784ae 100644
--- a/catalog-ui/src/app/models/heat-parameters.ts
+++ b/catalog-ui/src/app/models/heat-parameters.ts
@@ -30,6 +30,7 @@
description:string;
currentValue:string;
defaultValue:string;
+ envDisplayName:string;
filterTerm:string;
constructor(parameter?:HeatParameterModel) {
diff --git a/catalog-ui/src/app/models/home-filter.ts b/catalog-ui/src/app/models/home-filter.ts
new file mode 100644
index 0000000..2aa509b
--- /dev/null
+++ b/catalog-ui/src/app/models/home-filter.ts
@@ -0,0 +1,30 @@
+import { IEntityFilterObject, ISearchFilter } from "app/ng2/pipes/entity-filter.pipe";
+
+export interface IHomeFilterParams {
+ 'filter.term': string;
+ 'filter.distributed': string;
+ 'filter.status': string
+}
+
+
+export class HomeFilter implements IEntityFilterObject{
+ selectedStatuses: Array<string>;
+ distributed: Array<string>;
+ search: ISearchFilter;
+
+ constructor(params = {}) {
+ this.search = { filterTerm : params['filter.term'] || "" };
+ this.selectedStatuses = params['filter.status']? params['filter.status'].split(',') : [];
+ this.distributed = params['filter.distributed']? params['filter.distributed'].split(',') : []
+
+ }
+
+ public toUrlParam = ():IHomeFilterParams => {
+ return {
+ 'filter.term': this.search.filterTerm,
+ 'filter.distributed': this.distributed && this.distributed.join(',') || null,
+ 'filter.status': this.selectedStatuses && this.selectedStatuses.join(',') || null
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/inputs.ts b/catalog-ui/src/app/models/inputs.ts
index e5b2274..49fd16d 100644
--- a/catalog-ui/src/app/models/inputs.ts
+++ b/catalog-ui/src/app/models/inputs.ts
@@ -27,7 +27,7 @@
import {SchemaPropertyGroupModel} from "./aschema-property";
export class InputsGroup {
- constructor(inputsObj?:InputsGroup) {
+ constructor(inputsObj?: InputsGroup) {
_.forEach(inputsObj, (inputs:Array<InputModel>, instance) => {
this[instance] = [];
_.forEach(inputs, (input:InputModel):void => {
diff --git a/catalog-ui/src/app/models/modules/base-module.ts b/catalog-ui/src/app/models/modules/base-module.ts
index e27065b..b016427 100644
--- a/catalog-ui/src/app/models/modules/base-module.ts
+++ b/catalog-ui/src/app/models/modules/base-module.ts
@@ -48,7 +48,7 @@
public groupInstanceUniqueId:string; // This will only have a value if this is a group instance
constructor(module?:Module) {
- if (module) {
+ if (module) {
this.name = module.name;
this.groupUUID = module.groupUUID;
this.invariantUUID = module.invariantUUID;
diff --git a/catalog-ui/src/app/models/operation.ts b/catalog-ui/src/app/models/operation.ts
index bf03772..30095b9 100644
--- a/catalog-ui/src/app/models/operation.ts
+++ b/catalog-ui/src/app/models/operation.ts
@@ -2,16 +2,20 @@
export class OperationParameter {
name: string;
- type: String;
- inputId: string;
- required: boolean;
+ type: string;
+ inputId?: string;
+ required?: boolean;
+ property?: string;
+ mandatory?: boolean;
constructor(param?: any) {
if (param) {
this.name = param.name;
this.type = param.type;
- this.inputId = param.inputId;
+ this.inputId = param.inputId ;
this.required = param.required;
+ this.property = param.property;
+ this.mandatory = param.mandatory;
}
}
}
@@ -76,17 +80,41 @@
}
}
-export class OperationModel extends BEOperationModel {
+export class OperationModel extends BEOperationModel{
interfaceType: string;
interfaceId: string;
- artifactFileName: string;
- artifactData: any;
+ operationType: string;
+ description: string;
+ uniqueId: string;
+ artifactFileName?: string;
+ artifactData?: any;
+
+ inputParams: IOperationParamsList;
+ outputParams: IOperationParamsList;
+
+ workflowId: string;
+ workflowVersionId: string;
+
+ protected OperationTypeEnum: Array<String> = [
+ 'Create',
+ 'Delete',
+ 'Instantiate',
+ 'Start',
+ 'Stop'
+ ];
constructor(operation?: any) {
super(operation);
if (operation) {
this.interfaceId = operation.interfaceId;
this.interfaceType = operation.interfaceType;
+ this.description = operation.description;
+ this.inputParams = operation.inputParams;
+ this.operationType = operation.operationType;
+ this.outputParams = operation.outputParams;
+ this.uniqueId = operation.uniqueId;
+ this.workflowId = operation.workflowId;
+ this.workflowVersionId = operation.workflowVersionId;
this.artifactFileName = operation.artifactFileName;
this.artifactData = operation.artifactData;
}
@@ -95,6 +123,22 @@
public displayType(): string {
return displayType(this.interfaceType);
}
+
+ public createInputParamsList(inputParams: Array<OperationParameter>): void {
+ this.inputParams = {
+ listToscaDataDefinition: inputParams
+ };
+ }
+
+ public createOutputParamsList(outputParams: Array<OperationParameter>): void {
+ this.outputParams = {
+ listToscaDataDefinition: outputParams
+ };
+ }
+}
+
+export interface CreateOperationResponse extends OperationModel {
+ artifactUUID: string;
}
export class InterfaceModel {
@@ -115,4 +159,4 @@
}
}
-const displayType = (type:string) => type && type.substr(type.lastIndexOf('.') + 1);
+const displayType = (type:string) => type && type.substr(type.lastIndexOf('.') + 1);
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/paths-and-names.ts b/catalog-ui/src/app/models/paths-and-names.ts
index 7304d96..1e15164 100644
--- a/catalog-ui/src/app/models/paths-and-names.ts
+++ b/catalog-ui/src/app/models/paths-and-names.ts
@@ -20,4 +20,4 @@
export class PathsAndNamesDefinition {
constructor(public path: string, public friendlyName: string, public searchable: boolean = true) {}
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts b/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts
index 33e83ce..82f15a8 100644
--- a/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts
+++ b/catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts
@@ -55,7 +55,6 @@
this.name = UUID.UUID();
this.parentName = parentName;
this.propertiesName = parentName + '#' + this.name;
-
if (property.type == PROPERTY_TYPES.LIST) {
this.mapKey = property.schema.property.type.split('.').pop();
@@ -75,6 +74,7 @@
this.schema = new SchemaPropertyGroupModel(new SchemaProperty(property.schema.property));
this.updateValueObjOrig();
}
+ // this.constraints = property ? property.constraints : null;
this.valueObjIsValid = true;
this.derivedDataType = this.getDerivedPropertyType();
}
diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts
index 5d25142..1d263bd 100644
--- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts
+++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts
@@ -18,8 +18,11 @@
* ============LICENSE_END=========================================================
*/
-import {PropertyInputDetail, SchemaPropertyGroupModel, SchemaProperty, ToscaPresentationData} from "app/models";
-import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils';
+import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils/constants';
+import { SchemaProperty, SchemaPropertyGroupModel } from '../aschema-property';
+import { ToscaPresentationData } from '../tosca-presentation';
+import { PropertyInputDetail } from './property-input-detail';
+
export enum DerivedPropertyType {
SIMPLE,
LIST,
@@ -29,7 +32,7 @@
export class PropertyPolicyDetail {
policyId: string;
propertyName: string;
- constructor(propertyPolicy?:PropertyPolicyDetail) {
+ constructor(propertyPolicy?: PropertyPolicyDetail) {
if(propertyPolicy) {
this.policyId = propertyPolicy.policyId;
this.propertyName = propertyPolicy.propertyName;
@@ -39,13 +42,13 @@
export class PropertyBEModel {
- constraints: Array<any>;
+ constraints: any[];
defaultValue: string;
definition: boolean;
description: string;
fromDerived: boolean;
- getInputValues: Array<PropertyInputDetail>;
- getPolicyValues: Array<PropertyPolicyDetail>;
+ getInputValues: PropertyInputDetail[];
+ getPolicyValues: PropertyPolicyDetail[];
name: string;
origName: string;
parentUniqueId: string;
@@ -88,54 +91,28 @@
if (!this.schema || !this.schema.property) {
this.schema = new SchemaPropertyGroupModel(new SchemaProperty());
- } else { //forcing creating new object, so editing different one than the object in the table
+ } else { // forcing creating new object, so editing different one than the object in the table
this.schema = new SchemaPropertyGroupModel(new SchemaProperty(this.schema.property));
}
}
-
-
public toJSON = (): any => {
- let temp = angular.copy(this);
- temp.value = temp.value === "{}" || temp.value === "[]" ? undefined : temp.value;
- temp.defaultValue = temp.defaultValue === "{}" || temp.defaultValue === "[]" ? undefined : temp.defaultValue;
+ const temp = angular.copy(this);
+ temp.value = temp.value === '{}' || temp.value === '[]' ? undefined : temp.value;
+ temp.defaultValue = temp.defaultValue === '{}' || temp.defaultValue === '[]' ? undefined : temp.defaultValue;
return temp;
- };
+ }
public getDerivedPropertyType = () => {
if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1) {
return DerivedPropertyType.SIMPLE;
- } else if (this.type == PROPERTY_TYPES.LIST) {
+ } else if (this.type === PROPERTY_TYPES.LIST) {
return DerivedPropertyType.LIST;
- } else if (this.type == PROPERTY_TYPES.MAP) {
+ } else if (this.type === PROPERTY_TYPES.MAP) {
return DerivedPropertyType.MAP;
} else {
return DerivedPropertyType.COMPLEX;
}
}
-
}
-
-// EXTRAS FROM CONSTRUCTOR:
-// this.source = property.source;
-// this.valueUniqueUid = property.valueUniqueUid;
-// this.path = property.path;
-// this.rules = property.rules;
-// this.resourceInstanceUniqueId = property.resourceInstanceUniqueId;
-// this.readonly = property.readonly;
-// this.simpleType = property.simpleType;
-// this.componentInstanceId = property.componentInstanceId;
-// this.parentValue = property.parentValue;
-//NEW PROPERTIES MAY NEED:
-// export class PropertyFEModel extends PropertyBEModel {
-// componentInstanceId: string;
-// isAlreadySelected: boolean;
-// filterTerm: string;
-// }
-//FOR INPUTS, BE ALSO INCLUDES:
-//export class InputFEModel extends PropertyBEModel {
-// hidden: boolean;
-// label: string;
-// immutable: boolean;
-// }
diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts
index 016c5b9..b87edff 100644
--- a/catalog-ui/src/app/models/properties.ts
+++ b/catalog-ui/src/app/models/properties.ts
@@ -40,6 +40,7 @@
export interface IPropertyModel extends InputPropertyBase {
//server data
+ //constraints:Array<Object>;
source:string;
//instance properties
@@ -59,6 +60,7 @@
//server data
uniqueId:string;
name:string;
+ constraints:Array<Object>;
defaultValue:string;
description:string;
password:boolean;
@@ -91,6 +93,7 @@
constructor(property?:PropertyModel) {
super(property);
if (property) {
+ // this.constraints = property.constraints;
this.source = property.source;
this.valueUniqueUid = property.valueUniqueUid;
this.path = property.path;
diff --git a/catalog-ui/src/app/models/relationship-types.ts b/catalog-ui/src/app/models/relationship-types.ts
index 8ae827b..72e6402 100644
--- a/catalog-ui/src/app/models/relationship-types.ts
+++ b/catalog-ui/src/app/models/relationship-types.ts
@@ -14,7 +14,7 @@
* permissions and limitations under the License.
*/
-import {ToscaPresentationData} from "./tosca-presentation";
+import {ToscaPresentationData} from './tosca-presentation';
export class RelationshipTypesMap {
relationshipTypesMap: RelationshipTypesMapData;
diff --git a/catalog-ui/src/app/models/requirement.ts b/catalog-ui/src/app/models/requirement.ts
index 3cc0cf2..d58aabd 100644
--- a/catalog-ui/src/app/models/requirement.ts
+++ b/catalog-ui/src/app/models/requirement.ts
@@ -51,7 +51,7 @@
uniqueId:string;
relationship:string;
leftOccurrences:string;
- minOccurrences: number;
+ minOccurrences:string | number;
maxOccurrences:string;
//custom
filterTerm:string;
@@ -102,4 +102,14 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
+export class RequirementUI extends Requirement {
+ isCreatedManually: boolean;
+
+ constructor(input: Requirement, componentUniqueId: string) {
+ super(input);
+ this.isCreatedManually = input.ownerId === componentUniqueId;
+ }
+}
+
diff --git a/catalog-ui/src/app/models/schema-attribute.ts b/catalog-ui/src/app/models/schema-attribute.ts
index c635203..35211d4 100644
--- a/catalog-ui/src/app/models/schema-attribute.ts
+++ b/catalog-ui/src/app/models/schema-attribute.ts
@@ -19,12 +19,13 @@
*/
'use strict';
-import {SchemaProperty} from "./aschema-property";
+
+import { SchemaProperty } from './aschema-property';
export class SchemaAttributeGroupModel {
- property:SchemaAttribute;
+ property: SchemaAttribute;
- constructor(schemaAttribute?:SchemaAttribute) {
+ constructor(schemaAttribute?: SchemaAttribute) {
this.property = schemaAttribute;
}
}
diff --git a/catalog-ui/src/app/models/server-error-response.spec.ts b/catalog-ui/src/app/models/server-error-response.spec.ts
new file mode 100644
index 0000000..c5c465d
--- /dev/null
+++ b/catalog-ui/src/app/models/server-error-response.spec.ts
@@ -0,0 +1,74 @@
+import { ServerErrors } from '../utils/constants';
+import { ServerErrorResponse } from './server-error-response';
+
+describe('Test Error Response', () => {
+
+ const requestError = {
+ serviceException: {
+ ecompRequestId: 'd01d4bca-2afa-4394-97c5-6d1b04409545',
+ messageId: 'SVC4558',
+ text: 'Error: Action is not permitted as your \'%1\' includes non-validated \'%2\' resource.',
+ variables: ['service', 'vf1']
+ }
+ };
+
+ const ng1ErrorResponse = {
+ status: 403,
+ data: { requestError },
+ statusText: 'Forbidden'
+ };
+
+ const ng5ErrorResponse = {
+ status: 403,
+ error: { requestError },
+ statusText: 'Forbidden'
+ };
+
+ const ng5InternalServerError = {
+ status: 500,
+ error: 'Oops, server error has occurred...',
+ statusText: 'Internal Server Error'
+ };
+
+ const ng1InternalServerError = {
+ status: 500,
+ data: 'Oops, server error has occurred...',
+ statusText: 'Internal Server Error'
+ };
+
+ it('NG1: Verify that server error response is constructed correctly from NG1 structure', () => {
+ const response: ServerErrorResponse = new ServerErrorResponse(ng1ErrorResponse, true);
+ const formatterMessage = 'Action is not permitted as your \'service\' includes non-validated \'vf1\' resource.';
+
+ expect(response.ecompRequestId).toEqual(ng1ErrorResponse.data.requestError.serviceException.ecompRequestId);
+ expect(response.message).toEqual(formatterMessage);
+ expect(response.status).toEqual(ng1ErrorResponse.status);
+ expect(response.title).toEqual(ServerErrors.ERROR_TITLE);
+ });
+
+ it('NG5: Verify that server error response is constructed correctly from NG5 structure', () => {
+ const response: ServerErrorResponse = new ServerErrorResponse(ng5ErrorResponse);
+ const formatterMessage = 'Action is not permitted as your \'service\' includes non-validated \'vf1\' resource.';
+
+ expect(response.ecompRequestId).toEqual(ng5ErrorResponse.error.requestError.serviceException.ecompRequestId);
+ expect(response.message).toEqual(formatterMessage);
+ expect(response.status).toEqual(ng5ErrorResponse.status);
+ expect(response.title).toEqual(ServerErrors.ERROR_TITLE);
+ });
+
+ it('NG1: Verify that internal server error produce generic message', () => {
+ const response: ServerErrorResponse = new ServerErrorResponse(ng1InternalServerError, true);
+
+ expect(response.message).toEqual(ServerErrors.DEFAULT_ERROR);
+ expect(response.status).toEqual(ng5InternalServerError.status);
+ expect(response.title).toEqual(ServerErrors.ERROR_TITLE);
+ });
+
+ it('NG5: Verify that internal server error produce generic message', () => {
+ const response: ServerErrorResponse = new ServerErrorResponse(ng5InternalServerError);
+
+ expect(response.message).toEqual(ServerErrors.DEFAULT_ERROR);
+ expect(response.status).toEqual(ng5InternalServerError.status);
+ expect(response.title).toEqual(ServerErrors.ERROR_TITLE);
+ });
+});
diff --git a/catalog-ui/src/app/models/server-error-response.ts b/catalog-ui/src/app/models/server-error-response.ts
index 61d09af..247774c 100644
--- a/catalog-ui/src/app/models/server-error-response.ts
+++ b/catalog-ui/src/app/models/server-error-response.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.
@@ -21,9 +21,8 @@
/**
* Created by ngordon on 7/27/2017.
*/
-
-import { Response } from '@angular/http';
-import { SEVERITY, ServerErrors } from "../utils/constants";
+import { ServerErrors } from '../utils/constants';
+import '../utils/prototypes';
export class ServerErrorResponse {
@@ -31,48 +30,72 @@
message: string;
messageId: string;
status: number;
- severity: SEVERITY;
+ ecompRequestId: string;
- constructor(response?: Response) {
-
+ constructor(response?: any, isNg1Response?: boolean) {
if (response) {
- let rejectionObj: any = {};
- if (response.text().length) {
- let rejection = response.json();
- rejectionObj = rejection.serviceException || rejection.requestError && (rejection.requestError.serviceException || rejection.requestError.policyException);
- rejectionObj.text = this.getFormattedMessage(rejectionObj.text || ServerErrors.MESSAGE_ERROR, rejectionObj.variables);
+ if (isNg1Response) {
+ // Shall handle the case where this error response is generated from the NG1 http interceptor
+ this.setValuesByRejectionObject(response, response.data);
+ } else {
+ // Shall handle NG5 http error responses
+ this.setValuesByRejectionObject(response, response.error);
}
-
- this.title = ServerErrors.ERROR_TITLE;
- this.message = rejectionObj.text || response.statusText || ServerErrors.DEFAULT_ERROR;
- this.messageId = rejectionObj.messageId;
- this.status = response.status;
- this.severity = SEVERITY.ERROR;
}
}
+ private setValuesByRejectionObject(response: any, errorResponseBody: any) {
+ let rejectionObj: any = {};
- private getFormattedMessage = (text: string, variables: Array<string>): string => { //OLD CODE
- // Remove the "Error: " text at the begining
- if (text.trim().indexOf("Error:") === 0) {
- text = text.replace("Error:", "").trim();
+ // If it is an internal server error, we dont want to expose anything to the user, just display a default error an return
+ if (response.status === 500) {
+ this.title = ServerErrors.ERROR_TITLE;
+ this.message = ServerErrors.DEFAULT_ERROR;
+ this.status = response.status;
+ return;
}
- //mshitrit DE199895 bug fix
+ if (errorResponseBody) {
+ if (errorResponseBody.requestError || errorResponseBody.serviceException) {
+ rejectionObj = errorResponseBody.serviceException || errorResponseBody.requestError.serviceException || errorResponseBody.requestError.policyException;
+ rejectionObj.text = this.getFormattedMessage(rejectionObj.text || ServerErrors.MESSAGE_ERROR, rejectionObj.variables);
+ } else if (errorResponseBody.type === 'application/octet-stream') {
+ rejectionObj.text = 'Error downloading file';
+ rejectionObj.title = ServerErrors.DOWNLOAD_ERROR;
+ } else if (errorResponseBody.message) {
+ rejectionObj.text = response.error.message;
+ } else {
+ rejectionObj.text = response.error;
+ }
+ }
+ this.title = rejectionObj.title || ServerErrors.ERROR_TITLE;
+ this.message = rejectionObj.text || response.statusText || ServerErrors.DEFAULT_ERROR;
+ this.messageId = rejectionObj.messageId;
+ this.status = response.status;
+ this.ecompRequestId = rejectionObj.ecompRequestId;
+ }
+
+ private getFormattedMessage = (text: string, variables: string[]): string => {
+ // Remove the "Error: " text at the beginning
+ if (text.trim().indexOf('Error:') === 0) {
+ text = text.replace('Error:', '').trim();
+ }
+
+ // mshitrit DE199895 bug fix
let count: number = 0;
- variables.forEach(function (item) {
+ variables.forEach( (item) => {
variables[count] = item ? item.replace('<', '<').replace('>', '>') : '';
count++;
});
// Format the message in case has array to <ul><li>
- text = text.replace(/\[%(\d+)\]/g, function (_, m) {
- let tmp = [];
- let list = variables[--m].split(";");
- list.forEach(function (item) {
- tmp.push("<li>" + item + "</li>");
+ text = text.replace(/\[%(\d+)\]/g, (_, m) => {
+ const tmp = [];
+ const list = variables[--m].split(';');
+ list.forEach((item) => {
+ tmp.push('<li>' + item + '</li>');
});
- return "<ul>" + tmp.join("") + "</ul>";
+ return '<ul>' + tmp.join('') + '</ul>';
});
// Format the message %1 %2
@@ -80,5 +103,5 @@
return text;
- };
-}
\ No newline at end of file
+ }
+}
diff --git a/catalog-ui/src/app/models/service-instance-properties-and-interfaces.ts b/catalog-ui/src/app/models/service-instance-properties-and-interfaces.ts
index 168b0af..41bd184 100644
--- a/catalog-ui/src/app/models/service-instance-properties-and-interfaces.ts
+++ b/catalog-ui/src/app/models/service-instance-properties-and-interfaces.ts
@@ -13,8 +13,7 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-
-import {PropertyModel, InputModel, InterfaceModel} from 'app/models';
+import { PropertyModel, InputModel, InterfaceModel} from 'app/models';
export class ServiceInstanceObject {
id: string;
@@ -23,8 +22,8 @@
inputs: Array<InputModel> = [];
interfaces: Array<InterfaceModel> = [];
- constructor(input?:any) {
- if(input) {
+ constructor(input?: any) {
+ if (input) {
this.id = input.id;
this.name = input.name;
this.properties = input.properties;
diff --git a/catalog-ui/src/app/models/service-instance-properties.ts b/catalog-ui/src/app/models/service-instance-properties.ts
deleted file mode 100644
index 9e9f1cc..0000000
--- a/catalog-ui/src/app/models/service-instance-properties.ts
+++ /dev/null
@@ -1,31 +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.
- */
-
-import {PropertyModel} from 'app/models';
-
-export class ServiceInstanceObject {
- id: string;
- name: string;
- properties: Array<PropertyModel> = [];
-
- constructor(input?:any) {
- if(input) {
- this.id = input.id;
- this.name = input.name;
- this.properties = input.properties;
- }
- }
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/user.ts b/catalog-ui/src/app/models/user.ts
index 0fb5364..7a9bed8 100644
--- a/catalog-ui/src/app/models/user.ts
+++ b/catalog-ui/src/app/models/user.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.
@@ -17,69 +17,68 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-
'use strict';
export enum UserRole {
ADMIN,
- DESIGNER,
- TESTER,
- GOVERNOR,
- OPS
+ DESIGNER
}
+// tslint:disable-next-line:interface-name
export interface IUserManager {
- isInEditMode:boolean;
- filterTerm:string;
+ isInEditMode: boolean;
+ filterTerm: string;
}
+// tslint:disable-next-line:interface-name
export interface IUserProperties extends IUserManager {
- firstName:string;
- lastName:string;
- userId:string;
- email:string;
- role:string;
- tempRole:string;
- lastLoginTime:string;
- status:string;
+ firstName: string;
+ lastName: string;
+ userId: string;
+ email: string;
+ role: string;
+ tempRole: string;
+ lastLoginTime: string;
+ status: string;
}
+// tslint:disable-next-line:interface-name
export interface IUser {
- userInfo:IUserProperties;
- getRole():UserRole;
- getRoleToView():string;
- getName():string;
- getFirstName():string;
- getLastName():string;
+ userInfo: IUserProperties;
+ getRole(): UserRole;
+ getRoleToView(): string;
+ getName(): string;
+ getFirstName(): string;
+ getLastName(): string;
}
export class User implements IUser {
- constructor(public userInfo:IUserProperties) {
+ constructor(public userInfo: IUserProperties) {
}
public getLastName = () => {
return this.userInfo.lastName;
- };
+ }
public getFirstName = () => {
return this.userInfo.firstName;
- };
+ }
public getName = () => {
return this.userInfo.firstName + ' ' + this.userInfo.lastName;
- };
+ }
public getLastLogin = () => {
- if (!this.userInfo.lastLoginTime || this.userInfo.lastLoginTime === "0") {
- return "";
+ if (!this.userInfo.lastLoginTime || this.userInfo.lastLoginTime === '0') {
+ return '';
} else {
return this.userInfo.lastLoginTime;
}
- };
+ }
- public getRole = ():UserRole => {
- let role:UserRole;
+ public getRole = (): UserRole => {
+ let role: UserRole;
switch (UserRole[this.userInfo.role.toUpperCase()]) {
case UserRole.ADMIN:
role = UserRole.ADMIN;
@@ -87,21 +86,12 @@
case UserRole.DESIGNER:
role = UserRole.DESIGNER;
break;
- case UserRole.TESTER:
- role = UserRole.TESTER;
- break;
- case UserRole.GOVERNOR:
- role = UserRole.GOVERNOR;
- break;
- case UserRole.OPS:
- role = UserRole.OPS;
- break;
}
return role;
- };
+ }
- public getRoleToView = ():string => {
- let role:string = this.userInfo.role.toLowerCase().replace('governor', 'governance_Rep');
+ public getRoleToView = (): string => {
+ const role: string = this.userInfo.role.toLowerCase().replace('governor', 'governance_Rep');
return role.charAt(0).toUpperCase() + role.slice(1).replace('_', ' ');
}
}
diff --git a/catalog-ui/src/app/models/validation-config.ts b/catalog-ui/src/app/models/validation-config.ts
index ac15d28..0e594fd 100644
--- a/catalog-ui/src/app/models/validation-config.ts
+++ b/catalog-ui/src/app/models/validation-config.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.
@@ -24,9 +24,16 @@
}
class validationPatterns {
- string: string;
- comment:string;
- integer: string;
+ vendorRelease: RegExp;
+ stringOrEmpty: string;
+ vendorName: RegExp;
+ vendorModelNumber: RegExp;
+ tag: RegExp;
+ contactId: RegExp;
+ componentName: RegExp;
+ string: RegExp;
+ comment:RegExp;
+ integer: RegExp;
}
export class Validations {
@@ -38,3 +45,25 @@
static validation: Validations;
}
+
+export class Validation {
+ componentNameValidationPattern:RegExp;
+ contactIdValidationPattern:RegExp;
+ tagValidationPattern:RegExp;
+ VendorReleaseValidationPattern:RegExp;
+ VendorNameValidationPattern:RegExp;
+ VendorModelNumberValidationPattern:RegExp;
+ commentValidationPattern:RegExp;
+
+ constructor(validationData?:Validations) {
+ if(validationData) {
+ this.commentValidationPattern = validationData.validationPatterns.comment;
+ this.componentNameValidationPattern = validationData.validationPatterns.componentName;
+ this.contactIdValidationPattern = validationData.validationPatterns.contactId;
+ this.tagValidationPattern = validationData.validationPatterns.tag;
+ this.VendorModelNumberValidationPattern = validationData.validationPatterns.vendorModelNumber;
+ this.VendorNameValidationPattern = validationData.validationPatterns.vendorName;
+ this.VendorReleaseValidationPattern = validationData.validationPatterns.vendorRelease;
+ }
+ }
+}
diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts
index 720d29f..23dc3cf 100644
--- a/catalog-ui/src/app/modules/directive-module.ts
+++ b/catalog-ui/src/app/modules/directive-module.ts
@@ -3,7 +3,6 @@
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nokia. 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.
@@ -50,7 +49,10 @@
import {ValidationOnLoadDirective} from "../directives/utils/validation-on-load/validation-on-load";
import {InfoTooltipDirective} from "../directives/info-tooltip/info-tooltip";
import {SdcTabsDirective} from "../directives/sdc-tabs/sdc-tabs-directive";
-import {SdcSingleTabDirective, InnerSdcSingleTabDirective} from "../directives/sdc-tabs/sdc-single-tab/sdc-single-tab-directive";
+import {
+ SdcSingleTabDirective,
+ InnerSdcSingleTabDirective
+} from "../directives/sdc-tabs/sdc-single-tab/sdc-single-tab-directive";
import {ExpandCollapseListHeaderDirective} from "../directives/utils/expand-collapse-list-header/expand-collapse-list-header";
import {JsonExportExcelDirective} from "../directives/export-json-to-excel/export-json-to-excel";
import {TopProgressDirective} from "../directives/layout/top-progress/top-progress";
@@ -61,21 +63,8 @@
import {PropertyRowDirective} from "../directives/inputs-and-properties/properties/property-row-directive";
import {NodesFactory} from "../models/graph/nodes/nodes-factory";
import {LinksFactory} from "../models/graph/graph-links/links-factory";
-import {ImageCreatorService} from "../directives/graphs-v2/image-creator/image-creator.service";
-import {Palette} from "../directives/graphs-v2/palette/palette.directive";
-import {CompositionGraph} from "../directives/graphs-v2/composition-graph/composition-graph.directive";
-import {DeploymentGraph} from "../directives/graphs-v2/deployment-graph/deployment-graph.directive";
-import {CommonGraphUtils} from "../directives/graphs-v2/common/common-graph-utils";
-import {CompositionGraphNodesUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils";
-import {CompositionGraphGeneralUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-general-utils";
-import {CompositionGraphLinkUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-links-utils";
-import {DeploymentGraphGeneralUtils} from "../directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils";
-import {CompositionGraphPaletteUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-palette-utils";
-import {CompositionGraphZoneUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils";
-import {MatchCapabilitiesRequirementsUtils} from "../directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils";
import {CapabilitiesListDirective} from "../directives/capabilities-and-requirements/capability/capabilities-list-directive";
import {RequirementsListDirective} from "../directives/capabilities-and-requirements/requirement/requirements-list-directive";
-import {ServicePathGraphUtils} from "../directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils";
import {PreventDoubleClickDirective} from "../directives/prevent-double-click/prevent-double-click";
let moduleName:string = 'Sdc.Directives';
@@ -139,31 +128,6 @@
// //Util service for Graph
directiveModule.service('NodesFactory', NodesFactory);
directiveModule.service('LinksFactory', LinksFactory);
-directiveModule.service('ImageCreatorService', ImageCreatorService);
-//
-// //composition
-directiveModule.directive('palette', Palette.factory);
-directiveModule.directive('compositionGraph', CompositionGraph.factory);
-
-//
-// //deployment
-directiveModule.directive('deploymentGraph', DeploymentGraph.factory);
-//
-// //Graph Utils - Common
-directiveModule.service('CommonGraphUtils', CommonGraphUtils);
-//
-// //Composition Graph Utils
-directiveModule.service('CompositionGraphNodesUtils', CompositionGraphNodesUtils);
-directiveModule.service('CompositionGraphGeneralUtils', CompositionGraphGeneralUtils);
-directiveModule.service('CompositionGraphLinkUtils', CompositionGraphLinkUtils);
-directiveModule.service('CompositionGraphPaletteUtils', CompositionGraphPaletteUtils);
-directiveModule.service('CompositionGraphZoneUtils', CompositionGraphZoneUtils);
-directiveModule.service('MatchCapabilitiesRequirementsUtils', MatchCapabilitiesRequirementsUtils);
-directiveModule.service('ServicePathGraphUtils', ServicePathGraphUtils);
-
-//
-// //Deployment Graph Utils
-directiveModule.service('DeploymentGraphGeneralUtils', DeploymentGraphGeneralUtils);
//Compoisiton right tab directives
@@ -172,24 +136,34 @@
// *** NG2 Components (downgraded) *** //
-import { downgradeComponent } from "@angular/upgrade/static";
-import { MenuListNg2Component } from "../ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component";
-import { TopNavComponent } from "../ng2/components/layout/top-nav/top-nav.component";
-import { ZoneContainerComponent } from "../ng2/components/ui/canvas-zone/zone-container.component";
-import { ZoneInstanceComponent } from "../ng2/components/ui/canvas-zone/zone-instance/zone-instance.component";
-import { CompositionPanelComponent } from 'app/ng2/pages/composition/panel/panel.component';
-import { PropertiesAssignmentComponent } from "../ng2/pages/properties-assignment/properties-assignment.page.component";
-import { SearchWithAutoCompleteComponent } from "../ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component";
-import { PalettePopupPanelComponent } from "../ng2/components/ui/palette-popup-panel/palette-popup-panel.component";
-import { ServicePathComponent } from '../ng2/components/logic/service-path/service-path.component';
-import { ServicePathSelectorComponent } from '../ng2/components/logic/service-path-selector/service-path-selector.component';
-import { ServiceConsumptionComponent } from '../ng2/components/logic/service-consumption/service-consumption.component';
-import { ServiceDependenciesComponent } from '../ng2/components/logic/service-dependencies/service-dependencies.component';
-import { MultilineEllipsisComponent } from "../ng2/shared/multiline-ellipsis/multiline-ellipsis.component";
+import {downgradeComponent} from "@angular/upgrade/static";
+import {MenuListNg2Component} from "../ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component";
+import {TopNavComponent} from "../ng2/components/layout/top-nav/top-nav.component";
+import {ZoneContainerComponent} from "../ng2/pages/composition/graph/canvas-zone/zone-container.component";
+import {ZoneInstanceComponent} from "../ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component";
+import {CompositionPanelComponent} from 'app/ng2/pages/composition/panel/composition-panel.component';
+import {PropertiesAssignmentComponent} from "../ng2/pages/properties-assignment/properties-assignment.page.component";
+import {SearchWithAutoCompleteComponent} from "../ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component";
+import {PalettePopupPanelComponent} from "../ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component";
+import {ServicePathSelectorComponent} from '../ng2/pages/composition/graph/service-path-selector/service-path-selector.component';
+import {MultilineEllipsisComponent} from "../ng2/shared/multiline-ellipsis/multiline-ellipsis.component";
import { InterfaceOperationComponent } from '../ng2/pages/interface-operation/interface-operation.page.component';
import { PluginFrameComponent } from "../ng2/components/ui/plugin/plugin-frame.component";
-import { TileComponent } from "../ng2/components/ui/tile/tile.component";
-
+import {TileComponent} from "../ng2/components/ui/tile/tile.component";
+import {CompositionPageComponent} from "../ng2/pages/composition/composition-page.component";
+import {CatalogComponent} from "../ng2/pages/catalog/catalog.component";
+import {HomeComponent} from "../ng2/pages/home/home.component";
+import {PluginContextViewPageComponent} from "../ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component";
+import {PluginTabViewPageComponent} from "../ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component";
+import {CompositionGraphComponent} from "../ng2/pages/composition/graph/composition-graph.component";
+import {DeploymentPageComponent} from "../ng2/pages/workspace/deployment/deployment-page.component";
+import {ActivityLogComponent} from "../ng2/pages/workspace/activity-log/activity-log.component";
+import {ToscaArtifactPageComponent} from "../ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component";
+import {InformationArtifactPageComponent} from "../ng2/pages/workspace/information-artifact/information-artifact-page.component";
+import {AttributesComponent} from "../ng2/pages/workspace/attributes/attributes.component";
+import {DeploymentArtifactsPageComponent} from "../ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component";
+import { ReqAndCapabilitiesComponent } from "../ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component";
+import { DistributionComponent } from '../ng2/pages/workspace/disribution/distribution.component';
directiveModule.directive('menuListNg2', downgradeComponent({
component: MenuListNg2Component,
@@ -204,14 +178,14 @@
directiveModule.directive('ng2ZoneContainer', downgradeComponent({
component: ZoneContainerComponent,
- inputs: ['title', 'count', 'type', 'visible', 'minimized'],
+ inputs: ['title', 'count', 'type', 'visible', 'minimized'],
outputs: ['minimize', 'backgroundClick']
}) as angular.IDirectiveFactory);
directiveModule.directive('ng2ZoneInstance', downgradeComponent({
- component: ZoneInstanceComponent,
- inputs: ['zoneInstance', 'isActive', 'activeInstanceMode', 'defaultIconText', 'isViewOnly', 'hidden', 'forceSave'],
- outputs: ['modeChange', 'tagHandleClick', 'assignmentSaveStart', 'assignmentSaveComplete']
+ component: ZoneInstanceComponent,
+ inputs: ['zoneInstance', 'isActive', 'activeInstanceMode', 'defaultIconText', 'isViewOnly', 'hidden', 'forceSave'],
+ outputs: ['modeChange', 'tagHandleClick', 'assignmentSaveStart', 'assignmentSaveComplete']
}) as angular.IDirectiveFactory);
directiveModule.directive('ng2CompositionPanel', downgradeComponent({
@@ -223,6 +197,26 @@
component: PropertiesAssignmentComponent
}) as angular.IDirectiveFactory);
+directiveModule.directive('compositionPage', downgradeComponent({
+ component: CompositionPageComponent
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('activityLog', downgradeComponent({
+ component: ActivityLogComponent
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('distribution', downgradeComponent({
+ component: DistributionComponent
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('attributes', downgradeComponent({
+ component: AttributesComponent
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('reqAndCapabilities', downgradeComponent({
+ component: ReqAndCapabilitiesComponent
+}) as angular.IDirectiveFactory);
+
directiveModule.directive('ng2SearchWithAutocomplete', downgradeComponent({
component: SearchWithAutoCompleteComponent,
inputs: ['searchPlaceholder', 'searchBarClass', 'autoCompleteValues'],
@@ -235,31 +229,13 @@
outputs: []
}) as angular.IDirectiveFactory);
-directiveModule.directive('ng2ServicePath', downgradeComponent({
- component: ServicePathComponent,
- inputs: ['onCreate', 'service', 'isViewOnly'],
- outputs: []
-}) as angular.IDirectiveFactory);
-
directiveModule.directive('ng2ServicePathSelector', downgradeComponent({
component: ServicePathSelectorComponent,
inputs: ['drawPath', 'deletePaths', 'service', 'selectedPathId'],
outputs: []
}) as angular.IDirectiveFactory);
-directiveModule.directive('ng2ServiceConsumption', downgradeComponent({
- component: ServiceConsumptionComponent,
- inputs: ['parentService', 'selectedService', 'selectedServiceInstanceId', 'instancesMappedList', 'parentServiceInputs', 'instancesCapabilitiesMap', 'readonly'],
- outputs: []
-}) as angular.IDirectiveFactory);
-
-directiveModule.directive('ng2ServiceDependencies', downgradeComponent({
- component: ServiceDependenciesComponent,
- inputs: ['compositeService', 'currentServiceInstance', 'selectedInstanceProperties', 'selectedInstanceSiblings', 'selectedInstanceConstraints', 'readonly'],
- outputs: ['updateRulesListEvent', 'loadRulesListEvent','dependencyStatus']
-}) as angular.IDirectiveFactory);
-
-directiveModule.directive('interfaceOperation', downgradeComponent({
+directiveModule.directive('ng2InterfaceOperation', downgradeComponent({
component: InterfaceOperationComponent,
inputs: ['component', 'readonly'],
outputs: []
@@ -277,8 +253,60 @@
outputs: ['onTileClick']
}) as angular.IDirectiveFactory);
-directiveModule.directive('pluginFrame', downgradeComponent( {
+directiveModule.directive('pluginFrame', downgradeComponent({
component: PluginFrameComponent,
inputs: ['plugin', 'queryParams'],
outputs: ['onLoadingDone']
}) as angular.IDirectiveFactory);
+
+directiveModule.directive('catalogPage', downgradeComponent({
+ component: CatalogComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('homePage', downgradeComponent({
+ component: HomeComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('pluginContextView', downgradeComponent({
+ component: PluginContextViewPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('pluginTabView', downgradeComponent({
+ component: PluginTabViewPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('compositionGraph', downgradeComponent({
+ component: CompositionGraphComponent,
+ inputs: ['topologyTemplate', 'isViewOnly'],
+ outputs: []
+}) as angular.IDirectiveFactory);
+directiveModule.directive('toscaArtifactPage', downgradeComponent({
+ component: ToscaArtifactPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('deploymentPage', downgradeComponent({
+ component: DeploymentPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
+directiveModule.directive('informationArtifactPage', downgradeComponent({
+ component: InformationArtifactPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
+directiveModule.directive('deploymentArtifactPage', downgradeComponent({
+ component: DeploymentArtifactsPageComponent,
+ inputs: [],
+ outputs: []
+}) as angular.IDirectiveFactory);
\ No newline at end of file
diff --git a/catalog-ui/src/app/modules/service-module.ts b/catalog-ui/src/app/modules/service-module.ts
index 7240682..e2f4f16 100644
--- a/catalog-ui/src/app/modules/service-module.ts
+++ b/catalog-ui/src/app/modules/service-module.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.
@@ -18,104 +18,112 @@
* ============LICENSE_END=========================================================
*/
-import {ConfigurationUiService} from "../services/configuration-ui-service";
-import {CookieService} from "../services/cookie-service";
-import {EntityService} from "../services/entity-service";
-import {AvailableIconsService} from "../services/available-icons-service";
-import {UrlToBase64Service} from "../services/url-tobase64-service";
-import {CacheService} from "../services/cache-service";
-import {HeaderInterceptor} from "../services/header-interceptor";
-import {HttpErrorInterceptor} from "../services/http-error-interceptor";
-import {SharingService} from "../services/sharing-service";
-import {SdcVersionService} from "../services/sdc-version-service";
-import {ActivityLogService} from "../services/activity-log-service";
-import {OnboardingService} from "../services/onboarding-service";
-import {EcompHeaderService} from "../services/ecomp-service";
-import {DataTypesService} from "../services/data-types-service";
-import {ComponentService} from "../services/components/component-service";
-import {ServiceService} from "../services/components/service-service";
-import {ResourceService} from "../services/components/resource-service";
-import {LeftPaletteLoaderService} from "../services/components/utils/composition-left-palette-service";
-import {EventListenerService} from "../services/event-listener-service";
-import {ProgressService} from "../services/progress-service";
-import {ArtifactsUtils} from "../utils/artifacts-utils";
-import {FileUtils} from "../utils/file-utils";
-import {ValidationUtils} from "../utils/validation-utils";
-import {AngularJSBridge} from "../services/angular-js-bridge-service";
-import {LoaderService} from "../services/loader-service";
-import {CategoryResourceService} from "../services/category-resource-service";
-import {downgradeInjectable} from "@angular/upgrade/static";
-import {ModalService} from "../ng2/services/modal.service";
-import {SdcUiComponents} from "sdc-ui/lib/angular";
-import {ComponentServiceNg2} from "../ng2/services/component-services/component.service";
-import {ServiceServiceNg2} from "../ng2/services/component-services/service.service";
-import {ComponentServiceFactoryNg2} from "../ng2/services/component-services/component.service.factory";
-import {ConnectionWizardService} from "../ng2/pages/connection-wizard/connection-wizard.service";
-import {ComponentInstanceServiceNg2} from "../ng2/services/component-instance-services/component-instance.service";
-import {UserService as UserServiceNg2} from "../ng2/services/user.service";
-import {PoliciesService as PoliciesServiceNg2} from "../ng2/services/policies.service";
-import {GroupsService as GroupsServiceNg2} from "../ng2/services/groups.service";
-import {PluginsService} from "../ng2/services/plugins.service";
-import {EventBusService} from "../ng2/services/event-bus.service";
-import {DynamicComponentService} from "app/ng2/services/dynamic-component.service";
-import {AutomatedUpgradeService} from "../ng2/pages/automated-upgrade/automated-upgrade.service";
-import {ArchiveService as ArchiveServiceNg2} from "app/ng2/services/archive.service";
+import { downgradeInjectable } from '@angular/upgrade/static';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { CatalogService } from 'app/ng2/services/catalog.service';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { DynamicComponentService } from 'app/ng2/services/dynamic-component.service';
import {GabService as GabServiceNg2} from "app/ng2/services/gab.service";
-import {ComponentFactory} from "app/utils/component-factory";
-import {ToscaTypesServiceNg2} from "app/ng2/services/tosca-types.service";
+import { ComponentFactory } from 'app/utils/component-factory';
+import { SdcUiServices } from 'onap-ui-angular';
+import { NodesFactory } from '../models/graph/nodes/nodes-factory';
+import { ImportVSPService } from '../ng2/components/modals/onboarding-modal/import-vsp.service';
+import { AutomatedUpgradeService } from '../ng2/pages/automated-upgrade/automated-upgrade.service';
+import { ConnectionWizardService } from '../ng2/pages/composition/graph/connection-wizard/connection-wizard.service';
+import { WorkspaceNg1BridgeService } from '../ng2/pages/workspace/workspace-ng1-bridge-service';
+import { WorkspaceService } from '../ng2/pages/workspace/workspace.service';
+import { AuthenticationService as AuthenticationServiceNg2 } from '../ng2/services/authentication.service';
+import { CacheService } from '../ng2/services/cache.service';
+import { ComponentInstanceServiceNg2 } from '../ng2/services/component-instance-services/component-instance.service';
+import { ComponentServiceNg2 } from '../ng2/services/component-services/component.service';
+import { ComponentServiceFactoryNg2 } from '../ng2/services/component-services/component.service.factory';
+import { ServiceServiceNg2 } from '../ng2/services/component-services/service.service';
+import { EventBusService } from '../ng2/services/event-bus.service';
+import { GroupsService as GroupsServiceNg2 } from '../ng2/services/groups.service';
+import { HomeService } from '../ng2/services/home.service';
+import { ModalService } from '../ng2/services/modal.service';
+import { OnboardingService } from '../ng2/services/onboarding.service';
+import { PluginsService } from '../ng2/services/plugins.service';
+import { PoliciesService as PoliciesServiceNg2 } from '../ng2/services/policies.service';
+import { SharingService } from '../ng2/services/sharing.service';
+import { ToscaTypesServiceNg2 } from '../ng2/services/tosca-types.service';
+import { UserService as UserServiceNg2 } from '../ng2/services/user.service';
+import { AngularJSBridge } from '../services/angular-js-bridge-service';
+import { AvailableIconsService } from '../services/available-icons-service';
+import { CategoryResourceService } from '../services/category-resource-service';
+import { ComponentService } from '../services/components/component-service';
+import { ResourceService } from '../services/components/resource-service';
+import { ServiceService } from '../services/components/service-service';
+import { LeftPaletteLoaderService } from '../services/components/utils/composition-left-palette-service';
+import { ConfigurationUiService } from '../services/configuration-ui-service';
+import { CookieService } from '../services/cookie-service';
+import { DataTypesService } from '../services/data-types-service';
+import { EcompHeaderService } from '../services/ecomp-service';
+import { EventListenerService } from '../services/event-listener-service';
+import { HeaderInterceptor } from '../services/header-interceptor';
+import { LoaderService } from '../services/loader-service';
+import { ProgressService } from '../services/progress-service';
+import { SdcVersionService } from '../services/sdc-version-service';
+import { UrlToBase64Service } from '../services/url-tobase64-service';
+import { FileUtils } from '../utils/file-utils';
+import { ValidationUtils } from '../utils/validation-utils';
+import {ReqAndCapabilitiesService} from "../ng2/pages/workspace/req-and-capabilities/req-and-capabilities.service";
-let moduleName:string = 'Sdc.Services';
-let serviceModule:ng.IModule = angular.module(moduleName, []);
+const moduleName: string = 'Sdc.Services';
+const serviceModule: ng.IModule = angular.module(moduleName, []);
serviceModule.service('Sdc.Services.ConfigurationUiService', ConfigurationUiService);
serviceModule.service('Sdc.Services.CookieService', CookieService);
serviceModule.service('Sdc.Services.ComponentFactory', ComponentFactory); // Why you need to declare it again, already done in utils.ts
-serviceModule.service('Sdc.Services.EntityService', EntityService);
serviceModule.service('Sdc.Services.AvailableIconsService', AvailableIconsService);
serviceModule.service('Sdc.Services.UrlToBase64Service', UrlToBase64Service);
-serviceModule.service('Sdc.Services.CacheService', CacheService);
serviceModule.service('Sdc.Services.HeaderInterceptor', HeaderInterceptor);
-serviceModule.service('Sdc.Services.HttpErrorInterceptor', HttpErrorInterceptor);
-serviceModule.service('Sdc.Services.SharingService', SharingService);
serviceModule.service('Sdc.Services.SdcVersionService', SdcVersionService);
-serviceModule.service('Sdc.Services.ActivityLogService', ActivityLogService);
-serviceModule.service('Sdc.Services.OnboardingService', OnboardingService);
serviceModule.service('Sdc.Services.EcompHeaderService', EcompHeaderService);
serviceModule.service('Sdc.Services.DataTypesService', DataTypesService);
-//Components Services
+// Components Services
serviceModule.service('Sdc.Services.Components.ComponentService', ComponentService);
-serviceModule.service('Sdc.Services.Components.ServiceService',ServiceService);
+serviceModule.service('Sdc.Services.Components.ServiceService', ServiceService);
serviceModule.service('Sdc.Services.Components.ResourceService', ResourceService);
serviceModule.service('LeftPaletteLoaderService', LeftPaletteLoaderService);
-serviceModule.service('EventListenerService', EventListenerService);
serviceModule.service('Sdc.Services.ProgressService', ProgressService);
-//Utils
-serviceModule.service('ArtifactsUtils', ArtifactsUtils);
+// Utils
serviceModule.service('FileUtils', FileUtils);
serviceModule.service('ValidationUtils', ValidationUtils);
-
-serviceModule.service('AngularJSBridge',AngularJSBridge);
+serviceModule.service('AngularJSBridge', AngularJSBridge);
serviceModule.service('LoaderService', LoaderService);
-
serviceModule.factory('Sdc.Services.CategoryResourceService', CategoryResourceService.getResource);
// Angular2 upgraded services - This is in order to use the service in angular1 till we finish remove all angular1 code
+serviceModule.service('Sdc.Services.SharingService', downgradeInjectable(SharingService));
+serviceModule.service('Sdc.Services.CacheService', downgradeInjectable(CacheService));
serviceModule.factory('ComponentServiceNg2', downgradeInjectable(ComponentServiceNg2));
+serviceModule.factory('TopologyTemplateService', downgradeInjectable(TopologyTemplateService));
+serviceModule.factory('WorkspaceNg1BridgeService', downgradeInjectable(WorkspaceNg1BridgeService));
+serviceModule.factory('workspaceService', downgradeInjectable(WorkspaceService));
serviceModule.factory('ComponentServiceFactoryNg2', downgradeInjectable(ComponentServiceFactoryNg2));
serviceModule.factory('ServiceServiceNg2', downgradeInjectable(ServiceServiceNg2));
serviceModule.factory('ModalServiceNg2', downgradeInjectable(ModalService));
-serviceModule.factory('ModalServiceSdcUI', downgradeInjectable(SdcUiComponents.ModalService));
+serviceModule.factory('ModalServiceSdcUI', downgradeInjectable(SdcUiServices.ModalService));
serviceModule.factory('ConnectionWizardServiceNg2', downgradeInjectable(ConnectionWizardService));
serviceModule.factory('ComponentInstanceServiceNg2', downgradeInjectable(ComponentInstanceServiceNg2));
serviceModule.factory('UserServiceNg2', downgradeInjectable(UserServiceNg2));
+serviceModule.factory('AuthenticationServiceNg2', downgradeInjectable(AuthenticationServiceNg2));
serviceModule.factory('PoliciesServiceNg2', downgradeInjectable(PoliciesServiceNg2));
serviceModule.factory('GroupsServiceNg2', downgradeInjectable(GroupsServiceNg2));
serviceModule.factory('PluginsService', downgradeInjectable(PluginsService));
serviceModule.factory('EventBusService', downgradeInjectable(EventBusService));
serviceModule.factory('DynamicComponentService', downgradeInjectable(DynamicComponentService));
-serviceModule.factory('ArchiveServiceNg2', downgradeInjectable(ArchiveServiceNg2));
+serviceModule.factory('HomeService', downgradeInjectable(HomeService));
+serviceModule.factory('CatalogService', downgradeInjectable(CatalogService));
serviceModule.factory('GabServiceNg2', downgradeInjectable(GabServiceNg2));
serviceModule.factory('AutomatedUpgradeService', downgradeInjectable(AutomatedUpgradeService));
serviceModule.factory('ToscaTypesServiceNg2', downgradeInjectable(ToscaTypesServiceNg2));
+serviceModule.factory('EventListenerService', downgradeInjectable(EventListenerService));
+serviceModule.factory('CompositionService', downgradeInjectable(CompositionService));
+serviceModule.factory('ReqAndCapabilitiesService', downgradeInjectable(ReqAndCapabilitiesService));
+serviceModule.factory('NodesFactory', downgradeInjectable(NodesFactory));
+serviceModule.service('OnboardingService', downgradeInjectable(OnboardingService));
+serviceModule.service('ImportVSPService', downgradeInjectable(ImportVSPService));
diff --git a/catalog-ui/src/app/modules/view-model-module.ts b/catalog-ui/src/app/modules/view-model-module.ts
index c633201..5b8fc59 100644
--- a/catalog-ui/src/app/modules/view-model-module.ts
+++ b/catalog-ui/src/app/modules/view-model-module.ts
@@ -3,7 +3,6 @@
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nokia. 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.
@@ -20,127 +19,44 @@
*/
import {AddCategoryModalViewModel} from "../view-models/admin-dashboard/add-category-modal/add-category-modal-view-model";
-import {DashboardViewModel} from "../view-models/dashboard/dashboard-view-model";
import {WorkspaceViewModel} from "../view-models/workspace/workspace-view-model";
-import {CompositionViewModel} from "../view-models/workspace/tabs/composition/composition-view-model";
-import {DetailsViewModel} from "../view-models/workspace/tabs/composition/tabs/details/details-view-model";
-import {ResourceArtifactsViewModel} from "../view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model";
-import {ServiceConsumptionViewModel} from "../view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model";
-import {ServiceDependenciesViewModel} from "../view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view-model";
import {PropertyFormBaseView} from "../view-models/forms/property-forms/base-property-form/property-form-base-model";
import {PropertyFormViewModel} from "../view-models/forms/property-forms/component-property-form/property-form-view-model";
import {ModulePropertyView} from "../view-models/forms/property-forms/module-property-modal/module-property-model";
-import {ArtifactResourceFormViewModel} from "../view-models/forms/artifact-form/artifact-form-view-model";
import {SelectDataTypeViewModel} from "../view-models/forms/property-forms/select-datatype-modal/select-datatype-modal-view-model";
-import {AttributeFormViewModel} from "../view-models/forms/attribute-form/attribute-from-view-model";
-import {ResourcePropertiesViewModel} from "../view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model";
-import {CatalogViewModel} from "../view-models/catalog/catalog-view-model";
import {OnboardVendorViewModel} from "../view-models/onboard-vendor/onboard-vendor-view-model";
-import {DistributionViewModel} from "../view-models/workspace/tabs/distribution/distribution-view-model";
-import {SupportViewModel} from "../view-models/support/support-view-model";
-import {ConfirmationModalViewModel} from "../view-models/modals/confirmation-modal/confirmation-modal-view-model";
-import {EmailModalViewModel} from "../view-models/modals/email-modal/email-modal-view-model";
-import {MessageModalViewModel} from "../view-models/modals/message-modal/message-base-modal-model";
-import {ServerMessageModalViewModel} from "../view-models/modals/message-modal/message-server-modal/server-message-modal-view-model";
-import {ClientMessageModalViewModel} from "../view-models/modals/message-modal/message-client-modal/client-message-modal-view-model";
import {ErrorViewModel} from "../view-models/modals/error-modal/error-view-model";
-import {RelationsViewModel} from "../view-models/workspace/tabs/composition/tabs/relations/relations-view-model";
-import {ResourceInstanceNameViewModel} from "../view-models/forms/resource-instance-name-form/resource-instance-name-model";
-import {WelcomeViewModel} from "../view-models/welcome/welcome-view";
-import {PreLoadingViewModel} from "../view-models/preloading/preloading-view";
-import {TutorialEndViewModel} from "../view-models/tutorial-end/tutorial-end";
import {AdminDashboardViewModel} from "../view-models/admin-dashboard/admin-dashboard-view-model";
-import {EnvParametersFormViewModel} from "../view-models/forms/env-parameters-form/env-parameters-form";
-import {StructureViewModel} from "../view-models/workspace/tabs/composition/tabs/structure/structure-view";
import {UserManagementViewModel} from "../view-models/admin-dashboard/user-management/user-management-view-model";
import {CategoryManagementViewModel} from "../view-models/admin-dashboard/category-management/category-management-view-model";
-
-import {OnboardingModalViewModel} from "../view-models/modals/onboarding-modal/onboarding-modal-view-model";
-import {DistributionStatusModalViewModel} from "../view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model";
import {DcaeAppViewModel} from "../view-models/dcae-app/dcae-app-view-model";
import {GeneralViewModel} from "../view-models/workspace/tabs/general/general-view-model";
import {IconsModalViewModel} from "../view-models/modals/icons-modal/icons-modal-view";
-import {DeploymentArtifactsViewModel} from "../view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model";
-import {InformationArtifactsViewModel} from "../view-models/workspace/tabs/information-artifacts/information-artifacts-view-model";
-import {ToscaArtifactsViewModel} from "../view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model";
import {PropertiesViewModel} from "../view-models/workspace/tabs/properties/properties-view-model";
-import {AttributesViewModel} from "../view-models/workspace/tabs/attributes/attributes-view-model";
-import {ActivityLogViewModel} from "../view-models/workspace/tabs/activity-log/activity-log";
import {ManagementWorkflowViewModel} from "../view-models/workspace/tabs/management-workflow/management-workflow-view-model";
import {InterfaceOperationViewModel} from "../view-models/workspace/tabs/interface-operation/interface-operation-view-model";
import {NetworkCallFlowViewModel} from "../view-models/workspace/tabs/network-call-flow/network-call-flow-view-model";
-import {DeploymentViewModel} from "../view-models/workspace/tabs/deployment/deployment-view-model";
-import {ReqAndCapabilitiesViewModel} from "../view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-view-model";
-import {InputFormViewModel} from "../view-models/forms/input-form/input-form-view-modal";
-import {HierarchyViewModel} from "../view-models/tabs/hierarchy/hierarchy-view-model";
-import {ConformanceLevelModalViewModel} from "../view-models/modals/conformance-level-modal/conformance-level-modal-view-model";
-import {PluginsTabViewModel} from "../view-models/plugins/plugins-tab-view-model";
-import {PluginsContextViewModel} from "../view-models/workspace/tabs/plugins/plugins-context-view-model";
let moduleName:string = 'Sdc.ViewModels';
let viewModelModule:ng.IModule = angular.module(moduleName, []);
viewModelModule
- .controller(moduleName + '.DashboardViewModel', DashboardViewModel)
-
- .controller(moduleName + '.DetailsViewModel', DetailsViewModel)
- .controller(moduleName + '.ResourceArtifactsViewModel', ResourceArtifactsViewModel)
- .controller(moduleName + '.ServiceConsumptionViewModel', ServiceConsumptionViewModel)
- .controller(moduleName + '.ServiceDependenciesViewModel', ServiceDependenciesViewModel)
.controller(moduleName + '.PropertyFormBaseView', PropertyFormBaseView)
.controller(moduleName + '.PropertyFormViewModel', PropertyFormViewModel)
.controller(moduleName + '.ModulePropertyView', ModulePropertyView)
.controller(moduleName + '.SelectDataTypeViewModel', SelectDataTypeViewModel)
- .controller(moduleName + '.ArtifactResourceFormViewModel', ArtifactResourceFormViewModel)
- .controller(moduleName + '.AttributeFormViewModel', AttributeFormViewModel)
- .controller(moduleName + '.ResourcePropertiesViewModel', ResourcePropertiesViewModel)
- .controller(moduleName + '.CatalogViewModel', CatalogViewModel)
.controller(moduleName + '.OnboardVendorViewModel', OnboardVendorViewModel)
- .controller(moduleName + '.DistributionViewModel', DistributionViewModel)
- .controller(moduleName + '.SupportViewModel', SupportViewModel)
- .controller(moduleName + '.ConfirmationModalViewModel', ConfirmationModalViewModel)
- .controller(moduleName + '.EmailModalViewModel', EmailModalViewModel)
- .controller(moduleName + '.MessageModalViewModel', MessageModalViewModel)
- .controller(moduleName + '.ServerMessageModalViewModel', ServerMessageModalViewModel)
- .controller(moduleName + '.ClientMessageModalViewModel', ClientMessageModalViewModel)
.controller(moduleName + '.ErrorViewModel', ErrorViewModel)
- .controller(moduleName + '.RelationsViewModel', RelationsViewModel)
- .controller(moduleName + '.ResourceInstanceNameViewModel', ResourceInstanceNameViewModel)
- .controller(moduleName + '.WelcomeViewModel', WelcomeViewModel)
- .controller(moduleName + '.PreLoadingViewModel', PreLoadingViewModel)
- .controller(moduleName + '.TutorialEndViewModel', TutorialEndViewModel)
.controller(moduleName + '.AdminDashboardViewModel', AdminDashboardViewModel)
- .controller(moduleName + '.EnvParametersFormViewModel', EnvParametersFormViewModel)
- .controller(moduleName + '.StructureViewModel', StructureViewModel)
.controller(moduleName + '.AddCategoryModalViewModel', AddCategoryModalViewModel)
.controller(moduleName + '.UserManagementViewModel', UserManagementViewModel)
.controller(moduleName + '.CategoryManagementViewModel', CategoryManagementViewModel)
- .controller(moduleName + '.OnboardingModalViewModel', OnboardingModalViewModel)
.controller(moduleName + '.IconsModalViewModel', IconsModalViewModel)
- .controller(moduleName + '.DistributionStatusModalViewModel', DistributionStatusModalViewModel)
.controller(moduleName + '.DcaeAppViewModel', DcaeAppViewModel)
//
// //NEW
.controller(moduleName + '.WorkspaceViewModel', WorkspaceViewModel)
- .controller(moduleName + '.ConformanceLevelModalViewModel', ConformanceLevelModalViewModel)
- .controller(moduleName + '.CompositionViewModel', CompositionViewModel)
.controller(moduleName + '.GeneralViewModel', GeneralViewModel)
- .controller(moduleName + '.DeploymentArtifactsViewModel', DeploymentArtifactsViewModel)
- .controller(moduleName + '.InformationArtifactsViewModel', InformationArtifactsViewModel)
- .controller(moduleName + '.ToscaArtifactsViewModel', ToscaArtifactsViewModel)
.controller(moduleName + '.PropertiesViewModel', PropertiesViewModel)
- .controller(moduleName + '.AttributesViewModel', AttributesViewModel)
- .controller(moduleName + '.ActivityLogViewModel', ActivityLogViewModel)
.controller(moduleName + '.ManagementWorkflowViewModel', ManagementWorkflowViewModel)
.controller(moduleName + '.InterfaceOperationViewModel', InterfaceOperationViewModel)
- .controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel)
- .controller(moduleName + '.DeploymentViewModel', DeploymentViewModel)
- .controller(moduleName + '.ReqAndCapabilitiesViewModel', ReqAndCapabilitiesViewModel)
- .controller(moduleName + '.InputFormViewModel', InputFormViewModel)
- .controller(moduleName + '.PluginsTabViewModel', PluginsTabViewModel)
- .controller(moduleName + '.PluginsContextViewModel', PluginsContextViewModel)
- //
- // //TABS
- .controller(moduleName + '.HierarchyViewModel', HierarchyViewModel);
-
-// NG2
-//.controller(moduleName + '.NG2Example', downgradeComponent({component: NG2Example2Component}) );
+ .controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel);
diff --git a/catalog-ui/src/app/ng2/app.component.css b/catalog-ui/src/app/ng2/app.component.css
deleted file mode 100644
index e69de29..0000000
--- a/catalog-ui/src/app/ng2/app.component.css
+++ /dev/null
diff --git a/catalog-ui/src/app/ng2/app.component.html b/catalog-ui/src/app/ng2/app.component.html
index c98da88..c66c360 100644
--- a/catalog-ui/src/app/ng2/app.component.html
+++ b/catalog-ui/src/app/ng2/app.component.html
@@ -13,11 +13,5 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
-<!--<nav>
- <app-navbar></app-navbar>
-</nav>
-<main>
- <router-outlet></router-outlet>
-</main>-->
\ No newline at end of file
+
+<sdc-loader global="true" name="general" testId="loader"></sdc-loader>
diff --git a/catalog-ui/src/app/ng2/app.component.ts b/catalog-ui/src/app/ng2/app.component.ts
index cb10581..06139ca 100644
--- a/catalog-ui/src/app/ng2/app.component.ts
+++ b/catalog-ui/src/app/ng2/app.component.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.
@@ -17,18 +17,16 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-
-import { Component, Inject, ViewContainerRef } from '@angular/core';
+import { Component, ViewContainerRef} from '@angular/core';
import { AuthenticationService } from './services/authentication.service';
@Component({
selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
+ templateUrl: './app.component.html'
})
export class AppComponent {
- constructor(auth:AuthenticationService, public viewContainerRef:ViewContainerRef){
+ constructor(auth: AuthenticationService, public viewContainerRef: ViewContainerRef){
}
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index b541beb..3f43feb 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -3,7 +3,6 @@
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nokia. 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.
@@ -19,6 +18,7 @@
* ============LICENSE_END=========================================================
*/
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { FormsModule } from '@angular/forms';
@@ -26,84 +26,110 @@
import { AppComponent } from './app.component';
import { UpgradeAdapter } from '@angular/upgrade';
import { UpgradeModule } from '@angular/upgrade/static';
-import { SdcUiComponentsModule, SdcUiComponents } from "sdc-ui/lib/angular";
+import { SdcUiComponentsModule, SdcUiComponents } from 'onap-ui-angular';
import { PropertiesAssignmentModule } from './pages/properties-assignment/properties-assignment.module';
-import { PropertyCreatorModule } from './pages/properties-assignment/property-creator/property-creator.module';
import {
- DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, StateServiceFactory,
- StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider, ScopeServiceFactory,
+ DataTypesServiceProvider, CookieServiceProvider, StateServiceFactory,
+ StateParamsServiceFactory, ScopeServiceFactory,
NotificationServiceProvider, ComponentFactoryProvider
-} from "./utils/ng1-upgraded-provider";
-import { ConfigService } from "./services/config.service";
-import { HttpModule } from '@angular/http';
-import { HttpService } from './services/http.service';
+} from './utils/ng1-upgraded-provider';
+import { ConfigService } from './services/config.service';
import { AuthenticationService } from './services/authentication.service';
-import { Cookie2Service } from "./services/cookie.service";
-import { ComponentServiceNg2 } from "./services/component-services/component.service";
-import { ComponentServiceFactoryNg2 } from "./services/component-services/component.service.factory";
-import { ServiceServiceNg2 } from "./services/component-services/service.service";
-import { ComponentInstanceServiceNg2 } from "./services/component-instance-services/component-instance.service";
-import { WorkflowServiceNg2 } from './services/workflow.service';
-import {ToscaTypesServiceNg2} from "./services/tosca-types.service";
-import { ModalService } from "./services/modal.service";
-import { UiElementsModule } from "./components/ui/ui-elements.module";
-import { ConnectionWizardModule } from "./pages/connection-wizard/connection-wizard.module";
-import { InterfaceOperationModule } from "./pages/interface-operation/interface-operation.module";
-import { OperationCreatorModule } from "./pages/interface-operation/operation-creator/operation-creator.module";
-import { LayoutModule } from "./components/layout/layout.module";
-import { UserService } from "./services/user.service";
-import { DynamicComponentService } from "./services/dynamic-component.service";
-import { SdcConfig } from "./config/sdc-config.config";
-import { SdcMenu } from "./config/sdc-menu.config";
-import { TranslateModule } from "./shared/translator/translate.module";
-import { TranslationServiceConfig } from "./config/translation.service.config";
-import { MultilineEllipsisModule } from "./shared/multiline-ellipsis/multiline-ellipsis.module";
-import { ServicePathCreatorModule } from './pages/service-path-creator/service-path-creator.module';
-import { ServicePathsListModule } from './pages/service-paths-list/service-paths-list.module';
-import { ServicePathModule } from 'app/ng2/components/logic/service-path/service-path.module';
-import { ServicePathSelectorModule } from 'app/ng2/components/logic/service-path-selector/service-path-selector.module';
-import { ServiceConsumptionModule } from 'app/ng2/components/logic/service-consumption/service-consumption.module';
-import { ServiceConsumptionCreatorModule } from './pages/service-consumption-editor/service-consumption-editor.module';
-import {ServiceDependenciesModule} from 'app/ng2/components/logic/service-dependencies/service-dependencies.module';
-import {ServiceDependenciesEditorModule} from './pages/service-dependencies-editor/service-dependencies-editor.module';
-import { CompositionPanelModule } from 'app/ng2/pages/composition/panel/panel.module';
-import { WindowRef } from "./services/window.service";
-import {ArchiveService} from "./services/archive.service";
+import { Cookie2Service } from './services/cookie.service';
+import { ComponentServiceNg2 } from './services/component-services/component.service';
+import { ComponentServiceFactoryNg2 } from './services/component-services/component.service.factory';
+import { ServiceServiceNg2 } from './services/component-services/service.service';
+import { ComponentInstanceServiceNg2 } from './services/component-instance-services/component-instance.service';
+import { ModalService } from './services/modal.service';
+import { UiElementsModule } from './components/ui/ui-elements.module';
+import { ConnectionWizardModule } from './pages/composition/graph/connection-wizard/connection-wizard.module';
+import { InterfaceOperationModule } from './pages/interface-operation/interface-operation.module';
+import { OperationCreatorModule } from './pages/interface-operation/operation-creator/operation-creator.module';
+import { LayoutModule } from './components/layout/layout.module';
+import { UserService } from './services/user.service';
+import { DynamicComponentService } from './services/dynamic-component.service';
+import { SdcConfig } from './config/sdc-config.config';
+import { SdcMenu } from './config/sdc-menu.config';
+import { TranslateModule } from './shared/translator/translate.module';
+import { TranslationServiceConfig } from './config/translation.service.config';
+import { MultilineEllipsisModule } from './shared/multiline-ellipsis/multiline-ellipsis.module';
+import { ServicePathCreatorModule } from './pages/composition/graph/service-path-creator/service-path-creator.module';
+import { ServicePathsListModule } from './pages/composition/graph/service-paths-list/service-paths-list.module';
+import { ServicePathSelectorModule } from 'app/ng2/pages/composition/graph/service-path-selector/service-path-selector.module';
+import { CompositionPanelModule } from 'app/ng2/pages/composition/panel/composition-panel.module';
+import { CatalogModule } from './pages/catalog/catalog.module';
+import { HomeModule } from './pages/home/home.module';
+import { WindowRef } from './services/window.service';
+import { CatalogService } from './services/catalog.service';
import { ModalsHandlerProvider } from './utils/ng1-upgraded-provider';
-import {PluginFrameModule} from "./components/ui/plugin/plugin-frame.module";
-import {PluginsService} from "./services/plugins.service";
-import {EventBusService} from "./services/event-bus.service";
-import {GroupsService} from "./services/groups.service";
-import {PoliciesService} from "./services/policies.service";
-import {AutomatedUpgradeService} from "./pages/automated-upgrade/automated-upgrade.service";
-import {AutomatedUpgradeModule} from "./pages/automated-upgrade/automated-upgrade.module";
-import {RequirementsEditorModule} from "./pages/req-and-capabilities-editor/requirements-editor/requirements-editor.module"
-import {CapabilitiesEditorModule} from "./pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module"
-import {GenericArtifactBrowserModule} from "./components/logic/generic-artifact-browser/generic-artifact-browser.module";
-import {GabService} from "./services/gab.service";
-import {DeclareListModule} from "./pages/properties-assignment/declare-list/declare-list.module"
+import { PluginFrameModule } from './components/ui/plugin/plugin-frame.module';
+import { PluginsService } from './services/plugins.service';
+import { EventBusService } from './services/event-bus.service';
+import { GroupsService } from './services/groups.service';
+import { PoliciesService } from './services/policies.service';
+import { AutomatedUpgradeService } from './pages/automated-upgrade/automated-upgrade.service';
+import { AutomatedUpgradeModule } from './pages/automated-upgrade/automated-upgrade.module';
+import {WorkspaceModule} from './pages/workspace/workspace.module';
+import { ModalsModule } from './components/modals/modals.module';
+import { SharingService, CacheService, HomeService } from 'app/services-ng2';
+import { IUserProperties } from 'app/models';
+import { PluginsModule } from './pages/plugins/plugins-module';
+import {WorkspaceNg1BridgeService} from './pages/workspace/workspace-ng1-bridge-service';
+import {NgxsModule} from '@ngxs/store';
+import {NgxsLoggerPluginModule} from '@ngxs/logger-plugin';
+import {NgxsReduxDevtoolsPluginModule} from '@ngxs/devtools-plugin';
+import {EventListenerService} from '../services/event-listener-service';
+import { HttpClientModule } from '@angular/common/http';
+import { httpInterceptorProviders } from './http-interceptor';
+import { HttpHelperService } from './services/http-hepler.service';
+import { ModulesService } from "./services/modules.service";
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { FileUtilsService } from './services/file-utils.service';
+import { ImportVSPService } from './components/modals/onboarding-modal/import-vsp.service';
+import { OnboardingService } from './services/onboarding.service';
+import { ServiceConsumptionCreatorModule } from './pages/service-consumption-editor/service-consumption-editor.module';
+import { ServiceDependenciesModule } from './components/logic/service-dependencies/service-dependencies.module';
+import { ServiceDependenciesEditorModule } from './pages/service-dependencies-editor/service-dependencies-editor.module';
+import { PropertyCreatorModule } from './pages/properties-assignment/property-creator/property-creator.module';
+import { DeclareListModule } from './pages/properties-assignment/declare-list/declare-list.module';
+import { WorkflowServiceNg2 } from './services/workflow.service';
+import { ToscaTypesServiceNg2 } from "./services/tosca-types.service";
+
+
+declare const __ENV__: string;
export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
-export function configServiceFactory(config: ConfigService) {
- return () => {
- return Promise.all([
- config.loadValidationConfiguration(),
- config.loadPluginsConfiguration()
- ]);
- }
-}
+export function configServiceFactory(config: ConfigService, authService: AuthenticationService, eventListener: EventListenerService) {
+ return () => {
+ return authService.authenticate().toPromise()
+ .then((userInfo: IUserProperties) => {
+ authService.setLoggedinUser(userInfo);
+ return Promise.all([
+ config.loadSdcSetupData(),
+ config.loadValidationConfiguration(),
+ config.loadPluginsConfiguration(),
+ ])
+ }).then(() => {
+ eventListener.notifyObservers('ON_FINISH_LOADING');
+ })
+ .catch(() => {
+ console.log('AUTH FAILED! from app module');
+ });
+ };
+}
@NgModule({
declarations: [
AppComponent
],
imports: [
+ BrowserAnimationsModule,
BrowserModule,
UpgradeModule,
FormsModule,
- HttpModule,
+ HttpClientModule,
LayoutModule,
TranslateModule,
MultilineEllipsisModule,
@@ -111,80 +137,90 @@
CompositionPanelModule,
SdcUiComponentsModule,
AutomatedUpgradeModule,
- //We need to import them here since we use them in angular1
+
+ // We need to import them here since we use them in angular1
ConnectionWizardModule,
PropertiesAssignmentModule,
PropertyCreatorModule,
DeclareListModule,
PluginFrameModule,
+ PluginsModule,
InterfaceOperationModule,
OperationCreatorModule,
ServicePathCreatorModule,
ServicePathsListModule,
- ServicePathModule,
ServicePathSelectorModule,
- ServiceConsumptionModule,
ServiceConsumptionCreatorModule,
ServiceDependenciesModule,
ServiceDependenciesEditorModule,
- RequirementsEditorModule,
- CapabilitiesEditorModule,
- GenericArtifactBrowserModule
+ WorkspaceModule,
+ ModalsModule,
+ CatalogModule,
+ HomeModule,
+ NgxsModule.forRoot([]),
+ NgxsLoggerPluginModule.forRoot({ logger: console, collapsed: false }),
+ NgxsReduxDevtoolsPluginModule.forRoot({
+ disabled: __ENV__ === 'prod'
+ })
],
exports: [],
entryComponents: [
- // *** sdc-ui components to be used as downgraded:
- SdcUiComponents.SvgIconComponent
],
providers: [
WindowRef,
+ httpInterceptorProviders,
DataTypesServiceProvider,
- SharingServiceProvider,
+ SharingService,
+ CacheService,
+ HomeService,
ComponentFactoryProvider,
CookieServiceProvider,
StateServiceFactory,
StateParamsServiceFactory,
ScopeServiceFactory,
- CacheServiceProvider,
- EventListenerServiceProvider,
NotificationServiceProvider,
ModalsHandlerProvider,
- AuthenticationService,
+ UserService,
Cookie2Service,
ConfigService,
ComponentServiceNg2,
ComponentServiceFactoryNg2,
ModalService,
+ ImportVSPService,
+ OnboardingService,
ServiceServiceNg2,
AutomatedUpgradeService,
WorkflowServiceNg2,
ToscaTypesServiceNg2,
- HttpService,
- UserService,
+ WorkspaceNg1BridgeService,
+ HttpHelperService,
+ AuthenticationService,
PoliciesService,
GroupsService,
+ ModulesService,
DynamicComponentService,
SdcConfig,
SdcMenu,
ComponentInstanceServiceNg2,
+ EventListenerService,
TranslationServiceConfig,
+ TranslateService,
PluginsService,
- GabService,
- ArchiveService,
+ CatalogService,
EventBusService,
+ FileUtilsService,
{
provide: APP_INITIALIZER,
useFactory: configServiceFactory,
- deps: [ConfigService],
+ deps: [ConfigService, AuthenticationService, EventListenerService],
multi: true
},
],
bootstrap: [AppComponent]
})
-
export class AppModule {
- constructor(public upgrade: UpgradeModule, public eventBusService:EventBusService) {
+ constructor(public upgrade: UpgradeModule) {
}
}
diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts
index 85d1899..269a870 100644
--- a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts
+++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts
@@ -1,21 +1,19 @@
/*-
- * ============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=========================================================
+ <!--
+ ~ 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.
+ -->
*/
import { Component, Input } from '@angular/core';
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap
new file mode 100644
index 0000000..8cd085e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact form component should match current snapshot of artifact form component 1`] = `
+<artifact-form
+ artifactTypesOptions={[Function Array]}
+ cacheService={[Function Object]}
+ initArtifactTypes={[Function Function]}
+ onDescriptionChange={[Function Function]}
+ onLabelChange={[Function Function]}
+ onTypeChange={[Function Function]}
+ onUploadFile={[Function Function]}
+ onValidationChange={[Function Subject]}
+ verifyTypeAndFileWereFilled={[Function Function]}
+>
+ <form
+ class="artifact-form"
+ name="artifactForm"
+ novalidate=""
+ >
+ <onap-file-upload />
+ <div
+ class="artifact-form-container"
+ >
+
+ <div
+ class="right-form-container"
+ >
+ <sdc-textarea
+ label="Description"
+ testid="description"
+ />
+ <sdc-validation>
+ <sdc-required-validator />
+ <sdc-regex-validator />
+ </sdc-validation>
+ </div>
+ </div>
+ </form>
+</artifact-form>
+`;
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html
new file mode 100644
index 0000000..c84d6de
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html
@@ -0,0 +1,55 @@
+<form class="artifact-form" novalidate name="artifactForm">
+
+ <onap-file-upload [disabled]="isViewOnly || showTypeFields && !artifact.artifactType" [convertToBase64]="true" [(value)]="artifact.artifactName" (fileUpload)="onUploadFile($event)" [placeHolder]="'Select File'" [label]="'Upload File'" [testId]="'fileUploadElement'" [required]="true">
+
+ </onap-file-upload>
+ <div class="artifact-form-container">
+ <div class="left-form-container" *ngIf="showTypeFields">
+ <sdc-input #artifactLabel
+ required="true"
+ [(value)]="artifact.artifactLabel"
+ [maxLength]="25"
+ [label]="'Artifact Label'"
+ [disabled]="isViewOnly || artifact && artifact.uniqueId"
+ [testId]="'artifactLabel'"
+ (keyup)="verifyTypeAndFileWereFilled()">
+ </sdc-input>
+ <sdc-validation [validateElement]="artifactLabel" (validityChanged)="onLabelChange($event)">
+ <sdc-required-validator [message]="'ADD_ARTIFACT_ERROR_LABEL_REQUIRED' | translate"></sdc-required-validator>
+ <sdc-regex-validator [message]="'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate"
+ [pattern]="validationPatterns['label']"></sdc-regex-validator>
+ </sdc-validation>
+
+ <sdc-dropdown #artifactType [disabled]="isViewOnly || artifact && artifact.uniqueId" label="Type" [required]="true"
+ [selectedOption]="selectedFileType" placeHolder="Please choose type" (changed)="onTypeChange($event)"
+ [options]="artifactTypesOptions" [testId]="'artifacttype'"></sdc-dropdown>
+ <sdc-validation [validateElement]="artifactType">
+ <sdc-required-validator
+ [message]="'ADD_ARTIFACT_ERROR_TYPE_REQUIRED' | translate"></sdc-required-validator>
+ </sdc-validation>
+ </div>
+
+ <div class="right-form-container">
+ <sdc-textarea #artifactDescription
+ [(value)]="artifact.description"
+ [required]="true"
+ testId="description"
+ [maxLength]="256"
+ label="Description"
+ [disabled]="isViewOnly"
+ (keyup)="verifyTypeAndFileWereFilled()">
+ </sdc-textarea>
+ <sdc-validation [validateElement]="artifactDescription" (validityChanged)="onDescriptionChange($event)">
+ <sdc-required-validator
+ [message]="'ADD_ARTIFACT_ERROR_DESCRIPTION_REQUIRED' | translate:{'field': 'Message' }"></sdc-required-validator>
+ <sdc-regex-validator [message]="'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate"
+ [pattern]="validationPatterns['comment']"></sdc-regex-validator>
+ </sdc-validation>
+ </div>
+ </div>
+</form>
+
+<div *ngIf="artifact && artifact.esId">
+ <div>UUID: {{artifact.artifactUUID}}</div>
+ <div>Version: {{artifact.artifactVersion}}</div>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less
new file mode 100644
index 0000000..3b04122
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less
@@ -0,0 +1,23 @@
+.artifact-form {
+ display: flex;
+ justify-content: space-between;
+ flex-direction: column;
+
+ .artifact-form-container {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: row;
+ .left-form-container {
+ flex: 1;
+ padding-right: 10px;
+ }
+
+ .right-form-container {
+ flex: 1;
+
+ /deep/.sdc-textarea .sdc-textarea__textarea{
+ min-height: 110px;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts
new file mode 100644
index 0000000..fc69509
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts
@@ -0,0 +1,242 @@
+import {ArtifactFormComponent} from "./artifact-form.component";
+import {async, ComponentFixture} from "@angular/core/testing";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+import {CacheService} from "../../../services/cache.service";
+import {TranslateService} from "../../../shared/translator/translate.service";
+import {ArtifactModel} from "../../../../models/artifacts";
+import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
+import {Observable, Subject} from "rxjs";
+import {getValue} from "@ngxs/store";
+
+
+describe('artifact form component', () => {
+
+ let fixture: ComponentFixture<ArtifactFormComponent>;
+ let cacheServiceMock: Partial<CacheService>;
+ let onValidationChangeMock: Partial<Subject<boolean>>;
+
+ let artifactModel = new ArtifactModel();
+
+
+ beforeEach(
+ async(() => {
+
+ onValidationChangeMock = {
+ next: jest.fn()
+ }
+
+ cacheServiceMock = {
+ contains: jest.fn(),
+ remove: jest.fn(),
+ set: jest.fn(),
+ get: jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [ArtifactFormComponent],
+ imports: [TranslateModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: CacheService, useValue: cacheServiceMock},
+ {provide: TranslateService, useValue: {}}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(ArtifactFormComponent);
+ });
+ })
+ );
+
+
+ it('should verify initArtifactTypes for DEPLOYMENT and ArtifactType = HEAT_ENV', () =>{
+
+ cacheServiceMock.get.mockImplementation(() =>{
+ return {
+ artifacts: {
+ deployment:{
+ resourceInstanceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}],
+ }
+ }
+ }
+ });
+
+ fixture.componentInstance.artifactType = 'DEPLOYMENT';
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.artifactType = 'HEAT_ENV';
+
+ fixture.componentInstance.initArtifactTypes();
+
+ expect(fixture.componentInstance.selectedFileType).toEqual(undefined);
+
+ });
+
+ it('should verify initArtifactTypes for DEPLOYMENT and ComponentType = RESOURCE', () =>{
+
+ cacheServiceMock.get.mockImplementation(() =>{
+ return {
+ artifacts: {
+ deployment:{
+ resourceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}],
+ }
+ }
+ }
+ });
+
+ fixture.componentInstance.artifactType = 'DEPLOYMENT';
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.componentType = 'RESOURCE';
+
+ fixture.componentInstance.initArtifactTypes();
+
+ expect(fixture.componentInstance.selectedFileType).toEqual(undefined);
+
+ });
+
+ it('should verify initArtifactTypes for DEPLOYMENT and NOT ComponentType = RESOURCE OR NOT ArtifactType = HEAT_ENV', () =>{
+
+ cacheServiceMock.get.mockImplementation(() =>{
+ return {
+ artifacts: {
+ deployment:{
+ serviceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}],
+ }
+ }
+ }
+ });
+
+ fixture.componentInstance.artifactType = 'DEPLOYMENT';
+ fixture.componentInstance.artifact = artifactModel;
+ // fixture.componentInstance.componentType = 'RESOURCE';
+
+ fixture.componentInstance.initArtifactTypes();
+
+ expect(fixture.componentInstance.selectedFileType).toEqual(undefined);
+
+ });
+
+ it('should verify initArtifactTypes for INFORMATION', () =>{
+
+ cacheServiceMock.get.mockImplementation(() =>{
+ return {
+ artifacts: {
+ other: [{name: "Val1"}, {name: "ExpectedValToBeSelected"}, {name: "Val3"}]
+ }
+ }
+ });
+
+ fixture.componentInstance.artifactType = 'INFORMATIONAL';
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.artifactType = 'ExpectedValToBeSelected';
+
+ fixture.componentInstance.initArtifactTypes();
+
+ expect(fixture.componentInstance.selectedFileType).toEqual({"label": "ExpectedValToBeSelected", "value": "ExpectedValToBeSelected"});
+
+ });
+
+
+ it('should match current snapshot of artifact form component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should verify onUploadFile -> file gets file name', () => {
+ let file = {
+ filename:'dummyFileName'
+ }
+
+ fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn();
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.onUploadFile(file);
+
+ expect(fixture.componentInstance.artifact.artifactName).toBe('dummyFileName');
+
+ const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled');
+ expect(spy1).toHaveBeenCalled();
+ });
+
+ it('should verify onUploadFile -> file is null', () => {
+ let file = null;
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.onUploadFile(file);
+
+ expect(fixture.componentInstance.artifact.artifactName).toBe(null);
+ });
+
+ it('should verify onTypeChange -> verifyTypeAndFileWereFilled is being called', () => {
+ let selectedFileType:IDropDownOption;
+ selectedFileType = {"label": "dummyLabel", "value": "dummyValue"};
+ fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn();
+
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.onTypeChange(selectedFileType);
+
+ const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled');
+ expect(spy1).toHaveBeenCalled();
+ });
+
+ it('should verify onDescriptionChange -> verifyTypeAndFileWereFilled is being called', () => {
+ fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn();
+ fixture.componentInstance.onValidationChange.next = jest.fn(() => true);
+
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.onDescriptionChange();
+
+ const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled');
+ expect(spy1).toHaveBeenCalled();
+ });
+
+ it('should verify onLabelChange -> verifyTypeAndFileWereFilled is being called', () => {
+ fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn();
+ fixture.componentInstance.onValidationChange.next = jest.fn(() => true);
+
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.onLabelChange(true);
+
+ const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled');
+ expect(spy1).toHaveBeenCalled();
+ });
+
+ it('should verify verifyTypeAndFileWereFilled -> verify branch this.artifact.artifactType !== \'DEPLOYMENT\' ==>> onValidationChange.next(false)', () => {
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.artifactType = 'NOT_DEPLOYMENT';
+ fixture.componentInstance.artifact.mandatory = true;
+ fixture.componentInstance.descriptionIsValid = false;
+
+ let onValidationChangeResult;
+
+ fixture.componentInstance.onValidationChange.subscribe((data) => {
+ onValidationChangeResult = data;
+ // console.log("Subscriber got data >>>>> "+ data);
+ });
+
+ fixture.componentInstance.verifyTypeAndFileWereFilled();
+
+ expect(onValidationChangeResult).toBe(false);
+ });
+
+ it('should verify verifyTypeAndFileWereFilled -> verify branch this.artifact.artifactType !== \'DEPLOYMENT\' ==>> onValidationChange.next(true)', () => {
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.artifactType = 'NOT_DEPLOYMENT';
+ fixture.componentInstance.artifact.mandatory = true;
+ fixture.componentInstance.artifact.artifactName = 'Something';
+ fixture.componentInstance.descriptionIsValid = true;
+
+ let onValidationChangeResult;
+
+ fixture.componentInstance.onValidationChange.subscribe((data) => {
+ onValidationChangeResult = data;
+ // console.log("Subscriber got data >>>>> "+ data);
+ });
+
+ fixture.componentInstance.verifyTypeAndFileWereFilled();
+
+ expect(onValidationChangeResult).toBe(true);
+ });
+
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts
new file mode 100644
index 0000000..905d1a2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts
@@ -0,0 +1,132 @@
+/**
+ * Created by rc2122 on 5/31/2018.
+ */
+import { Component, Input } from '@angular/core';
+import * as _ from 'lodash';
+import { IDropDownOption } from 'onap-ui-angular/dist/form-elements/dropdown/dropdown-models';
+import { Subject } from 'rxjs/Subject';
+import { ArtifactModel } from '../../../../models';
+import { ArtifactType, ComponentType } from '../../../../utils';
+import { Dictionary } from '../../../../utils/dictionary/dictionary';
+import { CacheService } from '../../../services/cache.service';
+
+@Component({
+ selector: 'artifact-form',
+ templateUrl: './artifact-form.component.html',
+ styleUrls: ['./artifact-form.component.less']
+})
+export class ArtifactFormComponent {
+
+ @Input() artifact: ArtifactModel;
+ @Input() artifactType: ArtifactType;
+ @Input() componentType: string;
+ @Input() instanceId: string;
+ @Input() isViewOnly: boolean;
+
+ public artifactTypesOptions: IDropDownOption[] = [];
+ public validationPatterns: Dictionary<string, RegExp>;
+ public selectedFileType: IDropDownOption;
+ public showTypeFields: boolean;
+ private onValidationChange: Subject<boolean> = new Subject();
+ private descriptionIsValid: boolean;
+ private labelIsValid: boolean;
+
+ constructor(private cacheService: CacheService) {
+ }
+
+ ngOnInit(): void {
+ this.validationPatterns = this.cacheService.get('validation').validationPatterns;
+ this.initArtifactTypes();
+ this.artifact.artifactGroupType = this.artifact.artifactGroupType || this.artifactType.toString();
+ this.showTypeFields = (this.artifact.artifactGroupType === 'DEPLOYMENT' || !this.artifact.mandatory) && this.artifact.artifactGroupType !== 'SERVICE_API';
+ }
+
+ public onTypeChange = (selectedFileType: IDropDownOption) => {
+ this.artifact.artifactType = selectedFileType.value;
+ this.verifyTypeAndFileWereFilled();
+ }
+
+ public onUploadFile = (file) => {
+ if (file) {
+ this.artifact.artifactName = file.filename;
+ this.artifact.payloadData = file.base64;
+ console.log('FILE UPLOADED', file);
+ } else {
+ this.artifact.artifactName = null;
+ }
+ this.verifyTypeAndFileWereFilled();
+ }
+
+ private initArtifactTypes = (): void => {
+ const artifactTypes: any = this.cacheService.get('UIConfiguration');
+ let validExtensions: string[];
+ let artifactTypesList: string[];
+
+ switch (this.artifactType) {
+ case ArtifactType.DEPLOYMENT:
+ if (this.artifact.artifactType === ArtifactType.HEAT_ENV || this.instanceId) {
+ validExtensions = artifactTypes.artifacts.deployment.resourceInstanceDeploymentArtifacts;
+ } else if (this.componentType === ComponentType.RESOURCE) {
+ validExtensions = artifactTypes.artifacts.deployment.resourceDeploymentArtifacts;
+ } else {
+ validExtensions = artifactTypes.artifacts.deployment.serviceDeploymentArtifacts;
+ }
+ if (validExtensions) {
+ artifactTypesList = Object.keys(validExtensions);
+ }
+ break;
+ case ArtifactType.INFORMATION:
+ artifactTypesList = artifactTypes.artifacts.other.map((element: any) => {
+ return element.name;
+ });
+ _.remove(artifactTypesList, (item: string) => {
+ return _.has(ArtifactType.THIRD_PARTY_RESERVED_TYPES, item) ||
+ _.has(ArtifactType.TOSCA, item);
+ });
+ break;
+ }
+
+ _.forEach(artifactTypesList, (artifactType: string) => {
+ this.artifactTypesOptions.push({ label: artifactType, value: artifactType });
+ });
+
+ this.selectedFileType = _.find(this.artifactTypesOptions, (artifactType) => {
+ return artifactType.value === this.artifact.artifactType;
+ });
+
+ }
+
+ // Verify that the Type and the Name (file) are filled in the Modal
+ // For Description and Label - I used this.descriptionIsValid:boolean & this.labelIsValid:boolean as part of the sdc-validation Element
+ private verifyTypeAndFileWereFilled = () => {
+ if (this.artifact.artifactType === 'DEPLOYMENT' || !this.artifact.mandatory && this.artifact.artifactGroupType !== 'SERVICE_API') {
+ // In case of all fields are required:
+ // File, Description, Type and Label
+ if (this.artifact.artifactType && this.artifact.artifactName && this.descriptionIsValid && this.labelIsValid) {
+ this.onValidationChange.next(true);
+ } else {
+ this.onValidationChange.next(false);
+ }
+ } else {
+ // In case of like Information Artifact
+ // Only file and description are required
+ if (this.descriptionIsValid && this.artifact.artifactName) {
+ this.onValidationChange.next(true);
+ } else {
+ this.onValidationChange.next(false);
+ }
+ }
+ }
+
+ // sdc-validation for Description
+ private onDescriptionChange = (isValid: boolean): void => {
+ this.descriptionIsValid = isValid;
+ this.onValidationChange.next(isValid) && this.verifyTypeAndFileWereFilled();
+ }
+
+ // sdc-validation for Label
+ private onLabelChange = (isValid: boolean): void => {
+ this.labelIsValid = isValid;
+ this.onValidationChange.next(isValid) && this.verifyTypeAndFileWereFilled();
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts
new file mode 100644
index 0000000..dba8012
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts
@@ -0,0 +1,21 @@
+/**
+ * Created by rc2122 on 5/24/2018.
+ */
+import { NgModule } from "@angular/core";
+import { TranslateModule } from "app/ng2/shared/translator/translate.module";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import { CommonModule } from '@angular/common';
+import {ArtifactFormComponent} from "./artifact-form.component";
+
+@NgModule({
+ declarations: [ArtifactFormComponent],
+ imports: [TranslateModule,
+ SdcUiComponentsModule,
+ CommonModule],
+ exports: [ArtifactFormComponent],
+ entryComponents: [ArtifactFormComponent]
+})
+
+
+export class ArtifactFormModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts
new file mode 100644
index 0000000..f9400e9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts
@@ -0,0 +1,175 @@
+import { Injectable } from '@angular/core';
+import { Store } from '@ngxs/store';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { ArtifactModel } from '../../../../models';
+import { ArtifactGroupType, ArtifactType } from '../../../../utils/constants';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { CreateOrUpdateArtifactAction, DeleteArtifactAction } from '../../../store/actions/artifacts.action';
+import { EnvParamsComponent } from '../env-params/env-params.component';
+import { ArtifactFormComponent } from './artifact-form.component';
+
+import {
+ CreateInstanceArtifactAction,
+ DeleteInstanceArtifactAction,
+ UpdateInstanceArtifactAction
+} from '../../../store/actions/instance-artifacts.actions';
+
+@Injectable()
+export class ArtifactsService {
+
+ constructor(private serviceLoader: SdcUiServices.LoaderService,
+ private modalService: SdcUiServices.ModalService,
+ private topologyTemplateService: TopologyTemplateService,
+ private translateService: TranslateService,
+ private store: Store) {
+ }
+
+ public dispatchArtifactAction = (componentId: string, componentType: string, artifact: ArtifactModel, artifactType: ArtifactGroupType, instanceId: string) => {
+ const artifactObj = {
+ componentType,
+ componentId,
+ instanceId,
+ artifact
+ };
+
+ // Create or update instance artifact
+ if (instanceId) {
+ if (!artifact.uniqueId) {
+ // create instance artifact
+ return this.store.dispatch(new CreateInstanceArtifactAction(artifactObj));
+ } else {
+ // update instance artifact
+ return this.store.dispatch(new UpdateInstanceArtifactAction(artifactObj));
+ }
+ } else {
+ // Create or update artifact
+ return this.store.dispatch(new CreateOrUpdateArtifactAction(artifactObj));
+ }
+ }
+
+ public openArtifactModal = (componentId: string, componentType: string, artifact: ArtifactModel, artifactType: ArtifactGroupType, isViewOnly?: boolean, instanceId?: string) => {
+
+ let modalInstance;
+
+ const onOkPressed = () => {
+ const updatedArtifact = modalInstance.innerModalContent.instance.artifact;
+ this.serviceLoader.activate();
+ this.dispatchArtifactAction(componentId, componentType, updatedArtifact, artifactType, instanceId)
+ .subscribe().add(() => this.serviceLoader.deactivate());
+ };
+
+ const addOrUpdateArtifactModalConfig = {
+ title: (artifact && artifact.uniqueId) ? 'Update Artifact' : 'Create Artifact',
+ size: 'md',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'upgradeVspModal',
+ buttons: [
+ {
+ id: 'done',
+ text: 'DONE',
+ disabled: isViewOnly,
+ size: 'Add Another',
+ closeModal: true,
+ callback: onOkPressed
+ },
+ {text: 'CANCEL', size: 'sm', closeModal: true, type: 'secondary'}
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig;
+
+ modalInstance = this.modalService.openCustomModal(addOrUpdateArtifactModalConfig, ArtifactFormComponent, {
+ artifact: new ArtifactModel(artifact),
+ artifactType,
+ instanceId,
+ componentType,
+ isViewOnly
+ });
+
+ if (!isViewOnly) {
+ modalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => {
+ modalInstance.getButtonById('done').disabled = !isValid;
+ });
+ }
+ }
+
+ public openViewEnvParams(componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) {
+ const envParamsModal = {
+ title: artifact.artifactDisplayName,
+ size: 'xl',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'viewEnvParams',
+ isDisabled: false,
+ } as SdcUiCommon.IModalConfig;
+
+ this.modalService.openCustomModal(envParamsModal, EnvParamsComponent, {
+ isInstanceSelected: !!instanceId, // equals to instanceId ? true : false
+ artifact: new ArtifactModel(artifact),
+ isViewOnly: true
+ });
+ }
+
+ public openUpdateEnvParams(componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) {
+ let modalInstance;
+ const onOkPressed = () => {
+ const updatedArtifact = modalInstance.innerModalContent.instance.artifact;
+ this.serviceLoader.activate();
+ this.dispatchArtifactAction(componentId, componentType, updatedArtifact, ArtifactType.DEPLOYMENT, instanceId)
+ .subscribe().add(() => this.serviceLoader.deactivate());
+ };
+
+ const envParamsModal = {
+ title: artifact.artifactDisplayName,
+ size: 'xl',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'envParams',
+ isDisabled: false,
+ buttons: [
+ {
+ id: 'save',
+ text: 'Save',
+ spinner_position: 'left',
+ size: 'sm',
+ callback: onOkPressed,
+ closeModal: true
+ },
+ {text: 'Cancel', size: 'sm', closeModal: true, type: 'secondary'}
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig;
+
+ modalInstance = this.modalService.openCustomModal(envParamsModal, EnvParamsComponent, {
+ isInstanceSelected: !!instanceId, // equals to instanceId ? true : false
+ artifact: new ArtifactModel(artifact)
+ });
+
+ modalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => {
+ modalInstance.getButtonById('save').disabled = !isValid;
+ });
+ }
+
+ public deleteArtifact = (componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) => {
+
+ const artifactObject = {
+ componentType,
+ componentId,
+ artifact,
+ instanceId
+ };
+
+ const onOkPressed: Function = () => {
+ this.serviceLoader.activate();
+ this.store.dispatch((instanceId) ? new DeleteInstanceArtifactAction(artifactObject) : new DeleteArtifactAction(artifactObject))
+ .subscribe().add(() => this.serviceLoader.deactivate());
+ };
+
+ const title = this.translateService.translate('ARTIFACT_VIEW_DELETE_MODAL_TITLE');
+ const text = this.translateService.translate('ARTIFACT_VIEW_DELETE_MODAL_TEXT', {name: artifact.artifactDisplayName});
+ const okButton = {
+ testId: 'OK',
+ text: 'OK',
+ type: SdcUiCommon.ButtonType.warning,
+ callback: onOkPressed,
+ closeModal: true
+ } as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openWarningModal(title, text, 'delete-information-artifact-modal', [okButton]);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap
new file mode 100644
index 0000000..aa567bb
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap
@@ -0,0 +1,42 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`environment parameters component should match current snapshot of env-params component 1`] = `
+<env-params
+ cacheService={[Function Object]}
+ clearCurrentValue={[Function Function]}
+ copiedWorkingArtifactHeatParameters={[Function Array]}
+ defaultDeploymentTimeout={[Function Number]}
+ displayRegexValid={[Function String]}
+ maxDeploymentTimeout={[Function Number]}
+ minDeploymentTimeout={[Function Number]}
+ onValidationChange={[Function Subject]}
+ onValidityChange={[Function Function]}
+ openPopOver={[Function Function]}
+ popoverService={[Function Object]}
+ textArea="undefined"
+>
+ <div
+ class="filter-bar"
+ >
+ <sdc-filter-bar />
+ </div><ngx-datatable
+ class="material ngx-datatable"
+ >
+ <div
+ visibilityobserver=""
+ >
+
+ <datatable-body
+ class="datatable-body"
+ >
+ <datatable-selection>
+
+
+
+ </datatable-selection>
+ </datatable-body>
+
+ </div>
+ </ngx-datatable>
+</env-params>
+`;
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html
new file mode 100644
index 0000000..f55aff5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html
@@ -0,0 +1,71 @@
+<div class="filter-bar">
+ <sdc-filter-bar
+ [placeHolder]="'Search...'"
+ [testId]="'search-env-param-name'"
+ (keyup)="updateFilter($event)">
+ </sdc-filter-bar>
+</div>
+
+<ngx-datatable
+ class='material'
+ [rows]='artifact.heatParameters'
+ [columnMode]="'flex'"
+ [headerHeight]="40"
+ [rowHeight]="'auto'"
+ [scrollbarV]="false">
+
+ <ngx-datatable-column name="Parameter" [flexGrow]="2">
+ <ng-template let-row="row" ngx-datatable-cell-template prop="name">
+ {{row.name}}
+ <span *ngIf="row.description.length > 0" class="info">
+ <svg-icon [name]="'comment'" (click)="openPopOver('',row.description,{x:$event.pageX , y:$event.pageY },'bottom')"></svg-icon>
+ </span>
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-column name="DefaultValue"[flexGrow]="1">
+ <ng-template let-row="row" let-value="value" ngx-datatable-cell-template>
+ {{row.defaultValue}}
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-column name="CurrentValue" [flexGrow]="2">
+ <ng-template let-row="row" let-value="value" ngx-datatable-cell-template>
+ <sdc-input class="sdc-input-wrapper" #numberValidator
+ [placeHolder]="'Enter text'"
+ [isViewMode]="isViewOnly"
+ [size]="'medium'"
+ [(value)]=row.currentValue
+ [isIconClickable]="true"
+ (onRighIconClicked)="clearCurrentValue(row.name)"
+ [righIconName]="'trash-o'"
+ [testId] = "'value-field-of-' + row.name">
+ </sdc-input>
+
+ <sdc-validation [validateElement]="numberValidator" (validityChanged)="onValidityChange($event)" [disabled]="false" [testId]="_testId">
+ <sdc-regex-validator *ngIf="displayRegexValid && row.type == 'number' && row.currentValue !== null" [message]="'Value should be of type number.'" [pattern]="displayRegexValid" [disabled]="false"></sdc-regex-validator>
+ </sdc-validation>
+ </ng-template>
+ </ngx-datatable-column>
+
+</ngx-datatable>
+
+<div *ngIf="isInstanceSelected" class="artifactTimeout">
+
+ <sdc-number-input
+ label="Deployment Timeout ({{minDeploymentTimeout}}-{{maxDeploymentTimeout}} minutes)"
+ [required]="true"
+ [disabled]="false"
+ name="artifactTimeout"
+ testId="deploymentTimeout"
+ value="{{artifact.timeout}}"
+ [maxValue]="maxDeploymentTimeout"
+ [minValue]="minDeploymentTimeout"
+ (valueChange)="timeoutChanged($event)"
+ [isViewMode]="isViewOnly"
+ [step]="1"
+ >
+
+ </sdc-number-input>
+
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less
new file mode 100644
index 0000000..48b4cba
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less
@@ -0,0 +1,21 @@
+.filter-bar {
+ padding-bottom: 25px;
+}
+
+:host ::ng-deep {
+
+ .ngx-datatable {
+ //border: 1px solid red;
+ .datatable-body-cell {
+ .info {
+ float: right;
+ }
+ }
+ }
+}
+
+.artifactTimeout{
+ padding-top: 25px;
+ justify-content: start;
+ width: 230px;
+}
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts
new file mode 100644
index 0000000..f6b0eb4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts
@@ -0,0 +1,98 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {EnvParamsComponent} from "./env-params.component";
+import {SdcUiServices, SdcUiCommon} from "onap-ui-angular";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {ArtifactModel} from "../../../../models/artifacts";
+import { CacheService } from '../../../services/cache.service';
+
+describe('environment parameters component', () => {
+
+ let fixture: ComponentFixture<EnvParamsComponent>;
+ let popoverServiceMock: Partial<SdcUiServices.PopoverService>;
+ let regexPatterns: any;
+
+ let artifactModel = new ArtifactModel();
+
+ let mockHeatParameters = [
+ {currentValue: "1", defaultValue: null, description: "Description 1", empty:false, name: "Param1", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null},
+ {currentValue: "2", defaultValue: null, description: "Description 2", empty:false, name: "Param2", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null},
+ {currentValue: "3", defaultValue: null, description: "Description 3", empty:false, name: "Param3", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null}
+ ];
+
+ let keyboardEvent = new KeyboardEvent("keyup");
+
+ beforeEach(
+ async(() => {
+
+ popoverServiceMock = {
+ createPopOver : jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [EnvParamsComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: SdcUiServices.PopoverService, useValue: popoverServiceMock },
+ { provide: CacheService, useValue: { get: jest.fn() } }
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(EnvParamsComponent);
+ });
+ })
+ );
+
+ it('should match current snapshot of env-params component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should clear CurrentValue for a given name in the heat parameter', () => {
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.heatParameters = mockHeatParameters;
+ expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3);
+ expect(fixture.componentInstance.artifact.heatParameters[0].currentValue).toBe("1");
+ fixture.componentInstance.clearCurrentValue("Param1");
+ expect(fixture.componentInstance.artifact.heatParameters[0].currentValue).toBe("");
+ });
+
+ it("should update filter heatParameters so there won''t be any value to be displayed", () => {
+
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.heatParameters = mockHeatParameters;
+ fixture.componentInstance.ngOnInit();
+
+ let event = {
+ target : {
+ value: 'paramNotExist'
+ }
+ }
+
+ expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3);
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.artifact.heatParameters.length).toBe(0);
+ });
+
+ it("should update filter heatParameters so there will be only 1 value to be displayed", () => {
+
+ fixture.componentInstance.artifact = artifactModel;
+ fixture.componentInstance.artifact.heatParameters = mockHeatParameters;
+ fixture.componentInstance.ngOnInit();
+
+ let event = {
+ target : {
+ value: 'param1'
+ }
+ }
+
+ expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3);
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.artifact.heatParameters.length).toBe(1);
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts
new file mode 100644
index 0000000..58d266a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
+import { SdcUiCommon, SdcUiServices } from 'onap-ui-angular';
+import { Subject } from 'rxjs/Rx';
+import { ArtifactModel } from '../../../../models/artifacts';
+import { CacheService } from '../../../services/cache.service';
+
+export interface IPoint {
+ x: number;
+ y: number;
+}
+
+@Component({
+ selector: 'env-params',
+ templateUrl: './env-params.component.html',
+ styleUrls: ['../../../../../assets/styles/table-style.less', './env-params.component.less']
+})
+export class EnvParamsComponent implements OnInit {
+
+ @Input() public artifact: ArtifactModel;
+ @Input() public isInstanceSelected: boolean;
+ @Input() public isViewOnly: boolean;
+
+ @ViewChild('textArea') textArea: ElementRef;
+ private copiedWorkingArtifactHeatParameters = [];
+ private onValidationChange: Subject<boolean> = new Subject();
+ private displayRegexValid = SdcUiCommon.RegexPatterns.numberOrEmpty;
+
+ // Deployment timeout in minutes
+ private maxDeploymentTimeout: number = 120;
+ private minDeploymentTimeout: number = 1;
+ private defaultDeploymentTimeout: number = 60;
+
+ constructor(private cacheService: CacheService, private popoverService: SdcUiServices.PopoverService) {
+ const configuration = cacheService.get('UIConfiguration');
+ if (configuration && configuration.heatDeploymentTimeout) {
+ this.maxDeploymentTimeout = configuration.heatDeploymentTimeout.maxMinutes;
+ this.minDeploymentTimeout = configuration.heatDeploymentTimeout.minMinutes;
+ this.defaultDeploymentTimeout = configuration.heatDeploymentTimeout.defaultMinutes;
+ }
+ }
+
+ ngOnInit(): void {
+ this.copiedWorkingArtifactHeatParameters = [...this.artifact.heatParameters];
+ }
+
+ public clearCurrentValue = (name: string) => {
+ this.artifact.heatParameters.filter((param) => param.name === name)[0].currentValue = '';
+ }
+
+ public timeoutChanged(timeout) {
+ this.artifact.timeout = timeout;
+ }
+
+ updateFilter(event) {
+ const val = event.target.value.toLowerCase();
+ // filter our data
+ const temp = this.copiedWorkingArtifactHeatParameters.filter((param) => {
+ return !val || param.name ? param.name.toLowerCase().indexOf(val) !== -1 : -1 || param.currentValue ? param.currentValue.toLowerCase().indexOf(val) !== -1 : -1;
+ });
+ // update the rows
+ this.artifact.heatParameters = temp;
+ }
+
+ private openPopOver = (title: string, content: string, positionOnPage: IPoint, location: string) => {
+ this.popoverService.createPopOver(title, content, positionOnPage, location);
+ }
+
+ private onValidityChange = (isValid: boolean): void => {
+ this.onValidationChange.next(isValid);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts
new file mode 100644
index 0000000..85797bd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts
@@ -0,0 +1,28 @@
+import { NgModule } from "@angular/core";
+import { EnvParamsComponent } from "./env-params.component";
+import { NgxDatatableModule } from "@swimlane/ngx-datatable";
+import { SdcUiComponentsModule, SdcUiServices } from "onap-ui-angular";
+
+
+@NgModule({
+ declarations: [
+ EnvParamsComponent
+ ],
+ imports: [
+ NgxDatatableModule,
+ SdcUiComponentsModule
+ ],
+ exports: [
+ EnvParamsComponent
+ ],
+ entryComponents: [ //need to add anything that will be dynamically created
+ EnvParamsComponent
+ ],
+ providers: [
+ SdcUiServices.ModalService
+ ]
+})
+
+export class EnvParamsModule {
+
+}
diff --git a/catalog-ui/src/app/ng2/components/layout/layout.module.ts b/catalog-ui/src/app/ng2/components/layout/layout.module.ts
index 8272093..f6d2cf4 100644
--- a/catalog-ui/src/app/ng2/components/layout/layout.module.ts
+++ b/catalog-ui/src/app/ng2/components/layout/layout.module.ts
@@ -13,7 +13,9 @@
FormsModule,
TranslateModule
],
- exports: [],
+ exports: [
+ TopNavComponent
+ ],
entryComponents: [ //need to add anything that will be dynamically created
TopNavComponent
],
diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap b/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap
new file mode 100644
index 0000000..c650a9c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact form component should match current snapshot of top-nav component 1`] = `
+<top-nav
+ $state={[Function Object]}
+ _getTopLvlSelectedIndexByState={[Function Function]}
+ authService={[Function Object]}
+ sdcConfig={[Function Object]}
+ searchTermChange={[Function EventEmitter]}
+ translateService={[Function Object]}
+>
+ <nav
+ class="top-nav"
+ >
+ <div
+ class="asdc-app-title-wrapper"
+ >
+ <a
+ class="asdc-app-title"
+ >
+
+ </a>
+ <div
+ class="asdc-version"
+ >
+ v.
+ </div>
+ </div>
+
+
+ <div
+ class="top-search"
+ >
+ <input
+ class="search-text"
+ data-tests-id="main-menu-input-search"
+ placeholder="Search"
+ type="text"
+ />
+ <span
+ class="w-sdc-search-icon magnification"
+ />
+ </div>
+
+ </nav>
+</top-nav>
+`;
diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts
new file mode 100644
index 0000000..54fbb36
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts
@@ -0,0 +1,161 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { PluginsConfiguration } from 'app/models';
+import { Observable } from 'rxjs';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { MenuItem, MenuItemGroup } from '../../../../utils/menu-handler';
+import { SdcConfigToken } from '../../../config/sdc-config.config';
+import { AuthenticationService } from '../../../services/authentication.service';
+import { TranslateModule } from '../../../shared/translator/translate.module';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { TopNavComponent } from './top-nav.component';
+
+describe('artifact form component', () => {
+
+ let fixture: ComponentFixture<TopNavComponent>;
+ let translateServiceMock: Partial<TranslateService>;
+ let mockStateService;
+ let authServiceMock;
+
+ const designerUser = {
+ email: 'designer@sdc.com',
+ firstName: 'Carlos',
+ fullName: 'Carlos Santana',
+ lastLoginTime: 1555587266566,
+ lastName: 'Santana',
+ role: 'DESIGNER',
+ status: 'ACTIVE',
+ userId: 'cs0008'
+ };
+
+ const pluginDisplayOptions = {
+ displayName : '',
+ displayContext : new Array<string>(),
+ displayRoles : new Array<string>()
+ };
+
+ let roleToReturn = designerUser;
+
+ const map1 = new Map();
+ map1.otherValue = pluginDisplayOptions;
+
+ const map2 = new Map();
+ pluginDisplayOptions.displayRoles = ['DESIGNER'];
+ pluginDisplayOptions.displayName = 'DCAE-DS';
+ map2.tab = pluginDisplayOptions;
+
+ PluginsConfiguration.plugins =
+ [
+ {pluginId: 'DCAED', pluginDiscoveryUrl: 'DCAED_discoveryURL', pluginSourceUrl: 'DCAED_sourceURL', pluginStateUrl: 'DCAED_stateURL', pluginDisplayOptions: map1, isOnline: true},
+ {pluginId: 'DCAE-DS', pluginDiscoveryUrl: 'DCAE-DS_discoveryURL', pluginSourceUrl: 'DCAE-DS_sourceURL', pluginStateUrl: 'DCAE-DS_stateURL', pluginDisplayOptions: map2, isOnline: true}
+ ];
+
+ beforeEach(
+ async(() => {
+ authServiceMock = {
+ getLoggedinUser: jest.fn().mockImplementation(() => {
+ return roleToReturn;
+ })
+ };
+
+ mockStateService = {
+ go: jest.fn(),
+ includes: jest.fn(() => true),
+ current : {
+ name : 'plugins'
+ },
+ params : {}
+ };
+
+ translateServiceMock = {
+ languageChangedObservable: Mock.of<Observable<string>>( {
+ subscribe : jest.fn().mockImplementation((cb) => {
+ cb();
+ })
+ }),
+ translate: jest.fn((str: string) => {
+ if (str === 'TOP_MENU_HOME_BUTTON') {
+ return 'HOME';
+ } else if (str === 'TOP_MENU_CATALOG_BUTTON') {
+ return 'CATALOG';
+ } else if (str === 'TOP_MENU_ON_BOARD_BUTTON') {
+ return 'ONBOARD';
+ } else {
+ return 'TBD...';
+ }
+ })
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [TopNavComponent],
+ imports: [TranslateModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: translateServiceMock},
+ {provide: '$state', useValue: mockStateService},
+ {provide: AuthenticationService, useValue: authServiceMock},
+ {provide: SdcConfigToken, useValue: {csarFileExtension: 'csar', toscaFileExtension: 'yaml,yml'}},
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(TopNavComponent);
+ });
+ })
+ );
+
+ it('should match current snapshot of top-nav component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('Once a Designer logged in, Menu Items will contain HOME, CATALOG, ONBOARD & DCAE-DS; HOME will be selected', () => {
+
+ // topLvlSelectedIndex = 1 => Ignore the inner call to _getTopLvlSelectedIndexByState.
+ fixture.componentInstance.topLvlSelectedIndex = 0;
+ fixture.componentInstance.ngOnInit();
+
+ expect(fixture.componentInstance.topLvlMenu.itemClick).toBe(true);
+
+ expect(fixture.componentInstance.topLvlMenu.menuItems.length).toBe(4);
+
+ expect(fixture.componentInstance.topLvlMenu.menuItems[0]).toEqual({
+ action: 'goToState',
+ blockedForTypes: null,
+ callback: null,
+ params: null,
+ state: 'dashboard',
+ text: 'HOME'
+ });
+ expect(fixture.componentInstance.topLvlMenu.menuItems[1]).toEqual({
+ action: 'goToState',
+ blockedForTypes: null,
+ callback: null,
+ params: null,
+ state: 'catalog',
+ text: 'CATALOG'
+ });
+ expect(fixture.componentInstance.topLvlMenu.menuItems[2]).toEqual({
+ action: 'goToState',
+ blockedForTypes: null,
+ callback: null,
+ params: null,
+ state: 'onboardVendor',
+ text: 'ONBOARD'
+ });
+ expect(fixture.componentInstance.topLvlMenu.menuItems[3]).toEqual({
+ action: 'goToState',
+ blockedForTypes: null,
+ callback: null,
+ params:
+ {path: 'DCAE-DS_stateURL'},
+ state: 'plugins',
+ text: 'DCAE-DS'
+ });
+
+ expect(fixture.componentInstance.topLvlMenu.selectedIndex).toBe(0);
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html
index f82e110..2636dd9 100644
--- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html
+++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html
@@ -65,6 +65,6 @@
<span class="w-sdc-search-icon magnification"></span>
</div>
- <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div>
+ <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user && user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div>
</nav>
diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less
index 5c99015..2bcdfc2 100644
--- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less
+++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less
@@ -120,7 +120,7 @@
height: 35px;
background-color: white;
font-size: 13px;
- width: 150px;
+ width: auto;
line-height: 35px;
padding: 0 10px;
diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts
index a253b3a..3bd2255 100644
--- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts
+++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts
@@ -19,14 +19,17 @@
*/
import * as _ from "lodash";
-import {Component, Inject, Input, Output, EventEmitter} from "@angular/core";
+import {Component, Inject, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges} from "@angular/core";
import {IHostedApplication, IUserProperties} from "app/models";
import {MenuItemGroup, MenuItem} from "app/utils";
-import {UserService} from "../../../services/user.service";
+import {AuthenticationService} from "../../../services/authentication.service";
import {SdcConfigToken, ISdcConfig} from "../../../config/sdc-config.config";
import {TranslateService} from "../../../shared/translator/translate.service";
import {PluginsConfiguration, Plugin} from "app/models";
-
+import { Subscription } from "rxjs";
+// import { Store } from "@ngrx/store";
+// import { AppState } from "app/ng2/store/app.state";
+// import * as unsavedChangesReducer from 'app/ng2/store/reducers/unsaved-changes.reducer';
declare const window:any;
@Component({
@@ -34,7 +37,7 @@
templateUrl: './top-nav.component.html',
styleUrls:['./top-nav.component.less']
})
-export class TopNavComponent {
+export class TopNavComponent implements OnInit, OnChanges {
@Input() public version:string;
@Input() public menuModel:Array<MenuItemGroup>;
@Input() public topLvlSelectedIndex:number;
@@ -48,15 +51,18 @@
this.searchTermChange.emit(event);
}
+ private subscription: Subscription;
+ private hasUnsavedChanges: boolean;
public topLvlMenu:MenuItemGroup;
public user:IUserProperties;
private topNavPlugins: Array<Plugin>;
constructor(private translateService:TranslateService,
@Inject('$state') private $state:ng.ui.IStateService,
- private userService:UserService,
+ private authService:AuthenticationService,
@Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
window.nav = this;
+
}
private _getTopLvlSelectedIndexByState = ():number => {
@@ -112,7 +118,7 @@
ngOnInit() {
console.log('Nav is init!', this.menuModel);
- this.user = this.userService.getLoggedinUser();
+ this.user = this.authService.getLoggedinUser();
this.topNavPlugins = _.filter(PluginsConfiguration.plugins, (plugin: Plugin) => {
return plugin.pluginDisplayOptions["tab"] !== undefined;
});
@@ -142,7 +148,6 @@
this.topLvlMenu = new MenuItemGroup(0, tmpArray, true);
this.topLvlMenu.selectedIndex = isNaN(this.topLvlSelectedIndex) ? this._getTopLvlSelectedIndexByState() : this.topLvlSelectedIndex;
-
this.generateMenu();
});
}
@@ -160,6 +165,7 @@
});
}
+
menuItemClick(itemGroup:MenuItemGroup, item:MenuItem) {
let onSuccessFunction = () => {
diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap
new file mode 100644
index 0000000..02e98e2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap
@@ -0,0 +1,59 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`filter-properties-assignemnt component should match current snapshot of artifact-tab component 1`] = `
+<filter-properties-assignment
+ allSelected="false"
+ clearAll={[Function Function]}
+ close={[Function Function]}
+ filterData={[Function FilterPropertiesAssignmentData]}
+ filterPopover={[Function ElementRef]}
+ footerButtons={[Function Object]}
+ onTypeSelected={[Function Function]}
+ search={[Function Function]}
+ searchProperties={[Function EventEmitter]}
+ selectAll={[Function Function]}
+ selectedTypes={[Function Object]}
+ someTypesSelectedAndThereIsPropertyName={[Function Function]}
+>
+ <popover-content
+ placement="bottom-right"
+ >
+ <form>
+ <div
+ class="field"
+ >
+ <label>
+ Resource Type
+ </label>
+ <div>
+ <checkbox
+ data-tests-id="filter-checkbox-all"
+ />
+ </div>
+
+ </div>
+ <div
+ class="field"
+ >
+ <label>
+ Property Name
+ </label>
+ <input
+ class="i-sdc-form-input"
+ data-tests-id="filter-box"
+ name="propertyName"
+ placeholder="Type here"
+ required=""
+ />
+ </div>
+ </form>
+ </popover-content><div
+ class="open-filter-button"
+ >
+ <div
+ class="sprite-new filter-icon"
+ data-tests-id="filter-button"
+ />
+ </div>
+</filter-properties-assignment>
+`;
diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html
index 9593ade..1c2d77a 100644
--- a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html
@@ -38,6 +38,6 @@
</div>
</form>
</popover-content>
-<div class="open-filter-button" [popover]="filterPopover" [ngClass]="{'open':showPopover}" (onShown)="showPopover = true" (onHidden)="showPopover = false">
+<div class="open-filter-button" [popover]="filterPopover" >
<div class="sprite-new filter-icon" data-tests-id="filter-button"></div>
</div>
diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts
new file mode 100644
index 0000000..bcc5535
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts
@@ -0,0 +1,141 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {FilterPropertiesAssignmentComponent} from "./filter-properties-assignment.component";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {FilterPropertiesAssignmentData} from "../../../../models/filter-properties-assignment-data";
+import {PopoverComponent} from "../../ui/popover/popover.component";
+
+
+
+describe('filter-properties-assignemnt component', () => {
+
+ let fixture: ComponentFixture<FilterPropertiesAssignmentComponent>;
+
+ beforeEach(
+ async(() => {
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [FilterPropertiesAssignmentComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(FilterPropertiesAssignmentComponent);
+
+ });
+ })
+ );
+
+
+ it('should match current snapshot of artifact-tab component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('on selectAll', () => {
+ let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData();
+ filterData.propertyName = 'testVal';
+ let typesOptions:Array<string> = ['option1', 'option2', 'option3'];
+ let selectedTypes:Object = {};
+
+ fixture.componentInstance.filterData = filterData;
+ fixture.componentInstance.typesOptions = typesOptions;
+ fixture.componentInstance.selectedTypes = selectedTypes;
+
+ fixture.componentInstance.selectAll();
+
+ let expectedRes = {"option1": false,"option2": false,"option3": false};
+ expect(fixture.componentInstance.selectedTypes).toEqual(expectedRes);
+ });
+
+
+ it ('on onTypeSelected allSelected set to False', () => {
+ let selectedTypes:Object = {"option1": true,"option2": false,"option3": true};
+ fixture.componentInstance.selectedTypes = selectedTypes;
+ fixture.componentInstance.allSelected = true;
+ fixture.componentInstance.onTypeSelected('option2');
+
+ expect(fixture.componentInstance.allSelected).toBe(false);
+ });
+
+ it ('on onTypeSelected allSelected remains True', () => {
+ let selectedTypes:Object = {"option1": true,"option2": true,"option3": true};
+ fixture.componentInstance.selectedTypes = selectedTypes;
+ fixture.componentInstance.allSelected = true;
+ fixture.componentInstance.onTypeSelected('option2');
+
+ expect(fixture.componentInstance.allSelected).toBe(true);
+ });
+
+ it ('on clearAll', () => {
+ let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData();
+ filterData.propertyName = 'testVal';
+ let selectedTypes:Object = {"option1": true,"option2": false,"option3": true};
+
+ fixture.componentInstance.filterData = filterData;
+ fixture.componentInstance.selectedTypes = selectedTypes;
+ fixture.componentInstance.allSelected = true;
+
+ fixture.componentInstance.clearAll();
+
+ expect(fixture.componentInstance.filterData.propertyName).toBe('');
+ expect(fixture.componentInstance.allSelected).toBe(false);
+ });
+
+ it ('someTypesSelectedAndThereIsPropertyName return True', ()=> {
+ let res = fixture.componentInstance.someTypesSelectedAndThereIsPropertyName();
+
+ expect(res).toBe(true)
+ });
+
+ it ('someTypesSelectedAndThereIsPropertyName return Null', ()=> {
+ let selectedTypes:Object = {"option1": true,"option2": false,"option3": true};
+ let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData();
+ filterData.propertyName = 'testVal';
+
+ fixture.componentInstance.selectedTypes = selectedTypes;
+ fixture.componentInstance.filterData = filterData;
+
+ let res = fixture.componentInstance.someTypesSelectedAndThereIsPropertyName();
+
+ expect(res).toBe(null)
+ });
+
+ it ('search', ()=> {
+
+ let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData();
+ filterData.selectedTypes = ["CP"];
+ fixture.componentInstance.filterData = filterData;
+
+ let componentType: string = 'resource';
+ fixture.componentInstance.componentType = componentType;
+
+ let selectedTypes:Object = {"option1": true,"CP": true,"option3": true};
+ fixture.componentInstance.selectedTypes = selectedTypes;
+
+ let temp:any;
+ let filterPopover: PopoverComponent = new PopoverComponent(temp , temp );
+ fixture.componentInstance.filterPopover = filterPopover;
+ fixture.componentInstance.filterPopover.hide = jest.fn();
+
+ fixture.componentInstance.search();
+
+ expect(fixture.componentInstance.filterData.selectedTypes).toEqual(["CP"]);
+ expect(fixture.componentInstance.filterPopover.hide).toHaveBeenCalled();
+ });
+
+ it('close', () => {
+ let temp:any;
+ let filterPopover: PopoverComponent = new PopoverComponent(temp , temp );
+ fixture.componentInstance.filterPopover = filterPopover;
+ fixture.componentInstance.filterPopover.hide = jest.fn();
+
+ fixture.componentInstance.close();
+
+ expect(fixture.componentInstance.filterPopover.hide).toHaveBeenCalled();
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html
index 41ecaa8..9d1a2fa 100644
--- a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html
@@ -29,8 +29,8 @@
[rowHeight]="200"
[reorderable]="false"
>
- <ngx-datatable-column prop="{{col.prop}}" [minWidth]="100" *ngFor="let col of columns">
- <template let-column="column" height="100" ngx-datatable-header-template>
+ <ngx-datatable-column *ngFor="let col of columns" prop="{{col.prop}}" [minWidth]="100" >
+ <ng-template let-column="column" height="100" ngx-datatable-header-template>
<span class="datatable-column-span">
<b>{{col.name}}</b>
<div *ngIf="canBeDeleted(col.name)" style="width: 45px !important; color: red; "
@@ -44,23 +44,23 @@
placeholder='Filter column...'
(keyup)='updateColumnFilter($event, col.prop)'
/>
- </template>
+ </ng-template>
</ngx-datatable-column>
<ngx-datatable-column *ngIf="addNewColumn" class="datatable-white-body-cell" [minWidth]="220" [maxWidth]="220" [width]="220" >
- <template ngx-datatable-header-template>
+ <ng-template ngx-datatable-header-template>
<gab-column-provider [pathsAndNames]="pathsandnames" (onCancel)="hideAddNewColumn()" (onSave)="refresh()"></gab-column-provider>
- </template>
- <template class="datatable-white-body-cell" ngx-datatable-cell-template>
- </template>
+ </ng-template>
+ <ng-template class="datatable-white-body-cell" ngx-datatable-cell-template>
+ </ng-template>
</ngx-datatable-column>
<ngx-datatable-column class="datatable-white-body-cell" [minWidth]="50" [maxWidth]="50" [width]="50" >
- <template ngx-datatable-header-template>
+ <ng-template ngx-datatable-header-template>
<div data-tests-id="gab-add-btn" class="add-btn add-btn-div" (click)="showAddNewColumn()">Add</div>
- </template>
- <template class="datatable-white-body-cell" ngx-datatable-cell-template>
- </template>
+ </ng-template>
+ <ng-template class="datatable-white-body-cell" ngx-datatable-cell-template>
+ </ng-template>
</ngx-datatable-column>
</ngx-datatable>
-</div>
\ No newline at end of file
+</div>
diff --git a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts
index 4de7ff0..ea8039e 100644
--- a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts
@@ -64,8 +64,8 @@
this.gabService.getArtifact(this.artifactid, this.resourceid, paths)
.subscribe(
response => {
- let typedServerResponse: IServerResponse = response.json() as IServerResponse;
- this.normalizeDataForNgxDatatable(typedServerResponse.data);
+ // let typedServerResponse: IServerResponse = response.json() as IServerResponse;
+ this.normalizeDataForNgxDatatable(response['data']);
},
() => {
this.ready = false;
diff --git a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts
new file mode 100644
index 0000000..fc76463
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts
@@ -0,0 +1,52 @@
+import { async, ComponentFixture } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import 'jest-dom/extend-expect';
+import {HierarchyNavigationComponent} from "./hierarchy-navigation.component";
+import {HierarchyDisplayOptions} from "./hierarchy-display-options";
+
+
+describe('hierarchyNavigationComponent', () => {
+ let fixture: ComponentFixture<HierarchyNavigationComponent>;
+ let hierarchyDisplayOptions: HierarchyDisplayOptions;
+ beforeEach(
+ async(() => {
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [HierarchyNavigationComponent]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(HierarchyNavigationComponent);
+ hierarchyDisplayOptions = new HierarchyDisplayOptions("id", "name", "children");
+ fixture.componentInstance.displayOptions = hierarchyDisplayOptions;
+ fixture.detectChanges();
+ fixture.componentInstance.displayData = [{name: "aaa", id: "1", children: [{name: "bbb", id: "1.1"}, {name: "ccc", id: "1.2", children: [{name: "aaa", id: "1.2.1"}]}]}, {name: "bbb", id: "2"}];
+ fixture.detectChanges();
+ });
+ })
+ );
+
+ it('should have a selected class after user click on a tree node',
+ () => {
+ let firstNodeElement = fixture.debugElement.query(By.css('.node-item'));
+ fixture.componentInstance.updateSelected.subscribe((item) => {
+ fixture.componentInstance.selectedItem = item.id;
+ fixture.detectChanges();
+ });
+ firstNodeElement.nativeElement.click();
+ fixture.whenStable().then(() => {
+ expect(firstNodeElement.children[0].nativeElement).toHaveClass('selected');
+ });
+ });
+
+ it('should call onClick function when user click on a tree node',
+ () => {
+ spyOn(fixture.componentInstance, 'onClick');
+ let firstNodeElement = fixture.debugElement.query(By.css('.node-item')).nativeElement;
+ firstNodeElement.click();
+ expect(fixture.componentInstance.onClick).toHaveBeenCalled();
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts
index 1698157..8b20aa2 100644
--- a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts
@@ -21,7 +21,6 @@
import {Component, Input, Output, EventEmitter} from '@angular/core';
import {HierarchyDisplayOptions} from './hierarchy-display-options';
-
@Component({
selector: 'hierarchy-navigation',
templateUrl: './hierarchy-navigation.component.html',
@@ -32,7 +31,6 @@
@Input() displayData: Array<any>;
@Input() selectedItem: any;
@Input() displayOptions: HierarchyDisplayOptions;
-
@Output() updateSelected:EventEmitter<any> = new EventEmitter();
onClick = ($event, item) => {
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
index 3ef1f57..eeba590 100644
--- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
@@ -35,33 +35,37 @@
<div class="no-data" *ngIf="!inputs || !inputs.length">No data to display</div>
<div>
<div class="table-row" *ngFor="let input of inputs" (click)="selectedInputId = input.path" [ngClass]="{'selected': selectedInputId && selectedInputId === input.path}">
+ <!-- Property Name -->
<div class="table-cell col1">
<div class="inner-cell-div" tooltip="{{input.name}}"><span class="property-name">{{input.name}}</span></div>
<span *ngIf="input.description"
class="property-description-icon sprite-new show-desc"
tooltip="{{input.description}}" tooltipDelay="0"></span>
</div>
+ <!-- From Instance -->
<div class="table-cell col3">
<div class="inner-cell-div" tooltip="{{instanceNamesMap[input.instanceUniqueId]?.name}}">
<span>{{instanceNamesMap[input.instanceUniqueId]?.name}}</span>
</div>
</div>
+ <!-- Type -->
<div class="table-cell col2">
<div class="inner-cell-div" tooltip="{{input.type | contentAfterLastDot}}">
<span>{{input.type | contentAfterLastDot}}</span>
</div>
</div>
+ <!-- Value -->
<div class="table-cell valueCol input-value-col" [class.inner-table-container]="input.childrenProperties || !input.isSimpleType">
<dynamic-element class="value-input"
- *ngIf="input.isSimpleType"
+ *ngIf="checkInstanceFePropertiesMapIsFilled() && input.isSimpleType"
pattern="validationUtils.getValidationPattern(input.type)"
[value]="input.defaultValueObj"
[type]="input.type"
- [constraints]="input.constraints"
[name]="input.name"
(elementChanged)="onInputChanged(input, $event)"
[readonly]="readonly"
- [testId]="'input-' + input.name">
+ [testId]="'input-' + input.name"
+ [constraints] = "getConstraints(input)">
</dynamic-element>
<div class="delete-button-container">
<span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span>
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
index d95198f..f45d5a8 100644
--- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
@@ -26,6 +26,8 @@
import { InputFEModel } from "app/models";
import { ModalService } from "../../../services/modal.service";
import { InstanceFeDetails } from "app/models/instance-fe-details";
+import { InstanceFePropertiesMap } from "../../../../models/properties-inputs/property-fe-map";
+import { DataTypeService } from "../../../services/data-type.service";
@Component({
selector: 'inputs-table',
@@ -41,6 +43,8 @@
@Output() inputChanged: EventEmitter<any> = new EventEmitter<any>();
@Output() deleteInput: EventEmitter<any> = new EventEmitter<any>();
+ @Input() fePropertiesMap: InstanceFePropertiesMap;
+
sortBy: String;
reverse: boolean;
selectedInputToDelete: InputFEModel;
@@ -74,7 +78,8 @@
};
- constructor(private modalService: ModalService) {
+ constructor(private modalService: ModalService, private dataTypeService: DataTypeService){
+ var x = 5
}
@@ -89,9 +94,40 @@
};
openDeleteModal = (input: InputFEModel) => {
+ console.log('exist inputs: ' + this.inputs)
+
+
this.selectedInputToDelete = input;
this.modalService.createActionModal("Delete Input", "Are you sure you want to delete this input?", "Delete", this.onDeleteInput, "Close").instance.open();
}
+
+ getConstraints(input:InputFEModel): string[]{
+
+ if (input.inputPath){
+ const pathValuesName = input.inputPath.split('#');
+ const rootPropertyName = pathValuesName[0];
+ const propertyName = pathValuesName[1];
+ let filterredRootPropertyType = _.values(this.fePropertiesMap)[0].filter(property =>
+ property.name == rootPropertyName);
+ if (filterredRootPropertyType.length > 0){
+ let rootPropertyType = filterredRootPropertyType[0].type;
+ return this.dataTypeService.getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName);
+ }else{
+ return null;
+ }
+
+ }
+ // else if(input.constraints.length > 0){
+ // return input.constraints[0].validValues
+ // }
+ else{
+ return null;
+ }
+ }
+
+ checkInstanceFePropertiesMapIsFilled(){
+ return _.keys(this.fePropertiesMap).length > 0
+ }
}
diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts
index aa5f242..9613439 100644
--- a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts
@@ -14,12 +14,11 @@
* permissions and limitations under the License.
*/
-
-import { Component, Input, Output, EventEmitter } from "@angular/core";
-import { PolicyInstance } from "app/models";
-import { ModalService } from "../../../services/modal.service";
-import { InstanceFeDetails } from "app/models/instance-fe-details";
-import {TranslateService} from 'app/ng2/shared/translator/translate.service';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { PolicyInstance } from 'app/models';
+import { InstanceFeDetails } from 'app/models/instance-fe-details';
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { ModalService } from '../../../services/modal.service';
@Component({
selector: 'policies-table',
@@ -28,13 +27,13 @@
})
export class PoliciesTableComponent {
- @Input() policies: Array<PolicyInstance>;
+ @Input() policies: PolicyInstance[];
@Input() instanceNamesMap: Map<string, InstanceFeDetails>;
@Input() readonly: boolean;
@Input() isLoading: boolean;
@Output() deletePolicy: EventEmitter<any> = new EventEmitter<any>();
- sortBy: String;
+ sortBy: string;
reverse: boolean;
selectedPolicyToDelete: PolicyInstance;
deleteMsgTitle: string;
@@ -42,43 +41,39 @@
modalDeleteBtn: string;
modalCancelBtn: string;
- sort = (sortBy) => {
- this.reverse = (this.sortBy === sortBy) ? !this.reverse : true;
- let reverse = this.reverse ? 1 : -1;
- this.sortBy = sortBy;
- let instanceNameMapTemp = this.instanceNamesMap;
- let itemIdx1Val = "";
- let itemIdx2Val = "";
- this.policies.sort(function (itemIdx1, itemIdx2) {
- if (sortBy == 'instanceUniqueId') {
- itemIdx1Val = (itemIdx1[sortBy] && instanceNameMapTemp[itemIdx1[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx1[sortBy]].name : "";
- itemIdx2Val = (itemIdx2[sortBy] && instanceNameMapTemp[itemIdx2[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx2[sortBy]].name : "";
- }
- else {
- itemIdx1Val = itemIdx1[sortBy];
- itemIdx2Val = itemIdx2[sortBy];
- }
- if (itemIdx1Val < itemIdx2Val) {
- return -1 * reverse;
- }
- else if (itemIdx1Val > itemIdx2Val) {
- return 1 * reverse;
- }
- else {
- return 0;
- }
- });
- };
-
-
constructor(private modalService: ModalService, private translateService: TranslateService) {
}
+ sort = (sortBy) => {
+ this.reverse = (this.sortBy === sortBy) ? !this.reverse : true;
+ const reverse = this.reverse ? 1 : -1;
+ this.sortBy = sortBy;
+ const instanceNameMapTemp = this.instanceNamesMap;
+ let itemIdx1Val = '';
+ let itemIdx2Val = '';
+ this.policies.sort((itemIdx1, itemIdx2) => {
+ if (sortBy === 'instanceUniqueId') {
+ itemIdx1Val = (itemIdx1[sortBy] && instanceNameMapTemp[itemIdx1[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx1[sortBy]].name : '';
+ itemIdx2Val = (itemIdx2[sortBy] && instanceNameMapTemp[itemIdx2[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx2[sortBy]].name : '';
+ } else {
+ itemIdx1Val = itemIdx1[sortBy];
+ itemIdx2Val = itemIdx2[sortBy];
+ }
+ if (itemIdx1Val < itemIdx2Val) {
+ return -1 * reverse;
+ } else if (itemIdx1Val > itemIdx2Val) {
+ return 1 * reverse;
+ } else {
+ return 0;
+ }
+ });
+ }
+
ngOnInit() {
- this.translateService.languageChangedObservable.subscribe(lang => {
- this.deleteMsgTitle = this.translateService.translate("DELETE_POLICY_TITLE");
- this.modalDeleteBtn = this.translateService.translate("MODAL_DELETE");
- this.modalCancelBtn = this.translateService.translate("MODAL_CANCEL");
+ this.translateService.languageChangedObservable.subscribe((lang) => {
+ this.deleteMsgTitle = this.translateService.translate('DELETE_POLICY_TITLE');
+ this.modalDeleteBtn = this.translateService.translate('MODAL_DELETE');
+ this.modalCancelBtn = this.translateService.translate('MODAL_CANCEL');
});
}
@@ -86,15 +81,13 @@
onDeletePolicy = () => {
this.deletePolicy.emit(this.selectedPolicyToDelete);
this.modalService.closeCurrentModal();
- };
+ }
openDeleteModal = (policy: PolicyInstance) => {
this.selectedPolicyToDelete = policy;
- this.translateService.languageChangedObservable.subscribe(lang => {
- this.deleteMsgBodyTxt = this.translateService.translate("DELETE_POLICY_MSG", {policyName: policy.name});
+ this.translateService.languageChangedObservable.subscribe((lang) => {
+ this.deleteMsgBodyTxt = this.translateService.translate('DELETE_POLICY_MSG', {policyName: policy.name});
this.modalService.createActionModal(this.deleteMsgTitle, this.deleteMsgBodyTxt, this.modalDeleteBtn, this.onDeletePolicy, this.modalCancelBtn).instance.open();
});
}
}
-
-
diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts
index f780c62..57cb13c 100644
--- a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts
+++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts
@@ -14,12 +14,12 @@
* permissions and limitations under the License.
*/
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {PoliciesTableComponent} from "./policies-table.component";
-import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {GlobalPipesModule} from "../../../pipes/global-pipes.module";
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from 'app/ng2/shared/translator/translate.module';
+import { GlobalPipesModule } from '../../../pipes/global-pipes.module';
+import { PoliciesTableComponent } from './policies-table.component';
@NgModule({
declarations: [
@@ -38,4 +38,4 @@
providers: []
})
export class PoliciesTableModule {
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html
index c4639ae..f6396e6 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html
@@ -12,8 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-
-
+
+
<div *ngIf="!property.hidden" class="dynamic-property-row nested-level-{{nestedLevel}}" [@fadeIn]
[ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName, 'readonly': property.isDisabled ||property.isDeclared}"
[class.with-top-border]="property.isChildOfListOrMap"
@@ -48,13 +48,13 @@
pattern="validationUtils.getValidationPattern(property.type)"
[value]="property.isDeclared ? property.value : property.valueObj"
[type]="property.isDeclared ? 'string' : property.type"
- [childType]="property.schema.property.type"
[name]="property.name"
[path]="property.propertiesName"
- [constraints]="property.constraints"
(elementChanged)="onElementChanged($event)"
[readonly]="readonly || property.isDeclared || property.isDisabled"
[testId]="'prop-' + propertyTestsId"
+ [declared] = "property.isDeclared"
+ [constraints] = "constraints"
></dynamic-element>
</div>
</ng-container>
@@ -69,7 +69,7 @@
<ng-container *ngIf="!property.isDeclared">
<a *ngIf="(propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && !property.isChildOfListOrMap" class="property-icon add-item" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly || preventInsertItem(property)}" [attr.data-tests-id]="'add-to-list-' + propertyTestsId">Add value to list</a>
<span *ngIf="property.isChildOfListOrMap" (click)="deleteItem.emit(property);" class="property-icon sprite-new delete-item-icon" [ngClass]="{'disabled':readonly}" [attr.data-tests-id]="'delete-from-list-' + propertyTestsId"></span>
- <span *ngIf="!isPropertyFEModel && (propType == derivedPropertyTypes.COMPLEX || ((propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && hasChildren))" (click)="expandChildById(propPath)" class="property-icon sprite-new round-expand-icon" [class.open]="expandedChildId.indexOf(propPath) == 0" [attr.data-tests-id]="'expand-' + propertyTestsId"></span>
+ <span *ngIf="!isPropertyFEModel && (propType == derivedPropertyTypes.COMPLEX || ((propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && hasChildren))" (click)="expandChildById(propPath)" class="property-icon sprite-new round-expand-icon" [class.open]="expandedChildId.indexOf(propPath) == 0" [attr.data-tests-id]="'expand-' + propertyTestsId" ></span>
</ng-container>
</div>
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less
index 0adce2c..1007292 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less
@@ -60,7 +60,7 @@
align-self:center;
cursor:pointer;
}
-
+
}
.filtered {
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts
index 6e19c95..715426f 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts
@@ -23,7 +23,7 @@
import { PropertyFEModel, DerivedFEProperty, DerivedPropertyType } from "app/models";
import { PROPERTY_TYPES } from 'app/utils';
import { DataTypeService } from "../../../../services/data-type.service";
-import { trigger, state, style, transition, animate } from '@angular/core';
+import { trigger, state, style, transition, animate } from '@angular/animations';
import {PropertiesUtils} from "../../../../pages/properties-assignment/services/properties.utils";
import {IUiElementChangeEvent} from "../../../ui/form-components/ui-element-base.component";
import {DynamicElementComponent} from "../../../ui/dynamic-element/dynamic-element.component";
@@ -42,6 +42,7 @@
isPropertyFEModel: boolean;
nestedLevel: number;
propertyTestsId: string;
+ constraints:string[];
@Input() canBeDeclared: boolean;
@Input() property: PropertyFEModel | DerivedFEProperty;
@@ -72,7 +73,30 @@
this.propPath = (this.property instanceof PropertyFEModel) ? this.property.name : this.property.propertiesName;
this.nestedLevel = (this.property.propertiesName.match(/#/g) || []).length;
this.rootProperty = (this.rootProperty) ? this.rootProperty : <PropertyFEModel>this.property;
- this.propertyTestsId = this.getPropertyTestsId();
+ this.propertyTestsId = this.getPropertyTestsId();
+
+ this.initConsraintsValues();
+
+
+ }
+
+ initConsraintsValues(){
+ let primitiveProperties = ['string', 'integer', 'float', 'boolean'];
+
+ //Property has constraints
+ if(this.property.constraints){
+ this.constraints = this.property.constraints[0].validValues
+ }
+
+ //Complex Type
+ else if (primitiveProperties.indexOf(this.rootProperty.type) == -1 && primitiveProperties.indexOf(this.property.type) >= 0 ){
+ this.constraints = this.dataTypeService.getConstraintsByParentTypeAndUniqueID(this.rootProperty.type, this.property.name);
+ }
+
+ else{
+ this.constraints = null;
+ }
+
}
ngDoCheck() {
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html
index 2068b17..89b85d3 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html
@@ -37,18 +37,18 @@
<div class="no-data" *ngIf="!fePropertiesMap || !(fePropertiesMap | keys).length">No data to display</div>
<ng-container *ngFor="let instanceId of fePropertiesMap | keys; trackBy:vspId">
+ <!-- Icon & Instance Name -->
<div class="table-rows-header white-sub-header" *ngIf="feInstanceNamesMap">
-
-
<span [ngClass]="['prop-instance-icon', feInstanceNamesMap[instanceId].iconClass, 'small']"></span>
- {{feInstanceNamesMap[instanceId].name}}
+ {{feInstanceNamesMap[instanceId].name}}
<div class="sprite-new archive-label" *ngIf="feInstanceNamesMap[instanceId].originArchived == true"></div>
</div>
-
- <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm | orderBy:{path: path, direction: direction}; trackBy:property?.name "
+
+ <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm | propertiesOrderBy:{path: path, direction: direction}; trackBy:property?.name "
(click)="onClickPropertyRow(property, instanceId, $event)" [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name, 'readonly': property.isDisabled || property.isDeclared}">
<div class="table-cell col1" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared">
+ <!-- Property Name -->
<div class="property-name">
<checkbox *ngIf="hasDeclareOption" [(checked)]="property.isSelected" [disabled]="property.isDisabled || property.isDeclared || readonly"
(checkedChange)="propertyChecked(property)" [attr.data-tests-id]="property.name"></checkbox>
@@ -62,16 +62,19 @@
<span *ngIf="showDelete" class="sprite-new delete-btn" [ngClass]="{'disabled' : property.isDisabled || property.isDeclared}" (click)="openDeleteModal(property)" data-tests-id="delete-input-button"></span>
</div>
</div>
+ <!-- Property Type -->
<div class="table-cell col2" *ngIf="!hidePropertyType">
<div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}">
<span>{{property.type | contentAfterLastDot}}</span>
</div>
</div>
+ <!-- Property ES (Entry Schema) -->
<div class="table-cell col3" *ngIf="!hidePropertyType">
<div *ngIf="property.schema && property.schema.property && property.schema.property.type" class="inner-cell-div" tooltip="{{property.schema.property.type | contentAfterLastDot}}">
<span>{{property.schema.property.type | contentAfterLastDot}}</span>
</div>
</div>
+ <!-- Property Value -->
<div class="table-cell valueCol">
<!-- [ngClass]="{'filtered':property.name === propertyNameSearchText}" (selectProperty)="propertySelected(property, $event, flatProperty.propertiesName)" [propType]="property.type" [propSchema]="property.schema" [propKey]="" [propValue]="property.value"-->
<dynamic-property
@@ -86,9 +89,10 @@
(expandChild)="property.updateExpandedChildPropertyId($event)"
(clickOnPropertyRow)="onClickPropertyInnerRow($event, instanceId)"
(checkProperty)="propertyChecked(property, $event)"
- >
- </dynamic-property>
+ >
+
+ </dynamic-property>
</div>
</div>
</ng-container>
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts
new file mode 100644
index 0000000..ea524e5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts
@@ -0,0 +1,175 @@
+import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
+import { ComponentFixture } from '@angular/core/testing';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { DerivedFEProperty } from '../../../../models/properties-inputs/derived-fe-property';
+import { PropertyBEModel } from '../../../../models/properties-inputs/property-be-model';
+import { PropertyFEModel } from '../../../../models/properties-inputs/property-fe-model';
+import { ContentAfterLastDotPipe } from '../../../pipes/contentAfterLastDot.pipe';
+import { KeysPipe } from '../../../pipes/keys.pipe';
+import { PropertiesOrderByPipe } from '../../../pipes/properties-order-by.pipe';
+import { SearchFilterPipe } from '../../../pipes/searchFilter.pipe';
+import { ModalService } from '../../../services/modal.service';
+import { PropertiesService } from '../../../services/properties.service';
+import { PropertiesTableComponent, PropertyRowSelectedEvent } from './properties-table.component';
+
+describe('properties-table component', () => {
+
+ let fixture: ComponentFixture<PropertiesTableComponent>;
+ let propertiesServiceMock: Partial<PropertiesService>;
+ let modalServiceMock: Partial<ModalService>;
+
+ beforeEach(
+ () => {
+ propertiesServiceMock = {
+ undoDisableRelatedProperties: jest.fn(),
+ disableRelatedProperties: jest.fn()
+ };
+ modalServiceMock = {
+
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [
+ PropertiesTableComponent,
+ KeysPipe,
+ PropertiesOrderByPipe,
+ SearchFilterPipe,
+ ContentAfterLastDotPipe
+ ],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: PropertiesService, useValue: propertiesServiceMock},
+ {provide: ModalService, useValue: modalServiceMock}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(PropertiesTableComponent);
+ });
+ }
+ );
+
+ it('When Properties assignment page is loaded, it is sorted by property name (acsending)', () => {
+ const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true);
+ const changes = {
+ fePropertiesMap: fePropertiesMapValues
+ };
+
+ // init values before ngOnChanges was called
+ fixture.componentInstance.sortBy = 'existingValue';
+
+ fixture.componentInstance.ngOnChanges(changes);
+
+ expect (fixture.componentInstance.reverse).toEqual(true);
+ // expect (fixture.componentInstance.direction).toEqual(1);
+ expect (fixture.componentInstance.direction).toEqual(fixture.componentInstance.ascUpperLettersFirst);
+ expect (fixture.componentInstance.sortBy).toEqual('name');
+ expect (fixture.componentInstance.path.length).toEqual(1);
+ expect (fixture.componentInstance.path[0]).toEqual('name');
+ });
+
+ it('When ngOnChanges is called without fePropertiesMap,' +
+ ' sortBy will remain as it was', () => {
+ const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true);
+ const changes = {
+ dummyKey: fePropertiesMapValues
+ };
+
+ // init values before ngOnChanges was called
+ fixture.componentInstance.sortBy = 'existingValue';
+ fixture.componentInstance.sort = jest.fn();
+
+ fixture.componentInstance.ngOnChanges(changes);
+
+ expect (fixture.componentInstance.sortBy).toEqual('existingValue');
+ });
+
+ it ('When sort is called init this.direction to 1', () => {
+ // init values
+ fixture.componentInstance.reverse = false;
+ fixture.componentInstance.direction = 0;
+ fixture.componentInstance.sortBy = 'initialize.Value';
+ fixture.componentInstance.path = [];
+
+ // call sore function
+ fixture.componentInstance.sort('initialize.Value');
+
+ // expect that
+ expect (fixture.componentInstance.reverse).toBe(true);
+ expect (fixture.componentInstance.direction).toBe(fixture.componentInstance.ascUpperLettersFirst);
+ expect (fixture.componentInstance.sortBy).toBe('initialize.Value');
+ expect (fixture.componentInstance.path.length).toBe(2);
+ expect (fixture.componentInstance.path[0]).toBe('initialize');
+ expect (fixture.componentInstance.path[1]).toBe('Value');
+ });
+
+ it ('When sort is called init this.direction to -1', () => {
+ // init values
+ fixture.componentInstance.reverse = true;
+ fixture.componentInstance.direction = 0;
+ fixture.componentInstance.sortBy = 'initialize.Value';
+ fixture.componentInstance.path = [];
+
+ // call sore function
+ fixture.componentInstance.sort('initialize.Value');
+
+ // expect that
+ expect (fixture.componentInstance.reverse).toBe(false);
+ expect (fixture.componentInstance.direction).toBe(fixture.componentInstance.descLowerLettersFirst);
+ });
+
+ it ('When onPropertyChanged is called, event is emitted' , () => {
+ spyOn(fixture.componentInstance.emitter, 'emit');
+ fixture.componentInstance.onPropertyChanged('testProperty');
+ expect(fixture.componentInstance.emitter.emit).toHaveBeenCalledWith('testProperty');
+ });
+
+ it ('When onClickPropertyRow is called, selectedPropertyId is updated and event is emitted.' , () => {
+ const propertyFEModel = new PropertyFEModel(new PropertyBEModel());
+ propertyFEModel.name = 'propertyName';
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName');
+
+ spyOn(fixture.componentInstance.selectPropertyRow, 'emit');
+ fixture.componentInstance.onClickPropertyRow(propertyFEModel, 'instanceName');
+
+ expect (fixture.componentInstance.selectedPropertyId).toBe('propertyName');
+ expect (fixture.componentInstance.selectPropertyRow.emit).toHaveBeenCalledWith(propertyRowSelectedEvent);
+ });
+
+ it ('When onClickPropertyInnerRow is called, event is emitted.' , () => {
+ const derivedFEProperty = new DerivedFEProperty(new PropertyBEModel());
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(derivedFEProperty, 'instanceName');
+ spyOn(fixture.componentInstance.selectPropertyRow, 'emit');
+ fixture.componentInstance.onClickPropertyInnerRow(derivedFEProperty, 'instanceName');
+
+ expect (fixture.componentInstance.selectPropertyRow.emit).toHaveBeenCalledWith(propertyRowSelectedEvent);
+ });
+
+ it ('When propertyChecked is called, propertiesService.undoDisableRelatedProperties is called and event is emitted.' , () => {
+
+ const propertyFEModel = new PropertyFEModel(new PropertyBEModel());
+ propertyFEModel.isSelected = false;
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName1');
+
+ spyOn(fixture.componentInstance.updateCheckedPropertyCount, 'emit');
+ fixture.componentInstance.propertyChecked(propertyFEModel);
+ expect (propertiesServiceMock.undoDisableRelatedProperties).toHaveBeenCalledWith(propertyFEModel, undefined);
+ expect (fixture.componentInstance.updateCheckedPropertyCount.emit).toHaveBeenCalledWith(false);
+ });
+
+ it ('When propertyChecked is called, propertiesService.disableRelatedProperties is called and event is emitted.' , () => {
+
+ const propertyFEModel = new PropertyFEModel(new PropertyBEModel());
+ propertyFEModel.isSelected = true;
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName1');
+
+ spyOn(fixture.componentInstance.updateCheckedPropertyCount, 'emit');
+ fixture.componentInstance.propertyChecked(propertyFEModel);
+ expect (propertiesServiceMock.disableRelatedProperties).toHaveBeenCalledWith(propertyFEModel, undefined);
+ expect (fixture.componentInstance.updateCheckedPropertyCount.emit).toHaveBeenCalledWith(true);
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
index 0cc1881..e499b37 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
@@ -8,9 +8,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.
@@ -19,33 +19,33 @@
* ============LICENSE_END=========================================================
*/
-import { Component, Input, Output, EventEmitter} from "@angular/core";
-import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models";
-import {PropertiesService} from "../../../services/properties.service";
-import {ModalService} from "../../../services/modal.service";
-import { InstanceFeDetails } from "../../../../models/instance-fe-details";
+import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
+import { DerivedFEProperty, InstanceFePropertiesMap, PropertyFEModel } from 'app/models';
+import { InstanceFeDetails } from '../../../../models/instance-fe-details';
+import { PropertiesService } from '../../../services/properties.service';
+import { ModalService } from '../../../services/modal.service';
@Component({
selector: 'properties-table',
templateUrl: './properties-table.component.html',
styleUrls: ['./properties-table.component.less']
})
-export class PropertiesTableComponent {
+export class PropertiesTableComponent implements OnChanges {
@Input() fePropertiesMap: InstanceFePropertiesMap;
@Input() feInstanceNamesMap: Map<string, InstanceFeDetails>;
@Input() selectedPropertyId: string;
- @Input() propertyNameSearchText:string;
- @Input() searchTerm:string;
- @Input() readonly:boolean;
- @Input() isLoading:boolean;
- @Input() hasDeclareOption:boolean;
- @Input() hidePropertyType:boolean;
+ @Input() propertyNameSearchText: string;
+ @Input() searchTerm: string;
+ @Input() readonly: boolean;
+ @Input() isLoading: boolean;
+ @Input() hasDeclareOption: boolean;
+ @Input() hidePropertyType: boolean;
@Input() showDelete:boolean;
-
+
@Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
@Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>();
- @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption and hasDeclareListOption
+ @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); // only for hasDeclareOption
@Output() updateCheckedChildPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareListOption
@Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
private selectedPropertyToDelete: PropertyFEModel;
@@ -53,41 +53,48 @@
sortBy: String;
reverse: boolean;
direction: number;
- path:string[];
+ path: string[];
- sort(sortBy){
+ readonly ascUpperLettersFirst = 1;
+ readonly descLowerLettersFirst = -1;
+
+ constructor(private propertiesService: PropertiesService, private modalService: ModalService ) {
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.fePropertiesMap) {
+ this.sortBy = '';
+ this.sort('name');
+ }
+ }
+
+ sort(sortBy) {
this.reverse = (this.sortBy === sortBy) ? !this.reverse : true;
- this.direction = this.reverse ? 1 : -1;
+ this.direction = this.reverse ? this.ascUpperLettersFirst : this.descLowerLettersFirst;
this.sortBy = sortBy;
this.path = sortBy.split('.');
}
- constructor (private propertiesService:PropertiesService, private modalService: ModalService){
- }
-
- ngOnInit() {
- }
-
onPropertyChanged = (property) => {
this.emitter.emit(property);
- };
+ }
// Click on main row (row of propertyFEModel)
- onClickPropertyRow = (property:PropertyFEModel, instanceName:string, event?) => {
- //event && event.stopPropagation();
+ onClickPropertyRow = (property: PropertyFEModel, instanceName: string, event?) => {
+ // event && event.stopPropagation();
this.selectedPropertyId = property.name;
- let propertyRowSelectedEvent:PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName);
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName);
this.selectPropertyRow.emit(propertyRowSelectedEvent);
- };
+ }
// Click on inner row (row of DerivedFEProperty)
- onClickPropertyInnerRow = (property:DerivedFEProperty, instanceName:string) => {
- let propertyRowSelectedEvent:PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName);
+ onClickPropertyInnerRow = (property: DerivedFEProperty, instanceName: string) => {
+ const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName);
this.selectPropertyRow.emit(propertyRowSelectedEvent);
}
propertyChecked = (prop: PropertyFEModel, childPropName?: string) => {
- let isChecked: boolean = (!childPropName)? prop.isSelected : prop.flattenedChildren.find(prop => prop.propertiesName == childPropName).isSelected;
+ const isChecked: boolean = (!childPropName) ? prop.isSelected : prop.flattenedChildren.find((prop) => prop.propertiesName == childPropName).isSelected;
if (!isChecked) {
this.propertiesService.undoDisableRelatedProperties(prop, childPropName);
@@ -116,11 +123,10 @@
}
export class PropertyRowSelectedEvent {
- propertyModel:PropertyFEModel | DerivedFEProperty;
- instanceName:string;
- constructor ( propertyModel:PropertyFEModel | DerivedFEProperty, instanceName:string ){
+ propertyModel: PropertyFEModel | DerivedFEProperty;
+ instanceName: string;
+ constructor( propertyModel: PropertyFEModel | DerivedFEProperty, instanceName: string ) {
this.propertyModel = propertyModel;
this.instanceName = instanceName;
}
}
-
diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts
index cb8c9a6..4d968a0 100644
--- a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts
+++ b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts
@@ -4,7 +4,6 @@
import {FormsModule} from "@angular/forms";
import {UiElementsModule} from "../../ui/ui-elements.module";
import {CommonModule} from "@angular/common";
-import {HttpModule} from "@angular/http";
import {FilterChildPropertiesPipe} from "./pipes/filterChildProperties.pipe";
import {GlobalPipesModule} from "../../../pipes/global-pipes.module";
import {PropertiesService} from "../../../services/properties.service";
@@ -13,7 +12,6 @@
@NgModule({
imports: [
FormsModule,
- HttpModule,
CommonModule,
GlobalPipesModule,
UiElementsModule,
diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts
index 2e3c21c..d41b580 100644
--- a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts
@@ -9,6 +9,7 @@
import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils";
import {Requirement} from "../../../../models/requirement";
import {Capability, RequirementCapabilityModel} from "../../../../models/capability";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
const REQUIREMENT = 'Requirement';
const CAPABILITY = 'Capability';
@@ -24,14 +25,9 @@
@Input() optionalRequirementsMap:Dictionary<Requirement[]>; //optional requirement map - key is type, value is array of requirements
@Input() optionalCapabilitiesMap:Dictionary<Capability[]>; //optional capabilities map - key is type, value is array of capabilities
-
@Input() selectedReqOrCapOption:string; // the selection value chosen by the user (options: requirement / capability )
-
- @Input() currentComponent:ComponentModel;
@Input() componentInstanceId:string;
-
@Input() selectedReqOrCapModel:RequirementCapabilityModel;
-
@Output() updateSelectedReqOrCap:EventEmitter<RequirementCapabilityModel> = new EventEmitter<RequirementCapabilityModel>();
types:Array<string> = [];
@@ -51,7 +47,8 @@
private _loadingCapabilityProperties: Array<Capability>;
constructor(private componentInstanceServiceNg2:ComponentInstanceServiceNg2,
- private propertiesUtils:PropertiesUtils) {
+ private propertiesUtils:PropertiesUtils,
+ private workspaceService: WorkspaceService) {
this.selectOptions = [new RadioButtonModel(REQUIREMENT, REQUIREMENT), new RadioButtonModel(CAPABILITY, CAPABILITY)];
this._loadingCapabilityProperties = [];
}
@@ -171,14 +168,13 @@
}
}
-
private setCapabilityProperties = ():void => {
let selectedCapability = <Capability>this.selectedReqOrCapModel;
if (!selectedCapability.properties) {
this.loadingCapabilityProperties = true;
if (this._loadingCapabilityProperties.indexOf(selectedCapability) == -1) {
this._loadingCapabilityProperties.push(selectedCapability);
- this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.currentComponent, this.componentInstanceId, selectedCapability)
+ this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.componentInstanceId, selectedCapability)
.subscribe((response: Array<PropertyModel>) => {
if (this.selectedReqOrCapModel === selectedCapability) {
delete this.loadingCapabilityProperties;
diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less
index 5830c06..f4d673d 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less
+++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less
@@ -50,7 +50,7 @@
}
.operation-name {
- .s_1;
+ // .s_1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts
index ebcf9eb..08e6c36 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts
@@ -14,34 +14,38 @@
* permissions and limitations under the License.
*/
-import {Component, Input, ComponentRef} from '@angular/core';
-import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
-import {ComponentInstanceServiceNg2} from 'app/ng2/services/component-instance-services/component-instance.service';
-import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
-import {ModalService} from 'app/ng2/services/modal.service';
-import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
+import { Component, ComponentRef, Input } from '@angular/core';
import {
- ModalModel,
ButtonModel,
- OperationModel,
- Service,
- ServiceInstanceObject,
- PropertyFEModel,
- PropertyBEModel,
+ CapabilitiesGroup,
+ Capability,
+ Component as TopologyTemplate,
InputBEModel,
InterfaceModel,
- CapabilitiesGroup,
- Capability
+ ModalModel,
+ OperationModel,
+ PropertyBEModel,
+ PropertyFEModel
} from 'app/models';
-import {ServiceConsumptionCreatorComponent} from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component';
-
+import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
+import { ServiceConsumptionCreatorComponent } from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component';
+import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service';
+import { ComponentServiceNg2 } from 'app/ng2/services/component-services/component.service';
+import { ModalService } from 'app/ng2/services/modal.service';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { Resource } from '../../../../models/components/resource';
+import { FullComponentInstance } from '../../../../models/componentsInstances/fullComponentInstance';
+import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces';
+import { ComponentFactory } from '../../../../utils/component-factory';
+import { ComponentType } from '../../../../utils/constants';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
export class ConsumptionInput extends PropertyFEModel{
inputId: string;
type: string;
source: string;
value: any;
- constraints: Array<any>;
+ constraints: any[];
constructor(input?: any) {
super(input);
@@ -49,19 +53,20 @@
this.inputId = input.inputId;
this.type = input.type;
this.source = input.source;
- this.value = input.value || "";
+ this.value = input.value || '';
this.constraints = input.constraints;
}
}
}
+// tslint:disable-next-line:max-classes-per-file
export class ConsumptionInputDetails extends ConsumptionInput {
name: string;
expanded: boolean;
assignValueLabel: string;
- associatedProps: Array<string>;
- associatedInterfaces: Array<any>;
- associatedCapabilities: Array<Capability>;
+ associatedProps: string[];
+ associatedInterfaces: any[];
+ associatedCapabilities: Capability[];
origVal: string;
isValid: boolean;
@@ -74,7 +79,7 @@
this.associatedProps = input.associatedProps;
this.associatedInterfaces = input.associatedInterfaces;
this.associatedCapabilities = input.associatedCapabilities;
- this.origVal = input.value || "";
+ this.origVal = input.value || '';
this.isValid = input.isValid;
}
}
@@ -84,9 +89,10 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
export class ServiceOperation {
operation: OperationModel;
- consumptionInputs: Array<ConsumptionInputDetails>;
+ consumptionInputs: ConsumptionInputDetails[];
constructor(input?: any) {
if (input) {
@@ -96,24 +102,24 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
export class InterfaceWithServiceOperation {
interfaceId: string;
displayName: string;
- operationsList: Array<ServiceOperation>;
+ operationsList: ServiceOperation[];
isExpanded: boolean;
constructor(input?: InterfaceModel) {
if (input) {
this.interfaceId = input.uniqueId;
this.displayName = input.displayType();
- this.operationsList = _.map(input.operations, operation => new ServiceOperation({operation: operation}));
+ this.operationsList = _.map(input.operations, (operation) => new ServiceOperation({operation: operation}));
this.isExpanded = true;
}
}
}
-
-
+// tslint:disable-next-line:max-classes-per-file
@Component({
selector: 'service-consumption',
templateUrl: './service-consumption.component.html',
@@ -125,21 +131,23 @@
modalInstance: ComponentRef<ModalComponent>;
isLoading: boolean = false;
- interfacesList: Array<InterfaceWithServiceOperation>;
- operationsGroup: Array<ServiceOperation>;
- @Input() parentServiceInputs: Array<InputBEModel> = [];
- @Input() parentService: Service;
- @Input() selectedService: Service;
+ interfacesList: InterfaceWithServiceOperation[];
+ operationsGroup: ServiceOperation[];
+ @Input() parentServiceInputs: InputBEModel[] = [];
+ @Input() parentService: ComponentMetadata;
+ @Input() selectedService: TopologyTemplate | FullComponentInstance;
@Input() selectedServiceInstanceId: string;
- @Input() instancesMappedList: Array<ServiceInstanceObject>;
- @Input() instancesCapabilitiesMap: Map<string, Array<Capability>>;
+ @Input() instancesMappedList: ServiceInstanceObject[];
+ @Input() instancesCapabilitiesMap: Map<string, Capability[]>;
@Input() readonly: boolean;
- selectedInstanceSiblings: Array<ServiceInstanceObject>;
- selectedInstancePropertiesList: Array<PropertyBEModel> = [];
- selectedInstanceCapabilitisList: Array<Capability> = [];
+ selectedInstanceSiblings: ServiceInstanceObject[];
+ selectedInstancePropertiesList: PropertyBEModel[] = [];
+ selectedInstanceCapabilitisList: Capability[] = [];
- constructor(private ModalServiceNg2: ModalService, private serviceServiceNg2: ServiceServiceNg2, private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2:ComponentInstanceServiceNg2) {}
+ constructor(private modalServiceNg2: ModalService, private topologyTemplateService: TopologyTemplateService,
+ private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
+ private componentFactory: ComponentFactory) {}
ngOnInit() {
this.updateSelectedInstancePropertiesAndSiblings();
@@ -147,15 +155,15 @@
}
ngOnChanges(changes) {
- if(changes.selectedServiceInstanceId && changes.selectedServiceInstanceId.currentValue !== changes.selectedServiceInstanceId.previousValue) {
+ if (changes.selectedServiceInstanceId && changes.selectedServiceInstanceId.currentValue !== changes.selectedServiceInstanceId.previousValue) {
this.selectedServiceInstanceId = changes.selectedServiceInstanceId.currentValue;
- if(changes.selectedService && changes.selectedService.currentValue !== changes.selectedService.previousValue) {
+ if (changes.selectedService && changes.selectedService.currentValue !== changes.selectedService.previousValue) {
this.selectedService = changes.selectedService.currentValue;
}
this.updateSelectedInstancePropertiesAndSiblings();
this.updateSelectedServiceCapabilities();
}
- if(changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) {
+ if (changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) {
this.updateSelectedInstancePropertiesAndSiblings();
this.updateSelectedServiceCapabilities();
}
@@ -163,22 +171,22 @@
updateSelectedInstancePropertiesAndSiblings() {
this.interfacesList = [];
- let selectedInstanceMetadata: ServiceInstanceObject = _.find(this.instancesMappedList, coInstance => coInstance.id === this.selectedServiceInstanceId);
+ const selectedInstanceMetadata: ServiceInstanceObject = _.find(this.instancesMappedList, (coInstance) => coInstance.id === this.selectedServiceInstanceId);
if (selectedInstanceMetadata) {
- _.forEach(selectedInstanceMetadata.interfaces, (interfaceData:InterfaceModel) => {
+ _.forEach(selectedInstanceMetadata.interfaces, (interfaceData: InterfaceModel) => {
this.interfacesList.push(new InterfaceWithServiceOperation(interfaceData));
});
}
- this.interfacesList.sort((interf1:InterfaceWithServiceOperation, interf2:InterfaceWithServiceOperation) => interf1.displayName.localeCompare(interf2.displayName));
+ this.interfacesList.sort((interf1: InterfaceWithServiceOperation, interf2: InterfaceWithServiceOperation) => interf1.displayName.localeCompare(interf2.displayName));
this.selectedInstancePropertiesList = selectedInstanceMetadata && selectedInstanceMetadata.properties;
- this.selectedInstanceSiblings = _.filter(this.instancesMappedList, coInstance => coInstance.id !== this.selectedServiceInstanceId);
+ this.selectedInstanceSiblings = _.filter(this.instancesMappedList, (coInstance) => coInstance.id !== this.selectedServiceInstanceId);
}
updateSelectedServiceCapabilities() {
this.selectedInstanceCapabilitisList = _.filter(
CapabilitiesGroup.getFlattenedCapabilities(this.selectedService.capabilities),
- cap => cap.properties && cap.ownerId === this.selectedService.uniqueId
+ (cap) => cap.properties && cap.ownerId === this.selectedService.uniqueId
);
}
@@ -186,15 +194,15 @@
currInterface.isExpanded = !currInterface.isExpanded;
}
- onSelectOperation(event, currInterface:InterfaceWithServiceOperation, opIndex: number) {
+ onSelectOperation(event, currInterface: InterfaceWithServiceOperation, opIndex: number) {
event.stopPropagation();
- if(!this.readonly) {
+ if (!this.readonly) {
this.operationsGroup = currInterface.operationsList;
- let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createOrUpdateOperationInput, this.getDisabled);
- let modalModel: ModalModel = new ModalModel('l', 'Modify Operation Consumption', '', [saveButton, cancelButton], 'standard');
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(
+ const cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.modalServiceNg2.closeCurrentModal);
+ const saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createOrUpdateOperationInput, this.getDisabled);
+ const modalModel: ModalModel = new ModalModel('l', 'Modify Operation Consumption', '', [saveButton, cancelButton], 'standard');
+ this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
+ this.modalServiceNg2.addDynamicContentToModal(
this.modalInstance,
ServiceConsumptionCreatorComponent,
{
@@ -215,11 +223,11 @@
}
}
- createOrUpdateOperationInput = ():void => {
+ createOrUpdateOperationInput = (): void => {
this.isLoading = true;
- let consumptionInputsList:Array<{[id: string]: Array<ConsumptionInput>}> = _.map(this.operationsGroup, (serviceOp) => {
- let consumptionInputsArr: Array<any> = [];
- if(serviceOp.consumptionInputs) {
+ const consumptionInputsList: Array<{[id: string]: ConsumptionInput[]}> = _.map(this.operationsGroup, (serviceOp) => {
+ let consumptionInputsArr: any[] = [];
+ if (serviceOp.consumptionInputs) {
consumptionInputsArr = _.map(serviceOp.consumptionInputs, (input: ConsumptionInputDetails) => {
return {
inputId: input.inputId,
@@ -233,16 +241,24 @@
[serviceOp.operation.uniqueId]: consumptionInputsArr
};
});
- this.serviceServiceNg2.createOrUpdateServiceConsumptionInputs(this.parentService,this.selectedServiceInstanceId, consumptionInputsList).subscribe(() => {
+ this.topologyTemplateService.createOrUpdateServiceConsumptionInputs(this.convertMetaDataToComponent(this.parentService).uniqueId, this.selectedServiceInstanceId, consumptionInputsList)
+ .subscribe(() => {
this.isLoading = false;
- }, err=> {
+ }, (err) => {
this.isLoading = false;
});
- this.ModalServiceNg2.closeCurrentModal();
- };
+ this.modalServiceNg2.closeCurrentModal();
+ }
- getDisabled = ():boolean => {
+ getDisabled = (): boolean => {
return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
- };
+ }
+
+ //TODO remove when workspace page convert to angular5
+ convertMetaDataToComponent(componentMetadata: ComponentMetadata) {
+ const newResource: Resource = this.componentFactory.createEmptyComponent(ComponentType.RESOURCE) as Resource;
+ newResource.setComponentMetadata(componentMetadata);
+ return newResource;
+ }
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts
index 8593bef..70b5911 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts
+++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts
@@ -14,11 +14,11 @@
* permissions and limitations under the License.
*/
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {ServiceConsumptionComponent} from "./service-consumption.component";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from 'app/ng2/shared/translator/translate.module';
+import { ServiceConsumptionComponent } from './service-consumption.component';
@NgModule({
declarations: [
@@ -29,11 +29,13 @@
UiElementsModule,
TranslateModule
],
- exports: [],
+ exports: [
+ ServiceConsumptionComponent
+ ],
entryComponents: [
ServiceConsumptionComponent
],
providers: []
})
export class ServiceConsumptionModule {
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less
index ae990dc..2fccfb4 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less
+++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less
@@ -38,7 +38,7 @@
justify-content: space-between;
.rule-details {
- .s_1;
+ // .s_1;
display: flex;
flex: 1;
align-items: center;
@@ -67,4 +67,13 @@
}
}
+ .w-sdc-designer-sidebar-section-footer {
+ margin-top: 10px;
+ text-align: center;
+ width: 100%;
+ }
+ .w-sdc-designer-sidebar-section-footer-action {
+ width: 180px;
+ margin-top: 10px;
+ }
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts
index bc3531d..fa75a27 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts
@@ -13,22 +13,22 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-import {Component, Input, Output, EventEmitter, ComponentRef} from '@angular/core';
-import {ModalService} from 'app/ng2/services/modal.service';
+import { Component, ComponentRef, EventEmitter, Input, Output } from '@angular/core';
import {
- Service,
- ComponentInstance,
- ModalModel,
ButtonModel,
- PropertyBEModel,
+ ComponentInstance,
InputBEModel,
- ServiceInstanceObject
+ ModalModel,
+ PropertyBEModel,
} from 'app/models';
-import {ServiceDependenciesEditorComponent} from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
-import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
-import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
-import {TranslateService} from 'app/ng2/shared/translator/translate.service';
-import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response';
+import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
+import { ServiceDependenciesEditorComponent } from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
+import { ModalService } from 'app/ng2/services/modal.service';
+import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
export class ConstraintObject {
servicePropertyName: string;
@@ -48,12 +48,13 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
export class ConstraintObjectUI extends ConstraintObject{
isValidValue: boolean;
constructor(input?: any) {
super(input);
- if(input) {
+ if (input) {
this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
}
}
@@ -63,7 +64,7 @@
}
public isValidRule(isStatic) {
- let isValidValue = isStatic ? this.isValidValue : true;
+ const isValidValue = isStatic ? this.isValidValue : true;
return this.servicePropertyName != null && this.servicePropertyName !== ''
&& this.value != null && this.value !== '' && isValidValue;
}
@@ -75,6 +76,7 @@
LESS_THAN: 'less_than'
};
+// tslint:disable-next-line:max-classes-per-file
class I18nTexts {
static uncheckModalTitle: string;
static uncheckModalText: string;
@@ -89,21 +91,21 @@
static deleteRuleMsg: string;
public static translateTexts(translateService) {
- I18nTexts.uncheckModalTitle = translateService.translate("SERVICE_DEPENDENCY_UNCHECK_TITLE");
- I18nTexts.uncheckModalText = translateService.translate("SERVICE_DEPENDENCY_UNCHECK_TEXT");
- I18nTexts.modalApprove = translateService.translate("MODAL_APPROVE");
- I18nTexts.modalCancel = translateService.translate("MODAL_CANCEL");
- I18nTexts.modalCreate = translateService.translate("MODAL_CREATE");
- I18nTexts.modalSave = translateService.translate("MODAL_SAVE");
- I18nTexts.modalDelete = translateService.translate("MODAL_DELETE");
- I18nTexts.addRuleTxt = translateService.translate("SERVICE_DEPENDENCY_ADD_RULE");
- I18nTexts.updateRuleTxt = translateService.translate("SERVICE_DEPENDENCY_UPDATE_RULE");
- I18nTexts.deleteRuleTxt = translateService.translate("SERVICE_DEPENDENCY_DELETE_RULE");
- I18nTexts.deleteRuleMsg = translateService.translate("SERVICE_DEPENDENCY_DELETE_RULE_MSG");
+ I18nTexts.uncheckModalTitle = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TITLE');
+ I18nTexts.uncheckModalText = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TEXT');
+ I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
+ I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
+ I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
+ I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
+ I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
+ I18nTexts.addRuleTxt = translateService.translate('SERVICE_DEPENDENCY_ADD_RULE');
+ I18nTexts.updateRuleTxt = translateService.translate('SERVICE_DEPENDENCY_UPDATE_RULE');
+ I18nTexts.deleteRuleTxt = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE');
+ I18nTexts.deleteRuleMsg = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE_MSG');
}
}
-
+// tslint:disable-next-line:max-classes-per-file
@Component({
selector: 'service-dependencies',
templateUrl: './service-dependencies.component.html',
@@ -115,56 +117,55 @@
modalInstance: ComponentRef<ModalComponent>;
isDependent: boolean;
isLoading: boolean;
- parentServiceInputs: Array<InputBEModel> = [];
- rulesList: Array<ConstraintObject> = [];
- operatorTypes: Array<any>;
+ parentServiceInputs: InputBEModel[] = [];
+ rulesList: ConstraintObject[] = [];
+ operatorTypes: any[];
@Input() readonly: boolean;
- @Input() compositeService: Service;
+ @Input() compositeService: ComponentMetadata;
@Input() currentServiceInstance: ComponentInstance;
- @Input() selectedInstanceSiblings: Array<ServiceInstanceObject>;
- @Input() selectedInstanceConstraints: Array<ConstraintObject> = [];
- @Input() selectedInstanceProperties: Array<PropertyBEModel> = [];
- @Output() updateRulesListEvent:EventEmitter<Array<ConstraintObject>> = new EventEmitter<Array<ConstraintObject>>();
+ @Input() selectedInstanceSiblings: ServiceInstanceObject[];
+ @Input() selectedInstanceConstraints: ConstraintObject[] = [];
+ @Input() selectedInstanceProperties: PropertyBEModel[] = [];
+ @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
@Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
@Output() dependencyStatus = new EventEmitter<boolean>();
-
- constructor(private componentServiceNg2: ComponentServiceNg2, private ModalServiceNg2: ModalService, private translateService: TranslateService) {
+ constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) {
}
ngOnInit() {
this.isLoading = false;
this.operatorTypes = [
- {label: ">", value: OPERATOR_TYPES.GREATER_THAN},
- {label: "<", value: OPERATOR_TYPES.LESS_THAN},
- {label: "=", value: OPERATOR_TYPES.EQUAL}
+ {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
+ {label: '<', value: OPERATOR_TYPES.LESS_THAN},
+ {label: '=', value: OPERATOR_TYPES.EQUAL}
];
- this.componentServiceNg2.getComponentInputsWithProperties(this.compositeService).subscribe((result: ComponentGenericResponse) => {
+ this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((result: ComponentGenericResponse) => {
this.parentServiceInputs = result.inputs;
});
this.loadRules();
- this.translateService.languageChangedObservable.subscribe(lang => {
+ this.translateService.languageChangedObservable.subscribe((lang) => {
I18nTexts.translateTexts(this.translateService);
});
}
ngOnChanges(changes) {
- if(changes.currentServiceInstance) {
+ if (changes.currentServiceInstance) {
this.currentServiceInstance = changes.currentServiceInstance.currentValue;
this.isDependent = this.currentServiceInstance.isDependent();
}
- if(changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
+ if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
this.loadRules();
}
}
public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
- let actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
- let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
- let modalModel: ModalModel = new ModalModel('sm', I18nTexts.uncheckModalTitle, I18nTexts.uncheckModalText, [actionButton, cancelButton]);
- return this.ModalServiceNg2.createCustomModal(modalModel);
+ const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
+ const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
+ const modalModel: ModalModel = new ModalModel('sm', I18nTexts.uncheckModalTitle, I18nTexts.uncheckModalText, [actionButton, cancelButton]);
+ return this.modalServiceNg2.createCustomModal(modalModel);
}
loadRules() {
@@ -178,60 +179,59 @@
}
onUncheckDependency = () => {
- this.ModalServiceNg2.closeCurrentModal();
+ this.modalServiceNg2.closeCurrentModal();
this.isLoading = true;
- let isDepOrig = this.isDependent;
- let rulesListOrig = this.rulesList;
+ const isDepOrig = this.isDependent;
+ const rulesListOrig = this.rulesList;
this.currentServiceInstance.unmarkAsDependent();
this.updateComponentInstance(isDepOrig, rulesListOrig);
}
onCloseRemoveDependencyModal = () => {
this.isDependent = true;
- this.ModalServiceNg2.closeCurrentModal();
+ this.modalServiceNg2.closeCurrentModal();
}
onCheckDependency = () => {
- let isDepOrig = this.isDependent;
- let rulesListOrig = this.rulesList;
+ const isDepOrig = this.isDependent;
+ const rulesListOrig = this.rulesList;
this.currentServiceInstance.markAsDependent();
this.rulesList = [];
this.updateComponentInstance(isDepOrig, rulesListOrig);
}
onMarkAsDependent() {
- if(!this.currentServiceInstance.isDependent()) {
+ if (!this.currentServiceInstance.isDependent()) {
this.onCheckDependency();
- }
- else {
+ } else {
this.openRemoveDependencyModal().instance.open();
}
}
- updateComponentInstance(isDependent_origVal : boolean, rulesList_orig: Array<ConstraintObject>) {
+ updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) {
this.isLoading = true;
- this.componentServiceNg2.updateComponentInstance(this.compositeService, this.currentServiceInstance).subscribe((updatedServiceIns: ComponentInstance) => {
+ this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId, this.currentServiceInstance).subscribe((updatedServiceIns: ComponentInstance) => {
this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
this.isDependent = this.currentServiceInstance.isDependent();
this.dependencyStatus.emit(this.isDependent);
- if(this.isDependent) {
+ if (this.isDependent) {
this.loadRulesListEvent.emit();
}
this.isLoading = false;
- }, err=> {
- this.isDependent = isDependent_origVal;
- this.rulesList = rulesList_orig;
+ }, (err) => {
+ this.isDependent = isDependentOrigVal;
+ this.rulesList = rulesListOrig;
this.isLoading = false;
console.log('An error has occurred.');
});
}
- onAddRule () {
- let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', this.createRule, this.getDisabled);
- let modalModel: ModalModel = new ModalModel('l', I18nTexts.addRuleTxt, '', [saveButton, cancelButton], 'standard');
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(
+ onAddRule() {
+ const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
+ const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', this.createRule, this.getDisabled);
+ const modalModel: ModalModel = new ModalModel('l', I18nTexts.addRuleTxt, '', [saveButton, cancelButton], 'standard');
+ this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
+ this.modalServiceNg2.addDynamicContentToModal(
this.modalInstance,
ServiceDependenciesEditorComponent,
{
@@ -247,16 +247,16 @@
}
onSelectRule(index: number) {
- let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateRules(), this.getDisabled);
- let modalModel: ModalModel = new ModalModel('l', I18nTexts.updateRuleTxt, '', [saveButton, cancelButton], 'standard');
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(
+ const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
+ const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateRules(), this.getDisabled);
+ const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateRuleTxt, '', [saveButton, cancelButton], 'standard');
+ this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
+ this.modalServiceNg2.addDynamicContentToModal(
this.modalInstance,
ServiceDependenciesEditorComponent,
{
serviceRuleIndex: index,
- serviceRules: _.map(this.rulesList, rule => new ConstraintObjectUI(rule)),
+ serviceRules: _.map(this.rulesList, (rule) => new ConstraintObjectUI(rule)),
currentServiceName: this.currentServiceInstance.name,
operatorTypes: this.operatorTypes,
compositeServiceName: this.compositeService.name,
@@ -268,40 +268,40 @@
this.modalInstance.instance.open();
}
- getDisabled = ():boolean => {
+ getDisabled = (): boolean => {
return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
- };
+ }
- createRule = ():void => {
- let newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule);
+ createRule = (): void => {
+ const newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule);
this.isLoading = true;
- this.componentServiceNg2.createServiceFilterConstraints(
- this.compositeService,
- this.currentServiceInstance,
+ this.topologyTemplateService.createServiceFilterConstraints(
+ this.compositeService.uniqueId,
+ this.currentServiceInstance.uniqueId,
newRuleToCreate
).subscribe( (response) => {
this.updateRulesListEvent.emit(response.properties);
this.isLoading = false;
- }, err=> {
+ }, (err) => {
this.isLoading = false;
});
- this.ModalServiceNg2.closeCurrentModal();
- };
+ this.modalServiceNg2.closeCurrentModal();
+ }
- updateRules = ():void => {
- let allRulesToUpdate: Array<ConstraintObject> = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map(rule => new ConstraintObject(rule));
+ updateRules = (): void => {
+ const allRulesToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule));
this.isLoading = true;
- this.componentServiceNg2.updateServiceFilterConstraints(
- this.compositeService,
- this.currentServiceInstance,
+ this.topologyTemplateService.updateServiceFilterConstraints(
+ this.compositeService.uniqueId,
+ this.currentServiceInstance.uniqueId,
allRulesToUpdate
).subscribe((response) => {
this.updateRulesListEvent.emit(response.properties);
this.isLoading = false;
- }, err => {
+ }, (err) => {
this.isLoading = false;
});
- this.ModalServiceNg2.closeCurrentModal();
+ this.modalServiceNg2.closeCurrentModal();
}
getSymbol(constraintOperator) {
@@ -312,23 +312,23 @@
}
}
- onDeleteRule = (index:number) => {
+ onDeleteRule = (index: number) => {
this.isLoading = true;
- this.componentServiceNg2.deleteServiceFilterConstraints(
- this.compositeService,
- this.currentServiceInstance,
+ this.topologyTemplateService.deleteServiceFilterConstraints(
+ this.compositeService.uniqueId,
+ this.currentServiceInstance.uniqueId,
index
).subscribe( (response) => {
this.updateRulesListEvent.emit(response.properties);
this.isLoading = false;
- }, err=> {
+ }, (err) => {
this.isLoading = false;
});
- this.ModalServiceNg2.closeCurrentModal();
- };
+ this.modalServiceNg2.closeCurrentModal();
+ }
- openDeleteModal = (index:number) => {
- this.ModalServiceNg2.createActionModal(I18nTexts.deleteRuleTxt, I18nTexts.deleteRuleMsg,
+ openDeleteModal = (index: number) => {
+ this.modalServiceNg2.createActionModal(I18nTexts.deleteRuleTxt, I18nTexts.deleteRuleMsg,
I18nTexts.modalDelete, () => this.onDeleteRule(index), I18nTexts.modalCancel).instance.open();
}
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts
index 7e66ed9..5e2d03d 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts
+++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts
@@ -1,9 +1,9 @@
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {ServiceDependenciesComponent} from "./service-dependencies.component";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from 'app/ng2/shared/translator/translate.module';
+import { ServiceDependenciesComponent } from './service-dependencies.component';
@NgModule({
declarations: [
@@ -14,11 +14,13 @@
UiElementsModule,
TranslateModule
],
- exports: [],
+ exports: [
+ ServiceDependenciesComponent
+ ],
entryComponents: [
ServiceDependenciesComponent
],
providers: []
})
export class ServiceDependenciesModule {
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts b/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts
deleted file mode 100644
index e09001f..0000000
--- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-import {Component, Input, KeyValueDiffer, IterableDiffers, KeyValueDiffers, DoCheck} from '@angular/core';
-import {Service} from "app/models/components/service";
-import {TranslateService} from "app/ng2/shared/translator/translate.service";
-import {ForwardingPath} from "app/models/forwarding-path";
-import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
-
-@Component({
- selector: 'service-path-selector',
- templateUrl: './service-path-selector.component.html',
- styleUrls:['service-path-selector.component.less'],
- providers: [TranslateService]
-})
-
-export class ServicePathSelectorComponent implements DoCheck {
-
- defaultSelectedId: string;
- hideAllValue: string;
- hideAllId: string = '0';
- showAllValue: string;
- showAllId: string = '1';
-
- paths: Array<ForwardingPath> = [];
- dropdownOptions: Array<DropdownValue>;
- differ: KeyValueDiffer;
-
- @Input() service: Service;
- @Input() drawPath: Function;
- @Input() deletePaths: Function;
- @Input() selectedPathId: string;
-
- constructor(private differs: KeyValueDiffers, private translateService: TranslateService) {
-
- this.defaultSelectedId = this.hideAllId;
- this.convertPathsToDropdownOptions();
-
- this.translateService.languageChangedObservable.subscribe(lang => {
- this.hideAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_HIDE_ALL_VALUE");
- this.showAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_SHOW_ALL_VALUE");
- this.convertPathsToDropdownOptions();
- });
-
- }
-
- ngOnInit(): void {
-
- this.selectedPathId = this.defaultSelectedId;
- this.differ = this.differs.find(this.service.forwardingPaths).create(null);
-
- }
-
- ngDoCheck(): void {
-
- const pathsChanged = this.differ.diff(this.service.forwardingPaths);
-
- if (pathsChanged) {
- let oldPaths = _.cloneDeep(this.paths);
- this.populatePathsFromService();
-
- if (!(_.isEqual(oldPaths, this.paths))) {
- this.convertPathsToDropdownOptions();
-
- let temp = this.selectedPathId;
- this.selectedPathId = '-1';
-
- setTimeout(() => {
- this.selectedPathId = temp;
- this.onSelectPath();
- }, 0);
- }
- }
-
- }
-
- populatePathsFromService(): void {
-
- this.paths = [];
- let {forwardingPaths} = this.service;
-
- _.forEach(forwardingPaths, path => {
- this.paths.push(path);
- });
- this.paths.sort((a:ForwardingPath, b:ForwardingPath)=> {
- return a.name.localeCompare(b.name);
- });
-
- }
-
- convertPathsToDropdownOptions(): void {
-
- let result = [
- new DropdownValue(this.hideAllId, this.hideAllValue),
- new DropdownValue(this.showAllId, this.showAllValue)
- ];
-
- _.forEach(this.paths, (value: ForwardingPath) => {
- result[result.length] = new DropdownValue(value.uniqueId, value.name);
- });
-
- this.dropdownOptions = result;
-
- }
-
- onSelectPath = (): void => {
-
- if (this.selectedPathId !== '-1') {
- this.deletePaths();
-
- switch (this.selectedPathId) {
- case this.hideAllId:
- break;
-
- case this.showAllId:
- _.forEach(this.paths, path =>
- this.drawPath(path)
- );
- break;
-
- default:
- let path = this.paths.find(path =>
- path.uniqueId === this.selectedPathId
- );
- if (!path) {
- this.selectedPathId = this.defaultSelectedId;
- this.onSelectPath(); // currently does nothing in default case, but if one day it does, we want the selection to behave accordingly.
- break;
- }
- this.drawPath(path);
- break;
- }
- }
-
- }
-}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html
deleted file mode 100644
index 2a6a72a..0000000
--- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html
+++ /dev/null
@@ -1,31 +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='service-path'>
- <button class='zoom-icons create-path-button' data-tests-id="pathsMenuBtn" (click)="showServicePathMenu = !showServicePathMenu">...</button>
- <div class="service-path-menu" *ngIf="showServicePathMenu">
- <div >
- <ul>
- <li *ngIf='!isViewOnly'><div class="hand" (click)="onCreateServicePath()" data-tests-id="createPathMenuItem">
- Create Service Flow
- </div></li>
- <li><div class="hand" (click)="onListServicePath()" data-tests-id="pathsListMenuItem">
- Service Flows List
- </div></li>
- </ul>
- </div>
- </div>
-</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less
deleted file mode 100644
index 777b206..0000000
--- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less
+++ /dev/null
@@ -1,51 +0,0 @@
-//@import 'src/assets/styles/variables.less';
-@import './../../../../../assets/styles/variables.less';
-.service-path {
- position: relative;
- .create-path-button{
- &:extend(.search-bar-button);
- width: 30px;
- height: 30px;
- &:hover {
- color: @main_color_a;
- }
- &:active {
- background: @main_color_a;
- color: @main_color_p;
- }
- &:focus {
- outline: none;
- }
- }
- .service-path-menu {
- border: 1px solid @main_color_o;
- border-radius: 0 0 2px 2px;
- border-top-color: @main_color_a;
- border-top-width: 3px;
-
- box-sizing: border-box;
- box-shadow: 0 2px 4px 0 rgba(0,0,0,0.30);
-
- background-color: @main_color_p;
-
- padding: 5px 0;
- right: 34px;
- position: absolute;
- top: 10px;
- width: 150px;
- font-size: 13px;
- font-family: @font-opensans-regular;
-
- li {
- color: @main_color_m;
- padding: 0 10px;
- line-height: 20px;
- &:hover {
- cursor: pointer;
- color: @main_color_a;
- background-color: fade(@main_color_a, 5%);
- }
- }
-
- }
-}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts
deleted file mode 100644
index d66c5f0..0000000
--- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {Component, Input, ComponentRef} from '@angular/core';
-import {ModalService} from 'app/ng2/services/modal.service';
-import {ModalModel, ButtonModel} from 'app/models';
-import {ServicePathCreatorComponent} from 'app/ng2/pages/service-path-creator/service-path-creator.component';
-import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
-import ServicePathsListComponent from "app/ng2/pages/service-paths-list/service-paths-list.component";
-import {Service} from "app/models/components/service";
-
-@Component({
- selector: 'service-path',
- templateUrl: './service-path.component.html',
- styleUrls: ['service-path.component.less'],
- providers: [ModalService]
-})
-
-export class ServicePathComponent {
- showServicePathMenu: boolean = false;
- modalInstance: ComponentRef<ModalComponent>;
- @Input() service: Service;
- @Input() onCreate: Function;
- @Input() onSave: Function;
- @Input() isViewOnly:boolean;
-
- constructor(private ModalServiceNg2: ModalService) {}
-
- onCreateServicePath = ():void => {
- this.showServicePathMenu = false;
- let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let saveButton: ButtonModel = new ButtonModel('Create', 'blue', this.createPath, this.getDisabled );
- let modalModel: ModalModel = new ModalModel('l', 'Create Service Flow', '', [saveButton, cancelButton], 'standard', true);
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {service: this.service});
- this.modalInstance.instance.open();
- };
-
- onListServicePath = ():void => {
- this.showServicePathMenu = false;
- let cancelButton: ButtonModel = new ButtonModel('Close', 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let modalModel: ModalModel = new ModalModel('md', 'Service Flows List','', [cancelButton], 'standard', true);
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathsListComponent, {service: this.service,
- onCreateServicePath: this.onCreateServicePath, onEditServicePath: this.onEditServicePath, isViewOnly: this.isViewOnly});
- this.modalInstance.instance.open();
- };
-
- createPath = ():void => {
- this.onCreate(this.modalInstance.instance.dynamicContent.instance.createServicePathData());
- this.ModalServiceNg2.closeCurrentModal();
- };
-
- onEditServicePath = (id:string):void => {
- let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal);
- let saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createPath, this.getDisabled );
- let modalModel: ModalModel = new ModalModel('l', 'Edit Path', '', [saveButton, cancelButton], 'standard', true);
- this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
- this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {service: this.service, pathId: id});
- this.modalInstance.instance.open();
- };
-
- getDisabled = ():boolean => {
- return this.isViewOnly || !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
- };
-}
-
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts
deleted file mode 100644
index 96af247..0000000
--- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {ServicePathComponent} from "./service-path.component";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-
-@NgModule({
- declarations: [
- ServicePathComponent
- ],
- imports: [CommonModule,
- UiElementsModule],
- exports: [],
- entryComponents: [
- ServicePathComponent
- ],
- providers: []
-})
-export class ServicePathModule {
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html
new file mode 100644
index 0000000..127531b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html
@@ -0,0 +1,18 @@
+<form>
+ <div>
+ <div class="comment-modal-text" [innerHTML]="message"></div>
+ <sdc-textarea #comment1
+ [(value)]="comment.text"
+ placeHolder="{{'CONFIRMATION_MODAL_PLACEHOLDER' | translate }}"
+ [required]="true"
+ name="comment1"
+ testId="checkindialog"
+ [maxLength]="256">
+ </sdc-textarea>
+ <sdc-validation [validateElement]="comment1" (validityChanged)="onValidityChange($event)">
+ <sdc-required-validator message="{{ 'VALIDATION_ERROR_REQUIRED' | translate:{'field': 'Comment' } }}"></sdc-required-validator>
+ <sdc-regex-validator message="{{ 'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate}}"
+ [pattern]="commentValidationPattern"></sdc-regex-validator>
+ </sdc-validation>
+ </div>
+</form>
diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts
new file mode 100644
index 0000000..c66f60b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts
@@ -0,0 +1,25 @@
+/**
+ * Created by rc2122 on 5/31/2018.
+ */
+import { Component, Input } from "@angular/core";
+import { ValidationConfiguration } from "app/models";
+import { Subject } from "rxjs/Subject";
+
+@Component({
+ selector: 'comment-modal',
+ templateUrl: './comment-modal.component.html',
+ styleUrls: ['./comment-modal.less']
+})
+
+export class CommentModalComponent {
+
+ @Input() message:string;
+ onValidationChange: Subject<boolean> = new Subject();
+ //@Input() showComment:boolean;
+ private comment = {"text": ''};
+ private commentValidationPattern = ValidationConfiguration.validation.validationPatterns.comment;
+
+ private onValidityChange = (isValid: boolean):void => {
+ this.onValidationChange.next(isValid);
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less
new file mode 100644
index 0000000..8e20e81
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less
@@ -0,0 +1,3 @@
+.comment-modal-text {
+ padding-bottom: 5px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/modals/modals.module.ts b/catalog-ui/src/app/ng2/components/modals/modals.module.ts
new file mode 100644
index 0000000..5aa7f08
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/modals.module.ts
@@ -0,0 +1,29 @@
+/**
+ * Created by rc2122 on 5/24/2018.
+ */
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { CommentModalComponent } from 'app/ng2/components/modals/comment-modal/comment-modal.component';
+import { PopoverModule } from 'app/ng2/components/ui/popover/popover.module';
+import { TranslateModule } from 'app/ng2/shared/translator/translate.module';
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+import { OnboardingService } from '../../services/onboarding.service';
+import { ImportVSPService } from './onboarding-modal/import-vsp.service';
+import { OnboardingModalComponent } from './onboarding-modal/onboarding-modal.component';
+
+@NgModule({
+ declarations: [CommentModalComponent, OnboardingModalComponent],
+ imports: [TranslateModule,
+ SdcUiComponentsModule,
+ CommonModule,
+ PopoverModule,
+ NgxDatatableModule],
+ exports: [CommentModalComponent, OnboardingModalComponent],
+ entryComponents: [CommentModalComponent, OnboardingModalComponent],
+ providers: [OnboardingService, ImportVSPService],
+ bootstrap: []
+})
+
+export class ModalsModule {
+}
diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts
new file mode 100644
index 0000000..8e73646
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts
@@ -0,0 +1,36 @@
+import { Injectable, Inject } from "@angular/core";
+import { OnboardingModalComponent } from "./onboarding-modal.component";
+import { SdcUiServices, SdcUiCommon } from "onap-ui-angular";
+import { Observable, Subject } from "rxjs";
+import { CHANGE_COMPONENT_CSAR_VERSION_FLAG } from "../../../../utils/constants";
+import { CacheService } from "../../../services/cache.service";
+
+
+@Injectable()
+export class ImportVSPService {
+
+ constructor(private modalService: SdcUiServices.ModalService,
+ private cacheService:CacheService,
+ @Inject("$state") private $state:ng.ui.IStateService){
+
+ }
+
+ openOnboardingModal(csarUUID?: string, csarVersion?: string): Observable<any> {
+ var subject = new Subject<any>();
+ const onboardingModalConfig = {
+ size: SdcUiCommon.ModalSize.xlarge,
+ title: 'Import VSP',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'sampleTestIdModal1',
+ } as SdcUiCommon.IModalConfig;
+ const onboardingModalInstance = this.modalService.openCustomModal(onboardingModalConfig, OnboardingModalComponent, {currentCsarUUID: csarUUID, currentCsarVersion: csarVersion});
+ onboardingModalInstance.innerModalContent.instance.closeModalEvent.subscribe(
+ (result: any) => {
+ subject.next(result);
+ onboardingModalInstance.closeModal();
+ }, (err) =>{}
+ )
+ return subject.asObservable();
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html
new file mode 100644
index 0000000..6ba1f42
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html
@@ -0,0 +1,106 @@
+<div class="onboarding-modal">
+ <div class="search-wrapper">
+ <span class="sub-title-wrapper">
+ <svg-icon class="info-button"
+ (click) = "openPopover($event, 'ON_BOARDING_GENERAL_INFO')"
+ [name]="'info-circle-o'" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ <span class="sub-title">{{ 'ON_BOARDING_MODAL_SUB_TITLE' | translate }}</span>
+ </span>
+ <span class="sdc-filter-bar-wrapper">
+ <sdc-filter-bar
+ [placeHolder]="'Search'"
+ (keyup)="updateFilter($event)"
+ [testId]="'onboarding-search'">
+ </sdc-filter-bar>
+ </span>
+ </div>
+ <div class="datatable-components-wapper">
+ <ngx-datatable #componentsMetadataTable
+ columnMode="flex"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rows]="componentsMetadataList"
+ [sorts]="[{prop: 'name', dir: 'asc'}]"
+ (select)='onSelectComponent($event)'
+ [selectionType]="'single'">
+ <ngx-datatable-row-detail [rowHeight]="undefiend">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template >
+ <div class="onboarding-components-details">
+ <span class="row-details-description">
+ <div>
+ <div class="th">VSP Description:</div>
+ <div>{{row.description}}</div>
+ </div>
+ </span>
+ <span class="row-details-metadata1">
+ <div *ngIf="isCsarComponentExists">
+ <div class="th">VF'S Meta Data:</div>
+ <div><span class="th">Name:</span>{{componentFromServer.name}}</div>
+ <div><span class="th">Lifecycle:</span>{{componentFromServer.lifecycleState}}</div>
+ <div><span class="th">Creator:</span>{{componentFromServer.creatorFullName}}</div>
+ </div>
+ </span>
+ <span class="row-details-metadata2">
+ <div *ngIf="isCsarComponentExists">
+ <div class="th"> </div>
+ <div><span class="th">UUID:</span> {{componentFromServer.uuid}}</div>
+ <div><span class="th">Version:</span> {{componentFromServer.version}}</div>
+ <div><span class="th">Modifier:</span> {{componentFromServer.lastUpdaterFullName}}</div>
+ <div *ngIf="checkNotCertified()">
+ <span class="note">Designers cannot update a VSP if the VF is <br>checked out by another user.</span>
+ </div>
+ </div>
+ </span>
+ <span class="row-details-metadata3">
+ <svg-icon class="info-button"
+ (click) = "openPopover($event, isCsarComponentExists ? 'ON_BOARDING_UPDATE_INFO' : 'ON_BOARDING_IMPORT_INFO')"
+ [name]="'info-circle-o'" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ </span>
+ <span class="row-details-icon">
+ <div>
+ <sdc-button class="import-update-file-btn"
+ [text]="isCsarComponentExists ? 'Update VSP' : 'Import VSP'"
+ [testId]="isCsarComponentExists ? 'update-csar' : 'import-csar'"
+ [type]="'primary'"
+ [icon_name]="isCsarComponentExists ? 'sync-o' : 'alert-triangle-o'"
+ [icon_position]="'left'"
+ [icon_mode] = "'white'"
+ [size] = "'medium'"
+ (click)="importOrUpdateCsar()"
+ [disabled]="checkNotCertified()"
+ >
+ </sdc-button>
+ <svg-icon class="download-file-btn" sdc-tooltip [tooltip-text]="'Download-csar'"
+ [mode]="'primary'" [clickable]="true" [name]="'download-o'"
+ [testId]="'download-csar'" [size]="'medium'" (click)="downloadCsar(row.packageId)">
+ </svg-icon>
+ </div>
+ </span>
+ </div>
+ <sdc-loader [global]="false" [active]="isLoad" [size]="'small'"[relative]="true"></sdc-loader>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column *ngFor="let column of columns" [ngSwitch]="column.prop" [resizeable]="false" [draggable]="false" name={{column.name}}
+ [flexGrow]="column.flexGrow">
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'name'">
+ <span data-tests-id="csar-row" class="sprite table-arrow" [ngClass]="{'opened': selectedComponent && row.packageId === selectedComponent.packageId}"></span>
+ {{row[column.prop]}}
+ </ng-template>
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'categories'">
+ <span *ngIf="row[column.prop][0]">
+ {{row[column.prop][0].name}}
+ <span *ngIf="row[column.prop][0].subcategories[0]">{{row[column.prop][0].subcategories[0].name}}</span>
+ </span>
+ </ng-template>
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchDefault>
+ {{row[column.prop]}}
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
+</div>
+
+
+
diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less
new file mode 100644
index 0000000..2e4abda
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less
@@ -0,0 +1,97 @@
+@import "../../../../../assets/styles/variables";
+@import "../../../../../assets/styles/mixins";
+
+
+.onboarding-components-details{
+ display: flex;
+}
+.row-details-description,
+.row-details-metadata1,
+.row-details-metadata2,
+.row-details-metadata3{
+ .th { .m_14_m; }
+ flex-basis: 0;
+ overflow: hidden;
+ padding: 5px 15px;
+ white-space: normal;
+}
+.row-details-description,
+.row-details-metadata3 {
+ border-right: 1px solid @main_color_o;
+}
+
+.row-details-icon {
+ flex-basis: 0;
+ overflow: hidden;
+ padding: 5px 10px;
+ align-self: center;
+}
+
+.row-details-description {
+ flex-grow: 19;
+}
+.row-details-metadata1 {
+ flex-grow: 26.5;
+}
+.row-details-metadata2 {
+ flex-grow: 35;
+ .note {
+ color: @func_color_q;
+ }
+}
+.row-details-metadata3 {
+ flex-grow: 8;
+}
+.info-button{
+ cursor: pointer;
+ float: right;
+}
+.row-details-icon {
+ flex-grow: 18;
+}
+.download-file-btn {
+ cursor: pointer;
+ margin-left: 6px;
+}
+
+.import-update-file-btn {
+ cursor: pointer;
+}
+.sprite.table-arrow{
+ margin-right: 7px;
+}
+.search-wrapper {
+ .sdc-filter-bar-wrapper {
+ flex: 0 0 30%;
+ }
+ .sub-title-wrapper {
+ flex: 0 0 70%;
+ font-size: 15px;
+ line-height: 35px;
+ font-family: OpenSans-Regular, sans-serif;
+ align-items: center;
+ display: inline-flex;
+ .sub-title{
+ padding-left: 5px;
+ }
+ }
+ display: flex;
+ margin-top: 15px;
+ margin-bottom: 10px;
+ }
+
+ :host ::ng-deep {
+ .datatable-row-detail{
+ width: 1120px;
+ }
+ .datatable-body-row {
+ cursor: pointer;
+ }
+ }
+
+
+
+
+
+
+
diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts
new file mode 100644
index 0000000..565398b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts
@@ -0,0 +1,122 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import { NO_ERRORS_SCHEMA} from "@angular/core";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+
+import {Observable} from "rxjs/Observable";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {SdcUiServices, SdcUiCommon} from "onap-ui-angular";
+import 'rxjs/add/observable/of';
+import {OnboardingService} from "../../../services/onboarding.service";
+import {TranslateService} from "../../../shared/translator/translate.service";
+import {CacheService} from "../../../services/cache.service";
+import {FileUtilsService} from "../../../services/file-utils.service";
+import {onboardingModalVSPMock, onboardingModalUniqueVSPMock, vspFromServerMock} from "../../../../../jest/mocks/onboarding-vsp.mock";
+import {OnboardingModalComponent} from "./onboarding-modal.component";
+import {TranslatePipe} from "../../../shared/translator/translate.pipe";
+
+describe('onboarding modal component', () => {
+
+ let fixture: ComponentFixture<OnboardingModalComponent>;
+ let onboardingServiceMock: Partial<OnboardingService>;
+ let translateServiceMock: Partial<TranslateService>;
+ let cacheServiceMock: Partial<CacheService>;
+ let fileUtilsServiceMock: Partial<FileUtilsService>;
+ let popoverServiceMock: Partial<SdcUiServices.PopoverService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+
+ beforeEach(
+ async(() => {
+
+ onboardingServiceMock = {
+ getOnboardingComponents: jest.fn().mockImplementation(()=> Observable.of(onboardingModalUniqueVSPMock)),
+ getComponentFromCsarUuid: jest.fn().mockImplementation(()=> Observable.of(vspFromServerMock))
+ };
+
+ cacheServiceMock = {
+ set: jest.fn()
+ };
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ }
+
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [OnboardingModalComponent, TranslatePipe],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: OnboardingService, useValue: onboardingServiceMock },
+ { provide: TranslateService, useValue: translateServiceMock },
+ { provide: CacheService, useValue: cacheServiceMock },
+ { provide: FileUtilsService, useValue: fileUtilsServiceMock },
+ { provide: SdcUiServices.PopoverService, useValue: popoverServiceMock },
+ { provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(OnboardingModalComponent);
+ });
+ })
+ );
+
+ /*it('should match current snapshot of onboarding modal component', () => {
+ expect(fixture).toMatchSnapshot();
+ });*/
+
+ it('should see exactly 2 vsp in onboarding modal and call initOnboardingComponentsList', () => {
+ fixture.componentInstance.initOnboardingComponentsList();
+ expect(fixture.componentInstance.componentsMetadataList.length).toBe(2);
+ });
+
+ it('should see exactly 1 vsp in onboarding modal and call initOnboardingComponentsList', () => {
+ fixture.componentInstance.currentCsarUUID = "6348841e79a64871ba064ce340a968a4";
+ fixture.componentInstance.initOnboardingComponentsList();
+ expect(fixture.componentInstance.componentsMetadataList.length).toBe(1);
+ });
+
+ it('when get a list of vsp initMaxVersionOfItemsInList will return a list with unique items with the latest versions for each packageId', () => {
+ onboardingServiceMock.getOnboardingComponents = jest.fn().mockImplementation(() => Observable.of(onboardingModalVSPMock));
+ fixture.componentInstance.initOnboardingComponentsList();
+ expect(fixture.componentInstance.componentsMetadataList.length).toBe(2);
+ });
+
+ it('should filter out 1 vsp when searching and call updateFilter function', () => {
+ fixture.componentInstance.initOnboardingComponentsList();
+ let event = {
+ target : {
+ value : 'test new vsp'
+ }
+ }
+
+ expect(fixture.componentInstance.componentsMetadataList.length).toBe(2);
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.componentsMetadataList.length).toBe(1);
+ });
+
+ it('When select the selected vsp the row details closed and call onSelectComponent function', () => {
+ fixture.componentInstance.initOnboardingComponentsList();
+ fixture.componentInstance.onSelectComponent({selected: []});
+ expect(fixture.componentInstance.selectedComponent).toEqual(undefined);
+ expect(fixture.componentInstance.componentFromServer).toEqual(undefined);
+ });
+
+ it('When select vsp a row with its details will be opened and call onSelectComponent function', () => {
+ fixture.componentInstance.initOnboardingComponentsList();
+ fixture.componentInstance.onSelectComponent({selected: onboardingModalVSPMock});
+ expect(fixture.componentInstance.selectedComponent).not.toEqual(null);
+ expect(fixture.componentInstance.componentFromServer).not.toEqual(undefined);
+ expect(fixture.componentInstance.isCsarComponentExists).toEqual(true);
+ });
+ it('When select new vsp a row with import and download buttons will be opened and call onSelectComponent function', () => {
+ fixture.componentInstance.initOnboardingComponentsList();
+ onboardingServiceMock.getComponentFromCsarUuid.mockImplementation(() => Observable.of(undefined));
+ fixture.componentInstance.onSelectComponent({selected: onboardingModalVSPMock});
+ expect(fixture.componentInstance.selectedComponent).not.toEqual(null);
+ expect(fixture.componentInstance.componentFromServer).toEqual(undefined);
+ expect(fixture.componentInstance.isCsarComponentExists).toEqual(false);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts
new file mode 100644
index 0000000..2e41716
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts
@@ -0,0 +1,193 @@
+/**
+ * Created by rc2122 on 6/3/2018.
+ */
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import * as _ from 'lodash';
+import { SdcUiServices } from 'onap-ui-angular';
+import { ComponentMetadata, IComponentMetadata } from '../../../../models/component-metadata';
+import { IUserProperties } from '../../../../models/user';
+
+import { Resource } from '../../../../models/components/resource';
+import { ComponentType } from '../../../../utils/constants';
+import { CacheService } from '../../../services/cache.service';
+import { FileUtilsService } from '../../../services/file-utils.service';
+import { OnboardingService } from '../../../services/onboarding.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+
+export interface ImportVSPdata {
+ componentCsar: Resource;
+ previousComponent?: Resource;
+ type: string;
+}
+
+// tslint:disable-next-line:interface-name
+export interface IPoint {
+ x: number;
+ y: number;
+}
+
+@Component({
+ selector: 'onboarding-modal',
+ templateUrl: './onboarding-modal.component.html',
+ styleUrls: ['onboarding-modal.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class OnboardingModalComponent implements OnInit {
+ @Input() currentCsarUUID: string;
+ @Input() currentCsarVersion: string;
+ @ViewChild('componentsMetadataTable') table: any;
+ @Output() closeModalEvent: EventEmitter<ImportVSPdata> = new EventEmitter<ImportVSPdata>();
+
+ private columns = [
+ {name: 'Name', prop: 'name', flexGrow: 22},
+ {name: 'Vendor', prop: 'vendorName', flexGrow: 26},
+ {name: 'Category', prop: 'categories', flexGrow: 33},
+ {name: 'Version', prop: 'csarVersion', flexGrow: 10},
+ {name: 'Type', prop: 'resourceType', flexGrow: 10},
+ {name: '#', prop: '', flexGrow: 20}
+ ];
+ private componentsMetadataList: IComponentMetadata[] = [];
+ private temp: IComponentMetadata[] = [];
+ private componentFromServer: ComponentMetadata;
+ private isCsarComponentExists: boolean = false;
+ private selectedComponent: ComponentMetadata;
+ private isLoading: boolean;
+ private user: IUserProperties;
+
+ constructor(private onBoardingService: OnboardingService,
+ private translateService: TranslateService,
+ private cacheService: CacheService,
+ private fileUtilsService: FileUtilsService,
+ private popoverService: SdcUiServices.PopoverService,
+ private loaderService: SdcUiServices.LoaderService) {
+ }
+
+ public ngOnInit(): void {
+ this.initOnboardingComponentsList();
+ this.user = this.cacheService.get('user');
+ }
+
+ initMaxVersionOfItemsInList = (onboardingResponse: IComponentMetadata[]): void => {
+ // Get only the latest version of each item
+ this.componentsMetadataList = [];
+
+ // group all items according to packageId
+ const groupByPackageIdItems = _.groupBy(onboardingResponse, 'packageId');
+ // Loop on all the groups and push to componentsMetadataList the max version for each package
+ _.each(groupByPackageIdItems, (items: any): void => {
+ let maxItem: any = items[0];
+ items.forEach((item) => {
+ if (parseFloat(maxItem.csarVersion) < parseFloat(item.csarVersion)) {
+ maxItem = item;
+ }
+ });
+ if (maxItem) {
+ this.componentsMetadataList.push(maxItem);
+ }
+ });
+ }
+
+ onSelectComponent({selected}) {
+ this.table.rowDetail.collapseAllRows();
+ if (selected[0] === this.selectedComponent) {
+ this.selectedComponent = undefined;
+ this.componentFromServer = undefined;
+ this.table.rowDetail.toggleExpandRow(null);
+ return;
+ }
+ this.isLoading = true;
+ this.componentFromServer = undefined;
+ this.selectedComponent = selected[0];
+ this.onBoardingService.getComponentFromCsarUuid(this.selectedComponent.csarUUID).subscribe(
+ (componentFromServer: ComponentMetadata) => {
+ this.isLoading = false;
+ if (componentFromServer) {
+ this.componentFromServer = componentFromServer;
+ this.populateRowDetails(true);
+ } else {
+ this.populateRowDetails(false);
+ }
+ }, (error) => {
+ this.isLoading = false;
+ this.populateRowDetails(false);
+ });
+ }
+
+ populateRowDetails(isCsarComponentExists: boolean) {
+ this.isCsarComponentExists = isCsarComponentExists;
+ this.table.rowDetail.toggleExpandRow(this.selectedComponent);
+ }
+
+ importOrUpdateCsar = (): void => {
+ const selectedComponentConverted = this.onBoardingService.convertMetaDataToComponent(this.selectedComponent);
+ const componentFromServerConverted = this.componentFromServer ?
+ this.onBoardingService.convertMetaDataToComponent(this.componentFromServer) : undefined;
+ const importVSPdata: ImportVSPdata = {
+ componentCsar: selectedComponentConverted,
+ previousComponent: componentFromServerConverted,
+ type: ComponentType.RESOURCE.toLowerCase()
+ };
+ this.closeModalEvent.emit(importVSPdata);
+ }
+
+ downloadCsar = (packageId: string): void => {
+ this.isLoading = true;
+ this.onBoardingService.downloadOnboardingCsar(packageId).subscribe(
+ (file: any): void => {
+ this.isLoading = false;
+ if (file.body) {
+ this.fileUtilsService.downloadFile(file.body, packageId + '.csar');
+ }
+ }, (): void => {
+ this.isLoading = false;
+ }
+ );
+ }
+
+ updateFilter(event) {
+ const val = event.target.value.toLowerCase();
+
+ // filter our data
+ const temp = this.temp.filter((componentMetadata: ComponentMetadata) => {
+ return !val ||
+ (componentMetadata.name && componentMetadata.name.toLowerCase().indexOf(val) !== -1) ||
+ (componentMetadata.vendorName && componentMetadata.vendorName.toLowerCase().indexOf(val) !== -1) ||
+ (componentMetadata.categories[0] && componentMetadata.categories[0].name.toLowerCase().indexOf(val) !== -1) ||
+ (componentMetadata.categories[0] && componentMetadata.categories[0].subcategories[0] && componentMetadata.categories[0].subcategories[0].name.toLowerCase().indexOf(val) !== -1) ||
+ (componentMetadata.csarVersion && componentMetadata.csarVersion.toLowerCase().indexOf(val) !== -1) ||
+ (componentMetadata.description && componentMetadata.description.toLowerCase().indexOf(val) !== -1);
+ });
+
+ // update the rows
+ this.componentsMetadataList = temp;
+ }
+
+ checkNotCertified = (): boolean => {
+ return this.componentFromServer && this.componentFromServer.lifecycleState === 'NOT_CERTIFIED_CHECKOUT' &&
+ this.componentFromServer.lastUpdaterUserId !== this.user.userId;
+ }
+
+ openPopover = ($event: any, popoverContent): void => {
+ this.popoverService.createPopOver('', this.translateService.translate(popoverContent), {
+ x: $event.pageX,
+ y: $event.pageY
+ }, 'bottom');
+ }
+
+ private initOnboardingComponentsList = (): void => {
+ this.loaderService.activate();
+ this.onBoardingService.getOnboardingComponents().subscribe(
+ (onboardingResponse: IComponentMetadata[]) => {
+ this.loaderService.deactivate();
+ if (this.currentCsarUUID) {
+ onboardingResponse = _.filter(onboardingResponse, (input): boolean => {
+ return (input as ComponentMetadata).csarUUID === this.currentCsarUUID;
+ });
+ }
+ this.initMaxVersionOfItemsInList(onboardingResponse);
+ this.temp = [...this.componentsMetadataList];
+ }, (error) => {
+ this.loaderService.deactivate();
+ }
+ );
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts b/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts
new file mode 100644
index 0000000..8f47456
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts
@@ -0,0 +1,145 @@
+import { Component, Input } from "@angular/core";
+import {IFileDownload, Component as TopologyTemplate, ArtifactModel, FullComponentInstance} from "app/models";
+import {EventListenerService} from "app/services";
+import {CacheService} from "app/services-ng2";
+import {EVENTS} from "app/utils";
+import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+
+@Component({
+ selector: 'download-artifact',
+ template: `
+ <svg-icon [mode]="'primary2'" [disabled]="disabled" [clickable]="!disabled" [name]="iconType" [testId]="testId" mode="info" clickable="true" size="medium" (click)="download($event)"></svg-icon>
+`
+})
+export class DownloadArtifactComponent {
+
+ @Input() showLoader:boolean;
+ @Input() artifact:ArtifactModel;
+ @Input() isInstance: boolean;
+ @Input() downloadIconClass: string;
+ @Input() componentType: string;
+ @Input() componentId: string;
+ @Input() testId: string;
+ @Input() disabled: boolean;
+
+ public iconType:string;
+
+ private DOWNLOAD_CSS_CLASSES = {
+ DOWNLOAD_ICON: "download-o",
+ LOADER_ICON: "spinner"
+ }
+ constructor(private cacheService:CacheService, private EventListenerService:EventListenerService, private topologyTemplateService:TopologyTemplateService,
+ private componentInstanceService: ComponentInstanceServiceNg2, private workspaceService:WorkspaceService) {
+
+ }
+
+ ngOnInit () {
+ this.iconType = this.DOWNLOAD_CSS_CLASSES.DOWNLOAD_ICON;
+ this.initDownloadLoader();
+
+ }
+
+ private initDownloadLoader = ()=> {
+ //if the artifact is in a middle of download progress register form callBack & change icon from download to loader
+ if (this.showLoader && this.cacheService.get(this.artifact.uniqueId)) {
+ this.EventListenerService.registerObserverCallback(EVENTS.DOWNLOAD_ARTIFACT_FINISH_EVENT + this.artifact.uniqueId, this.updateDownloadIcon);
+ window.setTimeout(():void => {
+ if (this.cacheService.get(this.artifact.uniqueId)) {
+ this.iconType = this.DOWNLOAD_CSS_CLASSES.LOADER_ICON;
+ }
+ }, 1000);
+ }
+ };
+
+ private updateDownloadIcon = () => {
+ this.iconType = this.downloadIconClass || this.DOWNLOAD_CSS_CLASSES.DOWNLOAD_ICON;
+ };
+
+ public download = (event) => {
+ event.stopPropagation();
+ let onFaild = (response):void => {
+ console.info('onFaild', response);
+ this.removeDownloadedFileLoader();
+ };
+
+ let onSuccess = (data:IFileDownload):void => {
+ this.downloadFile(data);
+ this.removeDownloadedFileLoader();
+ };
+
+ this.setDownloadedFileLoader();
+
+ if (this.isInstance) {
+ this.componentInstanceService.downloadInstanceArtifact(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.componentId, this.artifact.uniqueId).subscribe(onSuccess, onFaild);
+ } else {
+ this.topologyTemplateService.downloadArtifact(this.componentType, this.componentId, this.artifact.uniqueId).subscribe(onSuccess, onFaild);
+ }
+ };
+
+ private setDownloadedFileLoader = ()=> {
+ if (this.showLoader) {
+ //set in cache service thet the artifact is in download progress
+ this.cacheService.set(this.artifact.uniqueId, true);
+ this.initDownloadLoader();
+ }
+ };
+
+ private removeDownloadedFileLoader = ()=> {
+ if (this.showLoader) {
+ this.cacheService.set(this.artifact.uniqueId, false);
+ this.EventListenerService.notifyObservers(EVENTS.DOWNLOAD_ARTIFACT_FINISH_EVENT + this.artifact.uniqueId);
+ }
+ };
+
+ private downloadFile = (file:IFileDownload):void => {
+ if (file) {
+ let blob = this.base64toBlob(file.base64Contents, '');
+ let fileName = file.artifactName;
+ this.triggerFileDownload(blob, fileName);
+ }
+ };
+
+ public base64toBlob = (base64Data, contentType):any => {
+ let byteCharacters = atob(base64Data);
+ return this.byteCharactersToBlob(byteCharacters, contentType);
+ };
+
+ public byteCharactersToBlob = (byteCharacters, contentType):any => {
+ contentType = contentType || '';
+ let sliceSize = 1024;
+ let bytesLength = byteCharacters.length;
+ let slicesCount = Math.ceil(bytesLength / sliceSize);
+ let byteArrays = new Array(slicesCount);
+
+ for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
+ let begin = sliceIndex * sliceSize;
+ let end = Math.min(begin + sliceSize, bytesLength);
+
+ let bytes = new Array(end - begin);
+ for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
+ bytes[i] = byteCharacters[offset].charCodeAt(0);
+ }
+ byteArrays[sliceIndex] = new Uint8Array(bytes);
+ }
+ return new Blob(byteArrays, {type: contentType});
+ };
+
+ public triggerFileDownload = (blob, fileName):void=> {
+ let url = window.URL.createObjectURL(blob);
+ let downloadLink = document.createElement("a");
+
+ downloadLink.setAttribute('href', url);
+ downloadLink.setAttribute('download', fileName);
+ document.body.appendChild(downloadLink);
+
+ var clickEvent = new MouseEvent("click", {
+ "view": window,
+ "bubbles": true,
+ "cancelable": true
+ });
+ downloadLink.dispatchEvent(clickEvent);
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts
index 049d408..5e3214d 100644
--- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts
@@ -37,11 +37,13 @@
BOOLEAN,
SUBNETPOOLID,
ENUM,
+ LIST,
DEFAULT
}
@Component({
selector: 'dynamic-element',
+ // Span - if constraints not empty
template: `<div #target></div>`,
styleUrls: ['./dynamic-element.component.less'],
entryComponents: [
@@ -61,6 +63,7 @@
@Input() readonly:boolean;
@Input() constraints: Array<any>;
@Input() path:string;//optional param. used only for for subnetpoolid type
+ @Input() declared:boolean;
@Input() value: any;
@Output() valueChange: EventEmitter<any> = new EventEmitter<any>();
@@ -72,16 +75,19 @@
validation = ValidationConfiguration.validation;
constructor(
+
private componentFactoryResolver: ComponentFactoryResolver,
private compiler: Compiler,
private el: ElementRef) {
+
+
}
updateComponent() {
if (!this.isViewInitialized) {
return;
}
-
+
// Factory to create component based on type or other property attributes.
const prevElementCreatorIdentifier: DynamicElementComponentCreatorIdentifier = this.elementCreatorIdentifier;
switch(true) {
@@ -112,7 +118,7 @@
}
// In case the dynamic element creator is changed, then destroy old and build new.
- if (this.elementCreatorIdentifier !== prevElementCreatorIdentifier) {
+ if (this.declared || this.elementCreatorIdentifier !== prevElementCreatorIdentifier) {
if (this.cmpRef) {
this.cmpRef.destroy();
}
@@ -149,64 +155,81 @@
}
createComponentByIdentifier() {
- switch(this.elementCreatorIdentifier) {
- case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID:
- if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name
- let pathArray = this.path.split("#");
- this.name = pathArray[pathArray.length - 2];
- }
- this.createComponent(UiElementPopoverInputComponent);
- break;
-
- case DynamicElementComponentCreatorIdentifier.ENUM:
- this.createComponent(UiElementDropDownComponent);
- let validVals:Array<DropdownValue> = [...this.getValidValues()].map(val => new DropdownValue(val, val));
- if (this.type === 'float' || this.type === 'integer') {
- this.value = this.value && Number(this.value);
- validVals = _.map(
- validVals,
- val => new DropdownValue(Number(val.value), val.value)
- );
- }
- this.cmpRef.instance.values = validVals;
- break;
-
- case DynamicElementComponentCreatorIdentifier.INTEGER:
- this.createComponent(UiElementIntegerInputComponent);
- this.cmpRef.instance.pattern = this.validation.validationPatterns.integer;
- break;
-
- case DynamicElementComponentCreatorIdentifier.FLOAT:
- this.createComponent(UiElementIntegerInputComponent);
- this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/.source;
- break;
-
- case DynamicElementComponentCreatorIdentifier.STRING:
- this.createComponent(UiElementInputComponent);
- break;
-
- case DynamicElementComponentCreatorIdentifier.BOOLEAN:
- this.createComponent(UiElementDropDownComponent);
-
- // Build drop down values
- let tmp = [];
- tmp.push(new DropdownValue(true,'TRUE'));
- tmp.push(new DropdownValue(false,'FALSE'));
- this.cmpRef.instance.values = tmp;
- try {
- if (typeof this.value === 'string') {
- this.value = JSON.parse(this.value);
+ // if(!this.constraints || this.declared){
+ switch(this.elementCreatorIdentifier) {
+ case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID:
+ if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name
+ let pathArray = this.path.split("#");
+ this.name = pathArray[pathArray.length - 2];
}
- } catch(err) {
- this.value = null;
- }
- break;
+ this.createComponent(UiElementPopoverInputComponent);
+ break;
+ case DynamicElementComponentCreatorIdentifier.ENUM:
+ this.createComponent(UiElementDropDownComponent);
+ let validVals:Array<DropdownValue> = [...this.getValidValues()].map(val => new DropdownValue(val, val));
+ if (this.type === 'float' || this.type === 'integer') {
+ this.value = this.value && Number(this.value);
+ validVals = _.map(
+ validVals,
+ (val) => new DropdownValue(Number(val.value), val.value)
+ );
+ }
+ this.cmpRef.instance.values = validVals;
+ break;
+ case DynamicElementComponentCreatorIdentifier.INTEGER:
+ this.createComponent(UiElementIntegerInputComponent);
+ this.cmpRef.instance.pattern = this.validation.validationPatterns.integer;
+ break;
- case DynamicElementComponentCreatorIdentifier.DEFAULT:
- default:
- this.createComponent(UiElementInputComponent);
- console.log("ERROR: No ui-models component to handle type: " + this.type);
- }
+ case DynamicElementComponentCreatorIdentifier.FLOAT:
+ this.createComponent(UiElementIntegerInputComponent);
+ this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/.source;
+ break;
+
+ case DynamicElementComponentCreatorIdentifier.STRING:
+ this.createComponent(UiElementInputComponent);
+ break;
+
+ case DynamicElementComponentCreatorIdentifier.BOOLEAN:
+ this.createComponent(UiElementDropDownComponent);
+
+ // Build drop down values
+ let tmp = [];
+ tmp.push(new DropdownValue(true,'TRUE'));
+ tmp.push(new DropdownValue(false,'FALSE'));
+ this.cmpRef.instance.values = tmp;
+ try {
+ if(typeof this.value === 'string'){
+ this.value = JSON.parse(this.value);
+ }
+ } catch (err) {
+ this.value = null;
+ }
+ break;
+
+ case DynamicElementComponentCreatorIdentifier.DEFAULT:
+ default:
+ this.createComponent(UiElementInputComponent);
+ console.log("ERROR: No ui-models component to handle type: " + this.type);
+ }
+ // }
+ // //There are consraints
+ // else {
+
+ // this.createComponent(UiElementDropDownComponent);
+
+ // // Build drop down values
+ // let items = [];
+ // this.constraints.forEach( (element) => {
+ // items.push(new DropdownValue(element,element));
+ // });
+
+ // items.push(new DropdownValue(this.value,this.value, true, true));
+ // this.cmpRef.instance.values = items;
+
+
+
+ // }
// Subscribe to change event of of ui-models-element-basic and fire event to change the value
this.cmpRef.instance.baseEmitter.subscribe((event) => { this.emitter.emit(event); });
diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts
index 50b2250..dc12551 100644
--- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts
@@ -23,6 +23,12 @@
import {TooltipModule} from "../tooltip/tooltip.module";
import {DynamicElementComponent} from "./dynamic-element.component";
import {FormElementsModule} from "../form-components/form-elements.module";
+// import {SdcUiComponentsModule} from "sdc-ui/lib/angular";
+// import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
+// import {SdcUiComponentsModule} from "onap-ui/lib/angular";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+
+import { CommonModule } from '@angular/common';
@NgModule({
declarations: [
@@ -31,7 +37,9 @@
imports: [
PopoverModule,
TooltipModule,
- FormElementsModule
+ FormElementsModule,
+ SdcUiComponentsModule,
+ CommonModule
],
exports: [
DynamicElementComponent
diff --git a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html
index fde7bca..9b678b2 100644
--- a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html
@@ -14,16 +14,15 @@
~ limitations under the License.
-->
-<h1 class="w-sdc-designer-sidebar-section-title"
- tooltip="{{titleTooltip}}"
- [ngClass]="{'expanded': state == 0, 'collapsed': state == 1}"
- (click)="toggleState()">
- {{caption}}<span class="w-sdc-designer-sidebar-section-title-icon"></span>
- <ng-content select="header"></ng-content>
- <span class="w-sdc-designer-sidebar-section-title-icon"></span>
-</h1>
+<div class="expand-collapse-container">
+ <h1 class="expand-collapse-title" [ngClass]="{'expanded': state == 0, 'collapsed': state == 1}"
+ tooltip="{{titleTooltip}}" (click)="toggleState()">{{caption}}
+ <ng-content select="header"></ng-content>
+ <svg-icon name="caret1-down-o" mode="info" size="small" class="expand-collapse-title-icon"></svg-icon>
+ </h1>
-<div class="expand-collapse-content" [ngClass]="{'visible': state === 0, 'hidden': state === 1}">
- <ng-content></ng-content>
- <ng-content select="content"></ng-content>
-</div>
+ <div class="expand-collapse-content" [ngClass]="{'expanded': state === 0, 'collapsed': state === 1}">
+ <ng-content></ng-content>
+ <ng-content select="content"></ng-content>
+ </div>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less
index e5dd252..deda687 100644
--- a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less
+++ b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less
@@ -5,3 +5,51 @@
text-decoration: underline;
text-align: left;
}
+
+
+.expand-collapse-title {
+ display:flex;
+ align-items: center;
+ cursor: pointer;
+ font-size: 14px;
+ text-transform: uppercase;
+ line-height: 32px;
+ padding: 0 10px 0 20px;
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ header {
+ flex: 1;
+ }
+
+ .expand-collapse-title-icon {
+ padding-top: 10px;
+ padding-left: 2px;
+ transition: transform .3s ease-out;
+
+ }
+
+ &.expanded .expand-collapse-title-icon {
+ transform: rotate(0);
+ }
+
+ &.collapsed .expand-collapse-title-icon {
+ transform: rotate(-180deg);
+ }
+
+}
+
+.expand-collapse-content {
+ overflow: hidden;
+ transition: max-height .3s ease-in;
+
+ &.collapsed {
+ max-height: 0px;
+ overflow:hidden;
+ transition: all .3s cubic-bezier(0, 1, 0, 1);
+
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html
new file mode 100644
index 0000000..14fc6ee
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html
@@ -0,0 +1,6 @@
+<label>
+ <input type="file" class="i-sdc-dashboard-item-upload-input"
+ (change)="onFileSelect($event)"
+ [accept]="extensionsWithDot"
+ [attr.data-tests-id]="'file-' + testsId" />
+</label>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.less
similarity index 100%
copy from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less
copy to catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.less
diff --git a/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts
new file mode 100644
index 0000000..1d1d4ce
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts
@@ -0,0 +1,45 @@
+import {Component, Input, Output, EventEmitter, SimpleChanges} from "@angular/core";
+
+@Component({
+ selector: 'file-opener',
+ templateUrl: './file-opener.component.html',
+ styleUrls: ['./file-opener.component.less']
+})
+export class FileOpenerComponent {
+ @Input() public testsId: string;
+ @Input() public extensions: string;
+ @Output() public onFileUpload: EventEmitter<any>;
+
+ public extensionsWithDot: string;
+
+ constructor() {
+ this.onFileUpload = new EventEmitter<any>();
+ }
+
+ public ngOnChanges(changes:SimpleChanges) {
+ if (changes.extensions) {
+ this.extensionsWithDot = this.getExtensionsWithDot(changes.extensions.currentValue);
+ }
+ }
+
+ public onFileSelect(event) {
+ const importFile:any = event.target.files[0];
+ const reader = new FileReader();
+ reader.readAsBinaryString(importFile);
+ reader.onload = () => {
+ this.onFileUpload.emit({
+ filename: importFile.name,
+ filetype: importFile.type,
+ filesize: importFile.size,
+ base64: btoa(reader.result)
+ });
+ };
+ }
+
+ public getExtensionsWithDot(extensions:string):string {
+ extensions = extensions || this.extensions || '';
+ return extensions.split(',')
+ .map(ext => '.' + ext.toString())
+ .join(',');
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts
index c8da016..c7b0af6 100644
--- a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts
@@ -19,7 +19,7 @@
*/
import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
-//import { trigger, state, style, transition, animate, keyframes } from '@angular/core';
+//import { trigger, state, style, transition, animate, keyframes } from '@angular/animations';
@Component({
selector: 'checkbox',
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html
index 45fd77e..9dca01e 100644
--- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html
@@ -15,5 +15,5 @@
-->
<select name='{{name}}' [(ngModel)]="value" (change)="onChange()" [ngClass]="{'disabled':readonly}" [attr.data-tests-id]="'value-' + testId">
- <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue">{{ddvalue.label||ddvalue}}</option>
+ <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue" [hidden]="ddvalue.hidden" [selected] = "ddvalue.selected">{{ddvalue.label||ddvalue}}</option>
</select>
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts
index 03a1fc6..6db2335 100644
--- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts
@@ -24,11 +24,21 @@
export class DropdownValue {
value:any;
label:string;
+ hidden?: boolean;
+ selected?: boolean;
- constructor(value:any,label:string) {
+
+ constructor(value:any,label:string, hidden: boolean = false, selected: boolean = false) {
this.value = value;
this.label = label;
+ this.hidden = hidden;
+ this.selected = selected;
+
+ // this.hidden = hidden ? true : "hidden": "";
+ // this.selected = selected ? true : "selected": "";
}
+
+
}
@Component({
@@ -37,8 +47,8 @@
styleUrls: ['./ui-element-dropdown.component.less'],
})
export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface {
- @Input()
- values: DropdownValue[]|string[];
+
+ @Input() values: DropdownValue[];
constructor() {
super();
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts
index e5bdf1f..b35d3ae 100644
--- a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts
@@ -1,19 +1,19 @@
/**
* Created by rc2122 on 9/5/2017.
*/
-import {NgModule} from "@angular/core";
-import {BrowserModule} from "@angular/platform-browser";
-import {FormsModule, ReactiveFormsModule} from "@angular/forms";
-import {UiElementPopoverInputComponent} from "./popover-input/ui-element-popover-input.component";
-import {UiElementIntegerInputComponent} from "./integer-input/ui-element-integer-input.component";
-import {UiElementInputComponent} from "./input/ui-element-input.component";
-import {UiElementDropDownComponent} from "./dropdown/ui-element-dropdown.component";
-import {UiElementBase} from "./ui-element-base.component";
-import {CheckboxModule} from "./checkbox/checkbox.module";
-import {RadioButtonComponent} from "./radio-buttons/radio-buttons.component";
-import {PopoverModule} from "../popover/popover.module";
-import {TooltipModule} from "../tooltip/tooltip.module";
-
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { BrowserModule } from '@angular/platform-browser';
+import { SdcUiComponentsModule } from 'onap-ui-angular/dist';
+import { PopoverModule } from '../popover/popover.module';
+import { TooltipModule } from '../tooltip/tooltip.module';
+import { CheckboxModule } from './checkbox/checkbox.module';
+import { UiElementDropDownComponent } from './dropdown/ui-element-dropdown.component';
+import { UiElementInputComponent } from './input/ui-element-input.component';
+import { UiElementIntegerInputComponent } from './integer-input/ui-element-integer-input.component';
+import { UiElementPopoverInputComponent } from './popover-input/ui-element-popover-input.component';
+import { RadioButtonComponent } from './radio-buttons/radio-buttons.component';
+import { UiElementBase } from './ui-element-base.component';
@NgModule({
imports: [
@@ -22,7 +22,8 @@
PopoverModule,
ReactiveFormsModule,
TooltipModule,
- CheckboxModule],
+ CheckboxModule,
+ SdcUiComponentsModule],
declarations: [UiElementDropDownComponent,
UiElementInputComponent,
@@ -39,4 +40,4 @@
TooltipModule,
CheckboxModule]
})
-export class FormElementsModule { }
\ No newline at end of file
+export class FormElementsModule { }
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html
index 85089f1..f9cf17f 100644
--- a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html
@@ -13,19 +13,18 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-<input
- class="value-input"
- [ngClass]="{'error': control.invalid, 'disabled':readonly}"
- type="text"
- [name]="name"
- [(ngModel)]="value"
- (input)="onChange()"
- [attr.maxlength]="validation.propertyValue.max"
- [attr.minlength]="validation.propertyValue.min"
- [pattern]="pattern"
- [formControl]="control"
- tooltip="{{value}}"
- [readonly]="readonly"
- [attr.data-tests-id]="'value-' + testId"
- />
+<div sdc-tooltip [tooltip-text]="value">
+ <input
+ class="value-input"
+ [ngClass]="{'error': control.invalid, 'disabled':readonly}"
+ type="text"
+ [name]="name"
+ [(ngModel)]="value"
+ (input)="onChange()"
+ [attr.maxlength]="validation.propertyValue.max"
+ [attr.minlength]="validation.propertyValue.min"
+ [pattern]="pattern"
+ [formControl]="control"
+ [attr.data-tests-id]="'value-' + testId"
+ />
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts b/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts
index 34404e5..b401778 100644
--- a/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts
@@ -1,15 +1,11 @@
import { NgModule } from "@angular/core";
import { CommonModule } from '@angular/common';
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { ValueEditComponent } from './value-edit/value-edit.component';
+import { SdcUiComponentsModule } from "onap-ui-angular";
import { UnsavedChangesComponent } from "./unsaved-changes/unsaved-changes.component";
import { UiElementsModule } from "../ui-elements.module";
-
-
@NgModule({
declarations: [
- ValueEditComponent,
UnsavedChangesComponent
],
imports: [
@@ -17,7 +13,7 @@
SdcUiComponentsModule,
UiElementsModule
],
- exports: [ValueEditComponent, UnsavedChangesComponent],
+ exports: [UnsavedChangesComponent],
entryComponents: [ UnsavedChangesComponent
],
providers: []
diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html
index bfb9e1b..0008305 100644
--- a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<div *ngIf="isVisible" data-tests-id="tlv-loader" [ngClass]="relative ? 'loader-relative' : 'loader-fixed'"
+<div *ngIf="isVisible" data-tests-id="loader" [ngClass]="relative ? 'loader-relative' : 'loader-fixed'"
[style.top]="offset.top" [style.left]="offset.left" [style.width]="offset.width" [style.height]="offset.height">
<div class="tlv-loader-back" [ngClass]="{'tlv-loader-relative':relative}"></div>
<div class="tlv-loader {{size}}"></div>
diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts
index 585c366..9658e6b 100644
--- a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts
@@ -79,6 +79,13 @@
width: (parentElement.offsetWidth !== undefined) ? parentElement.offsetWidth + "px" : undefined,
height: (parentElement.offsetHeight !== undefined) ? parentElement.offsetHeight + "px" : undefined
};
+ } else {
+ this.offset = {
+ left: '0px',
+ top: '0px',
+ width: '100%',
+ height: '100%'
+ }
}
this.isVisible = true;
}
diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts
index 3820573..8b20066 100644
--- a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts
@@ -1,5 +1,9 @@
/*-
+ * ============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
@@ -11,9 +15,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ * ============LICENSE_END=========================================================
*/
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts
index 939599f..290c8d0 100644
--- a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts
@@ -1,5 +1,9 @@
/*-
+ * ============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
@@ -11,9 +15,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ * ============LICENSE_END=========================================================
*/
-
import { Component, Input, ContentChildren, SimpleChanges, QueryList } from '@angular/core';
import { MenuItemComponent } from "./menu-item.component";
import { Point } from "app/models";
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts
index 1d05b27..ab36752 100644
--- a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts
@@ -1,9 +1,9 @@
/**
* Created by ob0695 on 11.04.2018.
*/
-import {Component, Input} from "@angular/core";
-import {UiBaseObject} from "../../../../../models/ui-models/ui-base-object";
-import {IDropDownOption} from "sdc-ui/lib/angular/form-elements/dropdown/dropdown-models";
+import { Component, Input } from "@angular/core";
+import { UiBaseObject } from "../../../../../models/ui-models/ui-base-object";
+import { IDropDownOption } from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
@Component({
selector: 'add-elements',
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts
index a1c34f5..70ad0a3 100644
--- a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts
@@ -1,14 +1,11 @@
/**
* Created by ob0695 on 11.04.2018.
*/
-import {NgModule} from "@angular/core";
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
-import {AddElementsComponent} from "./add-elements.component";
-import {CommonModule} from "@angular/common";
+import { NgModule } from "@angular/core";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import { AddElementsComponent } from "./add-elements.component";
+import { CommonModule } from "@angular/common";
-/**
- * Created by ob0695 on 9.04.2018.
- */
@NgModule({
declarations: [
AddElementsComponent
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts
index 777e9bd..2432c3b 100644
--- a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts
@@ -36,7 +36,7 @@
@Input() isMovable: boolean;
@Input() input: ModalModel;
@Input() dynamicContent: any;
- @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpService's catchError() for example.
+ @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpHelperService's catchError() for example.
private modalElement: JQuery;
constructor( el: ElementRef ) {
diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts
index 9219a30..1986e34 100644
--- a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts
@@ -20,10 +20,8 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-import {
- Component, ElementRef, forwardRef, Inject, Input, trigger, state, style,
- transition, animate, ViewChild, ViewContainerRef, ComponentRef
-} from "@angular/core";
+import { Component, ElementRef, forwardRef, Inject, Input, ViewChild, ViewContainerRef, ComponentRef} from "@angular/core";
+import {trigger, state, style, transition, animate} from '@angular/animations';
import {StepModel} from "app/models";
import {ModalService} from "../../../services/modal.service";
import {ModalComponent} from "../modal/modal.component";
diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts
index 3db217d..81a90b8 100644
--- a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts
@@ -4,7 +4,7 @@
import { NgModule } from "@angular/core";
import {MultiStepsWizardComponent} from "./multi-steps-wizard.component";
import {CommonModule} from "@angular/common";
-import {ConnectionWizardModule} from "../../../pages/connection-wizard/connection-wizard.module";
+import {ConnectionWizardModule} from "app/ng2/pages/composition/graph/connection-wizard/connection-wizard.module";
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html
new file mode 100644
index 0000000..277702e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html
@@ -0,0 +1,11 @@
+<div class="w-sdc-designer-sidebar-toggle" [class.active]="(withSidebar$ | async)" (click)="toggleSidebarDisplay()">
+ <div class="w-sdc-designer-sidebar-toggle-icon sprite-new pointer menu-open-left"></div>
+</div>
+
+<div class="w-sdc-designer-sidebar">
+ <ng-content></ng-content>
+</div>
+
+
+
+
diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less
new file mode 100644
index 0000000..cacb85d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less
@@ -0,0 +1,55 @@
+@import '../../../../../assets/styles/variables';
+
+.w-sdc-designer-sidebar {
+ background-color:@main_color_p ;
+ font-family: @font-opensans-regular;
+ font-size: 13px;
+ color: #191919;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ bottom: 0;
+ position: fixed;
+ right: -302px;
+ width: 302px;
+ top: 103px;
+ transition: right 0.2s;
+ z-index: 1010;
+ box-shadow: -7px -3px 6px -8px @main_color_n;
+}
+
+.w-sdc-designer-sidebar-toggle {
+ background-color: @main_color_p;
+ border-left: 1px solid @main_color_o;
+ border-bottom: 1px solid @main_color_o;
+ height: 21px;
+ position: absolute;
+ right: 0;
+ top: 53px;
+ width: 17px;
+ transition: right 0.2s;
+ z-index: 1005;
+ box-shadow: -1px 1px 3px 0 @main_color_n;
+ cursor: pointer;
+
+ &.active {
+ right: 302px;
+ .w-sdc-designer-sidebar-toggle-icon{
+ transform: rotate(180deg);
+ }
+ }
+}
+
+.w-sdc-designer-sidebar-toggle-icon {
+ margin-left: 6px;
+ margin-top: 6px;
+}
+
+.w-sdc-designer-sidebar-toggle.active + .w-sdc-designer-sidebar {
+ right: 0;
+ display: flex;
+ flex-direction: column;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts
new file mode 100644
index 0000000..e9c4a7d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts
@@ -0,0 +1,25 @@
+import {Component} from "@angular/core";
+import {Select, Store} from "@ngxs/store";
+import {Subscription} from "rxjs/Subscription";
+import {GraphState} from "../../../pages/composition/common/store/graph.state";
+import {OnSidebarOpenOrCloseAction} from "../../../pages/composition/common/store/graph.actions";
+
+@Component({
+ selector: 'panel-wrapper-component',
+ templateUrl: './panel-wrapper.component.html',
+ styleUrls: ['./panel-wrapper.component.less']
+})
+export class PanelWrapperComponent {
+ @Select(GraphState.withSidebar) withSidebar$: boolean;
+
+ tabs: Array<any>;
+ subscription: Subscription;
+
+ constructor(public store: Store) {
+ }
+
+ private toggleSidebarDisplay = () => {
+ // this.withSidebar = !this.withSidebar;
+ this.store.dispatch(new OnSidebarOpenOrCloseAction());
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts b/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts
new file mode 100644
index 0000000..ccc1e21
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts
@@ -0,0 +1,51 @@
+import {Directive, Input, ElementRef} from '@angular/core';
+import * as PerfectScrollbar from 'perfect-scrollbar';
+
+interface IPerfectScrollbarOptions {
+ wheelSpeed?: number;
+ wheelPropagation?: boolean;
+ minScrollbarLength?: number;
+ useBothWheelAxes?: boolean;
+ useKeyboard?: boolean;
+ suppressScrollX?: boolean;
+ suppressScrollY?: boolean;
+ scrollXMarginOffset?: number;
+ scrollYMarginOffset?: number;
+ includePadding?: boolean;
+}
+
+@Directive({
+ selector: '[perfectScrollbar]'
+})
+export class PerfectScrollbarDirective {
+ @Input() public perfectScrollbarOptions: IPerfectScrollbarOptions;
+
+ private psOptions: IPerfectScrollbarOptions;
+ private updatingPS: boolean;
+
+ constructor(public elemRef:ElementRef) {
+ console.log('PSbar: Constructor');
+ this.psOptions = Object.assign({}, this.perfectScrollbarOptions);
+ this.updatingPS = false;
+ }
+
+ public ngOnInit() {
+ console.log('PSbar: Initializing');
+ PerfectScrollbar.initialize(this.elemRef.nativeElement, this.psOptions);
+ }
+
+ public ngAfterContentChecked() {
+ // update perfect-scrollbar after content is checked (updated) - bounced
+ if (!this.updatingPS) {
+ this.updatingPS = true;
+ setTimeout(() => {
+ this.updatingPS = false;
+ PerfectScrollbar.update(this.elemRef.nativeElement);
+ }, 100);
+ }
+ }
+
+ public ngOnDestroy() {
+ PerfectScrollbar.destroy(this.elemRef.nativeElement);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html
index cce1c40..5294c67 100644
--- a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html
@@ -17,6 +17,7 @@
<div class="plugin-frame">
<div class="w-sdc-main-container">
<iframe *ngIf="plugin.isOnline" class="plugin-iframe" [src]="pluginUrl | safeUrlSanitizer"></iframe>
- <plugin-not-connected [pluginName]="plugin.pluginId" *ngIf="!plugin.isOnline && isPluginCheckDone"></plugin-not-connected>
+ <plugin-not-connected [pluginName]="plugin.pluginId"
+ *ngIf="!plugin.isOnline && isPluginCheckDone"></plugin-not-connected>
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts
index d70c448..d94f24d 100644
--- a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts
@@ -38,8 +38,7 @@
} else {
this.onLoadingDone.emit();
}
- })
-
+ });
}
private initPlugin() {
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html
index 88906d9..9a280e1 100644
--- a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html
@@ -19,7 +19,7 @@
[style.left]="left + 'px'"
[class.in]="isIn"
[class.fade]="animation"
- style="display: block"
+ [style.display] = "displayType"
role="popover"
[ngClass]="{'hide-arrow':hideArrow}">
<div [hidden]="!closeOnMouseOutside" class="virtual-area"></div>
@@ -29,13 +29,11 @@
<span class="close-button" (click)="popover.hide()"></span>
</div>
<ng-content></ng-content>
- <div class="popover-footer">
+ <div class="popover-footer" *ngIf="buttons">
<button *ngFor="let buttonName of buttonsNames"
- class="tlv-btn {{buttons[buttonName].cssClass}}"
+ class="tlv-btn {{buttons[buttonName].cssClass}}"
[attr.data-tests-id]="'filter-' + buttons[buttonName].text.toLowerCase() + '-button'"
[disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()"
(click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button>
</div>
</div>
-
-
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts
index 6eb3628..bea592d 100644
--- a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.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.
@@ -18,25 +18,25 @@
* ============LICENSE_END=========================================================
*/
-import {Component, Input, Output, AfterViewInit, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, EventEmitter, Renderer } from "@angular/core";
-import {ButtonsModelMap} from "app/models";
-import {PopoverComponent} from "./popover.component";
+import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, Output, Renderer, ViewChild } from '@angular/core';
+import { ButtonsModelMap } from 'app/models';
+import { PopoverComponent } from './popover.component';
@Component({
- selector: "popover-content",
- templateUrl:'./popover-content.component.html',
- styleUrls:['popover-content.component.less']
+ selector: 'popover-content',
+ templateUrl: './popover-content.component.html',
+ styleUrls: ['popover-content.component.less']
})
export class PopoverContentComponent implements AfterViewInit, OnDestroy {
@Input() public title: string;
- @Input() public buttons:ButtonsModelMap;
+ @Input() public buttons: ButtonsModelMap;
@Input()
content: string;
@Input()
- placement: "top"|"bottom"|"left"|"right"|"auto"|"auto top"|"auto bottom"|"auto left"|"auto right" = "bottom";
+ placement: 'top'|'bottom'|'left'|'right'|'auto'|'auto top'|'auto bottom'|'auto left'|'auto right' = 'bottom';
@Input()
animation: boolean = true;
@@ -50,52 +50,56 @@
@Input()
hideArrow: boolean = false;
- @ViewChild("popoverDiv")
+ @ViewChild('popoverDiv')
popoverDiv: ElementRef;
- buttonsNames:Array<string>;
+ buttonsNames: string[];
popover: PopoverComponent;
onCloseFromOutside = new EventEmitter();
- top: number = -10000;
- left: number = -10000;
+ top: number = 250;
+ left: number = 300;
isIn: boolean = false;
- displayType: string = "none";
+ displayType: string = 'none';
effectivePlacement: string;
- onDocumentMouseDown = (event: any) => {
- const element = this.element.nativeElement;
- if (!element || !this.popover) return;
- if (element.contains(event.target) || this.popover.getElement().contains(event.target)) return;
- this.hide();
- this.onCloseFromOutside.emit(undefined);
- };
-
+ listenClickFunc: any;
+ listenMouseFunc: any;
constructor(protected element: ElementRef,
protected cdr: ChangeDetectorRef,
protected renderer: Renderer) {
}
- listenClickFunc: any;
- listenMouseFunc: any;
+ onDocumentMouseDown = (event: any) => {
+ const element = this.element.nativeElement;
+ if (!element || !this.popover) { return; }
+ if (element.contains(event.target) || this.popover.getElement().contains(event.target)) { return; }
+ this.hide();
+ this.onCloseFromOutside.emit(undefined);
+ }
ngAfterViewInit(): void {
- this.buttonsNames = Object.keys(this.buttons);
- if (this.closeOnClickOutside)
- this.listenClickFunc = this.renderer.listenGlobal("document", "mousedown", (event: any) => this.onDocumentMouseDown(event));
- if (this.closeOnMouseOutside)
- this.listenMouseFunc = this.renderer.listenGlobal("document", "mouseover", (event: any) => this.onDocumentMouseDown(event));
+ if ( this.buttons ) {
+ this.buttonsNames = Object.keys(this.buttons);
+ }
+ if (this.closeOnClickOutside) {
+ this.listenClickFunc = this.renderer.listenGlobal('document', 'mousedown', (event: any) => this.onDocumentMouseDown(event));
+ }
+ if (this.closeOnMouseOutside) {
+ this.listenMouseFunc = this.renderer.listenGlobal('document', 'mouseover', (event: any) => this.onDocumentMouseDown(event));
+ }
- this.show();
this.cdr.detectChanges();
}
ngOnDestroy() {
- if (this.closeOnClickOutside)
+ if (this.closeOnClickOutside) {
this.listenClickFunc();
- if (this.closeOnMouseOutside)
+ }
+ if (this.closeOnMouseOutside) {
this.listenMouseFunc();
+ }
}
// -------------------------------------------------------------------------
@@ -103,11 +107,12 @@
// -------------------------------------------------------------------------
show(): void {
- if (!this.popover || !this.popover.getElement())
+ if (!this.popover || !this.popover.getElement()) {
return;
+ }
const p = this.positionElements(this.popover.getElement(), this.popoverDiv.nativeElement, this.placement);
- this.displayType = "block";
+ this.displayType = 'block';
this.top = p.top;
this.left = p.left;
this.isIn = true;
@@ -121,8 +126,7 @@
}
hideFromPopover() {
- this.top = -10000;
- this.left = -10000;
+ this.displayType = 'none';
this.isIn = true;
}
@@ -131,56 +135,56 @@
// -------------------------------------------------------------------------
protected positionElements(hostEl: HTMLElement, targetEl: HTMLElement, positionStr: string, appendToBody: boolean = false): { top: number, left: number } {
- let positionStrParts = positionStr.split("-");
+ const positionStrParts = positionStr.split('-');
let pos0 = positionStrParts[0];
- let pos1 = positionStrParts[1] || "center";
- let hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);
- let targetElWidth = targetEl.offsetWidth;
- let targetElHeight = targetEl.offsetHeight;
+ const pos1 = positionStrParts[1] || 'center';
+ const hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);
+ const targetElWidth = targetEl.offsetWidth;
+ const targetElHeight = targetEl.offsetHeight;
this.effectivePlacement = pos0 = this.getEffectivePlacement(pos0, hostEl, targetEl);
- let shiftWidth: any = {
- center: function (): number {
+ const shiftWidth: any = {
+ center(): number {
return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
},
- left: function (): number {
+ left(): number {
return hostElPos.left;
},
- right: function (): number {
+ right(): number {
return hostElPos.left + hostElPos.width - targetElWidth;
}
};
- let shiftHeight: any = {
- center: function (): number {
+ const shiftHeight: any = {
+ center(): number {
return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
},
- top: function (): number {
+ top(): number {
return hostElPos.top;
},
- bottom: function (): number {
+ bottom(): number {
return hostElPos.top + hostElPos.height - targetElHeight;
}
};
let targetElPos: { top: number, left: number };
switch (pos0) {
- case "right":
+ case 'right':
targetElPos = {
top: shiftHeight[pos1](),
left: hostElPos.left + hostElPos.width
};
break;
- case "left":
+ case 'left':
targetElPos = {
top: shiftHeight[pos1](),
left: hostElPos.left - targetElWidth
};
break;
- case "bottom":
+ case 'bottom':
targetElPos = {
top: hostElPos.top + hostElPos.height,
left: shiftWidth[pos1]()
@@ -228,18 +232,20 @@
}
protected getStyle(nativeEl: HTMLElement, cssProp: string): string {
- if ((nativeEl as any).currentStyle) // IE
+ if ((nativeEl as any).currentStyle) { // IE
return (nativeEl as any).currentStyle[cssProp];
+ }
- if (window.getComputedStyle)
+ if (window.getComputedStyle) {
return (window.getComputedStyle as any)(nativeEl)[cssProp];
+ }
// finally try and get inline style
return (nativeEl.style as any)[cssProp];
}
protected isStaticPositioned(nativeEl: HTMLElement): boolean {
- return (this.getStyle(nativeEl, "position") || "static" ) === "static";
+ return (this.getStyle(nativeEl, 'position') || 'static' ) === 'static';
}
protected parentOffsetEl(nativeEl: HTMLElement): any {
@@ -251,26 +257,26 @@
}
protected getEffectivePlacement(placement: string, hostElement: HTMLElement, targetElement: HTMLElement): string {
- const placementParts = placement.split(" ");
- if (placementParts[0] !== "auto") {
+ const placementParts = placement.split(' ');
+ if (placementParts[0] !== 'auto') {
return placement;
}
const hostElBoundingRect = hostElement.getBoundingClientRect();
- const desiredPlacement = placementParts[1] || "bottom";
+ const desiredPlacement = placementParts[1] || 'bottom';
- if (desiredPlacement === "top" && hostElBoundingRect.top - targetElement.offsetHeight < 0) {
- return "bottom";
+ if (desiredPlacement === 'top' && hostElBoundingRect.top - targetElement.offsetHeight < 0) {
+ return 'bottom';
}
- if (desiredPlacement === "bottom" && hostElBoundingRect.bottom + targetElement.offsetHeight > window.innerHeight) {
- return "top";
+ if (desiredPlacement === 'bottom' && hostElBoundingRect.bottom + targetElement.offsetHeight > window.innerHeight) {
+ return 'top';
}
- if (desiredPlacement === "left" && hostElBoundingRect.left - targetElement.offsetWidth < 0) {
- return "right";
+ if (desiredPlacement === 'left' && hostElBoundingRect.left - targetElement.offsetWidth < 0) {
+ return 'right';
}
- if (desiredPlacement === "right" && hostElBoundingRect.right + targetElement.offsetWidth > window.innerWidth) {
- return "left";
+ if (desiredPlacement === 'right' && hostElBoundingRect.right + targetElement.offsetWidth > window.innerWidth) {
+ return 'left';
}
return desiredPlacement;
diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html
new file mode 100644
index 0000000..fba99ca
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html
@@ -0,0 +1,12 @@
+<div class="sdc-element-icon">
+ <svg-icon [ngClass]="{'service-proxy': elementType === 'ServiceProxy'}"
+ [type]="elementIcon.type"
+ [name]="elementIcon.iconName"
+ [mode]="elementIcon.color"
+ [size]="elementIcon.size"
+ [backgroundShape]="elementIcon.shape"
+ [backgroundColor]="elementIcon.backgroundColor"></svg-icon>
+ <span *ngIf="uncertified" class="uncertified-icon-wapper">
+ <svg-icon class="element-non-certified" [name]="'alert-circle'" [mode]="'error'"></svg-icon>
+ </span>
+</div>
diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less
new file mode 100644
index 0000000..7fd5cbd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less
@@ -0,0 +1,25 @@
+@import "./../../../../../assets/styles/override";
+.service-proxy {
+ /deep/.svg-icon.bg-type-circle {
+ border: 2px solid @sdcui_color_blue;
+ }
+}
+
+.element-non-certified {
+ position: absolute;
+ top: 0.4px;
+ left: 0.4px;
+}
+.sdc-element-icon {
+ position: relative;
+}
+
+.uncertified-icon-wapper{
+ height: 17px;
+ width: 17px;
+ background-color: white;
+ border-radius: 50%;
+ position: absolute;
+ top: -2px;
+ left: -1px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts
new file mode 100644
index 0000000..baadbd8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts
@@ -0,0 +1,69 @@
+import {Component, Input, OnInit} from "@angular/core";
+import {ComponentType, SdcElementType, ResourceType} from "../../../../utils/constants";
+
+
+export class ElementIcon {
+ iconName: string;
+ color: string;
+ backgroundColor: string;
+ type: string
+ shape: string;
+ size: string;
+
+ constructor(name?: string, type?:string, backgroundColor?:string, color?:string, shape?: string, size?:string) {
+ this.iconName = name || 'default';
+ this.type = type || 'resource_24';
+ this.backgroundColor = backgroundColor || 'primary';
+ this.color = color || "white";
+ this.shape = shape || "circle";
+ this.size = size || "x_large";
+ }
+}
+
+@Component({
+ selector: 'sdc-element-icon',
+ templateUrl: './sdc-element-icon.component.html',
+ styleUrls: ['./sdc-element-icon.component.less']
+})
+export class SdcElementIconComponent {
+
+ @Input() iconName: string;
+ @Input() elementType: string;
+ @Input() uncertified: boolean = false;
+
+ public elementIcon;
+
+ private createIconForDisplay = () => {
+ switch (this.elementType) {
+
+ case ComponentType.SERVICE:
+ this.elementIcon = new ElementIcon(this.iconName, "services_24", "lightBlue");
+ break;
+ case ComponentType.SERVICE_PROXY:
+ this.elementIcon = new ElementIcon(this.iconName, "services_24", "white", "primary");
+ break;
+ case ResourceType.CONFIGURATION:
+ this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple", "white", 'circle', "medium");
+ break;
+ case SdcElementType.GROUP:
+ this.elementIcon = new ElementIcon("group", "resources_24", "blue", 'white', 'rectangle');
+ break;
+ case SdcElementType.POLICY:
+ this.elementIcon = new ElementIcon("policy", "resources_24", "darkBlue2", 'white', 'rectangle');
+ break;
+ case ResourceType.CP:
+ case ResourceType.VL:
+ this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple", '', '', 'medium');
+ break;
+ default:
+ this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple");
+ }
+ }
+
+ ngOnChanges():void {
+ this.createIconForDisplay();
+ }
+}
+
+
+
diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html
index 8682473..1f952c4 100644
--- a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html
@@ -1,21 +1,5 @@
-<!--
- ~ 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="search-bar-container {{class}}">
- <input class="search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/>
- <span class="clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span>
- <button class="search-bar-button" (click)="searchButtonClick()"></button>
+<div class="sdc-search-bar-container {{class}}">
+ <input class="sdc-search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/>
+ <span class="sdc-clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span>
+ <button class="sdc-search-bar-button" (click)="searchButtonClick()"></button>
</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less
index 751fcee..c09951a 100644
--- a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less
+++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less
@@ -1,9 +1,9 @@
-.search-bar-container {
+.sdc-search-bar-container {
display:flex;
border-radius: 4px;
box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
- .search-bar-input {
+ .sdc-search-bar-input {
border: 1px solid #cdcdcd;
border-radius: 4px;
border-right:none;
@@ -14,9 +14,11 @@
color: #5a5a5a;
font-size: 1em;
font-style: italic;
+
+
}
- .clear-search-x {
+ .sdc-clear-search-x {
position:absolute;
right:40px;
top:5px;
@@ -29,7 +31,7 @@
}
}
- .search-bar-button {
+ .sdc-search-bar-button {
background: url('../../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px;
background-color: rgba(234, 234, 234, 0.88);
width: 30px;
diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html
index 82dbbf3..da9b2c9 100644
--- a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html
@@ -14,9 +14,9 @@
~ limitations under the License.
-->
-<div class="search-with-autocomplete-container {{searchBarClass}}" [class.autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length">
+<div class="sdc-search-with-autocomplete-container {{searchBarClass}}" [class.sdc-autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length">
<search-bar [placeholder]="searchPlaceholder" [searchQuery]="searchQuery" (searchButtonClicked)="updateSearch($event)" (searchChanged)="searchChange($event)"></search-bar>
- <div class="autocomplete-results">
- <div *ngFor="let item of autoCompleteValues" class="autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div>
+ <div class="sdc-autocomplete-results">
+ <div *ngFor="let item of autoCompleteValues" class="sdc-autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div>
</div>
</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less
index f183084..9cd312a 100644
--- a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less
+++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less
@@ -1,13 +1,13 @@
-.search-with-autocomplete-container{
- &.autocomplete-visible {
+.sdc-search-with-autocomplete-container{
+ &.sdc-autocomplete-visible {
- .search-bar-input {
+ .sdc-search-bar-input {
border-bottom-left-radius: 0;
}
- .search-bar-button {
+ .sdc-search-bar-button {
border-bottom-right-radius: 0;
}
- .autocomplete-results {
+ .sdc-autocomplete-results {
border: solid 1px #d2d2d2;
border-top:none;
border-bottom-left-radius: 4px;
@@ -20,7 +20,7 @@
overflow-y: scroll;
}
- .autocomplete-result-item {
+ .sdc-autocomplete-result-item {
color:#5a5a5a;
padding: 5px 0;
cursor:pointer;
diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts
index f4b4103..cabac12 100644
--- a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts
@@ -21,7 +21,7 @@
import { Component, ContentChildren, QueryList, AfterContentInit, Input, Output, EventEmitter } from '@angular/core';
import { Tab } from './tab/tab.component';
import { ViewEncapsulation } from '@angular/core';
-import { trigger, state, style, transition, animate, keyframes } from '@angular/core';
+import { trigger, state, style, transition, animate, keyframes } from '@angular/animations';
export {Tab};
diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.module.ts b/catalog-ui/src/app/ng2/components/ui/tile/sdc-tile.module.ts
similarity index 64%
rename from catalog-ui/src/app/ng2/components/ui/tile/tile.module.ts
rename to catalog-ui/src/app/ng2/components/ui/tile/sdc-tile.module.ts
index 55b3440..5dec67e 100644
--- a/catalog-ui/src/app/ng2/components/ui/tile/tile.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/tile/sdc-tile.module.ts
@@ -3,13 +3,13 @@
import { TileComponent } from './tile.component';
import { GlobalPipesModule } from "../../../pipes/global-pipes.module";
import { TooltipModule } from "../tooltip/tooltip.module";
-import {MultilineEllipsisModule} from "../../../shared/multiline-ellipsis/multiline-ellipsis.module";
+import {SdcUiComponentsModule} from "onap-ui-angular";
@NgModule({
- imports: [BrowserModule, GlobalPipesModule, TooltipModule, MultilineEllipsisModule],
+ imports: [BrowserModule, GlobalPipesModule, SdcUiComponentsModule, TooltipModule],
declarations: [TileComponent],
exports: [TileComponent],
entryComponents: [TileComponent]
})
-export class TileModule { }
+export class SdcTileModule { }
diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html
index 018384d..239053e 100644
--- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html
+++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html
@@ -23,15 +23,21 @@
<div class='sdc-tile-content' data-tests-id="dashboard-Elements" (click)="tileClicked()">
<div class='sdc-tile-content-icon'>
- <div [ngClass]="[component.iconSprite, component.icon]" [ngClass]="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}"
+ <div [ngClass]="[component.iconSprite, component.icon]"
+ [ngClass]="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}"
[attr.data-tests-id]="component.name"></div>
</div>
<div class='sdc-tile-content-info'>
- <div class="sdc-tile-info-line title" [attr.data-tests-id]="component.name | resourceName" [tooltip]="component.name | resourceName" [tooltipDisabled]="!hasEllipsis">
- <multiline-ellipsis className="w-sdc-tile-multiline-ellipsis" [lines]="3" (hasEllipsisChanged)="hasEllipsis = $event">{{component.name | resourceName}}</multiline-ellipsis>
+ <div class="sdc-tile-info-line title" [attr.data-tests-id]="component.name | resourceName"
+ [tooltip]="component.name | resourceName" [tooltipDisabled]="!hasEllipsis">
+ <multiline-ellipsis className="w-sdc-tile-multiline-ellipsis" [lines]="3"
+ (hasEllipsisChanged)="hasEllipsis = $event">{{component.name | resourceName}}
+ </multiline-ellipsis>
</div>
- <div class="sdc-tile-info-line subtitle" [attr.data-tests-id]="component.name+'Version'">V {{component.version}}</div>
+ <div class="sdc-tile-info-line subtitle" [attr.data-tests-id]="component.name+'Version'">V
+ {{component.version}}
+ </div>
</div>
</div>
@@ -42,3 +48,32 @@
</div>
</div>
+
+<!--<sdc-tile>-->
+<!--<sdc-tile-header>-->
+<!--<div [ngClass]="{'blue': component.isService(), 'purple': component.isResource()}">{{component.isResource() ?-->
+<!--component.getComponentSubType(): 'S' }}-->
+<!--</div>-->
+<!--</sdc-tile-header>-->
+<!--<sdc-tile-content>-->
+<!--<div class='sdc-tile-content-icon blue'>-->
+<!--<svg-icon-->
+<!--[type]="catalogIcon.type"-->
+<!--[name]="catalogIcon.iconName"-->
+<!--[size]="catalogIcon.size"-->
+<!--[mode]="catalogIcon.color"-->
+<!--[backgroundShape]="catalogIcon.shape"-->
+<!--[backgroundColor]="catalogIcon.backgroundColor"-->
+<!--[disabled]="false"-->
+<!-->-->
+<!--</svg-icon>-->
+<!--</div>-->
+<!--<div class="sdc-tile-content-info">-->
+<!--<span class="sdc-tile-info-line title">{{component.name | resourceName}}</span>-->
+<!--<div class="sdc-tile-info-line subtitle">{{'V'+ component.version}}</div>-->
+<!--</div>-->
+<!--</sdc-tile-content>-->
+<!--<sdc-tile-footer>-->
+<!--<span class="sdc-tile-footer-cell">{{component.getStatus(sdcMenu)}}</span>-->
+<!--</sdc-tile-footer>-->
+<!--</sdc-tile>-->
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less
index e69de29..febf46e 100644
--- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less
+++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less
@@ -0,0 +1,15 @@
+
+
+//This was done as a fix for the wrong dispaly that was in every ui-tile.
+//All other styles located in mail.less
+
+.sdc-tile {
+ display: block;
+
+ .sdc-tile-content {
+ overflow: visible;
+ height: 80%;
+ .sdc-tile-content-icon {
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts
index b6f6358..f5d9e88 100644
--- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts
+++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts
@@ -1,6 +1,8 @@
import {Component, Input, Output, Inject, EventEmitter} from '@angular/core';
import {Component as ComponentModel} from 'app/models';
import {SdcMenuToken, IAppMenu} from "../../../config/sdc-menu.config";
+import {ElementIcon} from "../sdc-element-icon/sdc-element-icon.component";
+import {ComponentType, ResourceType, SdcElementType} from "../../../../utils/constants";
@Component({
selector: 'ui-tile',
@@ -10,14 +12,42 @@
export class TileComponent {
@Input() public component: ComponentModel;
@Output() public onTileClick: EventEmitter<ComponentModel>;
-
+ public catalogIcon: ElementIcon;
public hasEllipsis: boolean;
- constructor(@Inject(SdcMenuToken) public sdcMenu:IAppMenu) {
+ constructor(@Inject(SdcMenuToken) public sdcMenu: IAppMenu) {
this.onTileClick = new EventEmitter<ComponentModel>();
this.hasEllipsis = false;
}
+ ngOnInit(): void {
+ switch (this.component.componentType) {
+
+ case ComponentType.SERVICE:
+ if (this.component.icon === 'defaulticon') {
+ this.catalogIcon = new ElementIcon(this.component.icon, "services_60", 'lightBlue', 'white');
+ } else {
+ this.catalogIcon = new ElementIcon(this.component.icon, "services_60", '', 'lightBlue');
+ }
+ break;
+ case ComponentType.RESOURCE:
+ switch (this.component.getComponentSubType()) {
+ case ResourceType.CP:
+ case ResourceType.VL:
+ this.catalogIcon = new ElementIcon(this.component.icon, "resources_24", "purple", "white", "circle", 'medium');
+ break;
+ default:
+ if (this.component.icon === 'defaulticon') {
+ this.catalogIcon = new ElementIcon(this.component.icon, "resources_60", "purple", "white", "circle", 'x_large');
+ } else {
+ this.catalogIcon = new ElementIcon(this.component.icon, "resources_60", '', "error");
+ }
+
+ }
+
+ }
+ }
+
public tileClicked() {
this.onTileClick.emit(this.component);
}
diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
index e905db7..cdb173c 100644
--- a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
+++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts
@@ -18,82 +18,89 @@
* ============LICENSE_END=========================================================
*/
-import { NgModule } from '@angular/core';
-import { NavbarModule } from "./navbar/navbar.module";
-import { DynamicElementModule } from "./dynamic-element/dynamic-element.module";
-import { FormElementsModule } from "./form-components/form-elements.module";
-import { LoaderComponent } from "./loader/loader.component";
-import { ModalModule } from "./modal/modal.module";
-import { PopoverModule } from "./popover/popover.module";
-import { SearchBarComponent } from "./search-bar/search-bar.component";
-import { SearchWithAutoCompleteComponent } from "./search-with-autocomplete/search-with-autocomplete.component";
-import { PalettePopupPanelComponent } from "./palette-popup-panel/palette-popup-panel.component";
-import { ZoneContainerComponent } from "./canvas-zone/zone-container.component";
-import { ZoneInstanceComponent } from "./canvas-zone/zone-instance/zone-instance.component";
-import { PaletteAnimationComponent } from "./palette-animation/palette-animation.component"
-import { TabModule } from "./tabs/tabs.module";
-import { TooltipModule } from "./tooltip/tooltip.module";
-import { CommonModule } from "@angular/common";
-import { FormsModule } from "@angular/forms";
-import { BrowserModule } from "@angular/platform-browser";
-import { MultiStepsWizardModule } from "./multi-steps-wizard/multi-steps-wizard.module";
-import { MenuListModule } from "./menu/menu-list.module";
-import { MenuListNg2Module } from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module";
-import { ExpandCollapseComponent } from './expand-collapse/expand-collapse.component';
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { TileModule } from "./tile/tile.module";
+import {NgModule} from '@angular/core';
+import {NavbarModule} from "./navbar/navbar.module";
+import {DynamicElementModule} from "./dynamic-element/dynamic-element.module";
+import {FormElementsModule} from "./form-components/form-elements.module";
+import {LoaderComponent} from "./loader/loader.component";
+import {ModalModule} from "./modal/modal.module";
+import {PopoverModule} from "./popover/popover.module";
+import {SearchBarComponent} from "./search-bar/search-bar.component";
+import {SearchWithAutoCompleteComponent} from "./search-with-autocomplete/search-with-autocomplete.component";
+import { PaletteAnimationComponent } from "app/ng2/pages/composition/palette/palette-animation/palette-animation.component";
+import {TabModule} from "./tabs/tabs.module";
+import {TooltipModule} from "./tooltip/tooltip.module";
+import {CommonModule} from "@angular/common";
+import {FormsModule} from "@angular/forms";
+import {BrowserModule} from "@angular/platform-browser";
+import {MultiStepsWizardModule} from "./multi-steps-wizard/multi-steps-wizard.module";
+import {MenuListModule} from "./menu/menu-list.module";
+import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module";
+import {ExpandCollapseComponent} from './expand-collapse/expand-collapse.component';
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {SdcTileModule} from "./tile/sdc-tile.module";
+import {PerfectScrollbarDirective} from "./perfect-scroll-bar/perfect-scrollbar.directive";
+import {FileOpenerComponent} from "./file-opener/file-opener.component";
+import {DownloadArtifactComponent} from "app/ng2/components/ui/download-artifact/download-artifact.component";
+import {SdcElementIconComponent} from "./sdc-element-icon/sdc-element-icon.component";
+import {PanelWrapperComponent} from "./panel-wrapper/panel-wrapper.component";
@NgModule({
- declarations: [
- LoaderComponent,
- SearchBarComponent,
- SearchWithAutoCompleteComponent,
- PalettePopupPanelComponent,
- ZoneContainerComponent,
- ZoneInstanceComponent,
- PaletteAnimationComponent,
- ExpandCollapseComponent
-],
-
- imports: [
- SdcUiComponentsModule,
- BrowserModule,
- FormsModule,
- CommonModule,
- DynamicElementModule,
- NavbarModule,
- FormElementsModule,
- ModalModule,
- PopoverModule,
- TabModule,
- TooltipModule,
- MultiStepsWizardModule,
- MenuListModule,
- MenuListNg2Module,
- TileModule
- ],
- exports: [
- LoaderComponent,
- MultiStepsWizardModule,
- SearchBarComponent,
- SearchWithAutoCompleteComponent,
- PalettePopupPanelComponent,
- ZoneContainerComponent,
- ZoneInstanceComponent,
- DynamicElementModule,
- NavbarModule,
- FormElementsModule,
- ModalModule,
- PopoverModule,
- TabModule,
- TooltipModule,
- MenuListModule,
- MenuListNg2Module,
- PaletteAnimationComponent,
- ExpandCollapseComponent,
- TileModule
- ],
- entryComponents: [SearchWithAutoCompleteComponent, PalettePopupPanelComponent, ZoneContainerComponent, ZoneInstanceComponent, PaletteAnimationComponent]
+ declarations: [
+ LoaderComponent,
+ SearchBarComponent,
+ SearchWithAutoCompleteComponent,
+ PaletteAnimationComponent,
+ ExpandCollapseComponent,
+ PerfectScrollbarDirective,
+ FileOpenerComponent,
+ SdcElementIconComponent,
+ DownloadArtifactComponent,
+ PanelWrapperComponent
+ ],
+
+ imports: [
+ SdcUiComponentsModule,
+ BrowserModule,
+ FormsModule,
+ CommonModule,
+ DynamicElementModule,
+ NavbarModule,
+ FormElementsModule,
+ ModalModule,
+ PopoverModule,
+ TabModule,
+ TooltipModule,
+ MultiStepsWizardModule,
+ MenuListModule,
+ MenuListNg2Module,
+ SdcTileModule
+ ],
+ exports: [
+ LoaderComponent,
+ MultiStepsWizardModule,
+ SearchBarComponent,
+ SearchWithAutoCompleteComponent,
+ DynamicElementModule,
+ NavbarModule,
+ FormElementsModule,
+ ModalModule,
+ PopoverModule,
+ TabModule,
+ TooltipModule,
+ MenuListModule,
+ MenuListNg2Module,
+ PaletteAnimationComponent,
+ ExpandCollapseComponent,
+ SdcTileModule,
+ PerfectScrollbarDirective,
+ SdcElementIconComponent,
+ FileOpenerComponent,
+ DownloadArtifactComponent,
+ PanelWrapperComponent
+ ],
+ entryComponents: [SearchWithAutoCompleteComponent, SdcElementIconComponent, PaletteAnimationComponent]
})
-export class UiElementsModule {}
+export class UiElementsModule {
+}
diff --git a/catalog-ui/src/app/ng2/config/sdc-config.config.ts b/catalog-ui/src/app/ng2/config/sdc-config.config.ts
index b10a878..76e81b2 100644
--- a/catalog-ui/src/app/ng2/config/sdc-config.config.ts
+++ b/catalog-ui/src/app/ng2/config/sdc-config.config.ts
@@ -13,13 +13,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-- */
-
- import {Provider, OpaqueToken} from "@angular/core";
+import {Provider, InjectionToken} from "@angular/core";
import {getSdcConfig, ISdcConfig} from "./sdc-config.config.factory";
export { ISdcConfig };
-export const SdcConfigToken = new OpaqueToken('SdcConfigToken');
+export const SdcConfigToken = new InjectionToken('SdcConfigToken');
export const SdcConfig:Provider = {
provide: SdcConfigToken,
diff --git a/catalog-ui/src/app/ng2/config/sdc-menu.config.ts b/catalog-ui/src/app/ng2/config/sdc-menu.config.ts
index 44c2d28..9dd83e5 100644
--- a/catalog-ui/src/app/ng2/config/sdc-menu.config.ts
+++ b/catalog-ui/src/app/ng2/config/sdc-menu.config.ts
@@ -15,13 +15,13 @@
-- */
-import {Provider, OpaqueToken} from "@angular/core";
+import {Provider, InjectionToken} from "@angular/core";
import {getSdcMenu} from "./sdc-menu.config.factory";
import {IAppMenu} from "app/models";
export { IAppMenu };
-export const SdcMenuToken = new OpaqueToken('SdcMenuToken');
+export const SdcMenuToken = new InjectionToken('SdcMenuToken');
export const SdcMenu:Provider = {
provide: SdcMenuToken,
diff --git a/catalog-ui/src/app/ng2/http-interceptor/headers-interceptor.ts b/catalog-ui/src/app/ng2/http-interceptor/headers-interceptor.ts
new file mode 100644
index 0000000..00e2fd8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/http-interceptor/headers-interceptor.ts
@@ -0,0 +1,61 @@
+import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
+import { Injectable, Injector } from '@angular/core';
+import { SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { ButtonType } from 'onap-ui-angular/dist/common';
+import { Observable } from 'rxjs/Observable';
+import { ServerErrorResponse } from '../../models/server-error-response';
+import { Cookie2Service } from '../services/cookie.service';
+import { HttpHelperService } from '../services/http-hepler.service';
+import { TranslateService } from '../shared/translator/translate.service';
+
+@Injectable()
+export class HeadersInterceptor implements HttpInterceptor {
+
+ constructor(private injector: Injector, private cookieService: Cookie2Service, private httpHelperService: HttpHelperService) {}
+
+ intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
+ let authReq = req.clone({ headers: req.headers.set(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId())
+ .set('Content-Type', 'application/json; charset=UTF-8')
+ .set(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId())
+ .set(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId())
+ });
+
+ const uuidValue = this.httpHelperService.getUuidValue(authReq.url);
+ if (uuidValue !== '') {
+ authReq = authReq.clone({ headers: authReq.headers.set(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId())});
+ }
+ return next.handle(authReq).do(
+
+ (event: HttpEvent<any>) => { /* Do Nothing */ },
+
+ (err: any) => {
+ if (err instanceof HttpErrorResponse) {
+ const errorResponse: ServerErrorResponse = new ServerErrorResponse(err);
+ const modalService = this.injector.get(SdcUiServices.ModalService);
+ const translateService = this.injector.get(TranslateService);
+
+ const errorDetails = {
+ 'Error Code': errorResponse.messageId,
+ 'Status Code': errorResponse.status
+ };
+
+ if (errorResponse.ecompRequestId) {
+ errorDetails['Transaction ID'] = errorResponse.ecompRequestId;
+ }
+
+ if (errorResponse.messageId === 'POL5005') {
+ // Session and Role expiration special handling
+ modalService.openWarningModal(
+ 'Warning',
+ translateService.translate('ERROR_MODAL_TEXT', errorResponse),
+ 'warn-modal',
+ [ ] );
+ } else {
+ modalService.openErrorDetailModal('Error', errorResponse.message, 'error-modal', errorDetails);
+ }
+
+ return Observable.throwError(err);
+ }
+ });
+ }
+}
diff --git a/catalog-ui/src/app/ng2/http-interceptor/index.ts b/catalog-ui/src/app/ng2/http-interceptor/index.ts
new file mode 100644
index 0000000..57eb238
--- /dev/null
+++ b/catalog-ui/src/app/ng2/http-interceptor/index.ts
@@ -0,0 +1,7 @@
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { HeadersInterceptor } from './headers-interceptor';
+import IStateService = angular.ui.IStateService;
+
+export const httpInterceptorProviders = [
+ { provide: HTTP_INTERCEPTORS, useClass: HeadersInterceptor, multi: true },
+];
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-models/ui-component-to-upgrade.ts b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-models/ui-component-to-upgrade.ts
index 97fb71e..17e5ea7 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-models/ui-component-to-upgrade.ts
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-models/ui-component-to-upgrade.ts
@@ -21,7 +21,7 @@
this.icon = componentToUpgrade.icon;
this.version = componentToUpgrade.version;
this.isAlreadyUpgrade = true;
- this.isLock = componentToUpgrade.state === ComponentState.CERTIFICATION_IN_PROGRESS || componentToUpgrade.state === ComponentState.NOT_CERTIFIED_CHECKOUT;
+ this.isLock = componentToUpgrade.state === ComponentState.NOT_CERTIFIED_CHECKOUT;
this.vspInstances = [];
}
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component.html b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component.html
index f77c341..c1e9529 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component.html
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="components-to-upgrade-list-item">
<div class="component-to-upgrade-data">
<div class="component-to-upgrade-icon small sprite-services-icons {{upgradedComponent.icon}}"></div>
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component.html b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component.html
index b97e414..5c49735 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component.html
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component.html
@@ -13,8 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
<div class="components-to-upgrade-list-item ">
<div class="component-to-upgrade-data">
<sdc-checkbox class="component-to-upgrade-checkbox"
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.component.ts b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.component.ts
index 9ae7349..613caa4 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.component.ts
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.component.ts
@@ -29,8 +29,7 @@
@Component({
selector: 'upgrade-vsp',
templateUrl: './automated-upgrade.component.html',
- styleUrls: ['./automated-upgrade.component.less'],
- providers: [TranslateService]
+ styleUrls: ['./automated-upgrade.component.less']
})
export class AutomatedUpgradeComponent {
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.module.ts b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.module.ts
index 19f6412..8a4e8fb 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.module.ts
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.module.ts
@@ -2,16 +2,15 @@
* Created by ob0695 on 4/18/2018.
*/
import { NgModule } from "@angular/core";
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
-import {CommonModule} from "@angular/common";
-import {AutomatedUpgradeStatusComponent} from "./automated-upgrade-status/automated-upgrade-status.component";
-import {AutomatedUpgradeComponent} from "./automated-upgrade.component";
-import {UpgradeListItemComponent} from "./automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component";
-import {UpgradeListItemStatusComponent} from "./automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component";
-import {TranslateService} from "../../shared/translator/translate.service";
-import {UpgradeListItemInnerContent} from "./automated-upgrade-ui-components/list-item-inner-content/list-item-inner-content.component";
-import {UpgradeLineItemComponent} from "./automated-upgrade-ui-components/upgrade-line-item/upgrade-line-item.component";
-import {UpgradeListItemOrderPipe} from "./automated-upgrade-ui-components/list-item-order-pipe/list-item-order-pipe";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import { CommonModule } from "@angular/common";
+import { AutomatedUpgradeStatusComponent } from "./automated-upgrade-status/automated-upgrade-status.component";
+import { AutomatedUpgradeComponent } from "./automated-upgrade.component";
+import { UpgradeListItemComponent } from "./automated-upgrade-ui-components/upgrade-list-item/upgrade-list-item.component";
+import { UpgradeListItemStatusComponent } from "./automated-upgrade-ui-components/upgrade-list-item-status/upgrade-list-status-item.component";
+import { UpgradeListItemInnerContent } from "./automated-upgrade-ui-components/list-item-inner-content/list-item-inner-content.component";
+import { UpgradeLineItemComponent } from "./automated-upgrade-ui-components/upgrade-line-item/upgrade-line-item.component";
+import { UpgradeListItemOrderPipe } from "./automated-upgrade-ui-components/list-item-order-pipe/list-item-order-pipe";
@NgModule({
declarations: [
@@ -27,8 +26,7 @@
exports: [],
entryComponents: [
AutomatedUpgradeComponent, AutomatedUpgradeStatusComponent
- ],
- providers: [TranslateService]
+ ]
})
export class AutomatedUpgradeModule {
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.service.ts b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.service.ts
index 0acfece..14ca7f0 100644
--- a/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.service.ts
+++ b/catalog-ui/src/app/ng2/pages/automated-upgrade/automated-upgrade.service.ts
@@ -1,19 +1,15 @@
-import {SdcUiComponents} from "sdc-ui/lib/angular";
-import {Injectable, Inject} from "@angular/core";
-import {IModalConfig} from "sdc-ui/lib/angular/modals/models/modal-config";
-import {AutomatedUpgradeComponent} from "./automated-upgrade.component";
-import {Component} from "../../../models/components/component";
-import {ComponentServiceNg2} from "../../services/component-services/component.service";
-import {GeneralStatus, ComponentType} from "../../../utils/constants";
-import {IDependenciesServerResponse} from "../../services/responses/dependencies-server-response";
-import {AutomatedUpgradeStatusComponent} from "./automated-upgrade-status/automated-upgrade-status.component";
-import {AutomatedUpgradeStatusResponse} from "../../services/responses/automated-upgrade-response";
+import { SdcUiComponents, SdcUiCommon, SdcUiServices } from "onap-ui-angular";
+import { Injectable, ComponentRef } from "@angular/core";
+import { AutomatedUpgradeComponent } from "./automated-upgrade.component";
+import { Component } from "../../../models/components/component";
+import { ComponentServiceNg2 } from "../../services/component-services/component.service";
+import { GeneralStatus, ComponentType } from "../../../utils/constants";
+import { IDependenciesServerResponse } from "../../services/responses/dependencies-server-response";
+import { AutomatedUpgradeStatusComponent } from "./automated-upgrade-status/automated-upgrade-status.component";
+import { AutomatedUpgradeStatusResponse } from "../../services/responses/automated-upgrade-response";
+import { TranslateService, ITranslateArgs } from "../../shared/translator/translate.service";
+import { ServiceContainerToUpgradeUiObject, AllottedResourceInstanceUiObject, VspInstanceUiObject } from "./automated-upgrade-models/ui-component-to-upgrade";
import Dictionary = _.Dictionary;
-import {TranslateService, ITranslateArgs} from "../../shared/translator/translate.service";
-import {
- ServiceContainerToUpgradeUiObject,
- AllottedResourceInstanceUiObject, VspInstanceUiObject
-} from "./automated-upgrade-models/ui-component-to-upgrade";
export interface IAutomatedUpgradeRequestObj {
serviceId:string;
@@ -30,8 +26,9 @@
private vspComponent:Component;
private uiComponentsToUpgrade:Array<ServiceContainerToUpgradeUiObject>;
private componentType:string;
+ private modalInstance: ComponentRef<SdcUiComponents.ModalComponent>;
- constructor(private modalService:SdcUiComponents.ModalService,
+ constructor(private modalService:SdcUiServices.ModalService,
private componentService:ComponentServiceNg2,
private translateService:TranslateService) {
}
@@ -69,21 +66,21 @@
}
private disabledAllModalButtons = ():void => {
- this.modalService.getCurrentInstance().innerModalContent.instance.disabled = true;
- this.modalService.getCurrentInstance().buttons[0].show_spinner = true;
- this.modalService.getCurrentInstance().buttons[1].disabled = true;
+ this.modalInstance.instance.innerModalContent.instance.disabled = true;
+ this.modalInstance.instance.buttons[0].show_spinner = true;
+ this.modalInstance.instance.buttons[1].disabled = true;
}
public changeUpgradeButtonState = (isDisabled:boolean):void => {
- if (this.modalService.getCurrentInstance().buttons[0].disabled !== isDisabled) {
- this.modalService.getCurrentInstance().buttons[0].disabled = isDisabled;
+ if (this.modalInstance.instance.buttons[0].disabled !== isDisabled) {
+ this.modalInstance.instance.buttons[0].disabled = isDisabled;
}
}
//TODO We will need to replace this function after sdc-ui modal new design, this is just a workaround
public automatedUpgrade = ():void => {
- let selectedServices = this.modalService.getCurrentInstance().innerModalContent.instance.selectedComponentsToUpgrade;
+ let selectedServices = this.modalInstance.instance.innerModalContent.instance.selectedComponentsToUpgrade;
this.disabledAllModalButtons();
this.componentService.automatedUpgrade(this.vspComponent.componentType, this.vspComponent.uniqueId, this.convertToServerRequest(selectedServices)).subscribe((automatedUpgradeStatus:any) => {
@@ -105,11 +102,11 @@
});
let statusModalTitle = this.getTextByComponentType("_UPGRADE_STATUS_TITLE");
- this.modalService.getCurrentInstance().setTitle(statusModalTitle);
- this.modalService.getCurrentInstance().getButtons().splice(0, 1); // Remove the upgrade button
- this.modalService.getCurrentInstance().buttons[0].disabled = false; // enable close again
- this.modalService.getCurrentInstance().innerModalContent.destroy();
- this.modalService.createInnnerComponent(AutomatedUpgradeStatusComponent, {
+ this.modalInstance.instance.setTitle(statusModalTitle);
+ this.modalInstance.instance.getButtons().splice(0, 1); // Remove the upgrade button
+ this.modalInstance.instance.buttons[0].disabled = false; // enable close again
+ this.modalInstance.instance.innerModalContent.destroy();
+ this.modalService.createInnnerComponent(this.modalInstance, AutomatedUpgradeStatusComponent, {
upgradedComponentsList: upgradedComponent,
upgradeStatusMap: statusMap,
statusText: this.getStatusText(statusMap)
@@ -250,10 +247,10 @@
let modalTitle = this.getTextByComponentType("_UPGRADE_TITLE");
let certificationText = isAfterCertification ? this.getTextByComponentType("_CERTIFICATION_STATUS_TEXT", {resourceName: this.vspComponent.name}) : undefined;
- let upgradeVspModalConfig:IModalConfig = {
+ let upgradeVspModalConfig = {
title: modalTitle,
size: "md",
- type: "custom",
+ type: SdcUiCommon.ModalType.custom,
testId: "upgradeVspModal",
buttons: [
{
@@ -266,10 +263,11 @@
},
{text: 'CLOSE', size: 'sm', closeModal: true, type: 'secondary'}
- ]
- };
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig;
- this.modalService.openCustomModal(upgradeVspModalConfig, AutomatedUpgradeComponent, {
+ this.modalInstance = this.modalService.openModal(upgradeVspModalConfig);
+ this.modalService.createInnnerComponent(this.modalInstance, AutomatedUpgradeComponent, {
componentsToUpgrade: this.uiComponentsToUpgrade,
informationText: informationalText,
certificationStatusText: certificationText
diff --git a/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap
new file mode 100644
index 0000000..d6091cd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/__snapshots__/catalog.component.spec.ts.snap
@@ -0,0 +1,164 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`catalog component should match current snapshot of catalog component 1`] = `
+<catalog
+ $state={[Function Object]}
+ cacheService={[Function Object]}
+ catalogService={[Function Object]}
+ componentShouldReload={[Function Function]}
+ defaultFilterParams={[Function Object]}
+ getTestIdForCheckboxByText={[Function Function]}
+ initCatalogData={[Function Function]}
+ initLeftSwitch={[Function Function]}
+ initScopeMembers={[Function Function]}
+ isDefaultFilter={[Function Function]}
+ loaderService={[Function Object]}
+ resourceNamePipe={[Function Object]}
+ sdcConfig={[Function Object]}
+ sdcMenu={[Function Object]}
+ updateCatalogItems={[Function Function]}
+>
+ <div
+ class="sdc-catalog-container"
+ >
+ <div
+ class="w-sdc-main-container"
+ >
+ <div
+ class="i-sdc-designer-leftbar-section-left-switch-header"
+ >
+ <div
+ class="i-sdc-designer-leftbar-section-left-switch-header-text"
+ >
+
+ </div>
+ <div
+ class="i-sdc-designer-leftbar-section-left-switch-header-icon sprite-new arrow-up-small"
+ >
+
+ </div>
+
+ </div>
+ <div
+ class="sdc-catalog-body-container w-sdc-left-sidebar i-sdc-designer-left-sidebar"
+ perfectscrollbar=""
+ >
+ <div
+ class="sdc-catalog-leftbar-container"
+ >
+ <div
+ class="sdc-catalog-type-filter-container"
+ >
+ <div
+ class="i-sdc-designer-leftbar-section-title pointer"
+ >
+ <span
+ class="i-sdc-designer-leftbar-section-title-icon"
+ />
+ <span
+ class="i-sdc-designer-leftbar-section-title-text"
+ data-tests-id="typeFilterTitle"
+ >
+ Type
+ </span>
+ </div>
+ <div
+ class="i-sdc-designer-leftbar-section-content"
+ >
+ <sdc-checklist />
+ </div>
+ </div>
+ <div
+ class="sdc-catalog-categories-filter-container"
+ >
+ <div
+ class="i-sdc-designer-leftbar-section-title pointer"
+ >
+ <span
+ class="i-sdc-designer-leftbar-section-title-icon"
+ />
+ <span
+ class="i-sdc-designer-leftbar-section-title-text"
+ data-tests-id="categoriesFilterTitle"
+ >
+ Categories
+ </span>
+ </div>
+ <div
+ class="i-sdc-designer-leftbar-section-content"
+ >
+ <sdc-checklist />
+ </div>
+ </div>
+ <div
+ class="sdc-catalog-status-filter-container"
+ >
+ <div
+ class="i-sdc-designer-leftbar-section-title pointer"
+ >
+ <span
+ class="i-sdc-designer-leftbar-section-title-icon"
+ />
+ <span
+ class="i-sdc-designer-leftbar-section-title-text"
+ data-tests-id="statusFilterTitle"
+ >
+ Status
+ </span>
+ </div>
+ <div
+ class="i-sdc-designer-leftbar-section-content"
+ >
+ <sdc-checklist />
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="w-sdc-main-right-container w-sdc-catalog-main"
+ infinitescroll=""
+ >
+ <div
+ class="catalog-top-bar"
+ >
+ <div
+ class="w-sdc-dashboard-catalog-items-header"
+ />
+ <div
+ class="catalog-top-right-bar"
+ >
+ <span
+ class="w-sdc-dashboard-catalog-header-order1"
+ >
+
+ </span>
+
+ <a
+ class="w-sdc-dashboard-catalog-sort"
+ data-tests-id="sort-by-last-update"
+ >
+
+ </a>
+
+
+ <a
+ class="w-sdc-dashboard-catalog-sort"
+ data-tests-id="sort-by-alphabetical"
+ >
+
+ </a>
+
+
+ </div>
+ </div>
+ <div
+ class="catalog-elements-list"
+ >
+
+ </div>
+ </div>
+ </div>
+ <top-nav />
+ </div>
+</catalog>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html
new file mode 100644
index 0000000..4a13bee
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.html
@@ -0,0 +1,101 @@
+<div class="sdc-catalog-container">
+ <div class="w-sdc-main-container">
+ <div class="i-sdc-designer-leftbar-section-left-switch-header"
+ (click)="showCatalogSelector=!showCatalogSelector">
+ <div class="i-sdc-designer-leftbar-section-left-switch-header-text">
+ {{selectedCatalogItem.title}}
+ </div>
+ <div class="i-sdc-designer-leftbar-section-left-switch-header-icon sprite-new arrow-up-small"> </div>
+
+ <div class="sdc-catalog-selector-wrapper" *ngIf="showCatalogSelector">
+ <div class="sdc-catalog-selector-item"
+ *ngFor="let leftSwitchItem of catalogSelectorItems"
+ (click)="selectLeftSwitchItem(leftSwitchItem)">
+ <span>{{leftSwitchItem.title}}</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- LEFT SIDE -->
+ <div perfectScrollbar class="sdc-catalog-body-container w-sdc-left-sidebar i-sdc-designer-left-sidebar">
+ <div class="sdc-catalog-leftbar-container">
+ <div class="sdc-catalog-type-filter-container">
+ <div class="i-sdc-designer-leftbar-section-title pointer"
+ (click)="sectionClick('type')"
+ [ngClass]="{'expanded': expandedSection.indexOf('type') !== -1}">
+ <span class="i-sdc-designer-leftbar-section-title-icon"></span>
+ <span class="i-sdc-designer-leftbar-section-title-text"
+ data-tests-id="typeFilterTitle">Type</span>
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content">
+ <sdc-checklist [checklistModel]="typesChecklistModel" [testId]="'checklist-type'"
+ (checkedChange)="gui.onComponentTypeClick()"></sdc-checklist>
+ </div>
+ </div>
+
+ <div class="sdc-catalog-categories-filter-container">
+ <div class="i-sdc-designer-leftbar-section-title pointer" (click)="sectionClick('category')"
+ [ngClass]="{'expanded': expandedSection.indexOf('category') !== -1}">
+ <span class="i-sdc-designer-leftbar-section-title-icon"></span>
+ <span class="i-sdc-designer-leftbar-section-title-text" data-tests-id="categoriesFilterTitle">Categories</span>
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content">
+ <sdc-checklist [checklistModel]="categoriesChecklistModel" [testId]="'checklist-category'"
+ (checkedChange)="gui.onCategoryClick()"></sdc-checklist>
+ </div>
+ </div>
+
+ <!-- STATUS -->
+ <div class="sdc-catalog-status-filter-container">
+ <div class="i-sdc-designer-leftbar-section-title pointer" (click)="sectionClick('status')"
+ [ngClass]="{'expanded': expandedSection.indexOf('status') !== -1}">
+ <span class="i-sdc-designer-leftbar-section-title-icon"></span>
+ <span class="i-sdc-designer-leftbar-section-title-text"
+ data-tests-id="statusFilterTitle">Status</span>
+ </div>
+
+ <div class="i-sdc-designer-leftbar-section-content">
+ <sdc-checklist [checklistModel]="statusChecklistModel" [testId]="'checklist-status'"
+ (checkedChange)="gui.onStatusClick()"></sdc-checklist>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+ <!-- RIGHT SIDE -->
+ <div class="w-sdc-main-right-container w-sdc-catalog-main" infiniteScroll
+ (infiniteScroll)="raiseNumberOfElementToDisplay()" [infiniteScrollDistance]="100">
+ <!-- HEADER -->
+ <div class="catalog-top-bar">
+ <div class="w-sdc-dashboard-catalog-items-header"
+ [innerHTML]="getNumOfElements(catalogFilteredItems.length)">
+
+ </div>
+ <div class="catalog-top-right-bar">
+ <span class="w-sdc-dashboard-catalog-header-order1">{{'SORT_CAPTION'|translate}}</span>
+ <a class="w-sdc-dashboard-catalog-sort" data-tests-id="sort-by-last-update"
+ [ngClass]="{'blue' : sortBy==='lastUpdateDate'}"
+ (click)="order('lastUpdateDate')">{{'SORT_BY_UPDATE_DATE'|translate}}</a>
+ <span *ngIf="sortBy === 'lastUpdateDate'" class="w-sdc-catalog-sort-arrow"
+ [ngClass]="{'down': reverse, 'up':!reverse}"></span>
+ <a class="w-sdc-dashboard-catalog-sort" data-tests-id="sort-by-alphabetical"
+ [ngClass]="{'blue' : sortBy!=='lastUpdateDate'}"
+ (click)="order('resourceName')">{{'SORT_ALPHABETICAL'|translate}}</a>
+ <span *ngIf="sortBy !== 'lastUpdateDate'" class="w-sdc-catalog-sort-arrow"
+ [ngClass]="{'down': reverse, 'up':!reverse}"></span>
+ </div>
+ </div>
+
+ <div class='catalog-elements-list'>
+ <!-- Tile new -->
+ <ui-tile *ngFor="let component of catalogFilteredSlicedItems"
+ [component]="component" (onTileClick)="goToComponent(component)"></ui-tile>
+ <!-- Tile new -->
+ </div>
+ </div>
+ </div>
+
+ <top-nav [topLvlSelectedIndex]="1" [searchTerm]="search.filterTerm"
+ (searchTermChange)="gui.changeFilterTerm($event)" [version]="version"></top-nav>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.less b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.less
new file mode 100644
index 0000000..036db8d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.less
@@ -0,0 +1,113 @@
+@import '../../../../assets/styles/variables';
+@import '../../../../assets/styles/mixins';
+
+.w-sdc-catalog-main {
+ height: 100%;
+ overflow-y: scroll;
+ padding: 10px 50px;
+
+ .catalog-top-bar {
+ display: flex;
+ justify-content:space-between;
+ padding: 0px 10px;
+ }
+
+ .catalog-elements-list {
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: row;
+ }
+
+}
+
+
+.i-sdc-designer-left-sidebar {
+ margin-top: 43px;
+}
+
+.sdc-catalog-selector-item {
+ text-transform: none;
+ line-height: 40px;
+ font-family: OpenSans-Bold, sans-serif;
+ font-size: 14px;
+ color: #000000;
+ background-color: #ffffff;
+ padding-left: 20px;
+}
+
+.sdc-catalog-selector-wrapper {
+ position: absolute;
+ left: 0px;
+ top: 42px;
+ width: 241px;
+ height: auto;
+ cursor: pointer;
+ opacity: 1;
+ z-index: 1000;
+ box-shadow: 1px 2px 3px #b1b1b1;
+}
+
+.sdc-catalog-selector-item {
+ text-transform: none;
+ line-height: 40px;
+ font-family: OpenSans-Bold, sans-serif;
+ font-size: 14px;
+ color: @main_color_l;
+ background-color: @main_color_p;
+ padding-left: 20px;
+}
+
+.sdc-catalog-selector-item:hover {
+ color: @main_color_a;
+ background-color: @tlv_color_v;
+}
+
+.i-sdc-designer-leftbar-section-left-switch-header {
+ text-transform: uppercase;
+ .l_14_m;
+ line-height: 40px;
+ width: 243px;
+
+ font-family: OpenSans-Bold, sans-serif;
+ font-size: 14px;
+
+ color: @main_color_a;
+ background-color: @tlv_color_t;
+ border: solid 1px fade(@main_color_t, 40%);
+ cursor: pointer;
+ opacity: 1;
+ z-index: 9999;
+ position: relative;
+}
+
+.i-sdc-designer-leftbar-section-left-switch-header-text {
+ display: inline-block;
+ width: 180px;
+ margin-left: 20px;
+}
+
+.i-sdc-designer-leftbar-section-left-switch-header-icon {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.w-sdc-dashboard-catalog-items-header {
+ color: @main_color_m;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 12px;
+ display: inline-block;
+ font-style: normal; size: 12px;
+ margin-left: 11px;
+ font-weight: normal;
+ b {
+ font-family: OpenSans-Bold, sans-serif;
+ color: @main_color_l;
+ font-weight: bold;
+ }
+}
+
+.w-sdc-dashboard-catalog-header-order1 {
+ font-style: normal;
+ font-size: 12px;
+ font-weight: 800;
+}
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts
new file mode 100644
index 0000000..ff27ec7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.spec.ts
@@ -0,0 +1,649 @@
+
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import {ConfigureFn, configureTests} from "../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import { CacheService} from "../../../../app/services-ng2";
+import {CatalogComponent} from "./catalog.component";
+import { SdcUiServices } from "onap-ui-angular";
+import { SdcConfigToken } from "../../config/sdc-config.config";
+import { SdcMenuToken} from "../../config/sdc-menu.config";
+import { ResourceNamePipe } from "../../pipes/resource-name.pipe";
+import { CatalogService } from "../../services/catalog.service";
+import {TranslatePipe} from "../../shared/translator/translate.pipe";
+import {TranslateService} from "../../shared/translator/translate.service";
+import {Observable} from "rxjs";
+import {LoaderService} from "onap-ui-angular/dist/loader/loader.service";
+import {categoriesElements} from "../../../../jest/mocks/categories.mock";
+import {sdcMenu} from "../../../../jest/mocks/sdc-menu.mock";
+import {IEntityFilterObject} from "../../pipes/entity-filter.pipe";
+
+
+
+
+
+describe('catalog component', () => {
+
+ let fixture: ComponentFixture<CatalogComponent>;
+
+ //Data variables
+ let catalogSelectorItemsMock;
+ let checkListModelMock;
+ let filterParamsMock;
+ let checkboxesFilterMock;
+ let checkboxesFilterKeysMock;
+
+
+ //Service variables
+ let stateServiceMock;
+ let cacheServiceMock: Partial<CacheService>;
+ let loaderServiceMock: Partial<LoaderService>;
+ let catalogServiceMock: Partial<CatalogService>;
+
+
+ beforeEach(
+
+ async(() => {
+ console.info = jest.fn();
+ catalogSelectorItemsMock = [
+ {
+ value: 0,
+ title: 'Active Items',
+ header: 'Active'
+ },
+ {
+ value: 1,
+ title: 'Archive',
+ header: 'Archived'
+ }
+ ];
+ checkListModelMock = {
+ checkboxes: [
+ {label: "VF", disabled: false, isChecked: false, testId: "checkbox-vf", value: "Resource.VF"},
+ {label: "VFC", disabled: false, isChecked: false, testId: "checkbox-vfc", value: "Resource.VFC",
+ subLevelChecklist: {checkboxes:[{label: "VFD", disabled: false, isChecked: false, testId: "checkbox-vfd", value: "Resource.VFD"}],
+ selectedValues: ["Resource.VFD"]}
+ },
+ {label: "CR", disabled: false, isChecked: false, testId: "checkbox-cr", value: "Resource.CR",
+ subLevelChecklist: { checkboxes:[{label: "VF", disabled: false, isChecked: false, testId: "checkbox-vf", value: "Resource.VF"}],
+ selectedValues: []}
+ }],
+ selectedValues: ["Resource.VF"]
+ }
+ filterParamsMock = {
+ active: true,
+ categories: ["resourceNewCategory.allotted resource.allotted resource", "resourceNewCategory.allotted resource.contrail route", "resourceNewCategory.application l4+.application server"],
+ components: ["Resource.VF", "Resource.VFC"],
+ order: ["lastUpdateDate", true],
+ statuses: ["inDesign"],
+ term: "Vf"
+ }
+ checkboxesFilterMock = {
+ selectedCategoriesModel: ["serviceNewCategory.network l4+", "resourceNewCategory.allotted resource.allotted resource"],
+ selectedComponentTypes: ["Resource.VF", "Resource.VFC"],
+ selectedResourceSubTypes: ["VF", "VFC"],
+ selectedStatuses: ["NOT_CERTIFIED_CHECKOUT", "NOT_CERTIFIED_CHECKIN"]
+ };
+ checkboxesFilterKeysMock = {
+ categories:{_main: ["serviceNewCategory.network l4+"]},
+ componentTypes: { Resource: ["Resource.VF", "Resource.VFC"], _main: ["Resource.VFC"]},
+ statuses: {_main: ["inDesign"]}
+ }
+
+ stateServiceMock = {
+ go: jest.fn(),
+ current: jest.fn()
+ };
+ cacheServiceMock = {
+ get: jest.fn().mockImplementation(()=> categoriesElements),
+ set: jest.fn(),
+ contains: jest.fn().mockImplementation(()=> true)
+ };
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+ catalogServiceMock = {
+ //TODO create mock function of archive
+ getCatalog: jest.fn().mockImplementation(()=> Observable.of(categoriesElements)),
+ getArchiveCatalog: jest.fn().mockImplementation(()=> Observable.of(categoriesElements))
+ };
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [CatalogComponent, TranslatePipe],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: SdcConfigToken, useValue: {}},
+ {provide: SdcMenuToken, useValue: sdcMenu},
+ {provide: "$state", useValue: stateServiceMock },
+ {provide: CacheService, useValue: cacheServiceMock },
+ {provide: CatalogService, useValue: catalogServiceMock },
+ {provide: ResourceNamePipe, useValue: {}},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock },
+ {provide: TranslateService, useValue: {}}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(CatalogComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot of catalog component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it ('should call on catalog component onInit' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.initGui = jest.fn();
+ component.componentInstance.initLeftSwitch = jest.fn();
+ component.componentInstance.initScopeMembers = jest.fn();
+ component.componentInstance.loadFilterParams = jest.fn();
+ component.componentInstance.initCatalogData = jest.fn();
+ component.componentInstance.ngOnInit();
+ expect(component.componentInstance.initGui).toHaveBeenCalled();
+ expect(component.componentInstance.initLeftSwitch).toHaveBeenCalled();
+ expect(component.componentInstance.initScopeMembers).toHaveBeenCalled();
+ expect(component.componentInstance.loadFilterParams).toHaveBeenCalled();
+ expect(component.componentInstance.initCatalogData).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component initLeftSwitch' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.initLeftSwitch();
+ expect(component.componentInstance.showCatalogSelector).toEqual(false);
+ expect(component.componentInstance.catalogSelectorItems).toEqual(catalogSelectorItemsMock);
+ expect(component.componentInstance.selectedCatalogItem).toEqual(catalogSelectorItemsMock[0]);
+ });
+
+ it ('should call on catalog component initCatalogData and selectedCatalogItem is archive ' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.getArchiveCatalogItems = jest.fn();
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[1];
+ component.componentInstance.initCatalogData();
+ expect(component.componentInstance.getArchiveCatalogItems).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component initCatalogData and selectedCatalogItem is active ' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.getActiveCatalogItems = jest.fn();
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[0];
+ component.componentInstance.initCatalogData();
+ expect(component.componentInstance.getActiveCatalogItems).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component initScopeMembers' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.makeSortedCategories = jest.fn().mockImplementation(()=> categoriesElements);
+ component.componentInstance.initCategoriesMap = jest.fn();
+ component.componentInstance.initCheckboxesFilter = jest.fn();
+ component.componentInstance.initCheckboxesFilterKeys = jest.fn();
+ component.componentInstance.buildCheckboxLists = jest.fn();
+ component.componentInstance.initScopeMembers();
+ expect(component.componentInstance.numberOfItemToDisplay).toEqual(0);
+ expect(component.componentInstance.categories).toEqual(categoriesElements);
+ expect(component.componentInstance.confStatus).toEqual(component.componentInstance.sdcMenu.statuses);
+ expect(component.componentInstance.expandedSection).toEqual( ["type", "category", "status"]);
+ expect(component.componentInstance.catalogItems).toEqual([]);
+ expect(component.componentInstance.search).toEqual({FilterTerm: ""});
+ expect(component.componentInstance.initCategoriesMap).toHaveBeenCalled();
+ expect(component.componentInstance.initCheckboxesFilter).toHaveBeenCalled();
+ expect(component.componentInstance.initCheckboxesFilterKeys).toHaveBeenCalled();
+ expect(component.componentInstance.buildCheckboxLists).toHaveBeenCalled();
+ expect(component.componentInstance.version).toEqual(categoriesElements);
+ expect(component.componentInstance.sortBy).toEqual('lastUpdateDate');
+ expect(component.componentInstance.reverse).toEqual(true);
+ });
+
+ it ('should call on catalog component buildCheckboxLists ' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.buildChecklistModelForTypes = jest.fn();
+ component.componentInstance.buildChecklistModelForCategories = jest.fn();
+ component.componentInstance.buildChecklistModelForStatuses = jest.fn();
+ component.componentInstance.buildCheckboxLists();
+ expect(component.componentInstance.buildChecklistModelForTypes).toHaveBeenCalled();
+ expect(component.componentInstance.buildChecklistModelForCategories).toHaveBeenCalled();
+ expect(component.componentInstance.buildChecklistModelForStatuses).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component getTestIdForCheckboxByText ' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ let testId = component.componentInstance.getTestIdForCheckboxByText("catalog filter");
+ expect(testId).toEqual("checkbox-catalogfilter");
+ });
+
+ it ('should call on catalog component selectLeftSwitchItem with active catalog' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[1];
+ component.componentInstance.getActiveCatalogItems = jest.fn();
+ component.componentInstance.changeFilterParams = jest.fn();
+ component.componentInstance.selectLeftSwitchItem(catalogSelectorItemsMock[0]);
+ expect(component.componentInstance.getActiveCatalogItems).toBeCalledWith(true);
+ expect(component.componentInstance.changeFilterParams).toBeCalledWith({"active": true});
+ });
+
+ it ('should call on catalog component selectLeftSwitchItem with archive catalog' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[0];
+ component.componentInstance.getArchiveCatalogItems = jest.fn();
+ component.componentInstance.changeFilterParams = jest.fn();
+ component.componentInstance.selectLeftSwitchItem(catalogSelectorItemsMock[1]);
+ expect(component.componentInstance.getArchiveCatalogItems).toBeCalledWith(true);
+ expect(component.componentInstance.changeFilterParams).toBeCalledWith({"active": false});
+ });
+
+ it ('should call on catalog component buildChecklistModelForTypes' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.buildChecklistModelForTypes();
+ expect(component.componentInstance.componentTypes).toEqual({ Resource: ['VF', 'VFC', 'CR', 'PNF', 'CP', 'VL'],
+ Service: null})
+ expect(component.componentInstance.typesChecklistModel.checkboxes.length).toEqual(2);
+ });
+
+ it ('should call on catalog component buildChecklistModelForCategories' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.categories = categoriesElements;
+ component.componentInstance.buildChecklistModelForCategories();
+ expect(component.componentInstance.categoriesChecklistModel.checkboxes).not.toEqual(null);
+ });
+
+ it ('should call on catalog component buildChecklistModelForStatuses' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.categories = categoriesElements;
+ component.componentInstance.confStatus = sdcMenu.statuses;
+ component.componentInstance.buildChecklistModelForStatuses();
+ expect(component.componentInstance.statusChecklistModel.checkboxes.length).toEqual(3);
+ });
+
+ it ('should call on catalog component initCheckboxesFilter' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.initCheckboxesFilter();
+ expect(component.componentInstance.checkboxesFilter.selectedComponentTypes).toEqual([]);
+ expect(component.componentInstance.checkboxesFilter.selectedResourceSubTypes).toEqual([]);
+ expect(component.componentInstance.checkboxesFilter.selectedCategoriesModel).toEqual([]);
+ expect(component.componentInstance.checkboxesFilter.selectedStatuses).toEqual([]);
+ });
+
+ it ('should call on catalog component initCheckboxesFilterKeys' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.initCheckboxesFilterKeys();
+ expect(component.componentInstance.checkboxesFilterKeys.componentTypes).toEqual({ _main: [] });
+ expect(component.componentInstance.checkboxesFilterKeys.categories).toEqual({ _main: [] });
+ expect(component.componentInstance.checkboxesFilterKeys.statuses).toEqual({ _main: [] });
+ });
+
+ it ('should call on catalog component initCategoriesMap' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ const categoriesMap = component.componentInstance.initCategoriesMap(categoriesElements);
+ expect(categoriesMap["resourceNewCategory.allotted resource.allotted resource"].parent.name).toEqual("Allotted Resource");
+ expect(categoriesMap["resourceNewCategory.generic"].category.uniqueId).toEqual("resourceNewCategory.generic");
+ expect(categoriesMap["serviceNewCategory.voip call control"].category.name).toEqual("VoIP Call Control");
+
+ });
+
+
+ it ('should call on catalog component selectLeftSwitchItem with active and selectedCatalogItem equal to archived' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.getActiveCatalogItems = jest.fn();
+ component.componentInstance.changeFilterParams = jest.fn();
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[1]
+ component.componentInstance.selectLeftSwitchItem(catalogSelectorItemsMock[0]);
+ expect(component.componentInstance.getActiveCatalogItems).toHaveBeenCalledWith(true);
+ expect(component.componentInstance.changeFilterParams).toHaveBeenCalledWith({active: true})
+ });
+
+ it ('should call on catalog component selectLeftSwitchItem with archived and selectedCatalogItem equal to active' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.getArchiveCatalogItems = jest.fn();
+ component.componentInstance.changeFilterParams = jest.fn();
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[0]
+ component.componentInstance.selectLeftSwitchItem(catalogSelectorItemsMock[1]);
+ expect(component.componentInstance.getArchiveCatalogItems).toBeCalledWith(true);
+ expect(component.componentInstance.changeFilterParams).toHaveBeenCalledWith({active: false})
+ });
+
+ it ('should call on catalog component sectionClick with section contains in expandedSection' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.expandedSection = ["type", "category", "status"];
+ component.componentInstance.sectionClick("type");
+ expect(component.componentInstance.expandedSection).toEqual(["category", "status"])
+ });
+
+ it ('should call on catalog component sectionClick with section not contains in expandedSection' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.expandedSection = ["type", "category", "status"];
+ component.componentInstance.sectionClick("newItem");
+ expect(component.componentInstance.expandedSection).toEqual(["type", "category", "status", "newItem"])
+ });
+
+ it ('should call on catalog component makeFilterParamsFromCheckboxes with selected values' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ expect(component.componentInstance.makeFilterParamsFromCheckboxes(checkListModelMock)).toEqual(["Resource.VF", "Resource.VFD"])
+ });
+
+ it ('should call on catalog component order with resourceName value' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.changeFilterParams = jest.fn();
+ component.componentInstance.filterParams = filterParamsMock
+ component.componentInstance.order("resourceName");
+ expect(component.componentInstance.changeFilterParams).toHaveBeenCalledWith( {"order": ["resourceName", false]})
+ });
+
+ it ('should call on catalog component goToComponent' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ const componentMock = { uniqueId: "d3e80fed-12f6-4f29-aeb1-771050e5db72", componentType: "RESOURCE"}
+ component.componentInstance.goToComponent(componentMock);
+ expect(stateServiceMock.go).toHaveBeenCalledWith('workspace.general', {id: componentMock.uniqueId, type: componentMock.componentType.toLowerCase()})
+
+ });
+
+ it ('should call on catalog component getNumOfElements for active catalog' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.selectedCatalogItem = catalogSelectorItemsMock[0]
+ expect(component.componentInstance.getNumOfElements(3)).toEqual("3 <b>Active</b> Elements found")
+
+ });
+
+ it ('should call on catalog component raiseNumberOfElementToDisplay with empty catalogFilteredItems' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.catalogFilteredItems = []
+ component.componentInstance.raiseNumberOfElementToDisplay(true);
+ expect(component.componentInstance.numberOfItemToDisplay).toEqual(NaN);
+ expect(component.componentInstance.catalogFilteredSlicedItems).toEqual([]);
+ });
+
+ it ('should call on catalog component raiseNumberOfElementToDisplay with full catalogFilteredItems' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.catalogFilteredItems = [1 , 2 , 3, 4, 5, 6]
+ component.componentInstance.numberOfItemToDisplay = 2;
+ component.componentInstance.raiseNumberOfElementToDisplay(false);
+ expect(component.componentInstance.numberOfItemToDisplay).toEqual(6);
+ expect(component.componentInstance.catalogFilteredSlicedItems).toEqual([1 , 2 , 3, 4, 5, 6]);
+ });
+
+ it ('should call on catalog component componentShouldReload return false' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.isDefaultFilter = jest.fn().mockImplementation(() => false);
+ cacheServiceMock.get.mockImplementation(()=> "mockConstructor");
+ let componentShouldReload = component.componentInstance.componentShouldReload();
+ expect(component.componentInstance.cacheService.get()).toEqual(component.componentInstance.$state.current.name);
+ expect(component.componentInstance.cacheService.contains()).toEqual(true);
+ expect(component.componentInstance.isDefaultFilter).toHaveBeenCalled();
+ expect(componentShouldReload).toEqual(false);
+ });
+
+ it ('should call on catalog component componentShouldReload return true' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.isDefaultFilter = jest.fn();
+ let componentShouldReload = component.componentInstance.componentShouldReload();
+ expect(component.componentInstance.cacheService.get()).not.toEqual(component.componentInstance.$state.current.name);
+ expect(component.componentInstance.cacheService.contains()).toEqual(true);
+ expect(componentShouldReload).toEqual(true);
+ });
+
+ it ('should call on catalog component getActiveCatalogItems with true' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ let resp = component.componentInstance.cacheService.get();
+ component.componentInstance.updateCatalogItems = jest.fn().mockImplementation((resp) => {});
+ component.componentInstance.getActiveCatalogItems(true);
+ expect(component.componentInstance.loaderService.activate).toHaveBeenCalled();
+ expect(component.componentInstance.updateCatalogItems).toHaveBeenCalledWith(resp);
+ expect(component.componentInstance.loaderService.deactivate).toHaveBeenCalled();
+ expect(component.componentInstance.cacheService.set).toHaveBeenCalledWith('breadcrumbsComponentsState', "mockConstructor");
+ expect(component.componentInstance.cacheService.set).toHaveBeenCalledWith('breadcrumbsComponents', categoriesElements);
+ expect(component.componentInstance.catalogService.getCatalog).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component getActiveCatalogItems with false' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.componentShouldReload = jest.fn();
+ component.componentInstance.updateCatalogItems = jest.fn().mockImplementation((resp) => {});
+ component.componentInstance.getActiveCatalogItems(false);
+ expect(component.componentInstance.componentShouldReload).toHaveBeenCalled();
+ let resp = component.componentInstance.cacheService.get();
+ expect(component.componentInstance.updateCatalogItems).toHaveBeenCalledWith(resp);
+ });
+
+ it ('should call on catalog component getActiveCatalogItems with true observable return error' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ catalogServiceMock.getCatalog.mockImplementation(()=> Observable.throwError('error'));
+ component.componentInstance.getActiveCatalogItems(true);
+ expect(component.componentInstance.loaderService.activate).toHaveBeenCalled();
+ expect(console.info).toHaveBeenCalledWith('Failed to load catalog CatalogViewModel::getActiveCatalogItems');
+ expect(component.componentInstance.loaderService.deactivate).toHaveBeenCalled();
+ expect(component.componentInstance.catalogService.getCatalog).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component getArchiveCatalogItems with true' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ const resp = component.componentInstance.cacheService.get();
+ component.componentInstance.updateCatalogItems = jest.fn().mockImplementation((resp) => {});
+ component.componentInstance.getArchiveCatalogItems(true);
+ expect(component.componentInstance.loaderService.activate).toHaveBeenCalled();
+ expect(component.componentInstance.catalogService.getArchiveCatalog).toHaveBeenCalled();
+ expect(component.componentInstance.cacheService.set).toHaveBeenCalledWith('archiveComponents', categoriesElements);
+ expect(component.componentInstance.loaderService.deactivate).toHaveBeenCalled();
+ expect(component.componentInstance.updateCatalogItems).toHaveBeenCalledWith(resp)
+ });
+
+ it ('should call on catalog component getArchiveCatalogItems with false' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.updateCatalogItems = jest.fn().mockImplementation((resp) => Observable.of());
+ component.componentInstance.getArchiveCatalogItems(false);
+ expect(component.componentInstance.cacheService.contains).toHaveBeenCalled();
+ expect(component.componentInstance.cacheService.get).toHaveBeenCalled();
+ let resp = component.componentInstance.cacheService.get();
+ expect(component.componentInstance.updateCatalogItems).toHaveBeenCalledWith(resp);
+ });
+
+ it ('should call on catalog component getArchiveCatalogItems with true observable return error' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ catalogServiceMock.getArchiveCatalog.mockImplementation(()=> Observable.throwError('error'));
+ component.componentInstance.getArchiveCatalogItems(true);
+ expect(component.componentInstance.loaderService.activate).toHaveBeenCalled();
+ expect(component.componentInstance.catalogService.getArchiveCatalog).toHaveBeenCalled();
+ expect(component.componentInstance.loaderService.deactivate).toHaveBeenCalled();
+ expect(console.info).toHaveBeenCalledWith('Failed to load catalog CatalogViewModel::getArchiveCatalogItems');
+ });
+
+ it ('should call on catalog component updateCatalogItems' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.filterCatalogItems = jest.fn();
+ component.componentInstance.addFilterTermToComponent = jest.fn();
+ component.componentInstance.updateCatalogItems([1, 2, 3]);
+ expect(component.componentInstance.catalogItems).toEqual([1, 2, 3]);
+ expect(component.componentInstance.addFilterTermToComponent).toHaveBeenCalled();
+ expect(component.componentInstance.filterCatalogItems).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component applyFilterParamsToView' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.initCheckboxesFilter = jest.fn();
+ component.componentInstance.filterCatalogCategories = jest.fn();
+ component.componentInstance.applyFilterParamsComponents = jest.fn();
+ component.componentInstance.applyFilterParamsCategories = jest.fn();
+ component.componentInstance.applyFilterParamsStatuses = jest.fn();
+ component.componentInstance.applyFilterParamsOrder = jest.fn();
+ component.componentInstance.applyFilterParamsTerm = jest.fn();
+ component.componentInstance.filterCatalogItems = jest.fn();
+ component.componentInstance.applyFilterParamsToView(filterParamsMock);
+ expect(component.componentInstance.initCheckboxesFilter).toHaveBeenCalled();
+ expect(component.componentInstance.filterCatalogCategories).toHaveBeenCalled();
+ expect(component.componentInstance.applyFilterParamsComponents).toHaveBeenCalledWith(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsCategories).toHaveBeenCalledWith(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsStatuses).toHaveBeenCalledWith(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsOrder).toHaveBeenCalledWith(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsTerm).toHaveBeenCalledWith(filterParamsMock);
+ expect(component.componentInstance.filterCatalogItems).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component filterCatalogCategories' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.makeFilteredCategories = jest.fn();
+ component.componentInstance.buildChecklistModelForCategories = jest.fn();
+ component.componentInstance.categories = categoriesElements;
+ component.componentInstance.checkboxesFilter = {selectedComponentTypes: ["firstType", "secondType"]};
+ component.componentInstance.filterCatalogCategories();
+ expect(component.componentInstance.makeFilteredCategories).toHaveBeenCalledWith(categoriesElements, ["firstType", "secondType"]);
+ expect(component.componentInstance.buildChecklistModelForCategories).toHaveBeenCalled();
+ });
+
+ it ('should call on catalog component filterCatalogItems' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.makeFilteredItems = jest.fn().mockImplementation(() => [1,2,3]);
+ component.componentInstance.raiseNumberOfElementToDisplay = jest.fn();
+ component.componentInstance.catalogItems = ["firstComponent", "secondComponent"];
+ component.componentInstance.checkboxesFilter = {};
+ component.componentInstance.search = {};
+ component.componentInstance.sortBy = "";
+ component.componentInstance.reverse = true;
+ component.componentInstance.numberOfItemToDisplay = 2;
+ // component.componentInstance.catalogFilteredItems = component.componentInstance.makeFilteredItems();
+ component.componentInstance.filterCatalogItems();
+ expect(component.componentInstance.makeFilteredItems).toHaveBeenCalledWith(["firstComponent", "secondComponent"], {}, {}, "",true);
+ expect(component.componentInstance.raiseNumberOfElementToDisplay).toHaveBeenCalledWith(true);
+ expect(component.componentInstance.catalogFilteredSlicedItems).toEqual([1,2]);
+ });
+
+ it ('should call on catalog component applyFilterParamsToCheckboxes' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToCheckboxes(checkListModelMock, ["Resource.CR", "Resource.VFD", "Resource.VF"]);
+ expect(checkListModelMock.selectedValues).toEqual(["Resource.VF","Resource.CR"]);
+ expect(checkListModelMock.checkboxes[1].subLevelChecklist.selectedValues).toEqual(["Resource.VFD"]);
+ expect(checkListModelMock.checkboxes[2].subLevelChecklist.selectedValues).toEqual(["Resource.VF"])
+ });
+
+ it ('should call on catalog component applyFilterParamsComponents and filterParams.active equal true' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToCheckboxes = jest.fn();
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.checkboxesFilter = checkboxesFilterMock;
+ component.componentInstance.catalogSelectorItems = catalogSelectorItemsMock;
+ component.componentInstance.typesChecklistModel = checkListModelMock;
+ component.componentInstance.applyFilterParamsComponents(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsToCheckboxes).toHaveBeenCalledWith(checkListModelMock, filterParamsMock.components);
+ expect(component.componentInstance.checkboxesFilter.selectedComponentTypes).toEqual(["Resource.VFC"]);
+ expect(component.componentInstance.checkboxesFilter.selectedResourceSubTypes).toEqual(["VF", "VFC"]);
+ expect(component.componentInstance.selectedCatalogItem).toEqual(catalogSelectorItemsMock[0]);
+ });
+
+ it ('should call on catalog component applyFilterParamsComponents and filterParams.active equal false' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToCheckboxes = jest.fn();
+ filterParamsMock.active = false;
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.checkboxesFilter = checkboxesFilterMock;
+ component.componentInstance.catalogSelectorItems = catalogSelectorItemsMock;
+ component.componentInstance.typesChecklistModel = checkListModelMock;
+ component.componentInstance.applyFilterParamsComponents(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsToCheckboxes).toHaveBeenCalledWith(checkListModelMock, filterParamsMock.components);
+ expect(component.componentInstance.checkboxesFilter.selectedComponentTypes).toEqual(["Resource.VFC"]);
+ expect(component.componentInstance.checkboxesFilter.selectedResourceSubTypes).toEqual(["VF", "VFC"]);
+ expect(component.componentInstance.selectedCatalogItem).toEqual(catalogSelectorItemsMock[1]);
+ });
+
+ it ('should call on catalog component applyFilterParamsCategories' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToCheckboxes = jest.fn();
+ component.componentInstance.categoriesChecklistModel = checkListModelMock;
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.checkboxesFilter = checkboxesFilterMock;
+ component.componentInstance.applyFilterParamsCategories(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsToCheckboxes).toHaveBeenCalledWith(checkListModelMock, filterParamsMock.categories);
+ expect(component.componentInstance.checkboxesFilter.selectedCategoriesModel).toEqual(["serviceNewCategory.network l4+"]);
+ });
+
+ it ('should call on catalog component applyFilterParamsStatuses' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToCheckboxes = jest.fn();
+
+ component.componentInstance.statusChecklistModel = checkListModelMock;
+ component.componentInstance.checkboxesFilterKeys = checkboxesFilterKeysMock;
+ component.componentInstance.checkboxesFilter = checkboxesFilterMock;
+ component.componentInstance.confStatus = sdcMenu.statuses;
+ component.componentInstance.applyFilterParamsStatuses(filterParamsMock);
+ expect(component.componentInstance.applyFilterParamsToCheckboxes).toHaveBeenCalledWith(checkListModelMock, filterParamsMock.statuses);
+ expect(component.componentInstance.checkboxesFilter.selectedStatuses).toEqual(["NOT_CERTIFIED_CHECKOUT", "NOT_CERTIFIED_CHECKIN"]);
+ });
+
+ it ('should call on catalog component applyFilterParamsOrder' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsOrder(filterParamsMock);
+ expect(component.componentInstance.sortBy).toEqual("lastUpdateDate");
+ expect(component.componentInstance.reverse).toEqual( true);
+ });
+
+ it ('should call on catalog component applyFilterParamsTerm' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsTerm(filterParamsMock);
+ expect(component.componentInstance.search.filterTerm).toEqual("Vf");
+ });
+
+ // it ('should call on catalog component loadFilterParams' , () => {
+ // const component = TestBed.createComponent(CatalogComponent);
+ // component.componentInstance.$state = {params: {}};
+ // component.componentInstance.loadFilterParams();
+ // });
+
+ it ('should call on catalog component changeFilterParams' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToView = jest.fn();
+ component.componentInstance.filterParams = { active: true, categories: [], components: [], order: ["lastUpdateDate", true], statuses: [], term: ""};
+ component.componentInstance.$state.go = jest.fn().mockImplementation(() => Promise.resolve({ json: () => [] }));
+ const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
+ component.componentInstance.changeFilterParams(filterParamsMock);
+ expect(component.componentInstance.filterParams).toEqual(filterParamsMock);
+ expect(component.componentInstance.$state.go).toHaveBeenCalledWith('.',newParams, {location: 'replace', notify: false});
+ expect(component.componentInstance.applyFilterParamsToView).toHaveBeenCalledWith(filterParamsMock);
+ });
+
+ it ('should call on catalog component changeFilterParams and rebuild equal true' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ component.componentInstance.applyFilterParamsToView = jest.fn();
+ component.componentInstance.makeFilterParamsFromCheckboxes = jest.fn();
+ component.componentInstance.buildCheckboxLists = jest.fn();
+ component.componentInstance.filterParams = { active: true, categories: [], components: [], order: ["lastUpdateDate", true], statuses: [], term: ""};
+ component.componentInstance.$state.go = jest.fn().mockImplementation(() => Promise.resolve({ json: () => [] }));
+ const newParams = {"filter.active": true, "filter.categories": "resourceNewCategory.allotted resource.allotted resource,resourceNewCategory.allotted resource.contrail route,resourceNewCategory.application l4+.application server", "filter.components": "Resource.VF,Resource.VFC", "filter.order": "-lastUpdateDate", "filter.statuses": "inDesign", "filter.term": "Vf"}
+ component.componentInstance.typesChecklistModel = checkListModelMock;
+ component.componentInstance.categoriesChecklistModel = checkListModelMock;
+ component.componentInstance.statusChecklistModel = checkListModelMock;
+ component.componentInstance.changeFilterParams(filterParamsMock, true);
+ expect(component.componentInstance.filterParams).toEqual(filterParamsMock);
+ expect(component.componentInstance.$state.go).toHaveBeenCalledWith('.',newParams, {location: 'replace', notify: false});
+ //expect(component.componentInstance.makeFilterParamsFromCheckboxes).toHaveBeenCalledWith(component.componentInstance.typesChecklistModel);
+ //expect(component.componentInstance.buildCheckboxLists).toHaveBeenCalled();
+ expect(component.componentInstance.applyFilterParamsToView).toHaveBeenCalledWith(filterParamsMock);
+ });
+
+ it ('should call on catalog component makeFilteredCategories' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ const categoryMock = [{"name":"Network L1-3","normalizedName":"network l1-3","uniqueId":"serviceNewCategory.network l1-3","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null}];
+ cacheServiceMock.get.mockImplementation(()=> categoryMock);
+ const resp = component.componentInstance.makeFilteredCategories(categoriesElements, checkboxesFilterMock.selectedComponentTypes);
+ expect(component.componentInstance.cacheService.get).toHaveBeenCalledWith("resourceCategories");
+ expect(resp).toEqual(categoryMock);
+ });
+
+ it ('should call on catalog component makeFilteredCategories return unique elements' , () => {
+ const component = TestBed.createComponent(CatalogComponent);
+ const categoryMock = [{"name":"Network L1-3","normalizedName":"network l1-3","uniqueId":"serviceNewCategory.network l1-3","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},
+ {"name":"Network L1-3","normalizedName":"network l1-3","uniqueId":"serviceNewCategory.network l1-3","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},
+ {"name":"Network Service","normalizedName":"network service","uniqueId":"serviceNewCategory.network service","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null}];
+ const categoryUniqueMock = [{"name":"Network L1-3","normalizedName":"network l1-3","uniqueId":"serviceNewCategory.network l1-3","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},
+ {"name":"Network Service","normalizedName":"network service","uniqueId":"serviceNewCategory.network service","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null}];
+ cacheServiceMock.get.mockImplementation(()=> categoryMock);
+ checkboxesFilterMock.selectedComponentTypes = ["SERVICE", "Resource.VF"];
+ const resp = component.componentInstance.makeFilteredCategories(categoriesElements, checkboxesFilterMock.selectedComponentTypes);
+ expect(component.componentInstance.cacheService.get).toHaveBeenCalledWith("resourceCategories");
+ expect(resp).toEqual(categoryUniqueMock);
+ });
+
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts
new file mode 100644
index 0000000..5277648
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.component.ts
@@ -0,0 +1,666 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import { Component as NgComponent, Inject } from '@angular/core';
+import { SdcUiCommon, SdcUiServices } from "onap-ui-angular";
+import { CacheService, CatalogService } from "app/services-ng2";
+import { SdcConfigToken, ISdcConfig } from "../../config/sdc-config.config";
+import { SdcMenuToken, IAppMenu } from "../../config/sdc-menu.config";
+import { Component, ICategoryBase, IMainCategory, ISubCategory, IConfigStatuses, ICatalogSelector, CatalogSelectorTypes } from "app/models";
+import { ResourceNamePipe } from "../../pipes/resource-name.pipe";
+import { EntityFilterPipe, IEntityFilterObject, ISearchFilter} from "../../pipes/entity-filter.pipe";
+
+interface Gui {
+ onComponentSubTypesClick:Function;
+ onComponentTypeClick:Function;
+ onCategoryClick:Function;
+ onStatusClick:Function;
+ changeFilterTerm:Function;
+}
+
+interface IFilterParams {
+ components: string[];
+ categories: string[];
+ statuses: (string)[];
+ order: [string, boolean];
+ term: string;
+ active: boolean;
+}
+
+interface ICheckboxesFilterMap {
+ [key: string]: Array<string>;
+ _main: Array<string>;
+}
+
+interface ICheckboxesFilterKeys {
+ componentTypes: ICheckboxesFilterMap;
+ categories: ICheckboxesFilterMap;
+ statuses: ICheckboxesFilterMap;
+}
+
+interface ICategoriesMap {
+ [key: string]: {
+ category: ICategoryBase,
+ parent: ICategoryBase
+ }
+}
+
+@NgComponent({
+ selector: 'catalog',
+ templateUrl: './catalog.component.html',
+ styleUrls:['./catalog.component.less']
+})
+export class CatalogComponent {
+ public checkboxesFilter:IEntityFilterObject;
+ public checkboxesFilterKeys:ICheckboxesFilterKeys;
+ public gui:Gui;
+ public categories:Array<IMainCategory>;
+ public filteredCategories:Array<IMainCategory>;
+ public confStatus:IConfigStatuses;
+ public componentTypes:{[key:string]: Array<string>};
+ public catalogItems:Array<Component>;
+ public catalogFilteredItems:Array<Component>;
+ public catalogFilteredSlicedItems:Array<Component>;
+ public expandedSection:Array<string>;
+ public version:string;
+ public sortBy:string;
+ public reverse:boolean;
+ public filterParams:IFilterParams;
+ public search:ISearchFilter;
+
+ //this is for UI paging
+ public numberOfItemToDisplay:number;
+
+ public selectedCatalogItem: ICatalogSelector;
+ public catalogSelectorItems: Array<ICatalogSelector>;
+ public showCatalogSelector: boolean;
+
+ public typesChecklistModel: SdcUiCommon.ChecklistModel;
+ public categoriesChecklistModel: SdcUiCommon.ChecklistModel;
+ public statusChecklistModel: SdcUiCommon.ChecklistModel;
+
+ private defaultFilterParams:IFilterParams = {
+ components: [],
+ categories: [],
+ statuses: [],
+ order: ['lastUpdateDate', true],
+ term: '',
+ active: true
+ };
+ private categoriesMap:ICategoriesMap;
+
+ constructor(
+ @Inject(SdcConfigToken) private sdcConfig:ISdcConfig,
+ @Inject(SdcMenuToken) public sdcMenu:IAppMenu,
+ @Inject("$state") private $state:ng.ui.IStateService,
+ private cacheService:CacheService,
+ private catalogService:CatalogService,
+ private resourceNamePipe:ResourceNamePipe,
+ private loaderService: SdcUiServices.LoaderService
+ ) {}
+
+ ngOnInit(): void {
+ this.initGui();
+ this.initLeftSwitch();
+ this.initScopeMembers();
+ this.loadFilterParams();
+ this.initCatalogData(); // Async task to get catalog from server.
+ }
+
+ private initLeftSwitch = ():void => {
+ this.showCatalogSelector = false;
+
+ this.catalogSelectorItems = [
+ {value: CatalogSelectorTypes.Active, title: "Active Items", header: "Active"},
+ {value: CatalogSelectorTypes.Archive, title: "Archive", header: "Archived"}
+ ];
+ // set active items is default
+ this.selectedCatalogItem = this.catalogSelectorItems[0];
+ };
+
+ private initCatalogData = ():void => {
+ if(this.selectedCatalogItem.value === CatalogSelectorTypes.Archive){
+ this.getArchiveCatalogItems();
+ } else {
+ this.getActiveCatalogItems();
+ }
+ };
+
+
+ private initScopeMembers = ():void => {
+ this.numberOfItemToDisplay = 0;
+ this.categories = this.makeSortedCategories(this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')))
+ .map((cat) => <IMainCategory>cat);
+ this.confStatus = this.sdcMenu.statuses;
+ this.expandedSection = ["type", "category", "status"];
+ this.catalogItems = [];
+ this.search = {FilterTerm: ""};
+ this.categoriesMap = this.initCategoriesMap();
+ this.initCheckboxesFilter();
+ this.initCheckboxesFilterKeys();
+ this.buildCheckboxLists();
+
+ this.version = this.cacheService.get('version');
+ this.sortBy = 'lastUpdateDate';
+ this.reverse = true;
+ };
+
+ private buildCheckboxLists() {
+ this.buildChecklistModelForTypes();
+ this.buildChecklistModelForCategories();
+ this.buildChecklistModelForStatuses();
+ }
+
+ private getTestIdForCheckboxByText = ( text: string ):string => {
+ return 'checkbox-' + text.toLowerCase().replace(/ /g, '');
+ }
+
+ private buildChecklistModelForTypes() {
+ this.componentTypes = {
+ Resource: ['VF', 'VFC', 'CR', 'PNF', 'CP', 'VL'],
+ Service: null
+ };
+ this.typesChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.componentTypes._main,
+ Object.keys(this.componentTypes).map((ct) => {
+ let subChecklist = null;
+ if (this.componentTypes[ct]) {
+ this.checkboxesFilterKeys.componentTypes[ct] = this.checkboxesFilterKeys.componentTypes[ct] || [];
+ subChecklist = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.componentTypes[ct],
+ this.componentTypes[ct].map((st) => {
+ const stKey = [ct, st].join('.');
+ const testId = this.getTestIdForCheckboxByText(st);
+ return new SdcUiCommon.ChecklistItemModel(st, false, this.checkboxesFilterKeys.componentTypes[ct].indexOf(stKey) !== -1, null, testId, stKey);
+ })
+ );
+ }
+ const testId = this.getTestIdForCheckboxByText(ct);
+ return new SdcUiCommon.ChecklistItemModel(ct, false, this.checkboxesFilterKeys.componentTypes._main.indexOf(ct) !== -1, subChecklist, testId, ct);
+ })
+ );
+ }
+
+ private buildChecklistModelForCategories() {
+ this.categoriesChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.categories._main,
+ (this.filteredCategories || this.categories).map((cat) => {
+ this.checkboxesFilterKeys.categories[cat.uniqueId] = this.checkboxesFilterKeys.categories[cat.uniqueId] || [];
+ const subCategoriesChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.categories[cat.uniqueId],
+ (cat.subcategories || []).map((scat) => {
+ this.checkboxesFilterKeys.categories[scat.uniqueId] = this.checkboxesFilterKeys.categories[scat.uniqueId] || [];
+ const groupingsChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.categories[scat.uniqueId],
+ (scat.groupings || []).map(gcat =>
+ new SdcUiCommon.ChecklistItemModel(gcat.name, false, this.checkboxesFilterKeys.categories[scat.uniqueId].indexOf(gcat.uniqueId) !== -1, null, this.getTestIdForCheckboxByText(gcat.uniqueId), gcat.uniqueId))
+ );
+ return new SdcUiCommon.ChecklistItemModel(scat.name, false, this.checkboxesFilterKeys.categories[cat.uniqueId].indexOf(scat.uniqueId) !== -1, groupingsChecklistModel, this.getTestIdForCheckboxByText(scat.uniqueId), scat.uniqueId);
+ })
+ );
+ return new SdcUiCommon.ChecklistItemModel(cat.name, false, this.checkboxesFilterKeys.categories._main.indexOf(cat.uniqueId) !== -1, subCategoriesChecklistModel, this.getTestIdForCheckboxByText(cat.uniqueId), cat.uniqueId);
+ })
+ );
+ }
+
+ private buildChecklistModelForStatuses() {
+ // For statuses checklist model, use the statuses keys as values. On applying filtering map the statuses keys to statuses values.
+ this.statusChecklistModel = new SdcUiCommon.ChecklistModel(this.checkboxesFilterKeys.statuses._main,
+ Object.keys(this.confStatus).map((sKey) => new SdcUiCommon.ChecklistItemModel(
+ this.confStatus[sKey].name,
+ false,
+ this.checkboxesFilterKeys.statuses._main.indexOf(sKey) !== -1,
+ null,
+ this.getTestIdForCheckboxByText(sKey),
+ sKey))
+ );
+ }
+
+ private initCheckboxesFilter() {
+ // Checkboxes filter init
+ this.checkboxesFilter = <IEntityFilterObject>{};
+ this.checkboxesFilter.selectedComponentTypes = [];
+ this.checkboxesFilter.selectedResourceSubTypes = [];
+ this.checkboxesFilter.selectedCategoriesModel = [];
+ this.checkboxesFilter.selectedStatuses = [];
+ }
+
+ private initCheckboxesFilterKeys() {
+ // init checkboxes filter keys (for checklists values):
+ this.checkboxesFilterKeys = <ICheckboxesFilterKeys>{};
+ this.checkboxesFilterKeys.componentTypes = { _main: [] };
+ this.checkboxesFilterKeys.categories = { _main: [] };
+ this.checkboxesFilterKeys.statuses = { _main: [] };
+ }
+
+ private initCategoriesMap(categoriesList?:(ICategoryBase)[], parentCategory:ICategoryBase=null): ICategoriesMap {
+ categoriesList = (categoriesList) ? categoriesList : this.categories;
+
+ // Init categories map
+ return categoriesList.reduce((acc, cat) => {
+ acc[cat.uniqueId] = {
+ category: cat,
+ parent: parentCategory
+ };
+ const catChildren = ((<IMainCategory>cat).subcategories)
+ ? (<IMainCategory>cat).subcategories
+ : (((<ISubCategory>cat).groupings)
+ ? (<ISubCategory>cat).groupings
+ : null);
+ if (catChildren) {
+ Object.assign(acc, this.initCategoriesMap(catChildren, cat));
+ }
+ return acc;
+ }, <ICategoriesMap>{});
+ }
+
+ public selectLeftSwitchItem(item: ICatalogSelector): void {
+ if (this.selectedCatalogItem.value !== item.value) {
+ this.selectedCatalogItem = item;
+ switch (item.value) {
+ case CatalogSelectorTypes.Active:
+ this.getActiveCatalogItems(true);
+ break;
+
+ case CatalogSelectorTypes.Archive:
+ this.getArchiveCatalogItems(true);
+ break;
+ }
+ this.changeFilterParams({active: (item.value === CatalogSelectorTypes.Active)});
+ }
+ }
+
+ public sectionClick(section: string): void {
+ let index: number = this.expandedSection.indexOf(section);
+ if (index !== -1) {
+ this.expandedSection.splice(index, 1);
+ } else {
+ this.expandedSection.push(section);
+ }
+ }
+
+
+ private makeFilterParamsFromCheckboxes(checklistModel:SdcUiCommon.ChecklistModel): Array<string> {
+ return checklistModel.checkboxes.reduce((acc, chbox) => {
+ if (checklistModel.selectedValues.indexOf(chbox.value) !== -1) {
+ acc.push(chbox.value);
+ } else if (chbox.subLevelChecklist) { // else, if checkbox is not checked, then try to get values from sub checklists
+ acc.push(...this.makeFilterParamsFromCheckboxes(chbox.subLevelChecklist));
+ }
+ return acc;
+ }, []);
+ }
+
+ //default sort by descending last update. default for alphabetical = ascending
+ public order(sortBy: string): void {
+ this.changeFilterParams({
+ order: (this.filterParams.order[0] === sortBy)
+ ? [sortBy, !this.filterParams.order[1]]
+ : [sortBy, sortBy === 'lastUpdateDate']
+ });
+ }
+
+
+ public goToComponent(component: Component): void {
+ this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()});
+ }
+
+
+ // Will print the number of elements found in catalog
+ public getNumOfElements(num:number):string {
+ if (!num || num === 0) {
+ return `No <b>${this.selectedCatalogItem.header}</b> Elements found`;
+ } else if (num === 1) {
+ return `1 <b>${this.selectedCatalogItem.header}</b> Element found`;
+ } else {
+ return num + ` <b>${this.selectedCatalogItem.header}</b> Elements found`;
+ }
+ }
+
+ public initGui(): void {
+ this.gui = <Gui>{};
+
+ /**
+ * Select | unselect sub resource when resource is clicked | unclicked.
+ * @param type
+ */
+ this.gui.onComponentTypeClick = (): void => {
+ this.changeFilterParams({
+ components: this.makeFilterParamsFromCheckboxes(this.typesChecklistModel)
+ });
+ };
+
+ this.gui.onCategoryClick = (): void => {
+ this.changeFilterParams({
+ categories: this.makeFilterParamsFromCheckboxes(this.categoriesChecklistModel)
+ });
+ };
+
+ this.gui.onStatusClick = (statusChecklistItem: SdcUiCommon.ChecklistItemModel) => {
+ this.changeFilterParams({
+ statuses: this.makeFilterParamsFromCheckboxes(this.statusChecklistModel)
+ });
+ };
+
+ this.gui.changeFilterTerm = (filterTerm: string) => {
+ this.changeFilterParams({
+ term: filterTerm
+ });
+ };
+ }
+
+ public raiseNumberOfElementToDisplay(recalculate:boolean = false): void {
+ const scrollPageAmount = 35;
+ if (!this.catalogFilteredItems) {
+ this.numberOfItemToDisplay = 0;
+ } else if (this.catalogFilteredItems.length > this.numberOfItemToDisplay || recalculate) {
+ let fullPagesAmount = Math.ceil(this.numberOfItemToDisplay / scrollPageAmount) * scrollPageAmount;
+ if (!recalculate || fullPagesAmount === 0) { //TODO trigger infiniteScroll to check bottom and fire onBottomHit by itself (sdc-ui)
+ fullPagesAmount += scrollPageAmount;
+ }
+ this.numberOfItemToDisplay = Math.min(this.catalogFilteredItems.length, fullPagesAmount);
+ this.catalogFilteredSlicedItems = this.catalogFilteredItems.slice(0, this.numberOfItemToDisplay);
+ }
+ }
+
+ private isDefaultFilter = (): boolean => {
+ return angular.equals(this.defaultFilterParams, this.filterParams);
+ }
+
+ private componentShouldReload = ():boolean => {
+ let breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
+ return !breadcrumbsValid || this.isDefaultFilter();
+ }
+
+ private getActiveCatalogItems(forceReload?: boolean): void {
+ if (forceReload || this.componentShouldReload()) {
+ this.loaderService.activate();
+
+ let onSuccess = (followedResponse:Array<Component>):void => {
+ this.updateCatalogItems(followedResponse);
+ this.loaderService.deactivate();
+ this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); //catalog
+ this.cacheService.set('breadcrumbsComponents', followedResponse);
+
+ };
+
+ let onError = ():void => {
+ console.info('Failed to load catalog CatalogViewModel::getActiveCatalogItems');
+ this.loaderService.deactivate();
+ };
+ this.catalogService.getCatalog().subscribe(onSuccess, onError);
+ } else {
+ let cachedComponents = this.cacheService.get('breadcrumbsComponents');
+ this.updateCatalogItems(cachedComponents);
+ }
+ }
+
+ private getArchiveCatalogItems(forceReload?: boolean): void {
+ if(forceReload || !this.cacheService.contains("archiveComponents")) {
+ this.loaderService.activate();
+ let onSuccess = (followedResponse:Array<Component>):void => {
+ this.cacheService.set("archiveComponents", followedResponse);
+ this.loaderService.deactivate();
+ this.updateCatalogItems(followedResponse);
+ };
+
+ let onError = ():void => {
+ console.info('Failed to load catalog CatalogViewModel::getArchiveCatalogItems');
+ this.loaderService.deactivate();
+ };
+
+ this.catalogService.getArchiveCatalog().subscribe(onSuccess, onError);
+ } else {
+ let archiveCache = this.cacheService.get("archiveComponents");
+ this.updateCatalogItems(archiveCache);
+ }
+ }
+
+ private updateCatalogItems = (items:Array<Component>):void => {
+ this.catalogItems = items;
+ this.catalogItems.forEach(this.addFilterTermToComponent);
+ this.filterCatalogItems();
+ }
+
+ private applyFilterParamsToView(filterParams:IFilterParams) {
+ // reset checkboxes filter
+ this.initCheckboxesFilter();
+
+ this.filterCatalogCategories();
+
+ this.applyFilterParamsComponents(filterParams);
+ this.applyFilterParamsCategories(filterParams);
+ this.applyFilterParamsStatuses(filterParams);
+ this.applyFilterParamsOrder(filterParams);
+ this.applyFilterParamsTerm(filterParams);
+
+ // do filters when filter params are changed:
+ this.filterCatalogItems();
+ }
+
+ private filterCatalogCategories() {
+ this.filteredCategories = this.makeFilteredCategories(this.categories, this.checkboxesFilter.selectedComponentTypes);
+ this.buildChecklistModelForCategories();
+ }
+
+ private filterCatalogItems() {
+ this.catalogFilteredItems = this.makeFilteredItems(this.catalogItems, this.checkboxesFilter, this.search, this.sortBy, this.reverse);
+ this.raiseNumberOfElementToDisplay(true);
+ this.catalogFilteredSlicedItems = this.catalogFilteredItems.slice(0, this.numberOfItemToDisplay);
+ }
+
+ private applyFilterParamsToCheckboxes(checklistModel:SdcUiCommon.ChecklistModel, filterParamsList:Array<string>) {
+ checklistModel.checkboxes.forEach((chbox) => {
+ // if checkbox is checked, then add it to selected values if not there, and select all sub checkboxes
+ if (filterParamsList.indexOf(chbox.value) !== -1 && checklistModel.selectedValues.indexOf(chbox.value) === -1) {
+ checklistModel.selectedValues.push(chbox.value);
+ if (chbox.subLevelChecklist) {
+ this.applyFilterParamsToCheckboxes(chbox.subLevelChecklist, chbox.subLevelChecklist.checkboxes.map((subchbox) => subchbox.value));
+ }
+ } else if ( chbox.subLevelChecklist ) {
+ this.applyFilterParamsToCheckboxes(chbox.subLevelChecklist, filterParamsList);
+ }
+ });
+ }
+
+ private applyFilterParamsComponents(filterParams:IFilterParams) {
+ this.applyFilterParamsToCheckboxes(this.typesChecklistModel, filterParams.components);
+ this.checkboxesFilter.selectedComponentTypes = this.checkboxesFilterKeys.componentTypes._main;
+ Object.keys(this.checkboxesFilterKeys.componentTypes).forEach((chKey) => {
+ if (chKey !== '_main') {
+ this.checkboxesFilter['selected' + chKey + 'SubTypes'] = this.checkboxesFilterKeys.componentTypes[chKey].map((st) => st.substr(chKey.length + 1));
+ }
+ });
+
+ let selectedCatalogIndex = filterParams.active ? CatalogSelectorTypes.Active : CatalogSelectorTypes.Archive;
+ this.selectedCatalogItem = this.catalogSelectorItems[selectedCatalogIndex];
+ }
+
+ private applyFilterParamsCategories(filterParams:IFilterParams) {
+ this.applyFilterParamsToCheckboxes(this.categoriesChecklistModel, filterParams.categories);
+ this.checkboxesFilter.selectedCategoriesModel = <Array<string>>_.flatMap(this.checkboxesFilterKeys.categories);
+ }
+
+ private applyFilterParamsStatuses(filterParams: IFilterParams) {
+ this.applyFilterParamsToCheckboxes(this.statusChecklistModel, filterParams.statuses);
+ this.checkboxesFilter.selectedStatuses = _.reduce(_.flatMap(this.checkboxesFilterKeys.statuses), (stats, st:string) => [...stats, ...this.confStatus[st].values], []);
+ }
+
+ private applyFilterParamsOrder(filterParams: IFilterParams) {
+ this.sortBy = filterParams.order[0];
+ this.reverse = filterParams.order[1];
+ }
+
+ private applyFilterParamsTerm(filterParams: IFilterParams) {
+ this.search = {
+ filterTerm: filterParams.term
+ };
+ }
+
+ private loadFilterParams() {
+ const params = this.$state.params;
+ this.filterParams = angular.copy(this.defaultFilterParams);
+ Object.keys(params).forEach((k) => {
+ if (!angular.isUndefined(params[k])) {
+ let newVal;
+ let paramsChecklist: SdcUiCommon.ChecklistModel = null;
+ let filterKey = k.substr('filter.'.length);
+ switch (k) {
+ case 'filter.components':
+ paramsChecklist = paramsChecklist || this.typesChecklistModel;
+ case 'filter.categories':
+ paramsChecklist = paramsChecklist || this.categoriesChecklistModel;
+ case 'filter.statuses':
+ paramsChecklist = paramsChecklist || this.statusChecklistModel;
+
+ // for those cases above - split param by comma and make reduced checklist values for filter params (url)
+ newVal = _.uniq(params[k].split(','));
+ break;
+ case 'filter.order':
+ newVal = params[k].startsWith('-') ? [params[k].substr(1), true] : [params[k], false];
+ break;
+ case 'filter.term':
+ newVal = params[k];
+ break;
+ case 'filter.active':
+ newVal = (params[k] === "true" || params[k] === true)? true : false;
+ break;
+ default:
+ // unknown filter key
+ filterKey = null;
+ }
+ if (filterKey) {
+ this.filterParams[filterKey] = newVal;
+ }
+ }
+ });
+ // re-set filter params with valid values, and then re-build checklists
+ this.changeFilterParams(this.filterParams, true);
+ }
+
+ private changeFilterParams(changedFilterParams, rebuild:boolean = false) {
+ const newParams = {};
+ Object.keys(changedFilterParams).forEach((k) => {
+ let newVal;
+ switch (k) {
+ case 'components':
+ case 'categories':
+ case 'statuses':
+ newVal = changedFilterParams[k] && changedFilterParams[k].length ? changedFilterParams[k].join(',') : null;
+ break;
+ case 'order':
+ newVal = (changedFilterParams[k][1] ? '-' : '') + changedFilterParams[k][0];
+ break;
+ case 'term':
+ newVal = changedFilterParams[k] ? changedFilterParams[k] : null;
+ break;
+ case 'active':
+ newVal = (changedFilterParams[k] === "true" || changedFilterParams[k] === true);
+ break;
+ default:
+ return;
+ }
+ this.filterParams[k] = changedFilterParams[k];
+ newParams['filter.' + k] = newVal;
+ });
+ this.$state.go('.', newParams, {location: 'replace', notify: false}).then(() => {
+ if (rebuild) {
+ // fix the filter params to only valid values for checkboxes
+ this.changeFilterParams({
+ components: this.makeFilterParamsFromCheckboxes(this.typesChecklistModel),
+ categories: this.makeFilterParamsFromCheckboxes(this.categoriesChecklistModel),
+ statuses: this.makeFilterParamsFromCheckboxes(this.statusChecklistModel)
+ });
+ // rebuild the checkboxes to show selected
+ this.buildCheckboxLists();
+ }
+ });
+ this.applyFilterParamsToView(this.filterParams);
+ }
+
+ private makeFilteredCategories(categories:Array<IMainCategory>, selectedTypes:Array<string>=[]): Array<IMainCategory> {
+ let filteredCategories = categories.slice();
+
+ const filteredMainTypes = selectedTypes.reduce((acc, st) => {
+ const mainType = st.split('.')[0];
+ if (acc.indexOf(mainType) === -1) {
+ acc.push(mainType);
+ }
+ return acc;
+ }, []);
+
+ // filter by selected types
+ if (filteredMainTypes.length) {
+ const filteredTypesCategories = filteredMainTypes.reduce((acc, mainType: string) => {
+ acc.push(...this.cacheService.get(mainType.toLowerCase() + 'Categories'));
+ return acc;
+ }, []);
+
+ filteredCategories = _.intersectionBy(filteredCategories, filteredTypesCategories, c => c.uniqueId);
+ }
+
+ return filteredCategories;
+ }
+
+ private makeSortedCategories(categories:Array<IMainCategory|ISubCategory|ICategoryBase>, sortBy?:any): Array<IMainCategory|ISubCategory|ICategoryBase> {
+ sortBy = (sortBy !== undefined) ? sortBy : ['name'];
+ let sortedCategories = categories.map(cat => Object.assign({}, cat)); // copy each object in the array
+ sortedCategories = _.sortBy(sortedCategories, sortBy);
+
+ // inner sort of subcategories and groupings
+ sortedCategories.forEach((cat) => {
+ if ('subcategories' in cat && cat['subcategories'] && cat['subcategories'].length > 0) {
+ cat['subcategories'] = this.makeSortedCategories(cat['subcategories'], sortBy);
+ }
+ if ('groupings' in cat && cat['groupings'] && cat['groupings'].length > 0) {
+ cat['groupings'] = this.makeSortedCategories(cat['groupings'], sortBy);
+ }
+ });
+
+ return sortedCategories;
+ }
+
+ private addFilterTermToComponent(component:Component) {
+ component.filterTerm = component.name + ' ' + component.description + ' ' + component.tags.toString() + ' ' + component.version;
+ component.filterTerm = component.filterTerm.toLowerCase();
+ }
+
+ private makeFilteredItems(catalogItems:Array<Component>, filter:IEntityFilterObject, search:ISearchFilter, sortBy:string, reverse:boolean) {
+ let filteredComponents:Array<Component> = catalogItems;
+
+ // common entity filter
+ // --------------------------------------------------------------------------
+ filter = Object.assign({ search }, filter); // add search to entity filter object
+ filteredComponents = EntityFilterPipe.transform(filteredComponents, filter);
+
+ // sort
+ // --------------------------------------------------------------------------
+ if (sortBy) {
+ switch (sortBy) {
+ case 'resourceName':
+ filteredComponents = _.sortBy(filteredComponents, cat => this.resourceNamePipe.transform(cat.name));
+ break;
+ default:
+ filteredComponents = _.sortBy(filteredComponents, [sortBy]);
+ }
+ if (reverse) {
+ _.reverse(filteredComponents);
+ }
+ }
+
+ return filteredComponents;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/catalog/catalog.module.ts b/catalog-ui/src/app/ng2/pages/catalog/catalog.module.ts
new file mode 100644
index 0000000..5ef8de0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/catalog/catalog.module.ts
@@ -0,0 +1,33 @@
+import { NgModule } from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { CatalogComponent } from "./catalog.component";
+import { LayoutModule } from "../../components/layout/layout.module";
+import { UiElementsModule } from "../../components/ui/ui-elements.module";
+import { GlobalPipesModule } from "../../pipes/global-pipes.module";
+import { TranslateModule } from "../../shared/translator/translate.module";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import {SdcTileModule} from "../../components/ui/tile/sdc-tile.module";
+
+@NgModule({
+ declarations: [
+ CatalogComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ LayoutModule,
+ UiElementsModule,
+ GlobalPipesModule,
+ TranslateModule,
+ SdcTileModule
+ ],
+ exports: [
+ CatalogComponent
+ ],
+ entryComponents: [
+ CatalogComponent
+ ],
+ providers: []
+})
+export class CatalogModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/common/common-graph-data.service.ts b/catalog-ui/src/app/ng2/pages/composition/common/common-graph-data.service.ts
new file mode 100644
index 0000000..d4caa5e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/common/common-graph-data.service.ts
@@ -0,0 +1,64 @@
+import {Injectable} from "@angular/core";
+import 'rxjs/add/observable/forkJoin';
+import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
+import {SelectedComponentType} from "./store/graph.actions";
+import {RelationshipModel} from "../../../../models/graph/relationship";
+
+@Injectable()
+export class CommonGraphDataService {
+
+ public componentInstances: Array<ComponentInstance>;
+ public componentInstancesRelations: RelationshipModel[];
+ public selectedComponentType: SelectedComponentType;
+
+ constructor() {
+ }
+
+ //------------------------ RELATIONS ---------------------------------//
+ public setRelations = (componentInstancesRelations: RelationshipModel[]) => {
+ this.componentInstancesRelations = this.componentInstancesRelations;
+ }
+
+ public getRelations = (): RelationshipModel[] => {
+ return this.componentInstancesRelations;
+ }
+
+ public addRelation = (componentInstancesRelations: RelationshipModel) => {
+ this.componentInstancesRelations.push(componentInstancesRelations);
+ }
+
+ public deleteRelation(relationToDelete: RelationshipModel) {
+ this.componentInstancesRelations = _.filter(this.componentInstancesRelations, (relationship: RelationshipModel) => {
+ return relationship.relationships[0].relation.id !== relationToDelete.relationships[0].relation.id;
+ });
+ }
+
+ //---------------------------- COMPONENT INSTANCES ------------------------------------//
+ public getComponentInstances = (): Array<ComponentInstance> => {
+ return this.componentInstances;
+ }
+
+ public addComponentInstance = (instance: ComponentInstance) => {
+ return this.componentInstances.push(instance);
+ }
+
+ public updateComponentInstances = (componentInstances: ComponentInstance[]) => {
+ _.unionBy(this.componentInstances, componentInstances, 'uniqueId');
+ }
+
+ public updateInstance = (instance: ComponentInstance) => {
+ this.componentInstances = this.componentInstances.map(componentInstance => instance.uniqueId === componentInstance.uniqueId? instance : componentInstance);
+ }
+
+ public deleteComponentInstance(instanceToDelete: string) {
+ this.componentInstances = _.filter(this.componentInstances, (instance: ComponentInstance) => {
+ return instance.uniqueId !== instanceToDelete;
+ });
+ }
+
+ //----------------------------SELECTED COMPONENT -----------------------//
+
+ public setSelectedComponentType = (selectedType: SelectedComponentType) => {
+ this.selectedComponentType = selectedType;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/common/store/graph.actions.ts b/catalog-ui/src/app/ng2/pages/composition/common/store/graph.actions.ts
new file mode 100644
index 0000000..9bd5d0d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/common/store/graph.actions.ts
@@ -0,0 +1,33 @@
+export enum SelectedComponentType {
+ COMPONENT_INSTANCE = "COMPONENT_INSTANCE",
+ GROUP = "GROUP",
+ POLICY = "POLICY",
+ TOPOLOGY_TEMPLATE = "TOPOLOGY_TEMPLATE"
+}
+
+export class UpdateSelectedComponentAction {
+ static readonly type = '[COMPOSITION] UpdateSelectedComponent';
+
+ constructor(public payload: {uniqueId?: string, type?: string}) {
+ }
+}
+
+export class SetSelectedComponentAction {
+ static readonly type = '[COMPOSITION] SetSelectedComponent';
+
+ constructor(public payload: {component?: any, type?: SelectedComponentType}) {
+ }
+}
+
+export class OnSidebarOpenOrCloseAction {
+ static readonly type = '[COMPOSITION] OnSidebarOpenOrCloseAction';
+
+ constructor() {
+ }
+}
+
+export class TogglePanelLoadingAction {
+ static readonly type = '[COMPOSITION] TogglePanelLoading';
+ constructor(public payload: { isLoading: boolean}) {
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/common/store/graph.state.ts b/catalog-ui/src/app/ng2/pages/composition/common/store/graph.state.ts
new file mode 100644
index 0000000..d58bb44
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/common/store/graph.state.ts
@@ -0,0 +1,170 @@
+import { Action, Selector, State, StateContext} from '@ngxs/store';
+import {
+ OnSidebarOpenOrCloseAction,
+ SelectedComponentType,
+ SetSelectedComponentAction,
+ TogglePanelLoadingAction
+} from "./graph.actions";
+import { PolicyInstance, GroupInstance, Component as TopologyTemplate, ComponentInstance, LeftPaletteComponent, FullComponentInstance} from "app/models";
+import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service";
+import { tap } from "rxjs/operators";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import {GroupsService} from "../../../../services/groups.service";
+import {PoliciesService} from "../../../../services/policies.service";
+import {WorkspaceService} from "../../../workspace/workspace.service";
+
+export class CompositionStateModel {
+
+ isViewOnly?: boolean;
+ panelLoading?: boolean;
+ selectedComponentType?: SelectedComponentType;
+ selectedComponent?: PolicyInstance | GroupInstance | TopologyTemplate | ComponentInstance;
+ withSidebar?: boolean;
+}
+
+@State<CompositionStateModel>({
+ name: 'composition',
+ defaults: {
+ withSidebar: true
+ }
+})
+export class GraphState {
+
+ constructor(private topologyTemplateService: TopologyTemplateService,
+ private compositionService: CompositionService,
+ private policiesService:PoliciesService, private groupsService:GroupsService,
+ private workspaceService: WorkspaceService) {}
+
+ @Action(SetSelectedComponentAction)
+ setSelectedComponent({dispatch, getState, patchState}:StateContext<CompositionStateModel>, action: SetSelectedComponentAction) {
+
+ const state:CompositionStateModel = getState();
+
+ patchState({ panelLoading: true });
+
+ if(action.payload.component instanceof ComponentInstance){
+ let originComponent = this.compositionService.getOriginComponentById(action.payload.component.getComponentUid());
+ if(!originComponent) {
+ return this.topologyTemplateService.getFullComponent(action.payload.component.originType, action.payload.component.getComponentUid())
+ .pipe(tap(resp => {
+ this.compositionService.addOriginComponent(resp);
+ this.compositionService.setSelectedComponentType(SelectedComponentType.COMPONENT_INSTANCE);
+ patchState({
+ selectedComponent: new FullComponentInstance(action.payload.component, resp),
+ selectedComponentType: action.payload.type,
+ panelLoading: false
+ });
+ }, err => {
+ patchState({
+ panelLoading: false
+ })
+ }
+ ));
+ } else {
+ patchState({
+ selectedComponent: new FullComponentInstance(action.payload.component, originComponent),
+ selectedComponentType: action.payload.type,
+ panelLoading: false
+ });
+ }
+ } else if (action.payload.component instanceof PolicyInstance) {
+ let topologyTemplate = this.workspaceService.metadata;
+ return this.policiesService.getSpecificPolicy(topologyTemplate.componentType, topologyTemplate.uniqueId, action.payload.component.uniqueId).pipe(tap(resp =>
+ {
+ this.compositionService.updatePolicy(resp);
+ patchState({
+ selectedComponent: resp,
+ selectedComponentType: action.payload.type,
+ panelLoading: false
+ })
+ }, err => {
+ patchState({
+ panelLoading: false
+ })
+ }
+ ));
+
+ } else if (action.payload.component instanceof GroupInstance) {
+ let topologyTemplate = this.workspaceService.metadata;
+ return this.groupsService.getSpecificGroup(topologyTemplate.componentType, topologyTemplate.uniqueId, action.payload.component.uniqueId).pipe(tap(resp => {
+ this.compositionService.updateGroup(resp);
+ patchState({
+ selectedComponent: resp,
+ selectedComponentType: action.payload.type,
+ panelLoading: false
+ });
+ }, err => {
+ patchState({
+ panelLoading: false
+ })
+ }
+ ));
+ } else { //TopologyTemplate
+ patchState({
+ selectedComponent: action.payload.component,
+ selectedComponentType: action.payload.type,
+ panelLoading: false
+ })
+ }
+ }
+
+
+ // @Action(UpdateSelectedComponentNameAction)
+ // UpdateSelectedComponentNameAction({patchState}:StateContext<CompositionStateModel>, action: UpdateSelectedComponentNameAction) {
+
+ // switch(action.payload.type){
+ // case SelectedComponentType.COMPONENT_INSTANCE:
+ // this.store.dispatch(new UpdateComponentInstancesAction([action.payload.component]));
+ // break;
+ // case SelectedComponentType.POLICY:
+ // this.store.dispatch(new UpdatePolicyNameAction(action.payload.uniqueId, action.payload.newName));
+ // break;
+ // case SelectedComponentType.GROUP:
+ // this.store.dispatch(new UpdateGroupInstancesAction)
+
+ // }
+ // if(action.payload.type === SelectedComponentType.COMPONENT_INSTANCE){
+
+ // }
+
+ // }
+
+ @Selector()
+ static getSelectedComponent(state:CompositionStateModel) {
+ return state.selectedComponent;
+ }
+
+ @Selector()
+ static getSelectedComponentId(state:CompositionStateModel) {
+ return state.selectedComponent.uniqueId;
+ }
+
+ @Selector()
+ static getSelectedComponentType(state:CompositionStateModel) {
+ return state.selectedComponentType;
+ }
+
+
+ @Action(OnSidebarOpenOrCloseAction)
+ onSidebarOpenOrCloseAction({getState, setState}:StateContext<CompositionStateModel>) {
+ const state:CompositionStateModel = getState();
+
+ setState({
+ ...state,
+ withSidebar: !state.withSidebar
+ });
+ }
+
+ @Action(TogglePanelLoadingAction)
+ TogglePanelLoading({patchState}:StateContext<CompositionStateModel>, action: TogglePanelLoadingAction) {
+
+ patchState({
+ panelLoading: action.payload.isLoading
+ });
+ }
+
+ @Selector() static withSidebar(state):boolean {
+ return state.withSidebar;
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/composition-page.component.html b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.html
new file mode 100644
index 0000000..e1851d5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.html
@@ -0,0 +1,8 @@
+<div class="workspace-composition-page">
+ <div class="composition-graph">
+ <composition-palette></composition-palette>
+ <app-palette-popup-panel></app-palette-popup-panel>
+ <composition-graph dndDropzone [dndAllowExternal]=true [topologyTemplate]="topologyTemplate" [testId]="'canvas'"></composition-graph>
+ <ng2-composition-panel [topologyTemplate]="topologyTemplate"></ng2-composition-panel>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/composition-page.component.less b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.less
new file mode 100644
index 0000000..a80333e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.less
@@ -0,0 +1,26 @@
+@import "./../../../../assets/styles/override";
+.workspace-composition-page {
+ height:100%;
+ display: block;
+ text-align: left;
+ align-items: left;
+ padding: 0;
+
+ .composition-graph {
+ height:100%;
+ background-color: @sdcui_color_white;
+ bottom: 0;
+ display:flex;
+ flex-direction: row;
+
+ .view-mode{
+ background-color: #f8f8f8;
+ border:0;
+ }
+ }
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/composition-page.component.ts b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.ts
new file mode 100644
index 0000000..ed1b82e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/composition-page.component.ts
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
+import { Component as TopologyTemplate } from 'app/models';
+import * as Constants from 'constants';
+import { EventListenerService } from '../../../services/event-listener-service';
+import { EVENTS } from '../../../utils';
+
+@Component({
+ templateUrl: './composition-page.component.html',
+ styleUrls: ['composition-page.component.less']
+})
+export class CompositionPageComponent implements OnInit, OnDestroy {
+
+ private topologyTemplate: TopologyTemplate;
+
+ constructor(@Inject('$stateParams') private stateParams, private eventListenerService: EventListenerService) {
+ this.topologyTemplate = stateParams.component;
+ }
+
+ ngOnInit(): void {
+ this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, (comp) => {
+ this.topologyTemplate = comp;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.eventListenerService.unRegisterObserver(EVENTS.ON_CHECKOUT);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/composition-page.module.ts b/catalog-ui/src/app/ng2/pages/composition/composition-page.module.ts
new file mode 100644
index 0000000..d0ca05b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/composition-page.module.ts
@@ -0,0 +1,30 @@
+/**
+ * Created by ob0695 on 6/4/2018.
+ */
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {CompositionGraphModule} from "./graph/composition-graph.module";
+import {CompositionPageComponent} from "./composition-page.component";
+import {NgxsModule} from "@ngxs/store";
+import {PaletteModule} from "./palette/palette.module";
+import {PalettePopupPanelComponent} from "./palette/palette-popup-panel/palette-popup-panel.component";
+import { CompositionPanelModule } from "app/ng2/pages/composition/panel/composition-panel.module";
+import {CompositionService} from "./composition.service";
+import {DndModule} from "ngx-drag-drop";
+import {GraphState} from "./common/store/graph.state";
+
+@NgModule({
+ declarations: [CompositionPageComponent, PalettePopupPanelComponent],
+ imports: [CommonModule,
+ CompositionGraphModule,
+ CompositionPanelModule,
+ PaletteModule,
+ DndModule,
+ NgxsModule.forFeature([
+ GraphState])],
+ exports: [CompositionPageComponent],
+ entryComponents: [CompositionPageComponent],
+ providers: [CompositionService]
+})
+export class CompositionPageModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/composition.service.ts b/catalog-ui/src/app/ng2/pages/composition/composition.service.ts
new file mode 100644
index 0000000..e5e9d2d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/composition.service.ts
@@ -0,0 +1,59 @@
+import {Injectable} from "@angular/core";
+import 'rxjs/add/observable/forkJoin';
+import {Component, PropertiesGroup, AttributesGroup, PolicyInstance} from "app/models";
+import {GroupInstance} from "app/models/graph/zones/group-instance";
+import {CommonGraphDataService} from "./common/common-graph-data.service";
+import {ForwardingPath} from "../../../models/forwarding-path";
+import {SelectedComponentType} from "./common/store/graph.actions";
+
+@Injectable()
+export class CompositionService extends CommonGraphDataService{
+
+ public originComponents: Array<Component>; //This contains the full data set after specifically requesting it. The uniqueId matches the 'componentUid' in the componentInstances array
+ public componentInstancesProperties:PropertiesGroup;
+ public componentInstancesAttributes:AttributesGroup;
+ public groupInstances: GroupInstance[];
+ public policies: PolicyInstance[];
+ public forwardingPaths: { [key:string]:ForwardingPath };
+ public selectedComponentType: SelectedComponentType;
+
+ //---------------------------- COMPONENT INSTANCES ------------------------------------//
+
+ public getOriginComponentById = (uniqueId:string):Component => {
+ return this.originComponents && this.originComponents.find(instance => instance.uniqueId === uniqueId);
+ }
+
+ public addOriginComponent = (originComponent:Component) => {
+ if(!this.originComponents) this.originComponents = [];
+ if(!this.getOriginComponentById(originComponent.uniqueId)){
+ this.originComponents.push(originComponent);
+ }
+ }
+
+
+ public updateGroup = (instance: GroupInstance) => {
+ this.groupInstances = this.groupInstances.map(group => instance.uniqueId === group.uniqueId? instance : group);
+ }
+
+ public updatePolicy = (instance: PolicyInstance) => {
+ this.policies = this.policies.map(policy => instance.uniqueId === policy.uniqueId? instance : policy);
+ }
+
+ //---------------------------- POLICIES---------------------------------//
+ public addPolicyInstance = (instance: PolicyInstance) => {
+ return this.policies.push(instance);
+ }
+
+
+ //---------------------------- POLICIES---------------------------------//
+ public addGroupInstance = (instance: GroupInstance) => {
+ return this.groupInstances.push(instance);
+ }
+
+
+ //----------------------------SELECTED COMPONENT -----------------------//
+
+ public setSelectedComponentType = (selectedType: SelectedComponentType) => {
+ this.selectedComponentType = selectedType;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html
new file mode 100644
index 0000000..4a163ee
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html
@@ -0,0 +1 @@
+<div class="sdc-deployment-graph-wrapper"></div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less
new file mode 100644
index 0000000..9b80fcd65
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less
@@ -0,0 +1,13 @@
+.sdc-deployment-graph-wrapper {
+ height: 100%;
+ width: 100%;
+
+ ::ng-deep canvas {
+ /*canvas z-index is initialized to 999 while top-nav z-Index is 10, which makes top-nav disappear, so z-Index must be overwritten here*/
+ z-index: 10 !important;
+ }
+ }
+
+::ng-deep .sdc-workspace-container .w-sdc-main-right-container .w-sdc-main-container-body-content.deploy-body-content{
+ padding: 0px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts
new file mode 100644
index 0000000..823086f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts
@@ -0,0 +1,92 @@
+import {async, ComponentFixture} from '@angular/core/testing';
+import 'jest-dom/extend-expect';
+import {DeploymentGraphComponent} from "./deployment-graph.component";
+import {DeploymentGraphService} from "./deployment-graph.service";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import * as cytoscape from "cytoscape/dist/cytoscape"
+import {AngularJSBridge} from "../../../../services/angular-js-bridge-service";
+import {NodesFactory} from "../../../../models/graph/nodes/nodes-factory";
+import {CommonGraphUtils} from "../graph/common/common-graph-utils";
+import {groupsMock} from "../../../../../jest/mocks/groups.mock";
+import {Module} from "../../../../models/modules/base-module";
+import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
+import {componentInstancesMock} from "../../../../../jest/mocks/component-instance.mock";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../../workspace/workspace.service";
+import {SdcConfigToken} from "../../../config/sdc-config.config";
+import {CompositionGraphLinkUtils} from "../graph/utils";
+
+describe('DeploymentGraphComponent', () => {
+
+ let fixture: ComponentFixture<DeploymentGraphComponent>;
+ let deploymentGraphServiceMock: Partial<DeploymentGraphService>;
+ let nodeFactoryServiceMock: Partial<NodesFactory>;
+ let commonGraphUtilsServiceMock: Partial<CommonGraphUtils>;
+ let angularJsBridgeServiceMock: Partial<AngularJSBridge>;
+ let sdcConfigTokenMock: Partial<AngularJSBridge>;
+
+ beforeEach(
+ async(() => {
+
+ deploymentGraphServiceMock = {
+ modules: <Array<Module>>groupsMock,
+ componentInstances: <Array<ComponentInstance>>componentInstancesMock
+ }
+
+ nodeFactoryServiceMock = {
+ createModuleNode: jest.fn().mockResolvedValue(() => {
+ }),
+ createNode: jest.fn().mockResolvedValue(() => {
+ })
+ }
+
+ commonGraphUtilsServiceMock = {
+ addNodeToGraph: jest.fn(),
+ addComponentInstanceNodeToGraph: jest.fn()
+ }
+
+ sdcConfigTokenMock = {
+ imagePath: ''
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [DeploymentGraphComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: DeploymentGraphService, useValue: deploymentGraphServiceMock},
+ {provide: NodesFactory, useValue: nodeFactoryServiceMock},
+ {provide: TopologyTemplateService, useValue: {}},
+ {provide: WorkspaceService, useValue: {}},
+ {provide: CommonGraphUtils, useValue: commonGraphUtilsServiceMock},
+ {provide: CompositionGraphLinkUtils, useValue: {}},
+ {provide: AngularJSBridge, useValue: angularJsBridgeServiceMock},
+ {provide: SdcConfigToken, useValue: SdcConfigToken}
+ ]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(DeploymentGraphComponent);
+ });
+ })
+ );
+
+ it('expected deployment graph component to be defined', () => {
+ expect(fixture).toBeDefined();
+ });
+
+
+ it('expected to addNodeToGraph to haveBeenCalled 6 times out of 7 cause one of the instances have no parent module', () => {
+ fixture.componentInstance._cy = cytoscape({
+ zoomingEnabled: false,
+ selectionType: 'single',
+ });
+ jest.spyOn(fixture.componentInstance, 'findInstanceModule');
+ fixture.componentInstance.initGraphComponentInstances();
+ expect(fixture.componentInstance.findInstanceModule).toHaveBeenCalledTimes(7);
+ expect(commonGraphUtilsServiceMock.addComponentInstanceNodeToGraph).toHaveBeenCalledTimes(6);
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts
new file mode 100644
index 0000000..143a759
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts
@@ -0,0 +1,127 @@
+import {Component, ElementRef, Inject, OnInit} from "@angular/core";
+import {DeploymentGraphService} from "./deployment-graph.service";
+import '@bardit/cytoscape-expand-collapse';
+import * as _ from "lodash";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../../workspace/workspace.service";
+import {NodesFactory} from "../../../../models/graph/nodes/nodes-factory";
+import {CommonGraphUtils} from "../graph/common/common-graph-utils";
+import {ISdcConfig, SdcConfigToken} from "../../../config/sdc-config.config";
+import {Module} from "../../../../models/modules/base-module";
+import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
+import {ComponentGenericResponse} from "../../../services/responses/component-generic-response";
+import {ComponentInstanceFactory} from "../../../../utils/component-instance-factory";
+import {ModulesNodesStyle} from "../graph/common/style/module-node-style";
+import {ComponentInstanceNodesStyle} from "../graph/common/style/component-instances-nodes-style";
+import {CompositionGraphLinkUtils} from "../graph/utils/composition-graph-links-utils";
+
+@Component({
+ selector: 'deployment-graph',
+ templateUrl: './deployment-graph.component.html',
+ styleUrls: ['./deployment-graph.component.less']
+})
+
+export class DeploymentGraphComponent implements OnInit {
+ constructor(private elRef: ElementRef,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private deploymentService: DeploymentGraphService,
+ private commonGraphUtils: CommonGraphUtils,
+ private nodeFactory: NodesFactory,
+ private commonGraphLinkUtils: CompositionGraphLinkUtils,
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig) {
+
+ }
+
+ public _cy: Cy.Instance;
+
+ ngOnInit(): void {
+ this.topologyTemplateService.getDeploymentGraphData(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId).subscribe((response: ComponentGenericResponse) => {
+ this.deploymentService.componentInstances = response.componentInstances;
+ this.deploymentService.componentInstancesRelations = response.componentInstancesRelations;
+ this.deploymentService.modules = response.modules;
+ this.loadGraph();
+ });
+ }
+
+ public findInstanceModule = (groupsArray: Array<Module>, componentInstanceId: string): string => {
+ let parentGroup: Module = _.find(groupsArray, (group: Module) => {
+ return _.find(_.values(group.members), (member: string) => {
+ return member === componentInstanceId;
+ });
+ });
+ return parentGroup ? parentGroup.uniqueId : "";
+ };
+
+ public initGraphModules = () => {
+ if (this.deploymentService.modules) { // Init module nodes
+ _.each(this.deploymentService.modules, (groupModule: Module) => {
+ let moduleNode = this.nodeFactory.createModuleNode(groupModule);
+ this.commonGraphUtils.addNodeToGraph(this._cy, moduleNode);
+ });
+ }
+ }
+
+ public initGraphComponentInstances = () => {
+ _.each(this.deploymentService.componentInstances, (instance: ComponentInstance) => { // Init component instance nodes
+ let componentInstanceNode = this.nodeFactory.createNode(instance);
+ componentInstanceNode.parent = this.findInstanceModule(this.deploymentService.modules, instance.uniqueId);
+ if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module
+ this.commonGraphUtils.addComponentInstanceNodeToGraph(this._cy, componentInstanceNode);
+ }
+ });
+ }
+
+ public handleEmptyModule = () => {
+ // This is a special functionality to pass the cytoscape default behavior - we can't create Parent module node without children's
+ // so we must add an empty dummy child node
+ _.each(this._cy.nodes('[?isGroup]'), (moduleNode: Cy.CollectionFirstNode) => {
+ if (!moduleNode.isParent()) {
+ let dummyInstance = ComponentInstanceFactory.createEmptyComponentInstance();
+ let componentInstanceNode = this.nodeFactory.createNode(dummyInstance);
+ componentInstanceNode.parent = moduleNode.id();
+ let dummyNode = this.commonGraphUtils.addNodeToGraph(this._cy, componentInstanceNode, moduleNode.position());
+ dummyNode.addClass('dummy-node');
+ }
+ })
+ }
+
+ public initGraphNodes = (): void => {
+ this.initGraphModules();
+ this.initGraphComponentInstances();
+ this.handleEmptyModule();
+ };
+
+ private loadGraph = () => {
+
+ let graphEl = this.elRef.nativeElement.querySelector('.sdc-deployment-graph-wrapper');
+ this._cy = cytoscape({
+ container: graphEl,
+ style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()),
+ zoomingEnabled: false,
+ selectionType: 'single',
+
+ });
+
+ //adding expand collapse extension
+ this._cy.expandCollapse({
+ layoutBy: {
+ name: "grid",
+ animate: true,
+ randomize: false,
+ fit: true
+ },
+ fisheye: false,
+ undoable: false,
+ expandCollapseCueSize: 18,
+ expandCueImage: this.sdcConfig.imagesPath + '/assets/styles/images/resource-icons/' + 'closeModule.png',
+ collapseCueImage: this.sdcConfig.imagesPath + '/assets/styles/images/resource-icons/' + 'openModule.png',
+ expandCollapseCueSensitivity: 2,
+ cueOffset: -20
+ });
+
+ this.initGraphNodes(); //creating instances nodes
+ this.commonGraphLinkUtils.initGraphLinks(this._cy, this.deploymentService.componentInstancesRelations);
+ this._cy.collapseAll();
+ };
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts
new file mode 100644
index 0000000..91f97db
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts
@@ -0,0 +1,15 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {DeploymentGraphComponent} from "./deployment-graph.component";
+
+@NgModule({
+ declarations: [DeploymentGraphComponent],
+ imports: [CommonModule],
+ exports: [DeploymentGraphComponent],
+ entryComponents: [DeploymentGraphComponent],
+ providers: [
+
+ ]
+})
+export class DeploymentGraphModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts
new file mode 100644
index 0000000..7ec346c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts
@@ -0,0 +1,8 @@
+import {Injectable} from "@angular/core";
+import 'rxjs/add/observable/forkJoin';
+import {CommonGraphDataService} from "../common/common-graph-data.service";
+import {Module} from "../../../../models/modules/base-module";
+@Injectable()
+export class DeploymentGraphService extends CommonGraphDataService {
+ public modules:Array<Module>;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.html
new file mode 100644
index 0000000..a8645dc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.html
@@ -0,0 +1,23 @@
+<div class="canvas-search-component" [ngClass]="{'results-shown': autoCompleteResults.length}"
+ [class.canvas-search-visible]="autoCompleteValues && autoCompleteValues.length" [attr.data-tests-id]="testId">
+ <div class="canvas-search-bar-container" [attr.data-tests-id]="testId"
+ [class.active]="searchQuery && searchQuery.length">
+ <sdc-search-bar class="canvas-search-bar"
+ [placeHolder]="placeholder"
+ (onSearchClicked)="onSearchClicked($event)"
+ [size]="'medium'"
+ [value]="searchQuery"
+ (valueChange)="onSearchQueryChanged($event)">
+ </sdc-search-bar>
+ <svg-icon class="canvas-clear-search"
+ [name]="'close'"
+ [clickable]="true"
+ [mode]="'secondary'"
+ [size]="'small'"
+ (click)="onClearSearch()">
+ </svg-icon>
+ </div>
+ <dropdown-results *ngIf="autoCompleteResults && autoCompleteResults.length" [options]="autoCompleteResults"
+ (onItemSelected)="onItemSelected($event)"></dropdown-results>
+</div>
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.less
new file mode 100644
index 0000000..247f2a3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.less
@@ -0,0 +1,42 @@
+.canvas-search-component {
+
+ .canvas-search-bar-container {
+ display:flex;
+ border-radius: 4px;
+ align-items: center;
+ box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
+
+ /deep/.sdc-search-bar .search-bar-container .search-button {
+ border: solid 1px #d2d2d2;
+ }
+
+ /deep/.sdc-input__input {
+ width: 250px;
+ transition: all 0.4s;
+ }
+
+ .canvas-clear-search {
+ position: absolute;
+ right: 45px;
+ }
+ }
+
+ &:not(:hover):not(.canvas-search-visible):not(.active) {
+ border-radius: 0;
+ box-shadow: none;
+
+ /deep/.sdc-input__input:not(:focus) {
+ border: none;
+ padding: 0px;
+ width: 0px;
+ }
+ .canvas-clear-search {
+ display: none;
+ }
+ }
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.ts
new file mode 100644
index 0000000..c1a45a9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.component.ts
@@ -0,0 +1,25 @@
+import {Component, EventEmitter, Input, Output} from '@angular/core';
+import {AutoCompleteComponent} from "onap-ui-angular/dist/autocomplete/autocomplete.component";
+
+@Component({
+ selector: 'canvas-search',
+ templateUrl: './canvas-search.component.html',
+ styleUrls: ['./canvas-search.component.less']
+})
+export class CanvasSearchComponent extends AutoCompleteComponent {
+
+ @Output() public searchButtonClicked: EventEmitter<string> = new EventEmitter<string>();
+ @Output() public onSelectedItem: EventEmitter<string> = new EventEmitter<string>();
+
+ public onSearchClicked = (searchText:string)=> {
+ this.searchButtonClicked.emit(searchText);
+ }
+
+ public onItemSelected = (selectedItem) => {
+ this.searchQuery = selectedItem.value;
+ this.autoCompleteResults = [];
+ this.searchButtonClicked.emit(this.searchQuery);
+ this.onSelectedItem.emit(selectedItem);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.module.ts
new file mode 100644
index 0000000..6df0606
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-search/canvas-search.module.ts
@@ -0,0 +1,30 @@
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import { NgModule } from "@angular/core";
+import {CanvasSearchComponent} from "./canvas-search.component";
+import {CommonModule} from "@angular/common";
+import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
+import {HttpClientModule} from "@angular/common/http";
+import {BrowserModule} from "@angular/platform-browser";
+import {AutocompletePipe} from "onap-ui-angular/dist/autocomplete/autocomplete.pipe";
+
+@NgModule({
+ declarations: [
+ CanvasSearchComponent
+ ],
+ imports: [
+ CommonModule,
+ BrowserModule,
+ HttpClientModule,
+ BrowserAnimationsModule,
+ SdcUiComponentsModule,
+ ],
+ exports: [
+ CanvasSearchComponent
+ ],
+ entryComponents: [
+ CanvasSearchComponent
+ ],
+ providers: [AutocompletePipe]
+})
+export class CanvasSearchModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/__snapshots__/zone-container.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/__snapshots__/zone-container.component.spec.ts.snap
new file mode 100644
index 0000000..d4e2a7a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/__snapshots__/zone-container.component.spec.ts.snap
@@ -0,0 +1,35 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ZoneContainerComponent should match current snapshot of palette element component 1`] = `
+<zone-container
+ backgroundClick={[Function EventEmitter]}
+ backgroundClicked={[Function Function]}
+ minimize={[Function EventEmitter]}
+ unminifyZone={[Function Function]}
+>
+ <div>
+ <div
+ class="sdc-canvas-zone__header"
+ >
+ <div
+ class="sdc-canvas-zone__title"
+ >
+
+ <span
+ class="sdc-canvas-zone__counter"
+ >
+
+ </span>
+ </div>
+ <span
+ class="sdc-canvas-zone__state-button"
+ >
+ –
+ </span>
+ </div>
+ <div
+ class="sdc-canvas-zone__container"
+ />
+ </div>
+</zone-container>
+`;
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.html
similarity index 82%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.html
index 50a93fa..d6343a4 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.html
@@ -15,14 +15,16 @@
-->
-<div class="sdc-canvas-zone {{class}}-zone" [class.minimized]="minimized" [class.hidden]="!visible" (click)="backgroundClicked()">
- <div class="sdc-canvas-zone__header" (click)="unminifyZone(); $event.stopPropagation();" >
- <div class="sdc-canvas-zone__title">{{title}}
+<div class="sdc-canvas-zone {{class}}-zone" [class.minimized]="minimized" [class.hidden]="!visible"
+ (click)="backgroundClicked()">
+ <div class="sdc-canvas-zone__header" (click)="unminifyZone(); $event.stopPropagation();">
+ <div class="sdc-canvas-zone__title">{{title}}
<span class="sdc-canvas-zone__counter">{{count}}</span>
</div>
<span class="sdc-canvas-zone__state-button">–</span>
</div>
- <div class="sdc-canvas-zone__container" #scrollDiv >
+ <div class="sdc-canvas-zone__container" #scrollDiv>
<ng-content></ng-content>
</div>
-</div>
\ No newline at end of file
+</div>
+
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.less
similarity index 97%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.less
index 02880a9..827786c 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.less
@@ -3,12 +3,12 @@
max-height:186px;
display:flex;
flex-direction:column;
- align-self: flex-end;
color:white;
font-family:OpenSans-Regular, sans-serif;
transition: width .2s ease-in-out, max-height .2s ease-in-out .1s;
position:relative;
bottom:0px;
+ margin-right: 5px;
.sdc-canvas-zone__header {
background: #5A5A5A;
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.spec.ts
new file mode 100644
index 0000000..c432054
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.spec.ts
@@ -0,0 +1,46 @@
+import {async, ComponentFixture} from '@angular/core/testing';
+import {By} from '@angular/platform-browser';
+import {ConfigureFn, configureTests} from '../../../../../../jest/test-config.helper';
+import 'jest-dom/extend-expect';
+import {ZoneInstanceType} from '../../../../../../app/models/graph/zones/zone-instance';
+import {ZoneContainerComponent} from './zone-container.component';
+
+
+describe('ZoneContainerComponent', () => {
+ let fixture: ComponentFixture<ZoneContainerComponent>;
+
+ beforeEach(
+ async(() => {
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [ZoneContainerComponent]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(ZoneContainerComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot of palette element component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should have a group-zone class when the ZoneInstanceType is GROUP',
+ () => {
+ fixture.componentInstance.type = ZoneInstanceType.GROUP;
+ fixture.detectChanges();
+ const compiled = fixture.debugElement.query(By.css('.sdc-canvas-zone'));
+ expect(compiled.nativeElement).toHaveClass('group-zone');
+ });
+
+ it('should have a policy-zone class when the ZoneInstanceType is POLICY',
+ () => {
+ fixture.componentInstance.type = ZoneInstanceType.POLICY;
+ fixture.detectChanges();
+ const compiled = fixture.debugElement.query(By.css('.sdc-canvas-zone'));
+ expect(compiled.nativeElement).toHaveClass('policy-zone');
+ });
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.ts
similarity index 91%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.ts
index 4059ad6..4757c1f 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-container.component.ts
@@ -1,5 +1,5 @@
import { Component, Input, Output, ViewEncapsulation, EventEmitter, OnInit } from '@angular/core';
-import { ZoneInstanceType } from '../../../../models/graph/zones/zone-instance';
+import { ZoneInstanceType } from 'app/models/graph/zones/zone-instance';
@Component({
selector: 'zone-container',
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.html
similarity index 61%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.html
index 728764c..d97be69 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.html
@@ -12,15 +12,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-
-
-<div tooltip="{{zoneInstance.instanceData.name}}" #currentComponent
- class="zone-instance mode-{{zoneInstance.mode}}" [class.locked]="activeInstanceMode > MODE.HOVER" [class.hiding]="hidden"
+
+
+<div #currentComponent class="zone-instance mode-{{zoneInstance.mode}}" [class.locked]="activeInstanceMode > MODE.HOVER"
+ [class.hiding]="hidden"
(mouseenter)="setMode(MODE.HOVER)" (mouseleave)="setMode(MODE.NONE)" (click)="setMode(MODE.SELECTED, $event)">
- <div *ngIf="zoneInstance.handle" class="target-handle {{zoneInstance.handle}}" (click)="tagHandleClicked($event)"></div>
+ <div class="zone-instance__body" sdc-tooltip tooltip-text="{{zoneInstance.instanceData.name}}" [attr.data-tests-id]="zoneInstance.instanceData.name">
+ <div *ngIf="zoneInstance.handle" class="target-handle {{zoneInstance.handle}}"
+ (click)="tagHandleClicked($event)"></div>
<div *ngIf="!isViewOnly" class="zone-instance__handle" (click)="setMode(MODE.TAG, $event)">+</div>
- <div class="zone-instance__body">
- <div class="zone-instance__body-content">{{zoneInstance.assignments.length || defaultIconText}}</div>
- </div>
- <div class="zone-instance__name">{{zoneInstance.instanceData.name}}</div>
-</div>
\ No newline at end of file
+ <div class="zone-instance__body-content">{{zoneInstance.assignments.length || defaultIconText}}</div>
+ </div>
+ <div class="zone-instance__name">{{zoneInstance.instanceData.name}}</div>
+</div>
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.less
similarity index 82%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.less
index b562c08..c34b8e1 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.less
@@ -1,7 +1,7 @@
-@import '../../../../../../assets/styles/variables';
+@import '../../../../../../../assets/styles/variables';
.zone-instance {
- position:relative;
+
width:76px;
margin:5px;
opacity:1;
@@ -9,8 +9,8 @@
.zone-instance__handle {
display:none;
position:absolute;
- right:4px;
- top:10px;
+ left: 31px;
+ top: 8px;
width:22px;
height:22px;
cursor:pointer;
@@ -21,6 +21,7 @@
}
.zone-instance__body {
+ position:relative;
margin:0 auto;
width:43px;
height:43px;
@@ -55,16 +56,16 @@
height:18px;
display:block;
top: -4px;
- right: 10px;
+ right: -6px;
background-size: 100% 100%;
- cursor: url("../../../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer;
+ cursor: url("../../../../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer;
&.tagged-policy {
- background-image: url('../../../../../../assets/styles/images/canvas-tagging-icons/policy_added.svg');
+ background-image: url('../../../../../../../assets/styles/images/canvas-tagging-icons/policy_added.svg');
}
&.tag-available {
- background-image: url('../../../../../../assets/styles/images/canvas-tagging-icons/indication.svg');
+ background-image: url('../../../../../../../assets/styles/images/canvas-tagging-icons/indication.svg');
}
}
@@ -99,8 +100,8 @@
&.mode-3 .zone-instance__handle {
width:24px;
height:24px;
- right:3px;
- top:9px;
+ right:-6px;
+ top:7px;
display:block;
background-image: linear-gradient(-140deg, #009E98 0%, #97D648 100%);
border: 2px solid @main_color_p;
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.spec.ts
new file mode 100644
index 0000000..f5a5f6f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.spec.ts
@@ -0,0 +1,132 @@
+import { ComponentFixture, TestBed, async } from '@angular/core/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { SimpleChanges } from '@angular/core';
+import { PoliciesService } from 'app/ng2/services/policies.service';
+import { GroupsService } from 'app/ng2/services/groups.service';
+import { EventListenerService } from 'app/services';
+import { Store } from '@ngxs/store';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { ZoneInstanceComponent } from './zone-instance.component';
+import { ZoneInstanceType, ZoneInstance, ZoneInstanceMode, ZoneInstanceAssignmentType, IZoneInstanceAssignment } from "app/models";
+import { PolicyInstance } from "app/models/graph/zones/policy-instance";
+import { Subject, of } from 'rxjs';
+import { _throw } from 'rxjs/observable/throw';
+
+describe('ZoneInstanceComponent', () => {
+ let component: ZoneInstanceComponent;
+ let fixture: ComponentFixture<ZoneInstanceComponent>;
+
+ let createPolicyInstance = () => {
+ let policy = new PolicyInstance();
+ policy.targets = {COMPONENT_INSTANCES: [], GROUPS: []};
+ return new ZoneInstance(policy, '', '');
+ }
+
+ beforeEach(() => {
+ const policiesServiceStub = {updateZoneInstanceAssignments : jest.fn()};
+ const groupsServiceStub = {};
+ const eventListenerServiceStub = {};
+ const storeStub = {};
+ const compositionServiceStub = {};
+ TestBed.configureTestingModule({
+ schemas: [NO_ERRORS_SCHEMA],
+ declarations: [ZoneInstanceComponent],
+ providers: [
+ { provide: PoliciesService, useValue: policiesServiceStub },
+ { provide: GroupsService, useValue: groupsServiceStub },
+ { provide: EventListenerService, useValue: eventListenerServiceStub },
+ { provide: Store, useValue: storeStub },
+ { provide: CompositionService, useValue: compositionServiceStub }
+ ]
+ }).compileComponents().then(() => {
+ fixture = TestBed.createComponent(ZoneInstanceComponent);
+ component = fixture.componentInstance;
+ });
+ });
+
+ it('can load instance', async((done) => {
+ component.zoneInstance = <ZoneInstance>{type : ZoneInstanceType.POLICY, instanceData: {name: 'test policy'}, assignments: []};
+ component.forceSave = new Subject<Function>();
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ }));
+
+
+ it('if another instance is already tagging, i cannot change my mode', ()=> {
+ component.zoneInstance = <ZoneInstance>{ mode: ZoneInstanceMode.NONE };
+ component.isActive = false;
+ component.activeInstanceMode = ZoneInstanceMode.TAG;
+ component.setMode(ZoneInstanceMode.SELECTED);
+ expect(component.zoneInstance.mode).toBe(ZoneInstanceMode.NONE);
+ });
+
+ it('if i am active(selected) and NOT in tag mode, I can set another mode', ()=> {
+ component.isActive = true;
+ component.zoneInstance = <ZoneInstance>{ mode: ZoneInstanceMode.SELECTED };
+ jest.spyOn(component.modeChange, 'emit');
+ component.setMode(ZoneInstanceMode.NONE);
+ expect(component.modeChange.emit).toHaveBeenCalledWith({instance: component.zoneInstance, newMode: ZoneInstanceMode.NONE });
+ });
+
+ it('if i am active and in tag mode and i try to set mode other than tag, I am not allowed', ()=> {
+ component.isActive = true;
+ component.zoneInstance = <ZoneInstance>{ mode: ZoneInstanceMode.TAG };
+ component.setMode(ZoneInstanceMode.SELECTED);
+ expect(component.zoneInstance.mode).toBe(ZoneInstanceMode.TAG);
+ });
+
+ it('if i am active and in tag mode and click tag again and no changes, does NOT call save, but DOES turn tagging off', ()=> {
+ component.isActive = true;
+ component.zoneInstance = createPolicyInstance();
+ component.zoneService = component.policiesService;
+ component.zoneInstance.mode = ZoneInstanceMode.TAG;
+ jest.spyOn(component.zoneService, 'updateZoneInstanceAssignments');
+ jest.spyOn(component.modeChange, 'emit');
+
+ component.setMode(ZoneInstanceMode.TAG);
+
+ expect(component.zoneService.updateZoneInstanceAssignments).not.toHaveBeenCalled();
+ expect(component.modeChange.emit).toHaveBeenCalledWith({instance: component.zoneInstance, newMode: ZoneInstanceMode.NONE });
+
+ });
+ it('if i am active and in tag mode and click tag again and HAVE changes, calls save AND turns tagging off', ()=> {
+ component.isActive = true;
+ component.zoneInstance = createPolicyInstance();
+ component.zoneService = component.policiesService;
+ component.zoneInstance.mode = ZoneInstanceMode.TAG;
+ component.zoneInstance.assignments.push(<IZoneInstanceAssignment>{uniqueId: '123', type: ZoneInstanceAssignmentType.COMPONENT_INSTANCES});
+ jest.spyOn(component.zoneService, 'updateZoneInstanceAssignments').mockReturnValue(of(true));
+ jest.spyOn(component.modeChange, 'emit');
+
+ component.setMode(ZoneInstanceMode.TAG);
+
+ expect(component.zoneService.updateZoneInstanceAssignments).toHaveBeenCalled();
+ expect(component.modeChange.emit).toHaveBeenCalledWith({instance: component.zoneInstance, newMode: ZoneInstanceMode.NONE });
+ });
+
+ it('on save error, temporary assignment list is reverted to saved assignments', ()=> {
+ component.isActive = true;
+ component.zoneInstance = createPolicyInstance();
+ component.zoneService = component.policiesService;
+ component.zoneInstance.mode = ZoneInstanceMode.TAG;
+ component.zoneInstance.assignments.push(<IZoneInstanceAssignment>{uniqueId: '123', type: ZoneInstanceAssignmentType.COMPONENT_INSTANCES});
+ jest.spyOn(component.zoneService, 'updateZoneInstanceAssignments').mockReturnValue(_throw({status: 404}));
+
+ component.setMode(ZoneInstanceMode.TAG);
+
+ expect(component.zoneInstance.assignments.length).toEqual(0);
+ });
+
+ it('on save success, all changes are saved to zoneInstance.savedAssignments', ()=> {
+ component.isActive = true;
+ component.zoneInstance = createPolicyInstance();
+ component.zoneService = component.policiesService;
+ component.zoneInstance.mode = ZoneInstanceMode.TAG;
+ component.zoneInstance.assignments.push(<IZoneInstanceAssignment>{uniqueId: '123', type: ZoneInstanceAssignmentType.COMPONENT_INSTANCES});
+ jest.spyOn(component.zoneService, 'updateZoneInstanceAssignments').mockReturnValue(of(true));
+
+ component.setMode(ZoneInstanceMode.TAG);
+
+ expect(component.zoneInstance.instanceData.getSavedAssignments().length).toEqual(1);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
similarity index 70%
rename from catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
index 3c2dd45..1b1363e 100644
--- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
@@ -3,12 +3,17 @@
ZoneInstance, ZoneInstanceMode, ZoneInstanceType,
IZoneInstanceAssignment
} from 'app/models/graph/zones/zone-instance';
-import { PoliciesService } from '../../../../services/policies.service';
-import { GroupsService } from '../../../../services/groups.service';
-import { IZoneService } from "../../../../../models/graph/zones/zone";
+import { PoliciesService } from 'app/ng2/services/policies.service';
+import { GroupsService } from 'app/ng2/services/groups.service';
+import { IZoneService } from "app/models/graph/zones/zone";
import { EventListenerService } from 'app/services';
-import { GRAPH_EVENTS } from '../../../../../utils';
-import { Subject, Observable } from 'rxjs';
+import { GRAPH_EVENTS } from 'app/utils';
+import { Subject } from 'rxjs';
+import { Store } from "@ngxs/store";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { PolicyInstance } from "app/models";
+import {SelectedComponentType, SetSelectedComponentAction} from "../../../common/store/graph.actions";
+
@Component({
selector: 'zone-instance',
@@ -33,7 +38,7 @@
private MODE = ZoneInstanceMode;
private zoneService:IZoneService;
- constructor(private policiesService:PoliciesService, private groupsService:GroupsService, private eventListenerService:EventListenerService){}
+ constructor(private policiesService:PoliciesService, private groupsService:GroupsService, private eventListenerService:EventListenerService, private compositionService:CompositionService, private store:Store){}
ngOnInit(){
if(this.zoneInstance.type == ZoneInstanceType.POLICY){
@@ -41,9 +46,11 @@
} else {
this.zoneService = this.groupsService;
}
- this.forceSave.subscribe((afterSaveFunction:Function) => {
- this.setMode(ZoneInstanceMode.TAG, null, afterSaveFunction);
- })
+ if(this.forceSave) {
+ this.forceSave.subscribe((afterSaveFunction:Function) => {
+ this.setMode(ZoneInstanceMode.TAG, null, afterSaveFunction);
+ })
+ }
}
ngOnChanges(changes:SimpleChanges) {
@@ -53,7 +60,9 @@
}
ngOnDestroy() {
- this.forceSave.unsubscribe();
+ if(this.forceSave) {
+ this.forceSave.unsubscribe();
+ }
}
private setMode = (mode:ZoneInstanceMode, event?:any, afterSaveCallback?:Function):void => {
@@ -79,11 +88,17 @@
this.zoneService.updateZoneInstanceAssignments(this.zoneInstance.parentComponentType, this.zoneInstance.parentComponentID, this.zoneInstance.instanceData.uniqueId, this.zoneInstance.assignments).subscribe(
(success) => {
this.zoneInstance.instanceData.setSavedAssignments(this.zoneInstance.assignments);
- if(this.zoneInstance.type === ZoneInstanceType.POLICY){
+
+ if(this.zoneInstance.instanceData instanceof PolicyInstance){
+ this.compositionService.updatePolicy(this.zoneInstance.instanceData);
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, this.zoneInstance.instanceData);
+ this.store.dispatch(new SetSelectedComponentAction({component: this.zoneInstance.instanceData, type: SelectedComponentType.POLICY}));
} else {
+ this.compositionService.updateGroup(this.zoneInstance.instanceData);
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.zoneInstance.instanceData);
+ this.store.dispatch(new SetSelectedComponentAction({component: this.zoneInstance.instanceData, type: SelectedComponentType.GROUP}));
}
+
this.assignmentSaveComplete.emit(true);
if(afterSaveCallback) afterSaveCallback();
}, (error) => {
@@ -94,12 +109,15 @@
if(afterSaveCallback) afterSaveCallback();
}
this.modeChange.emit({newMode: ZoneInstanceMode.NONE, instance: this.zoneInstance});
+ // this.store.dispatch(new unsavedChangesActions.RemoveUnsavedChange(this.zoneInstance.instanceData.uniqueId));
+
} else {
this.modeChange.emit({newMode: mode, instance: this.zoneInstance});
+ if(mode == ZoneInstanceMode.TAG){
+ // this.store.dispatch(new unsavedChangesActions.AddUnsavedChange(this.zoneInstance.instanceData.uniqueId));
+ }
}
-
-
}
private tagHandleClicked = (event:Event) => {
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zones-module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zones-module.ts
new file mode 100644
index 0000000..3287c01
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zones-module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { ZoneContainerComponent } from "./zone-container.component";
+import { ZoneInstanceComponent } from "./zone-instance/zone-instance.component";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+
+@NgModule({
+ declarations: [ZoneContainerComponent, ZoneInstanceComponent],
+ imports: [CommonModule, SdcUiComponentsModule],
+ entryComponents: [ZoneContainerComponent, ZoneInstanceComponent],
+ exports: [ZoneContainerComponent, ZoneInstanceComponent],
+ providers: []
+})
+export class ZoneModules {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts
new file mode 100644
index 0000000..bfc540e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts
@@ -0,0 +1,304 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import {
+ CommonNodeBase,
+ Relationship,
+ CompositionCiNodeBase
+} from "app/models";
+import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
+import {Requirement, Capability} from "app/models";
+import {Injectable} from "@angular/core";
+
+
+
+@Injectable()
+export class CommonGraphUtils {
+
+ constructor() {
+
+ }
+
+ public safeApply = (scope:ng.IScope, fn:any) => { //todo remove to general utils
+ let phase = scope.$root.$$phase;
+ if (phase == '$apply' || phase == '$digest') {
+ if (fn && (typeof(fn) === 'function')) {
+ fn();
+ }
+ } else {
+ scope.$apply(fn);
+ }
+ };
+
+ /**
+ * Draw node on the graph
+ * @param cy
+ * @param compositionGraphNode
+ * @param position
+ * @returns {CollectionElements}
+ */
+ public addNodeToGraph(cy:Cy.Instance, compositionGraphNode:CommonNodeBase, position?:Cy.Position):Cy.CollectionElements {
+
+ let node = cy.add(<Cy.ElementDefinition> {
+ group: 'nodes',
+ position: position,
+ data: compositionGraphNode,
+ classes: compositionGraphNode.classes
+ });
+
+ this.initNodeTooltip(node);
+ return node;
+ };
+
+ /**
+ * The function will create a component instance node by the componentInstance position.
+ * If the node is UCPE the function will create all cp lan&wan for the ucpe
+ * @param cy
+ * @param compositionGraphNode
+ * @returns {Cy.CollectionElements}
+ */
+ public addComponentInstanceNodeToGraph(cy:Cy.Instance, compositionGraphNode:CompositionCiNodeBase):Cy.CollectionElements {
+
+ let nodePosition = {
+ x: +compositionGraphNode.componentInstance.posX,
+ y: +compositionGraphNode.componentInstance.posY
+ };
+
+ let node = this.addNodeToGraph(cy, compositionGraphNode, nodePosition);
+ return node;
+ };
+
+ /**
+ * Add service path link to graph - only draw the link
+ * @param cy
+ * @param link
+ */
+ public insertServicePathLinkToGraph = (cy:Cy.Instance, link:CompositionCiServicePathLink) => {
+ let linkElement = cy.add({
+ group: 'edges',
+ data: link,
+ classes: link.classes
+ });
+ this.initServicePathTooltip(linkElement, link);
+ };
+
+ /**
+ * Returns function for the link tooltip content
+ * @param {Relationship} linkRelation
+ * @param {Requirement} requirement
+ * @param {Capability} capability
+ * @returns {() => string}
+ * @private
+ */
+ private _getLinkTooltipContent(linkRelation:Relationship, requirement?:Requirement, capability?:Capability):string {
+ return '<div class="line">' +
+ '<span class="req-cap-label">R: </span>' +
+ '<span>' + (requirement ? requirement.getTitle() : linkRelation.relation.requirement) + '</span>' +
+ '</div>' +
+ '<div class="line">' +
+ '<div class="sprite-new link-tooltip-arrow"></div>' +
+ '<span class="req-cap-label">C: </span>' +
+ '<span>' + (capability ? capability.getTitle() : linkRelation.relation.capability) + '</span>' +
+ '</div>';
+ }
+
+ /**
+ * This function will init qtip tooltip on the link
+ * @param linkElement - the link we want the tooltip to apply on,
+ * @param link
+ * @param getLinkRequirementCapability
+ * link - the link obj
+ */
+ public initLinkTooltip(linkElement:Cy.CollectionElements, link:Relationship, getLinkRequirementCapability:Function) {
+ const content = () => this._getLinkTooltipContent(link); // base tooltip content without owner names
+ const render = (event, api) => {
+ // on render (called once at first show), get the link requirement and capability and change to full tooltip content (with owner names)
+ getLinkRequirementCapability().then((linkReqCap) => {
+ const fullContent = () => this._getLinkTooltipContent(link, linkReqCap.requirement, linkReqCap.capability);
+ api.set('content.text', fullContent);
+ });
+ };
+ linkElement.qtip(this.prepareInitTooltipData({content, events: {render}}));
+ };
+
+ /**
+ *
+ * @param linkElement
+ * @param link
+ */
+ public initServicePathTooltip(linkElement:Cy.CollectionElements, link:CompositionCiServicePathLink) {
+ let content = function () {
+ return '<div class="line">' +
+ '<div>' + link.pathName + '</div>' +
+ '</div>';
+ };
+ linkElement.qtip(this.prepareInitTooltipData({content}));
+ };
+
+ private prepareInitTooltipData(options?:Object) {
+ return _.merge({
+ position: {
+ my: 'top center',
+ at: 'bottom center',
+ adjust: {x: 0, y: 0},
+ effect: false
+ },
+ style: {
+ classes: 'qtip-dark qtip-rounded qtip-custom link-qtip',
+ tip: {
+ width: 16,
+ height: 8
+ }
+ },
+ show: {
+ event: 'mouseover',
+ delay: 1000
+ },
+ hide: {event: 'mouseout mousedown'},
+ includeLabels: true,
+ events: {}
+ }, options);
+ }
+
+ public HTMLCoordsToCytoscapeCoords(cytoscapeBoundingBox:Cy.Extent, mousePos:Cy.Position):Cy.Position {
+ return {x: mousePos.x + cytoscapeBoundingBox.x1, y: mousePos.y + cytoscapeBoundingBox.y1}
+ };
+
+
+ public getCytoscapeNodePosition = (cy:Cy.Instance, event:DragEvent | MouseEvent):Cy.Position => {
+ let targetOffset = $(event.target).offset();
+ if(event instanceof DragEvent) {
+ targetOffset = $('canvas').offset();
+ }
+
+ let x = (event.pageX - targetOffset.left) / cy.zoom();
+ let y = (event.pageY - targetOffset.top) / cy.zoom();
+
+ return this.HTMLCoordsToCytoscapeCoords(cy.extent(), {
+ x: x,
+ y: y
+ });
+ };
+
+
+ public getNodePosition(node:Cy.CollectionFirstNode):Cy.Position {
+ let nodePosition = node.relativePoint();
+ if (node.data().isUcpe) { //UCPEs use bounding box and not relative point.
+ nodePosition = {x: node.boundingbox().x1, y: node.boundingbox().y1};
+ }
+
+ return nodePosition;
+ }
+
+ /**
+ * Generic function that can be used for any html elements overlaid on canvas
+ * Returns the html position of a node on canvas, including left palette and header offsets. Option to pass in additional offset to add to return position.
+ * @param node
+ * @param additionalOffset
+ * @returns {Cy.Position}
+
+ public getNodePositionWithOffset = (node:Cy.CollectionFirstNode, additionalOffset?:Cy.Position): Cy.Position => {
+ if(!additionalOffset) additionalOffset = {x: 0, y:0};
+
+ let nodePosition = node.renderedPosition();
+ let posWithOffset:Cy.Position = {
+ x: nodePosition.x + GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET + additionalOffset.x,
+ y: nodePosition.y + GraphUIObjects.COMPOSITION_HEADER_OFFSET + additionalOffset.y
+ };
+ return posWithOffset;
+ };*/
+
+ /**
+ * return true/false if first node contains in second - this used in order to verify is node is entirely inside ucpe
+ * @param firstBox
+ * @param secondBox
+ * @returns {boolean}
+ */
+ public isFirstBoxContainsInSecondBox(firstBox:Cy.BoundingBox, secondBox:Cy.BoundingBox) {
+
+ return firstBox.x1 > secondBox.x1 && firstBox.x2 < secondBox.x2 && firstBox.y1 > secondBox.y1 && firstBox.y2 < secondBox.y2;
+
+ };
+
+ /**
+ *
+ * @param cy
+ * @param node
+ * @returns {Array}
+ */
+ public getLinkableNodes(cy:Cy.Instance, node:Cy.CollectionFirstNode):Array<CompositionCiNodeBase> {
+ let compatibleNodes = [];
+ _.each(cy.nodes(), (tempNode)=> {
+ if (this.nodeLocationsCompatible(node, tempNode)) {
+ compatibleNodes.push(tempNode.data());
+ }
+ });
+ return compatibleNodes;
+ }
+
+ /**
+ * Checks whether node locations are compatible in reference to UCPEs.
+ * Returns true if both nodes are in UCPE or both nodes out, or one node is UCPEpart.
+ * @param node1
+ * @param node2
+ */
+ public nodeLocationsCompatible(node1:Cy.CollectionFirstNode, node2:Cy.CollectionFirstNode) {
+ return (this.isFirstBoxContainsInSecondBox(node1.boundingbox(), node2.boundingbox()));
+ }
+
+ /**
+ * This function will init qtip tooltip on the node
+ * @param node - the node we want the tooltip to apply on
+ */
+ public initNodeTooltip(node:Cy.CollectionNodes) {
+
+ let opts = {
+ content: function () {
+ return this.data('name');
+ },
+ position: {
+ my: 'top center',
+ at: 'bottom center',
+ adjust: {x: 0, y: -5}
+ },
+ style: {
+ classes: 'qtip-dark qtip-rounded qtip-custom',
+ tip: {
+ width: 16,
+ height: 8
+ }
+ },
+ show: {
+ event: 'mouseover',
+ delay: 1000
+ },
+ hide: {event: 'mouseout mousedown'},
+ includeLabels: true
+ };
+
+ if (node.data().isUcpePart) { //fix tooltip positioning for UCPE-cps
+ opts.position.adjust = {x: 0, y: 20};
+ }
+
+ node.qtip(opts);
+ };
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts
new file mode 100644
index 0000000..2be92c7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts
@@ -0,0 +1,92 @@
+/*-
+ * ============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=========================================================
+ */
+'use strict';
+import {Injectable} from "@angular/core";
+
+export interface ICanvasImage {
+ src: string;
+ width: number
+ height: number;
+ x: number;
+ y: number;
+}
+
+@Injectable()
+export class ImageCreatorService {
+
+ private _canvas:HTMLCanvasElement;
+
+ constructor() {
+ this._canvas = <HTMLCanvasElement>$('<canvas>')[0];
+ this._canvas.setAttribute('style', 'display:none');
+
+ let body = document.getElementsByTagName('body')[0];
+ body.appendChild(this._canvas);
+ }
+
+ /**
+ * Create an image composed of different image layers
+ * @param canvasImages
+ * @param canvasWidth
+ * @param canvasHeight
+ * returns a PROMISE
+ */
+ getMultiLayerBase64Image(canvasImages: ICanvasImage[], canvasWidth?:number, canvasHeight?:number):Promise<string> {
+
+ var promise = new Promise<string>((resolve, reject) => {
+ if(canvasImages && canvasImages.length === 0){
+ return null;
+ }
+
+ //If only width was set, use it for height, otherwise use first canvasImage height
+ canvasHeight = canvasHeight || canvasImages[0].height;
+ canvasWidth = canvasWidth || canvasImages[0].width;
+
+ const images = [];
+ let imagesLoaded = 0;
+ const onImageLoaded = () => {
+ imagesLoaded++;
+ if(imagesLoaded < canvasImages.length){
+ return;
+ }
+ this._canvas.setAttribute('width', (canvasWidth * 4).toString());
+ this._canvas.setAttribute('height', (canvasHeight * 4).toString());
+ const canvasCtx = this._canvas.getContext('2d');
+ canvasCtx.scale(4,4);
+ canvasCtx.clearRect(0, 0, this._canvas.width, this._canvas.height);
+ images.forEach((image, index) => {
+ const canvasImage = canvasImages[index];
+ canvasCtx.drawImage(image, canvasImage.x, canvasImage.y, canvasImage.width, canvasImage.height);
+ });
+
+ let base64Image = this._canvas.toDataURL();
+ resolve(base64Image)
+ };
+ canvasImages.forEach(canvasImage => {
+ let image = new Image();
+ image.onload = onImageLoaded;
+ image.src = canvasImage.src;
+ images.push(image);
+ });
+ });
+
+ return promise;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts
new file mode 100644
index 0000000..54b3dbe
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts
@@ -0,0 +1,37 @@
+import {async} from "@angular/core/testing";
+import {ComponentInstanceNodesStyle} from "./component-instances-nodes-style";
+
+
+describe('component instance nodes style component', () => {
+
+ beforeEach(
+ async(() => {
+ const createElement = document.createElement.bind(document);
+ document.createElement = (tagName) => {
+ if (tagName === 'canvas') {
+ return {
+ getContext: () => ({
+ font: "",
+ measureText: (x) => ({width: x.length})
+ }),
+ };
+ }
+ return createElement(tagName);
+ };
+ })
+ );
+
+ it('verify getGraphDisplayName for String.length smaller than 67 chars', () => {
+ let inputString = 'SomeText';
+ let expectedRes = inputString;
+ let res = ComponentInstanceNodesStyle.getGraphDisplayName(inputString);
+ expect(res).toBe(expectedRes);
+ });
+
+ it('verify getGraphDisplayName for String.length greater than 67 chars', () => {
+ let inputString = 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGG12345678';
+ let expectedRes = 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFF...';
+ let res = ComponentInstanceNodesStyle.getGraphDisplayName(inputString);
+ expect(res).toBe(expectedRes);
+ });
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts
similarity index 94%
rename from catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts
index dd50524..cc9cac1 100644
--- a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts
@@ -172,16 +172,6 @@
}
},
{
- selector: '.archived',
- css: {
- 'shape': 'rectangle',
- 'background-image': (ele:Cy.Collection) => {
- return ele.data().setArchivedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE); //Change name to setArchivedImageBgStyle ??
- },
- "border-width": 0
- }
- },
- {
selector: '.vl-link',
css: {
'width': 3,
@@ -237,9 +227,10 @@
css: {
'shape': 'rectangle',
'background-image': (ele:Cy.Collection) => {
+ // return ele.data().setUncertifiedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE);//Change name to setUncertifiedImageBgStyle??
return ele.data().initUncertifiedImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE);
},
- "border-width": 0
+ 'border-width': 0
}
},
{
@@ -249,7 +240,7 @@
'background-image': (ele:Cy.Collection) => {
return ele.data().initDependentImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE)
},
- "border-width": 0
+ 'border-width': 0
}
},
{
@@ -259,7 +250,7 @@
'background-image': (ele:Cy.Collection) => {
return ele.data().initUncertifiedDependentImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE)
},
- "border-width": 0
+ 'border-width': 0
}
},
{
@@ -301,6 +292,16 @@
'overlay-color': GraphColors.NODE_BACKGROUND_COLOR,
'overlay-opacity': 0
}
+ },
+ {
+ selector: '.archived',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ return ele.data().setArchivedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE); //Change name to setArchivedImageBgStyle ??
+ },
+ "border-width": 0
+ }
}
]
}
@@ -341,21 +342,21 @@
imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_GROUP_TAGGED_ICON,
}
}
+
+ public static getGraphDisplayName(name:string):string {
+ let context = document.createElement("canvas").getContext("2d");
+ context.font = "13px Arial";
+ if (67 < context.measureText(name).width) {
+ let newLen = name.length - 3;
+ let newName = name.substring(0, newLen);
- // public static getUcpeCpNodeHandle = () => {
- // return {
- // positionX: "center",
- // positionY: "center",
- // offsetX: -8,
- // offsetY: -10,
- // color: "#27a337",
- // type: "default",
- // single: false,
- // nodeTypeNames: ["ucpe-cp-node"],
- // imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
- // lineWidth: 2,
- // lineStyle: 'dashed'
- // }
- // }
+ while (59 < (context.measureText(newName).width)) {
+ newName = newName.substring(0, (--newLen));
+ }
+ return newName + '...';
+ }
+ return name;
+ }
+
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/module-node-style.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts
similarity index 100%
rename from catalog-ui/src/app/directives/graphs-v2/common/style/module-node-style.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html
new file mode 100644
index 0000000..5a0ca3e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html
@@ -0,0 +1,57 @@
+<div class="sdc-composition-graph-wrapper {{zoneTagMode}}"
+ [ngClass]="{'with-sidebar': withSidebar$ | async, 'view-only':isViewOnly$ | async}">
+</div>
+
+<div class="sdc-composition-menu" [ngClass]="{'with-sidebar': withSidebar$ | async}">
+
+ <service-path-selector
+ *ngIf="topologyTemplate.isService() && compositionService.forwardingPaths"
+ [drawPath]="drawPathOnCy"
+ [deletePaths]="deletePathsOnCy"
+ [selectedPathId]="selectedPathId">
+ </service-path-selector>
+
+ <canvas-search *ngIf="componentInstanceNames" class="composition-search"
+ [placeholder]="'Type to search'"
+ [data]="componentInstanceNames"
+ (searchChanged)="getAutoCompleteValues($event)"
+ (searchButtonClicked)="highlightSearchMatches($event)">
+ </canvas-search>
+
+ <!--<service-path class="zoom-icons"-->
+ <!--*ngIf="!(isViewOnly$ | async) && topologyTemplate.isService()"-->
+ <!--[service]="topologyTemplate"-->
+ <!--[onCreate]="createOrUpdateServicePath">-->
+ <!--</service-path>-->
+
+ <svg-icon *ngIf="!(isViewOnly$ | async) && topologyTemplate.isService()" class="zoom-icons" [mode]="'primary2'" [size]="'medium'" [backgroundShape]="'rectangle'"
+ [backgroundColor]="'silver'" [name]="'browse'" [clickable]="true" [testId]="'pathsMenuBtn'"
+ (click)="openServicePathMenu($event)"></svg-icon>
+ <svg-icon class="zoom-icons" [mode]="'primary2'" [size]="'medium'" [backgroundShape]="'rectangle'"
+ [backgroundColor]="'silver'" [name]="'expand-o'" [clickable]="true"
+ (click)="zoomAllWithoutSidebar()"></svg-icon>
+ <svg-icon class="zoom-icons" [mode]="'primary2'" [size]="'medium'" [backgroundShape]="'rectangle'"
+ [backgroundColor]="'silver'" [name]="'plus'" [clickable]="true"
+ (click)="zoom(true)"></svg-icon>
+ <svg-icon class="zoom-icons" [mode]="'primary2'" [size]="'medium'" [backgroundShape]="'rectangle'"
+ [backgroundColor]="'silver'" [name]="'minus'" [clickable]="true"
+ (click)="zoom(false)"></svg-icon>
+</div>
+
+<div class="sdc-canvas-zones__wrapper {{zoneTagMode}}" [ngClass]="{'with-sidebar': withSidebar$ | async}">
+ <zone-container *ngFor="let zone of zones" [title]="zone.title" [type]="zone.type" [count]="zone.instances.length"
+ [visible]="zone.visible" [minimized]="zone.minimized" (minimize)="zoneMinimizeToggle(zone.type)"
+ (backgroundClick)="zoneBackgroundClicked()">
+ <zone-instance *ngFor="let instance of zone.instances" [hidden]="instance.hidden"
+ [zoneInstance]="instance" [defaultIconText]="zone.defaultIconText"
+ [isActive]="activeZoneInstance == instance"
+ [activeInstanceMode]="activeZoneInstance && activeZoneInstance.mode"
+ [isViewOnly]="isViewOnly$ | async"
+ [forceSave]="instance.forceSave"
+ (modeChange)="zoneInstanceModeChanged($event.newMode, $event.instance, zone.type)"
+ (tagHandleClick)="zoneInstanceTagged($event)"
+ (assignmentSaveStart)="zoneAssignmentSaveStart()"
+ (assignmentSaveComplete)="zoneAssignmentSaveComplete($event)">
+ </zone-instance>
+ </zone-container>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.less
new file mode 100644
index 0000000..b3e5ef3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.less
@@ -0,0 +1,93 @@
+:host(composition-graph) {
+ flex: 1;
+ padding-top: 53px;
+}
+
+.composition {
+ .custom-modal {
+ /* Hack solution to hide canvas tooltips under modals */
+ z-index: 20000 !important;
+ }
+}
+
+.sdc-composition-graph-wrapper {
+ height: 100%;
+ width: 100%;
+
+ &.with-sidebar {
+ width: calc(~'100% - 300px');
+ }
+}
+
+.view-only {
+ background-color: rgb(248, 248, 248);
+}
+
+.sdc-canvas-zones__wrapper {
+ position: absolute;
+ bottom: 10px;
+ right: 12px;
+ display: flex;
+ transition: right 0.2s;
+
+ &.with-sidebar {
+ right: 310px;
+ }
+
+ ng2-zone-container {
+ display: flex;
+ margin-left: 10px;
+ }
+}
+
+.group-tagging {
+ cursor: url("../../../../../assets/styles/images/canvas-tagging-icons/group_1.svg"), pointer;
+}
+
+.group-tagging-hover {
+ cursor: url("../../../../../assets/styles/images/canvas-tagging-icons/group_2.svg"), pointer;
+}
+
+.policy-tagging {
+ cursor: url("../../../../../assets/styles/images/canvas-tagging-icons/policy_1.svg"), pointer;
+}
+
+.policy-tagging-hover {
+ cursor: url("../../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer;
+}
+
+//Canvas menu
+.sdc-composition-menu {
+ position: absolute;
+ right: 18px;
+ top: 53px;
+ transition: right 0.2s;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ margin-right: 10px;
+ pointer-events: none;
+
+ & > * {
+ pointer-events: all;
+ }
+
+ &.with-sidebar {
+ right: 320px;
+ }
+
+ .composition-search {
+ margin-top: 12px;
+ }
+
+ .zoom-icons {
+ border: solid 1px #d2d2d2;
+ border-radius: 2px;
+ box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
+ margin-top: 10px;
+
+ /deep/ .svg-icon {
+ box-sizing: content-box;
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.spec.ts
new file mode 100644
index 0000000..9a15ecb
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.spec.ts
@@ -0,0 +1,354 @@
+import {NO_ERRORS_SCHEMA} from '@angular/core';
+import {async, ComponentFixture} from '@angular/core/testing';
+import {SdcUiServices} from 'onap-ui-angular';
+import 'rxjs/add/observable/of';
+import {ConfigureFn, configureTests} from '../../../../../jest/test-config.helper';
+import {CompositionGraphComponent} from "./composition-graph.component";
+import {WorkspaceService} from "../../workspace/workspace.service";
+import {ComponentInstance, GroupInstance, NodesFactory, ZoneInstance, ZoneInstanceMode} from "../../../../models";
+import {EventListenerService} from "../../../../services";
+import {
+ CompositionGraphGeneralUtils,
+ CompositionGraphNodesUtils,
+ CompositionGraphZoneUtils,
+ MatchCapabilitiesRequirementsUtils, ServicePathGraphUtils
+} from "./utils";
+import {CompositionGraphLinkUtils} from "./utils/composition-graph-links-utils";
+import {ConnectionWizardService} from "./connection-wizard/connection-wizard.service";
+import {CommonGraphUtils} from "./common/common-graph-utils";
+import {CompositionGraphPaletteUtils} from "./utils/composition-graph-palette-utils";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service";
+import {CompositionService} from "../composition.service";
+import {ModalService} from '../../../services/modal.service';
+import {Store} from '@ngxs/store';
+import {PoliciesService} from '../../../services/policies.service';
+import {GroupsService} from '../../../services/groups.service';
+import {PolicyInstance} from "../../../../models/graph/zones/policy-instance";
+import {ZoneInstanceType} from "../../../../models/graph/zones/zone-instance";
+import {GRAPH_EVENTS} from "../../../../utils/constants";
+import * as cytoscape from "cytoscape";
+import {ComponentMetadata} from "../../../../models/component-metadata";
+import {Zone} from "../../../../models/graph/zones/zone";
+import {SelectedComponentType, SetSelectedComponentAction} from "../common/store/graph.actions";
+
+describe('composition graph component', () => {
+
+ let fixture: ComponentFixture<CompositionGraphComponent>;
+ let instance: CompositionGraphComponent;
+ let eventServiceMock: Partial<EventListenerService>;
+ let compositionGraphZoneUtils: Partial<CompositionGraphZoneUtils>;
+ let generalGraphUtils: Partial<CompositionGraphGeneralUtils>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let policyService: Partial<PoliciesService>;
+ let storeStub;
+ let compositionGraphLinkUtils: Partial<CompositionGraphLinkUtils>;
+ let nodesGraphUtils: Partial<CompositionGraphNodesUtils>;
+
+ let createPolicyInstance = () => {
+ let policy = new PolicyInstance();
+ policy.targets = {COMPONENT_INSTANCES: [], GROUPS: []};
+ return new ZoneInstance(policy, '', '');
+ }
+
+ beforeEach(
+ async(() => {
+
+ eventServiceMock = {
+ notifyObservers: jest.fn(),
+ unRegisterObserver: jest.fn()
+ }
+
+ compositionGraphZoneUtils = {
+ endCyTagMode: jest.fn(),
+ showZoneTagIndications: jest.fn(),
+ hideZoneTagIndications: jest.fn(),
+ hideGroupZoneIndications: jest.fn(),
+ showGroupZoneIndications: jest.fn(),
+ startCyTagMode: jest.fn()
+ }
+
+ workspaceServiceMock = {
+ metadata: <ComponentMetadata>{
+ uniqueId: 'service_unique_id',
+ componentType: 'SERVICE'
+ }
+ }
+
+ compositionGraphLinkUtils = {
+ handleLinkClick: jest.fn(),
+ getModifyLinkMenu: jest.fn()
+ }
+
+ storeStub = {
+ dispatch: jest.fn()
+ }
+ policyService = {
+ getSpecificPolicy: jest.fn()
+ }
+
+ generalGraphUtils = {
+ zoomGraphTo: jest.fn()
+ }
+
+ nodesGraphUtils = {
+ onNodesPositionChanged: jest.fn()
+ }
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [CompositionGraphComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: NodesFactory, useValue: {}},
+ {provide: EventListenerService, useValue: eventServiceMock},
+ {provide: CompositionGraphZoneUtils, useValue: compositionGraphZoneUtils},
+ {provide: CompositionGraphGeneralUtils, useValue: generalGraphUtils},
+ {provide: CompositionGraphLinkUtils, useValue: compositionGraphLinkUtils},
+ {provide: CompositionGraphNodesUtils, useValue: nodesGraphUtils},
+ {provide: ConnectionWizardService, useValue: {}},
+ {provide: CommonGraphUtils, useValue: {}},
+ {provide: CompositionGraphPaletteUtils, useValue: {}},
+ {provide: TopologyTemplateService, useValue: {}},
+ {provide: ComponentInstanceServiceNg2, useValue: {}},
+ {provide: MatchCapabilitiesRequirementsUtils, useValue: {}},
+ {provide: CompositionService, useValue: {}},
+ {provide: SdcUiServices.LoaderService, useValue: {}},
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.NotificationsService, useValue: {}},
+ {provide: SdcUiServices.simplePopupMenuService, useValue: {}},
+ {provide: ServicePathGraphUtils, useValue: {}},
+ {provide: ModalService, useValue: {}},
+ {provide: PoliciesService, useValue: policyService},
+ {provide: GroupsService, useValue: {}},
+ {provide: Store, useValue: storeStub},
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(CompositionGraphComponent);
+ instance = fixture.componentInstance;
+ instance._cy = cytoscape({});
+ });
+ })
+ );
+
+ it('composition graph component should be defined', () => {
+ expect(fixture).toBeDefined();
+ });
+
+ describe('on zone instance mode changed', () => {
+ let newZoneInstance: ZoneInstance;
+
+ beforeEach(
+ async(() => {
+ newZoneInstance = createPolicyInstance();
+ instance.zoneTagMode = null;
+ instance.zones = [];
+ instance.zones[ZoneInstanceType.POLICY] = new Zone('Policies', 'P', ZoneInstanceType.POLICY);
+ instance.zones[ZoneInstanceType.GROUP] = new Zone('Groups', 'G', ZoneInstanceType.GROUP);
+ instance.activeZoneInstance = createPolicyInstance();
+ }))
+
+ it('zone instance in tag mode and we want to turn tag mode off', () => {
+ instance.zoneTagMode = 'some_zone_id';
+ instance.activeZoneInstance = newZoneInstance;
+ instance.zoneInstanceModeChanged(ZoneInstanceMode.NONE, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(instance.eventListenerService.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_CANVAS_TAG_END, newZoneInstance);
+ expect(instance.activeZoneInstance.mode).toBe(ZoneInstanceMode.SELECTED)
+ })
+
+ it('we are not in tag mode and policy instance mode changed to NONE - group and zone tag indication need to be removed', () => {
+ instance.zoneInstanceModeChanged(ZoneInstanceMode.NONE, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(instance.compositionGraphZoneUtils.hideZoneTagIndications).toHaveBeenCalledWith(instance._cy);
+ expect(instance.compositionGraphZoneUtils.hideGroupZoneIndications).toHaveBeenCalledWith(instance.zones[ZoneInstanceType.GROUP].instances);
+ })
+
+ it('we are not in tag mode and active zone instance gets hover/none - we dont actually change mode', () => {
+ let newMode = ZoneInstanceMode.SELECTED;
+ instance.zoneInstanceModeChanged(newMode, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(newZoneInstance.mode).toBe(newMode);
+ })
+
+ it('we are not in tag mode and zone instance mode changed to HOVER mode', () => {
+ instance.zoneInstanceModeChanged(ZoneInstanceMode.HOVER, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(instance.compositionGraphZoneUtils.showZoneTagIndications).toHaveBeenCalledWith(instance._cy, newZoneInstance);
+ expect(instance.compositionGraphZoneUtils.showGroupZoneIndications).toHaveBeenCalledWith(instance.zones[ZoneInstanceType.GROUP].instances, newZoneInstance);
+ expect(instance.eventListenerService.notifyObservers).not.toHaveBeenCalled();
+ })
+
+ it('we are not in tag mode and mode changed to SELECTED', () => {
+ instance.zoneInstanceModeChanged(ZoneInstanceMode.SELECTED, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(instance.compositionGraphZoneUtils.showZoneTagIndications).toHaveBeenCalledWith(instance._cy, newZoneInstance);
+ expect(instance.compositionGraphZoneUtils.showGroupZoneIndications).toHaveBeenCalledWith(instance.zones[ZoneInstanceType.GROUP].instances, newZoneInstance);
+ expect(instance.activeZoneInstance).toBe(newZoneInstance);
+ expect(instance.eventListenerService.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, newZoneInstance);
+ expect(instance.store.dispatch).toHaveBeenCalledWith(new SetSelectedComponentAction({
+ component: newZoneInstance.instanceData,
+ type: SelectedComponentType[ZoneInstanceType[newZoneInstance.type]]
+ }));
+ expect(instance.eventListenerService.notifyObservers).not.toHaveBeenCalledWith(GRAPH_EVENTS.ON_CANVAS_TAG_START, ZoneInstanceType.POLICY);
+ })
+
+
+ it('we are not in tag mode and and zone instance mode changed to TAG', () => {
+ instance.zoneInstanceModeChanged(ZoneInstanceMode.TAG, newZoneInstance, ZoneInstanceType.POLICY);
+ expect(instance.compositionGraphZoneUtils.showZoneTagIndications).toHaveBeenCalledWith(instance._cy, newZoneInstance);
+ expect(instance.compositionGraphZoneUtils.showGroupZoneIndications).toHaveBeenCalledWith(instance.zones[ZoneInstanceType.GROUP].instances, newZoneInstance);
+ expect(instance.activeZoneInstance).toBe(newZoneInstance);
+ expect(instance.eventListenerService.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, newZoneInstance);
+ expect(instance.store.dispatch).toHaveBeenCalledWith(new SetSelectedComponentAction({
+ component: newZoneInstance.instanceData,
+ type: SelectedComponentType[ZoneInstanceType[newZoneInstance.type]]
+ }));
+ expect(instance.compositionGraphZoneUtils.startCyTagMode).toHaveBeenCalledWith(instance._cy);
+ expect(instance.eventListenerService.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_CANVAS_TAG_START, ZoneInstanceType.POLICY);
+ })
+ })
+
+ it('unset active zone instance', () => {
+ instance.activeZoneInstance = createPolicyInstance();
+ instance.unsetActiveZoneInstance();
+ expect(instance.activeZoneInstance).toBeNull();
+ expect(instance.zoneTagMode).toBeNull();
+ })
+
+ it('zone background clicked - we are not in tag mode and active zone instance exist', () => {
+ instance.activeZoneInstance = createPolicyInstance();
+ jest.spyOn(instance, 'unsetActiveZoneInstance');
+ jest.spyOn(instance, 'selectTopologyTemplate');
+ instance.zoneBackgroundClicked();
+ expect(instance.unsetActiveZoneInstance).toHaveBeenCalled();
+ expect(instance.selectTopologyTemplate).toHaveBeenCalled();
+ })
+
+ it('zone background clicked - we are not in tag mode and no active zone instance exist', () => {
+ jest.spyOn(instance, 'unsetActiveZoneInstance');
+ jest.spyOn(instance, 'selectTopologyTemplate');
+ instance.zoneBackgroundClicked();
+ expect(instance.unsetActiveZoneInstance).not.toHaveBeenCalled();
+ expect(instance.selectTopologyTemplate).not.toHaveBeenCalled();
+ })
+
+ it('on zoom in', () => {
+ jest.spyOn(instance, 'zoom');
+ instance.zoom(true);
+ expect(instance.generalGraphUtils.zoomGraphTo).toHaveBeenCalledWith(instance._cy, instance._cy.zoom() + .1);
+ })
+
+ it('on zoom out', () => {
+ jest.spyOn(instance, 'zoom');
+ instance.zoom(false);
+ expect(instance.generalGraphUtils.zoomGraphTo).toHaveBeenCalledWith(instance._cy, instance._cy.zoom() - .1);
+ })
+
+ describe('cytoscape tap end event have been called', () => {
+
+ it('canvas background was clicked while zone instance in tag mode, zone instance still selected in tag mode)', () => {
+ let event = <Cy.EventObject>{cyTarget: instance._cy};
+ instance.zoneTagMode = 'instance_in_tag'
+ instance.onTapEnd(event);
+ expect(instance.zoneTagMode).toBe('instance_in_tag');
+ })
+
+ it('canvas background was clicked and no zone instance selected, topology template is now selected', () => {
+ let event = <Cy.EventObject>{cyTarget: instance._cy};
+ jest.spyOn(instance, 'selectTopologyTemplate');
+ instance.onTapEnd(event);
+ expect(instance.selectTopologyTemplate).toHaveBeenCalled();
+ expect(instance.eventListenerService.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
+ })
+
+ it('canvas background was clicked and zone instance was selected, topology template is now selected and zone instance is unselected', () => {
+ let event = <Cy.EventObject>{cyTarget: instance._cy};
+ instance.activeZoneInstance = createPolicyInstance();
+ jest.spyOn(instance, 'selectTopologyTemplate');
+ jest.spyOn(instance, 'unsetActiveZoneInstance');
+ instance.onTapEnd(event);
+ expect(instance.selectTopologyTemplate).toHaveBeenCalled();
+ expect(instance.unsetActiveZoneInstance).toHaveBeenCalled();
+ })
+
+
+ it('canvas background was clicked and zone instance was selected, topology template is now selected and zone instance is unselected', () => {
+ let event = <Cy.EventObject>{cyTarget: instance._cy};
+ instance.activeZoneInstance = createPolicyInstance();
+ jest.spyOn(instance, 'selectTopologyTemplate');
+ jest.spyOn(instance, 'unsetActiveZoneInstance');
+ instance.onTapEnd(event);
+ expect(instance.selectTopologyTemplate).toHaveBeenCalled();
+ expect(instance.unsetActiveZoneInstance).toHaveBeenCalled();
+ })
+
+ it('on simple edge clicked, open link menu and handle link click', () => {
+ let event = <Cy.EventObject>{
+ cyTarget: [{
+ isEdge: jest.fn().mockReturnValue(true),
+ data: jest.fn().mockReturnValue({type: 'simple'})
+ }
+ }];
+ instance.openModifyLinkMenu = jest.fn();
+ instance.onTapEnd(event);
+ expect(instance.compositionGraphLinkUtils.handleLinkClick).toHaveBeenCalledWith(instance._cy, event);
+ expect(instance.openModifyLinkMenu).toHaveBeenCalled();
+ })
+
+ it('on service path edge clicked, no menu is opened', () => {
+ let event = <Cy.EventObject>{
+ cyTarget: [{
+ isEdge: jest.fn().mockReturnValue(true),
+ data: jest.fn().mockReturnValue({type: 'service-path-link'})
+ }]
+ };
+ instance.openModifyLinkMenu = jest.fn();
+ instance.onTapEnd(event);
+ expect(instance.compositionGraphLinkUtils.handleLinkClick).toHaveBeenCalledWith(instance._cy, event);
+ expect(instance.openModifyLinkMenu).not.toHaveBeenCalled();
+ })
+
+ it('on drop after drag event (position has changed), call onNodesPositionChanged to update node position', () => {
+ let event = <Cy.EventObject>{
+ cyTarget: [{
+ isEdge: jest.fn().mockReturnValue(false),
+ position: jest.fn().mockReturnValue({x:2.11, y:2.44})
+ }]
+ };
+ instance.currentlyClickedNodePosition = <Cy.Position>{x:2.33, y:2.44};
+ instance.onTapEnd(event);
+ let nodesMoved: Cy.CollectionNodes = instance._cy.$(':grabbed');
+ expect(instance.nodesGraphUtils.onNodesPositionChanged).toHaveBeenCalledWith(instance._cy, instance.topologyTemplate, nodesMoved);
+
+ })
+
+ it('on node clicked (position not changed) while zone instance selected, unset active zone and call set selected instance', () => {
+ let event = <Cy.EventObject>{
+ cyTarget: [{
+ isEdge: jest.fn().mockReturnValue(false),
+ position: jest.fn().mockReturnValue({x:2.11, y:2.44}),
+ data: jest.fn().mockReturnValue({componentInstance: new ComponentInstance()})
+ }],
+ };
+ instance.currentlyClickedNodePosition = <Cy.Position>{x:2.11, y:2.44};
+ instance.activeZoneInstance = createPolicyInstance();
+ jest.spyOn(instance, 'unsetActiveZoneInstance');
+ jest.spyOn(instance, 'selectComponentInstance');
+ instance.onTapEnd(event);
+ expect(instance.unsetActiveZoneInstance).toHaveBeenCalled();
+ expect(instance.selectComponentInstance).toHaveBeenCalledWith(event.cyTarget[0].data().componentInstance);
+ })
+ })
+
+ it('initial view mode will turn off all cytoscape events', () => {
+ jest.spyOn(instance, 'isViewOnly').mockReturnValue(true);
+ jest.spyOn(instance._cy, 'off');
+ instance.initViewMode();
+ expect(instance._cy.off).toHaveBeenCalledWith('drag');
+ expect(instance._cy.off).toHaveBeenCalledWith('handlemouseout');
+ expect(instance._cy.off).toHaveBeenCalledWith('handlemouseover');
+ expect(instance._cy.off).toHaveBeenCalledWith('canvasredraw');
+ expect(instance._cy.off).toHaveBeenCalledWith('handletagclick');
+
+ })
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts
new file mode 100644
index 0000000..69ca3fa
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.ts
@@ -0,0 +1,768 @@
+/**
+ * Created by ob0695 on 4/24/2018.
+ */
+import { AfterViewInit, Component, ElementRef, HostBinding, Input } from '@angular/core';
+import { Select, Store } from '@ngxs/store';
+import {
+ ButtonModel,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ CompositionCiNodeBase,
+ ConnectRelationModel,
+ GroupInstance,
+ LeftPaletteComponent,
+ LinkMenu,
+ Match,
+ ModalModel,
+ NodesFactory,
+ Point,
+ PolicyInstance,
+ PropertyBEModel,
+ Relationship,
+ StepModel,
+ Zone,
+ ZoneInstance,
+ ZoneInstanceAssignmentType,
+ ZoneInstanceMode,
+ ZoneInstanceType
+} from 'app/models';
+import { ForwardingPath } from 'app/models/forwarding-path';
+import { CompositionCiServicePathLink } from 'app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link';
+import { UIZoneInstanceObject } from 'app/models/ui-models/ui-zone-instance-object';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { CommonGraphUtils } from 'app/ng2/pages/composition/graph/common/common-graph-utils';
+import { ComponentInstanceNodesStyle } from 'app/ng2/pages/composition/graph/common/style/component-instances-nodes-style';
+import { ConnectionPropertiesViewComponent } from 'app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component';
+import { ConnectionWizardHeaderComponent } from 'app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component';
+import { ConnectionWizardService } from 'app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service';
+import { FromNodeStepComponent } from 'app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component';
+import { PropertiesStepComponent } from 'app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component';
+import { ToNodeStepComponent } from 'app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ModalService } from 'app/ng2/services/modal.service';
+import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
+import { ServiceGenericResponse } from 'app/ng2/services/responses/service-generic-response';
+import { WorkspaceState } from 'app/ng2/store/states/workspace.state';
+import { EventListenerService } from 'app/services';
+import { ComponentInstanceFactory, EVENTS, SdcElementType } from 'app/utils';
+import { ComponentType, GRAPH_EVENTS, GraphColors, DEPENDENCY_EVENTS } from 'app/utils/constants';
+import * as _ from 'lodash';
+import { DndDropEvent } from 'ngx-drag-drop/ngx-drag-drop';
+import { SdcUiServices } from 'onap-ui-angular';
+import { NotificationSettings } from 'onap-ui-angular/dist/notifications/utilities/notification.config';
+import { menuItem } from 'onap-ui-angular/dist/simple-popup-menu/menu-data.interface';
+import { CytoscapeEdgeEditation } from '../../../../../third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js';
+import { SelectedComponentType, SetSelectedComponentAction } from '../common/store/graph.actions';
+import { GraphState } from '../common/store/graph.state';
+import {
+ CompositionGraphGeneralUtils,
+ CompositionGraphNodesUtils,
+ CompositionGraphZoneUtils,
+ MatchCapabilitiesRequirementsUtils
+} from './utils';
+import { CompositionGraphLinkUtils } from './utils/composition-graph-links-utils';
+import { CompositionGraphPaletteUtils } from './utils/composition-graph-palette-utils';
+import { ServicePathGraphUtils } from './utils/composition-graph-service-path-utils';
+
+declare const window: any;
+
+@Component({
+ selector: 'composition-graph',
+ templateUrl: './composition-graph.component.html',
+ styleUrls: ['./composition-graph.component.less']
+})
+
+export class CompositionGraphComponent implements AfterViewInit {
+
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+ @Select(GraphState.withSidebar) withSidebar$: boolean;
+ @Input() topologyTemplate: TopologyTemplate;
+ @HostBinding('attr.data-tests-id') dataTestId: string;
+ @Input() testId: string;
+
+ // tslint:disable:variable-name
+ private _cy: Cy.Instance;
+ private zoneTagMode: string;
+ private activeZoneInstance: ZoneInstance;
+ private zones: Zone[];
+ private currentlyClickedNodePosition: Cy.Position;
+ private dragElement: JQuery;
+ private dragComponent: ComponentInstance;
+ private componentInstanceNames: string[];
+ private topologyTemplateId: string;
+ private topologyTemplateType: string;
+
+ constructor(private elRef: ElementRef,
+ private nodesFactory: NodesFactory,
+ private eventListenerService: EventListenerService,
+ private compositionGraphZoneUtils: CompositionGraphZoneUtils,
+ private generalGraphUtils: CompositionGraphGeneralUtils,
+ private compositionGraphLinkUtils: CompositionGraphLinkUtils,
+ private nodesGraphUtils: CompositionGraphNodesUtils,
+ private connectionWizardService: ConnectionWizardService,
+ private commonGraphUtils: CommonGraphUtils,
+ private modalService: ModalService,
+ private compositionGraphPaletteUtils: CompositionGraphPaletteUtils,
+ private topologyTemplateService: TopologyTemplateService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
+ private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
+ private store: Store,
+ private compositionService: CompositionService,
+ private loaderService: SdcUiServices.LoaderService,
+ private workspaceService: WorkspaceService,
+ private notificationService: SdcUiServices.NotificationsService,
+ private simplePopupMenuService: SdcUiServices.simplePopupMenuService,
+ private servicePathGraphUtils: ServicePathGraphUtils) {
+ }
+
+ ngOnInit() {
+ this.dataTestId = this.testId;
+ this.topologyTemplateId = this.workspaceService.metadata.uniqueId;
+ this.topologyTemplateType = this.workspaceService.metadata.componentType;
+
+ this.store.dispatch(new SetSelectedComponentAction({
+ component: this.topologyTemplate,
+ type: SelectedComponentType.TOPOLOGY_TEMPLATE
+ }));
+ this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, () => {
+ this.loadGraphData();
+ });
+ this.loadCompositionData();
+ }
+
+ ngAfterViewInit() {
+ this.loadGraph();
+ }
+
+ ngOnDestroy() {
+ this._cy.destroy();
+ _.forEach(GRAPH_EVENTS, (event) => {
+ this.eventListenerService.unRegisterObserver(event);
+ });
+ this.eventListenerService.unRegisterObserver(EVENTS.ON_CHECKOUT);
+ this.eventListenerService.unRegisterObserver(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE);
+ }
+
+ public isViewOnly = (): boolean => {
+ return this.store.selectSnapshot((state) => state.workspace.isViewOnly);
+ }
+
+ public zoom = (zoomIn: boolean): void => {
+ const currentZoom: number = this._cy.zoom();
+ if (zoomIn) {
+ this.generalGraphUtils.zoomGraphTo(this._cy, currentZoom + .1);
+ } else {
+ this.generalGraphUtils.zoomGraphTo(this._cy, currentZoom - .1);
+ }
+ }
+
+ public zoomAllWithoutSidebar = () => {
+ setTimeout(() => { // wait for sidebar changes to take effect before zooming
+ this.generalGraphUtils.zoomAll(this._cy);
+ });
+ }
+
+ public getAutoCompleteValues = (searchTerm: string) => {
+ if (searchTerm.length > 1) { // US requirement: only display search results after 2nd letter typed.
+ const nodes: Cy.CollectionNodes = this.nodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+ this.componentInstanceNames = _.map(nodes, (node) => node.data('name'));
+ } else {
+ this.componentInstanceNames = [];
+ }
+ }
+
+ public highlightSearchMatches = (searchTerm: string) => {
+ this.nodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm);
+ const matchingNodes: Cy.CollectionNodes = this.nodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+ this.generalGraphUtils.zoomAll(this._cy, matchingNodes);
+ }
+
+ public onDrop = (dndEvent: DndDropEvent) => {
+ this.compositionGraphPaletteUtils.addNodeFromPalette(this._cy, dndEvent);
+ }
+
+ public openServicePathMenu = ($event): void => {
+
+ const menuConfig: menuItem[] = [];
+ if (!this.isViewOnly()) {
+ menuConfig.push({
+ text: 'Create Service Flow',
+ action: () => this.servicePathGraphUtils.onCreateServicePath()
+ });
+ }
+ menuConfig.push({
+ text: 'Service Flows List',
+ type: '',
+ action: () => this.servicePathGraphUtils.onListServicePath()
+ });
+ const popup = this.simplePopupMenuService.openBaseMenu(menuConfig, {
+ x: $event.x,
+ y: $event.y
+ });
+
+ }
+
+ public deletePathsOnCy = () => {
+ this.servicePathGraphUtils.deletePathsFromGraph(this._cy);
+ }
+
+ public drawPathOnCy = (data: ForwardingPath) => {
+ this.servicePathGraphUtils.drawPath(this._cy, data);
+ }
+
+ public onTapEnd = (event: Cy.EventObject) => {
+ if (this.zoneTagMode) {
+ return;
+ }
+ if (event.cyTarget === this._cy) { // On Background clicked
+ if (this._cy.$('node:selected').length === 0) { // if the background click but not dragged
+ if (this.activeZoneInstance) {
+ this.unsetActiveZoneInstance();
+ this.selectTopologyTemplate();
+ } else {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
+ this.selectTopologyTemplate();
+ }
+
+ }
+ } else if (event.cyTarget[0].isEdge()) { // and Edge clicked
+ this.compositionGraphLinkUtils.handleLinkClick(this._cy, event);
+ if (event.cyTarget[0].data().type === CompositionCiServicePathLink.LINK_TYPE) {
+ return;
+ }
+ this.openModifyLinkMenu(this.compositionGraphLinkUtils.getModifyLinkMenu(event.cyTarget[0], event), event);
+ } else { // On Node clicked
+
+ this._cy.nodes(':grabbed').style({'overlay-opacity': 0});
+
+ const newPosition = event.cyTarget[0].position();
+ // node position changed (drop after drag event) - we need to update position
+ if (this.currentlyClickedNodePosition.x !== newPosition.x || this.currentlyClickedNodePosition.y !== newPosition.y) {
+ const nodesMoved: Cy.CollectionNodes = this._cy.$(':grabbed');
+ this.nodesGraphUtils.onNodesPositionChanged(this._cy, this.topologyTemplate, nodesMoved);
+ } else {
+ if (this.activeZoneInstance) {
+ this.unsetActiveZoneInstance();
+ }
+ this.selectComponentInstance(event.cyTarget[0].data().componentInstance);
+ }
+ }
+ }
+
+ private registerCytoscapeGraphEvents() {
+
+ this._cy.on('addedgemouseup', (event, data) => {
+ const connectRelationModel: ConnectRelationModel = this.compositionGraphLinkUtils.onLinkDrawn(this._cy, data.source, data.target);
+ if (connectRelationModel != null) {
+ this.connectionWizardService.setRelationMenuDirectiveObj(connectRelationModel);
+ this.connectionWizardService.selectedMatch = null;
+
+ const steps: StepModel[] = [];
+ const fromNodeName: string = connectRelationModel.fromNode.componentInstance.name;
+ const toNodeName: string = connectRelationModel.toNode.componentInstance.name;
+ steps.push(new StepModel(fromNodeName, FromNodeStepComponent));
+ steps.push(new StepModel(toNodeName, ToNodeStepComponent));
+ steps.push(new StepModel('Properties', PropertiesStepComponent));
+ const wizardTitle = 'Connect: ' + fromNodeName + ' to ' + toNodeName;
+ const modalInstance = this.modalService.createMultiStepsWizard(wizardTitle, steps, this.createLinkFromMenu, ConnectionWizardHeaderComponent);
+ modalInstance.instance.open();
+ }
+ });
+
+ this._cy.on('tapstart', 'node', (event: Cy.EventObject) => {
+ this.currentlyClickedNodePosition = angular.copy(event.cyTarget[0].position()); // update node position on drag
+ });
+
+ this._cy.on('drag', 'node', (event: Cy.EventObject) => {
+ if (event.cyTarget.data().componentSubType !== SdcElementType.POLICY && event.cyTarget.data().componentSubType !== SdcElementType.GROUP) {
+ event.cyTarget.style({'overlay-opacity': 0.24});
+ if (this.generalGraphUtils.isValidDrop(this._cy, event.cyTarget)) {
+ event.cyTarget.style({'overlay-color': GraphColors.NODE_BACKGROUND_COLOR});
+ } else {
+ event.cyTarget.style({'overlay-color': GraphColors.NODE_OVERLAPPING_BACKGROUND_COLOR});
+ }
+ }
+ });
+
+ this._cy.on('handlemouseover', (event, payload) => {
+ // no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes
+ if (payload.node.grabbed() || this._cy.scratch('_edge_editation_highlights') === true) {
+ return;
+ }
+
+ if (this.zoneTagMode) {
+ this.zoneTagMode = this.zones[this.activeZoneInstance.type].getHoverTagModeId();
+ return;
+ }
+
+ const nodesData = this.nodesGraphUtils.getAllNodesData(this._cy.nodes());
+ const nodesLinks = this.generalGraphUtils.getAllCompositionCiLinks(this._cy);
+ const instance = payload.node.data().componentInstance;
+ const filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodesToComponentInstance(instance, nodesData, nodesLinks);
+ this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy);
+ this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data());
+
+ this._cy.scratch()._edge_editation_highlights = true;
+ });
+
+ this._cy.on('handlemouseout', () => {
+ if (this.zoneTagMode) {
+ this.zoneTagMode = this.zones[this.activeZoneInstance.type].getTagModeId();
+ return;
+ }
+ if (this._cy.scratch('_edge_editation_highlights') === true) {
+ this._cy.removeScratch('_edge_editation_highlights');
+ this._cy.emit('hidehandles');
+ this.matchCapabilitiesRequirementsUtils.resetFadedNodes(this._cy);
+ }
+ });
+
+ this._cy.on('tapend', (event: Cy.EventObject) => {
+ this.onTapEnd(event);
+ });
+
+ this._cy.on('boxselect', 'node', (event: Cy.EventObject) => {
+ this.unsetActiveZoneInstance();
+ this.selectComponentInstance(event.cyTarget.data().componentInstance);
+ });
+
+ this._cy.on('canvasredraw', (event: Cy.EventObject) => {
+ if (this.zoneTagMode) {
+ this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, this.activeZoneInstance);
+ }
+ });
+
+ this._cy.on('handletagclick', (event: Cy.EventObject, eventData: any) => {
+ this.compositionGraphZoneUtils.handleTagClick(this._cy, this.activeZoneInstance, eventData.nodeId);
+ });
+ }
+
+ private initViewMode() {
+
+ if (this.isViewOnly()) {
+ // remove event listeners
+ this._cy.off('drag');
+ this._cy.off('handlemouseout');
+ this._cy.off('handlemouseover');
+ this._cy.off('canvasredraw');
+ this._cy.off('handletagclick');
+ this._cy.edges().unselectify();
+ }
+ }
+
+ private saveChangedCapabilityProperties = (): Promise<PropertyBEModel[]> => {
+ return new Promise<PropertyBEModel[]>((resolve) => {
+ const capabilityPropertiesBE: PropertyBEModel[] = this.connectionWizardService.changedCapabilityProperties.map((prop) => {
+ prop.value = prop.getJSONValue();
+ const propBE = new PropertyBEModel(prop);
+ propBE.parentUniqueId = this.connectionWizardService.selectedMatch.relationship.relation.capabilityOwnerId;
+ return propBE;
+ });
+ if (capabilityPropertiesBE.length > 0) {
+ // if there are capability properties to update, then first update capability properties and then resolve promise
+ this.componentInstanceService
+ .updateInstanceCapabilityProperties(
+ this.topologyTemplate,
+ this.connectionWizardService.selectedMatch.toNode,
+ this.connectionWizardService.selectedMatch.capability,
+ capabilityPropertiesBE
+ )
+ .subscribe((response) => {
+ console.log('Update resource instance capability properties response: ', response);
+ this.connectionWizardService.changedCapabilityProperties = [];
+ resolve(capabilityPropertiesBE);
+ });
+ } else {
+ // no capability properties to update, immediately resolve promise
+ resolve(capabilityPropertiesBE);
+ }
+ });
+ }
+
+ private loadCompositionData = () => {
+ this.loaderService.activate();
+ this.topologyTemplateService.getComponentCompositionData(this.topologyTemplateId, this.topologyTemplateType).subscribe((response: ComponentGenericResponse) => {
+ if (this.topologyTemplateType === ComponentType.SERVICE) {
+ this.compositionService.forwardingPaths = (response as ServiceGenericResponse).forwardingPaths;
+ }
+ this.compositionService.componentInstances = response.componentInstances;
+ this.compositionService.componentInstancesRelations = response.componentInstancesRelations;
+ this.compositionService.groupInstances = response.groupInstances;
+ this.compositionService.policies = response.policies;
+ this.loadGraphData();
+ this.loaderService.deactivate();
+ }, (error) => { this.loaderService.deactivate(); });
+ }
+
+ private loadGraph = () => {
+ const graphEl = this.elRef.nativeElement.querySelector('.sdc-composition-graph-wrapper');
+ this.initGraph(graphEl);
+ this.zones = this.compositionGraphZoneUtils.createCompositionZones();
+ this.registerCytoscapeGraphEvents();
+ this.registerCustomEvents();
+ this.initViewMode();
+ }
+
+ private initGraphNodes() {
+
+ setTimeout(() => {
+ const handles = new CytoscapeEdgeEditation();
+ handles.init(this._cy);
+ if (!this.isViewOnly()) { // Init nodes handle extension - enable dynamic links
+ handles.initNodeEvents();
+ handles.registerHandle(ComponentInstanceNodesStyle.getAddEdgeHandle());
+ }
+ handles.registerHandle(ComponentInstanceNodesStyle.getTagHandle());
+ handles.registerHandle(ComponentInstanceNodesStyle.getTaggedPolicyHandle());
+ handles.registerHandle(ComponentInstanceNodesStyle.getTaggedGroupHandle());
+ }, 0);
+
+ _.each(this.compositionService.componentInstances, (instance) => {
+ const compositionGraphNode: CompositionCiNodeBase = this.nodesFactory.createNode(instance);
+ this.commonGraphUtils.addComponentInstanceNodeToGraph(this._cy, compositionGraphNode);
+ });
+
+ }
+
+ private loadGraphData = () => {
+ this.initGraphNodes();
+ this.compositionGraphLinkUtils.initGraphLinks(this._cy, this.compositionService.componentInstancesRelations);
+ this.compositionGraphZoneUtils.initZoneInstances(this.zones);
+ setTimeout(() => { // Need setTimeout so that angular canvas changes will take effect before resize & center
+ this.generalGraphUtils.zoomAllWithMax(this._cy, 1);
+ });
+ this.componentInstanceNames = _.map(this._cy.nodes(), (node) => node.data('name'));
+ }
+
+ private initGraph(graphEl: JQuery) {
+
+ this._cy = cytoscape({
+ container: graphEl,
+ style: ComponentInstanceNodesStyle.getCompositionGraphStyle(),
+ zoomingEnabled: true,
+ maxZoom: 1.2,
+ minZoom: .1,
+ userZoomingEnabled: false,
+ userPanningEnabled: true,
+ selectionType: 'single',
+ boxSelectionEnabled: true,
+ autolock: this.isViewOnly(),
+ autoungrabify: this.isViewOnly()
+ });
+
+ // Testing Bridge that allows Cypress tests to select a component on canvas not via DOM
+ if (window.Cypress) {
+ window.testBridge = this.createCanvasTestBridge();
+ }
+ }
+
+ private createCanvasTestBridge(): any {
+ return {
+ selectComponentInstance: (componentName: string) => {
+ const matchingNodesByName = this.nodesGraphUtils.getMatchingNodesByName(this._cy, componentName);
+ const component = new ComponentInstance(matchingNodesByName.first().data().componentInstance);
+ this.selectComponentInstance(component);
+ }
+ };
+ }
+
+ // -------------------------------------------- ZONES---------------------------------------------------------//
+ private zoneMinimizeToggle = (zoneType: ZoneInstanceType): void => {
+ this.zones[zoneType].minimized = !this.zones[zoneType].minimized;
+ }
+
+ private zoneInstanceModeChanged = (newMode: ZoneInstanceMode, instance: ZoneInstance, zoneId: ZoneInstanceType): void => {
+ if (this.zoneTagMode) { // we're in tag mode.
+ if (instance === this.activeZoneInstance && newMode === ZoneInstanceMode.NONE) { // we want to turn tag mode off.
+ this.zoneTagMode = null;
+ this.activeZoneInstance.mode = ZoneInstanceMode.SELECTED;
+ this.compositionGraphZoneUtils.endCyTagMode(this._cy);
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_END, instance);
+
+ }
+ } else {
+ // when active zone instance gets hover/none, don't actually change mode, just show/hide indications
+ if (instance !== this.activeZoneInstance || (instance === this.activeZoneInstance && newMode > ZoneInstanceMode.HOVER)) {
+ instance.mode = newMode;
+ }
+
+ if (newMode === ZoneInstanceMode.NONE) {
+ this.compositionGraphZoneUtils.hideZoneTagIndications(this._cy);
+ if (this.zones[ZoneInstanceType.GROUP]) {
+ this.compositionGraphZoneUtils.hideGroupZoneIndications(this.zones[ZoneInstanceType.GROUP].instances);
+ }
+ }
+ if (newMode >= ZoneInstanceMode.HOVER) {
+ this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, instance);
+ if (instance.type === ZoneInstanceType.POLICY && this.zones[ZoneInstanceType.GROUP]) {
+ this.compositionGraphZoneUtils.showGroupZoneIndications(this.zones[ZoneInstanceType.GROUP].instances, instance);
+ }
+ }
+ if (newMode >= ZoneInstanceMode.SELECTED) {
+ this._cy.$('node:selected').unselect();
+ if (this.activeZoneInstance && this.activeZoneInstance !== instance && newMode >= ZoneInstanceMode.SELECTED) {
+ this.activeZoneInstance.mode = ZoneInstanceMode.NONE;
+ }
+ this.activeZoneInstance = instance;
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, instance);
+ this.store.dispatch(new SetSelectedComponentAction({
+ component: instance.instanceData,
+ type: SelectedComponentType[ZoneInstanceType[instance.type]]
+ }));
+ }
+ if (newMode === ZoneInstanceMode.TAG) {
+ this.compositionGraphZoneUtils.startCyTagMode(this._cy);
+ this.zoneTagMode = this.zones[zoneId].getTagModeId();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_START, zoneId);
+ }
+ }
+ }
+
+ private zoneInstanceTagged = (taggedInstance: ZoneInstance) => {
+ this.activeZoneInstance.addOrRemoveAssignment(taggedInstance.instanceData.uniqueId, ZoneInstanceAssignmentType.GROUPS);
+ const newHandle: string = this.compositionGraphZoneUtils.getCorrectHandleForNode(taggedInstance.instanceData.uniqueId, this.activeZoneInstance);
+ taggedInstance.showHandle(newHandle);
+ }
+
+ private unsetActiveZoneInstance = (): void => {
+ if (this.activeZoneInstance) {
+ this.activeZoneInstance.mode = ZoneInstanceMode.NONE;
+ this.activeZoneInstance = null;
+ this.zoneTagMode = null;
+ }
+ }
+
+ private selectComponentInstance = (componentInstance: ComponentInstance) => {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_NODE_SELECTED, componentInstance);
+ this.store.dispatch(new SetSelectedComponentAction({
+ component: componentInstance,
+ type: SelectedComponentType.COMPONENT_INSTANCE
+ }));
+ }
+
+ private selectTopologyTemplate = () => {
+ this.store.dispatch(new SetSelectedComponentAction({
+ component: this.topologyTemplate,
+ type: SelectedComponentType.TOPOLOGY_TEMPLATE
+ }));
+ }
+
+ private zoneBackgroundClicked = (): void => {
+ if (!this.zoneTagMode && this.activeZoneInstance) {
+ this.unsetActiveZoneInstance();
+ this.selectTopologyTemplate();
+ }
+ }
+
+ private zoneAssignmentSaveStart = () => {
+ this.loaderService.activate();
+ }
+
+ private zoneAssignmentSaveComplete = (success: boolean) => {
+ this.loaderService.deactivate();
+ if (!success) {
+ this.notificationService.push(new NotificationSettings('error', 'Update Failed', 'Error'));
+ }
+ }
+
+ private deleteZoneInstance = (deletedInstance: UIZoneInstanceObject) => {
+ if (deletedInstance.type === ZoneInstanceType.POLICY) {
+ this.compositionService.policies = this.compositionService.policies.filter((policy) => policy.uniqueId !== deletedInstance.uniqueId);
+ } else if (deletedInstance.type === ZoneInstanceType.GROUP) {
+ this.compositionService.groupInstances = this.compositionService.groupInstances.filter((group) => group.uniqueId !== deletedInstance.uniqueId);
+ }
+ // remove it from zones
+ this.zones[deletedInstance.type].removeInstance(deletedInstance.uniqueId);
+ if (deletedInstance.type === ZoneInstanceType.GROUP && !_.isEmpty(this.zones[ZoneInstanceType.POLICY])) {
+ this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(deletedInstance.uniqueId, [this.zones[ZoneInstanceType.POLICY]], ZoneInstanceAssignmentType.GROUPS);
+ }
+ this.selectTopologyTemplate();
+ }
+ // -------------------------------------------------------------------------------------------------------------//
+
+ private registerCustomEvents() {
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, (groupInstance: GroupInstance) => {
+ this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(this.zones, groupInstance);
+ this.notificationService.push(new NotificationSettings('success', 'Group Updated', 'Success'));
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, (policyInstance: PolicyInstance) => {
+ this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(this.zones, policyInstance);
+ this.notificationService.push(new NotificationSettings('success', 'Policy Updated', 'Success'));
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, (leftPaletteComponent: LeftPaletteComponent) => {
+ this.compositionGraphPaletteUtils.onComponentHoverIn(leftPaletteComponent, this._cy);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ADD_ZONE_INSTANCE_FROM_PALETTE,
+ (component: TopologyTemplate, paletteComponent: LeftPaletteComponent, startPosition: Point) => {
+
+ const zoneType: ZoneInstanceType = this.compositionGraphZoneUtils.getZoneTypeForPaletteComponent(paletteComponent.categoryType);
+ this.compositionGraphZoneUtils.showZone(this.zones[zoneType]);
+
+ this.loaderService.activate();
+ this.compositionGraphZoneUtils.createZoneInstanceFromLeftPalette(zoneType, paletteComponent.type).subscribe((zoneInstance: ZoneInstance) => {
+ this.loaderService.deactivate();
+ this.compositionGraphZoneUtils.addInstanceToZone(this.zones[zoneInstance.type], zoneInstance, true);
+ this.compositionGraphZoneUtils.createPaletteToZoneAnimation(startPosition, zoneType, zoneInstance);
+ }, (error) => {
+ this.loaderService.deactivate();
+ });
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT, () => {
+ this._cy.emit('hidehandles');
+ this.matchCapabilitiesRequirementsUtils.resetFadedNodes(this._cy);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, (dragElement, dragComponent) => {
+ this.dragElement = dragElement;
+ this.dragComponent = ComponentInstanceFactory.createComponentInstanceFromComponent(dragComponent);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, (position: Point) => {
+ const draggedElement = document.getElementById('draggable_element');
+ draggedElement.className = this.compositionGraphPaletteUtils.isDragValid(this._cy, position) ? 'valid-drag' : 'invalid-drag';
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DROP, (event: DndDropEvent) => {
+ this.onDrop(event);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, (component: ComponentInstance) => {
+ const selectedNode = this._cy.getElementById(component.uniqueId);
+ selectedNode.data().componentInstance.name = component.name;
+ selectedNode.data('name', component.name); // used for tooltip
+ selectedNode.data('displayName', selectedNode.data().getDisplayName()); // abbreviated
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, (componentInstanceId: string) => {
+ const nodeToDelete = this._cy.getElementById(componentInstanceId);
+ this.nodesGraphUtils.deleteNode(this._cy, this.topologyTemplate, nodeToDelete);
+ this.selectTopologyTemplate();
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE, (deletedInstance: UIZoneInstanceObject) => {
+ this.deleteZoneInstance(deletedInstance);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, (componentInstanceId: string) => {
+ if (!_.isEmpty(this.zones)) {
+ this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(componentInstanceId, this.zones, ZoneInstanceAssignmentType.COMPONENT_INSTANCES);
+ }
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_EDGE, (releaseLoading: boolean, linksToDelete: Cy.CollectionEdges) => {
+ this.compositionGraphLinkUtils.deleteLink(this._cy, this.topologyTemplate, releaseLoading, linksToDelete);
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_VERSION_CHANGED, (component: ComponentInstance) => {
+ // Remove everything from graph and reload it all
+ this._cy.elements().remove();
+ this.loadCompositionData();
+ setTimeout(() => { this._cy.getElementById(component.uniqueId).select(); }, 1000);
+ this.selectComponentInstance(component);
+ });
+ this.eventListenerService.registerObserverCallback(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, (ischecked: boolean) => {
+ if (ischecked) {
+ this._cy.$('node:selected').addClass('dependent');
+ } else {
+ // due to defect in cytoscape, just changing the class does not replace the icon, and i need to revert to original icon with no markings.
+ this._cy.$('node:selected').removeClass('dependent');
+ this._cy.$('node:selected').style({'background-image': this._cy.$('node:selected').data('originalImg')});
+ }
+ });
+ }
+ private createLinkFromMenu = (): void => {
+ this.saveChangedCapabilityProperties().then(() => {
+ this.compositionGraphLinkUtils.createLinkFromMenu(this._cy, this.connectionWizardService.selectedMatch);
+ });
+ }
+
+ private deleteRelation = (link: Cy.CollectionEdges) => {
+ // if multiple edges selected, delete the VL itself so edges get deleted automatically
+ if (this._cy.$('edge:selected').length > 1) {
+ this.nodesGraphUtils.deleteNode(this._cy, this.topologyTemplate, this._cy.$('node:selected'));
+ } else {
+ this.compositionGraphLinkUtils.deleteLink(this._cy, this.topologyTemplate, true, link);
+ }
+ }
+
+ private viewRelation = (link: Cy.CollectionEdges) => {
+
+ const linkData = link.data();
+ const sourceNode: CompositionCiNodeBase = link.source().data();
+ const targetNode: CompositionCiNodeBase = link.target().data();
+ const relationship: Relationship = linkData.relation.relationships[0];
+
+ this.compositionGraphLinkUtils.getRelationRequirementCapability(relationship, sourceNode.componentInstance, targetNode.componentInstance).then((objReqCap) => {
+ const capability = objReqCap.capability;
+ const requirement = objReqCap.requirement;
+
+ this.connectionWizardService.connectRelationModel = new ConnectRelationModel(sourceNode, targetNode, []);
+ this.connectionWizardService.selectedMatch = new Match(requirement, capability, true, linkData.source, linkData.target);
+ this.connectionWizardService.selectedMatch.relationship = relationship;
+
+ const title = `Connection Properties`;
+ const saveButton: ButtonModel = new ButtonModel('Save', 'blue', () => {
+ this.saveChangedCapabilityProperties().then(() => {
+ this.modalService.closeCurrentModal();
+ });
+ });
+ const cancelButton: ButtonModel = new ButtonModel('Cancel', 'white', () => {
+ this.modalService.closeCurrentModal();
+ });
+ const modal = new ModalModel('xl', title, '', [saveButton, cancelButton]);
+ const modalInstance = this.modalService.createCustomModal(modal);
+ this.modalService.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
+ modalInstance.instance.open();
+
+ new Promise((resolve) => {
+ if (!this.connectionWizardService.selectedMatch.capability.properties) {
+ this.componentInstanceService.getInstanceCapabilityProperties(this.topologyTemplateType, this.topologyTemplateId, linkData.target, capability)
+ .subscribe(() => {
+ resolve();
+ }, () => { /* do nothing */ });
+ } else {
+ resolve();
+ }
+ }).then(() => {
+ this.modalService.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
+ });
+ }, () => { /* do nothing */ });
+ }
+
+ private openModifyLinkMenu = (linkMenuObject: LinkMenu, $event) => {
+
+ const menuConfig: menuItem[] = [{
+ text: 'View',
+ iconName: 'eye-o',
+ iconType: 'common',
+ iconMode: 'secondary',
+ iconSize: 'small',
+ type: '',
+ action: () => this.viewRelation(linkMenuObject.link as Cy.CollectionEdges)
+ }];
+
+ if (!this.isViewOnly()) {
+ menuConfig.push({
+ text: 'Delete',
+ iconName: 'trash-o',
+ iconType: 'common',
+ iconMode: 'secondary',
+ iconSize: 'small',
+ type: '',
+ action: () => this.deleteRelation(linkMenuObject.link as Cy.CollectionEdges)
+ });
+ }
+ this.simplePopupMenuService.openBaseMenu(menuConfig, {
+ x: $event.originalEvent.x,
+ y: $event.originalEvent.y
+ });
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.module.ts
new file mode 100644
index 0000000..e58d160
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.module.ts
@@ -0,0 +1,55 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {CompositionGraphComponent} from "./composition-graph.component";
+import {ZoneModules} from "./canvas-zone/zones-module";
+import {CompositionGraphZoneUtils} from "./utils/composition-graph-zone-utils";
+import {CompositionGraphGeneralUtils} from "./utils/composition-graph-general-utils";
+import {CommonGraphUtils} from "./common/common-graph-utils";
+import {LinksFactory} from "app/models/graph/graph-links/links-factory";
+import {NodesFactory} from "app/models/graph/nodes/nodes-factory";
+import {ImageCreatorService} from "./common/image-creator.service";
+import {MatchCapabilitiesRequirementsUtils} from "./utils/match-capability-requierment-utils";
+import {CompositionGraphNodesUtils} from "./utils/composition-graph-nodes-utils";
+import {ConnectionWizardService} from "app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service";
+import {CompositionGraphPaletteUtils} from "./utils/composition-graph-palette-utils";
+import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
+import {DndModule} from "ngx-drag-drop";
+import { MenuListNg2Module } from "app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module";
+import { UiElementsModule } from "app/ng2/components/ui/ui-elements.module";
+import {ServicePathSelectorModule} from "./service-path-selector/service-path-selector.module";
+import {SdcUiComponentsModule, SdcUiServices} from "onap-ui-angular";
+import {CanvasSearchModule} from "./canvas-search/canvas-search.module";
+import {CompositionGraphLinkUtils, ServicePathGraphUtils} from "./utils";
+
+
+@NgModule({
+ declarations: [CompositionGraphComponent],
+ imports: [CommonModule,
+ ServicePathSelectorModule,
+ SdcUiComponentsModule,
+ MenuListNg2Module,
+ UiElementsModule,
+ ZoneModules,
+ CanvasSearchModule,
+ DndModule],
+ exports: [CompositionGraphComponent],
+ entryComponents: [CompositionGraphComponent],
+ providers: [
+ CompositionGraphZoneUtils,
+ CompositionGraphGeneralUtils,
+ MatchCapabilitiesRequirementsUtils,
+ CompositionGraphNodesUtils,
+ CompositionGraphLinkUtils,
+ CommonGraphUtils,
+ NodesFactory,
+ LinksFactory,
+ ImageCreatorService,
+ ConnectionWizardService,
+ CompositionGraphPaletteUtils,
+ QueueServiceUtils,
+ SdcUiServices.simplePopupMenuService,
+ ServicePathGraphUtils
+ ]
+})
+export class CompositionGraphModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.html
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.less
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.less
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.ts
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-properties-view/connection-properties-view.component.ts
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.html
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.less
similarity index 86%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.less
index 72fa6e8..d8bab28 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.less
@@ -1,5 +1,5 @@
-@import '../../../../../assets/styles/sprite-proxy-services-icons';
-@import '../../../../../assets/styles/variables';
+@import '../../../../../../../assets/styles/sprite-proxy-services-icons';
+@import '../../../../../../../assets/styles/variables';
.header-main-container{
background-color: #f8f8f8;
width: 100%;
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.module.ts
similarity index 80%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.module.ts
index 6b4b412..80464dc 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.module.ts
@@ -3,9 +3,9 @@
import {FromNodeStepComponent} from "./from-node-step/from-node-step.component";
import {PropertiesStepComponent} from "./properties-step/properties-step.component";
import {ConnectionWizardService} from "./connection-wizard.service";
-import {SelectRequirementOrCapabilityModule} from "../../components/logic/select-requirement-or-capability/select-requirement-or-capability.module";
-import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module";
-import {FormElementsModule} from "../../components/ui/form-components/form-elements.module";
+import {SelectRequirementOrCapabilityModule} from "../../../../components/logic/select-requirement-or-capability/select-requirement-or-capability.module";
+import {PropertyTableModule} from "../../../../components/logic/properties-table/property-table.module";
+import {FormElementsModule} from "../../../../components/ui/form-components/form-elements.module";
import {ConnectionWizardHeaderComponent} from "./connection-wizard-header/connection-wizard-header.component";
import {ConnectionPropertiesViewComponent} from "./connection-properties-view/connection-properties-view.component";
import {BrowserModule} from "@angular/platform-browser";
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.spec.ts
new file mode 100644
index 0000000..8a5c5fc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.spec.ts
@@ -0,0 +1,85 @@
+import {TestBed} from "@angular/core/testing";
+import {WorkspaceService} from "../../../../pages/workspace/workspace.service";
+import { ConnectionWizardService } from "app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service";
+import { ConnectRelationModel, Match, Requirement, Capability } from "app/models";
+import { Mock } from "ts-mockery/dist";
+
+describe('Connection Wizard Service', () => {
+
+ let service: ConnectionWizardService;
+
+ const connectRelationModelMock = Mock.of<ConnectRelationModel>({
+ possibleRelations: [
+ Mock.of<Match>({isFromTo: true, requirement: Mock.of<Requirement>({uniqueId: 'requirement1', capability: "cap1"}), capability: Mock.of<Capability>({uniqueId: 'capability1', type: 'othertype'})}),
+ Mock.of<Match>({isFromTo: true, requirement: Mock.of<Requirement>({uniqueId: 'requirement2', capability: "cap1"}), capability: Mock.of<Capability>({uniqueId: 'capability2', type: 'tosca'})}),
+ Mock.of<Match>({isFromTo: true, requirement: Mock.of<Requirement>({uniqueId: 'requirement3', capability: "cap1"}), capability: Mock.of<Capability>({uniqueId: 'capability3', type: 'tosca'})}),
+ Mock.of<Match>({isFromTo: true, requirement: Mock.of<Requirement>({uniqueId: 'requirement4', capability: "cap1"}), capability: Mock.of<Capability>({uniqueId: 'capability2', type: 'tosca'})}),
+ Mock.of<Match>({isFromTo: true, requirement: Mock.of<Requirement>({uniqueId: 'requirement5', capability: "cap2"}), capability: Mock.of<Capability>({uniqueId: 'capability1', type: 'tosca'})}),
+ Mock.of<Match>({isFromTo: false, requirement: Mock.of<Requirement>({uniqueId: 'requirement6', capability: "cap2"}), capability: Mock.of<Capability>({uniqueId: 'capability2', type: 'tosca'})}),
+ Mock.of<Match>({isFromTo: false, requirement: Mock.of<Requirement>({uniqueId: 'requirement7', capability: "cap2"}), capability: Mock.of<Capability>({uniqueId: 'capability1', type: 'othertype'})})
+ ]
+ });
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [],
+ providers: [ConnectionWizardService,
+ {provide: WorkspaceService, useValue: {}}
+ ]
+ });
+
+ service = TestBed.get(ConnectionWizardService);
+ service.connectRelationModel = connectRelationModelMock;
+ });
+
+ describe('getOptionalRequirementsByInstanceUniqueId', () => {
+ it('if no capability to match is sent in and isFromTo is true, ALL isFromTo==true requirements are returned', () => {
+ const requirements = service.getOptionalRequirementsByInstanceUniqueId(true);
+ expect(requirements['cap1'].length).toBe(4);
+ expect(requirements['cap2'].length).toBe(1);
+ });
+
+ it('if no capability to match is sent in and isFromTo is false, ALL isFromTo==false requirements are returned', () => {
+ const requirements = service.getOptionalRequirementsByInstanceUniqueId(false);
+ expect(requirements['cap1']).toBeUndefined();
+ expect(requirements['cap2'].length).toBe(2);
+ });
+
+ it('if capability to match IS sent in and isFromTo is true, matches with the same uniqueID and isFromTo==true are returned', () => {
+ const capability = Mock.of<Capability>({uniqueId: 'capability1'});
+ const requirements = service.getOptionalRequirementsByInstanceUniqueId(true, capability);
+ expect(requirements['cap1'].length).toBe(1);
+ expect(requirements['cap2'].length).toBe(1);
+ });
+
+ it('if capability to match IS sent in and isFromTo is false, requirements with the same uniqueID and isFromTo==false are returned', () => {
+ const capability = Mock.of<Capability>({uniqueId: 'capability1'});
+ const requirements = service.getOptionalRequirementsByInstanceUniqueId(false, capability);
+ expect(requirements['cap1']).toBeUndefined();
+ expect(requirements['cap2'].length).toBe(1);
+ });
+ })
+
+ describe('getOptionalCapabilitiesByInstanceUniqueId', () => {
+ it('if requirement to match IS sent in and isFromTo is true, matches with the same uniqueID and isFromTo==true are returned', () => {
+ const requirement = Mock.of<Requirement>({uniqueId: 'requirement1'});
+ const capabilities = service.getOptionalCapabilitiesByInstanceUniqueId(true, requirement);
+ expect(capabilities['othertype'].length).toBe(1);
+ expect(capabilities['tosca']).toBeUndefined();
+ });
+
+ it('if no requirement to match is sent in and isFromTo is true, a UNIQUE list of all capabilities with isFromTo==true are returned', () => {
+ const capabilities = service.getOptionalCapabilitiesByInstanceUniqueId(true);
+ expect(capabilities['othertype'].length).toBe(1);
+ expect(capabilities['tosca'].length).toBe(2);
+ });
+
+ it('if no requirement to match is sent in and isFromTo is false, all capabilities with isFromTo==false are returned', () => {
+ const capabilities = service.getOptionalCapabilitiesByInstanceUniqueId(false);
+ expect(capabilities['othertype'].length).toBe(1);
+ expect(capabilities['tosca'].length).toBe(1);
+ });
+ });
+
+});
+
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.ts
similarity index 88%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.ts
index af8dcb4..2eb5428 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service.ts
@@ -1,20 +1,23 @@
import * as _ from "lodash";
-import {ConnectRelationModel} from "../../../models/graph/connectRelationModel";
+import {ConnectRelationModel} from "app/models/graph/connectRelationModel";
import {Injectable} from "@angular/core";
import { Requirement, Capability} from "app/models";
import {Dictionary} from "lodash";
import {Match, Component, PropertyFEModel} from "app/models";
+import {Store} from "@ngxs/store";
+import {WorkspaceService} from "../../../workspace/workspace.service";
@Injectable()
export class ConnectionWizardService {
connectRelationModel:ConnectRelationModel;
- currentComponent:Component;
selectedMatch:Match;
changedCapabilityProperties:PropertyFEModel[];
- constructor() {
+
+ constructor(private workspaceService: WorkspaceService) {
this.changedCapabilityProperties = [];
+
}
public setRelationMenuDirectiveObj = (connectRelationModel:ConnectRelationModel) => {
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/__snapshots__/from-node-step.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/__snapshots__/from-node-step.component.spec.ts.snap
new file mode 100644
index 0000000..739ce3d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/__snapshots__/from-node-step.component.spec.ts.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`from-node-step component should match current snapshot 1`] = `
+<from-node-step
+ connectWizardService={[Function Object]}
+ preventBack={[Function Function]}
+ preventNext={[Function Function]}
+ updateSelectedReqOrCap={[Function Function]}
+>
+ <select-requirement-or-capability />
+</from-node-step>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.html
similarity index 93%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.html
index 1cb3df7..0a70069 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.html
@@ -17,7 +17,6 @@
<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap"
[optionalCapabilitiesMap]="optionalCapabilitiesMap"
[selectedReqOrCapModel]="connectWizardService.selectedMatch && (connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.requirement : connectWizardService.selectedMatch.capability)"
- [currentComponent]="connectWizardService.currentComponent"
[componentInstanceId]="connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId"
(updateSelectedReqOrCap)="updateSelectedReqOrCap($event)">
</select-requirement-or-capability>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.spec.ts
new file mode 100644
index 0000000..59ff72a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.spec.ts
@@ -0,0 +1,114 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { Capability, Match } from 'app/models';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { Requirement } from '../../../../../../models/requirement';
+import { ConnectionWizardService } from '../connection-wizard.service';
+import { FromNodeStepComponent } from './from-node-step.component';
+
+describe('from-node-step component', () => {
+
+ let fixture: ComponentFixture<FromNodeStepComponent>;
+ let connectionWizardServiceMockWithoutSelectedMatch: Partial<ConnectionWizardService>;
+ let connectionWizardServiceMockWithSelectedMatch: Partial<ConnectionWizardService>;
+
+ const connectionWizardServiceMockSelectedMatchWithRequirements = {requirement: 'val'};
+
+ connectionWizardServiceMockWithoutSelectedMatch = {
+ getOptionalRequirementsByInstanceUniqueId: jest.fn().mockReturnValue(5),
+ getOptionalCapabilitiesByInstanceUniqueId: jest.fn().mockReturnValue(10),
+
+ connectRelationModel: {
+ fromNode: {
+ componentInstance: {
+ uniqueId : 'testUniqueID'
+ }
+ }
+ }
+ };
+
+ connectionWizardServiceMockWithSelectedMatch = {
+ selectedMatch: connectionWizardServiceMockSelectedMatchWithRequirements,
+ getOptionalRequirementsByInstanceUniqueId: jest.fn().mockReturnValue(5),
+ getOptionalCapabilitiesByInstanceUniqueId: jest.fn().mockReturnValue(10)
+ };
+
+ let expectedConnectionWizardServiceMock = connectionWizardServiceMockWithoutSelectedMatch;
+
+ beforeEach(
+ async(() => {
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [FromNodeStepComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: ConnectionWizardService, useValue: expectedConnectionWizardServiceMock}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(FromNodeStepComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('preventBack return true - always', () => {
+ fixture.componentInstance.ngOnInit();
+ const result = fixture.componentInstance.preventBack();
+ expect(result).toEqual(true);
+ });
+
+ it('preventNext return true since selectedMatch does not exist in connectionWizardServiceMock', () => {
+ fixture.componentInstance.ngOnInit();
+ const result = fixture.componentInstance.preventNext();
+ expect(result).toEqual(true);
+ });
+
+ it('preventNext return false since to selectedMatch or selectedMatch.capability & selectedMatch.requirement does exist in connectionWizardServiceMock', () => {
+ fixture.componentInstance.connectWizardService = connectionWizardServiceMockWithSelectedMatch;
+ fixture.componentInstance.ngOnInit();
+ const result = fixture.componentInstance.preventNext();
+ expect(result).toEqual(false);
+ });
+
+ it('updateSelectedReqOrCap is called with instance of requirement, the selectMatch will be set to an Instance of Match of type Requirement', () => {
+ const requirement = new Requirement();
+ fixture.componentInstance.updateSelectedReqOrCap(requirement);
+ const expectedSelectedMatch = fixture.componentInstance.connectWizardService.selectedMatch;
+
+ expect(expectedSelectedMatch).toBeInstanceOf(Match);
+ expect(expectedSelectedMatch.capability).toBe(null);
+ expect(expectedSelectedMatch.fromNode).toBe('testUniqueID');
+ expect(expectedSelectedMatch.isFromTo).toBe(true);
+ expect(expectedSelectedMatch.toNode).toBe(null);
+ expect(expectedSelectedMatch.requirement).toBeInstanceOf(Requirement);
+ });
+
+ it('updateSelectedReqOrCap is called with instance of capability, the selectMatch will be set to an Instance of Match of type Capability', () => {
+ const capability = new Capability();
+ fixture.componentInstance.updateSelectedReqOrCap(capability);
+ const expectedSelectedMatch = fixture.componentInstance.connectWizardService.selectedMatch;
+
+ expect(expectedSelectedMatch).toBeInstanceOf(Match);
+ expect(expectedSelectedMatch.requirement).toBe(null);
+ expect(expectedSelectedMatch.fromNode).toBe(null);
+ expect(expectedSelectedMatch.isFromTo).toBe(false);
+ expect(expectedSelectedMatch.toNode).toBe('testUniqueID');
+ expect(expectedSelectedMatch.capability).toBeInstanceOf(Capability);
+ });
+
+ it('updateSelectedReqOrCap is called with null, the selectMatch will be set to null', () => {
+ fixture.componentInstance.updateSelectedReqOrCap(null);
+ const expectedSelectedMatch = fixture.componentInstance.connectWizardService.selectedMatch;
+
+ expect(expectedSelectedMatch).toBe(null);
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.ts
new file mode 100644
index 0000000..cffd58c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/from-node-step/from-node-step.component.ts
@@ -0,0 +1,44 @@
+import { Component, forwardRef, Inject, OnInit } from '@angular/core';
+import { Match } from 'app/models';
+import { Capability } from 'app/models/capability';
+import { Requirement } from 'app/models/requirement';
+import { IStepComponent } from 'app/models/wizard-step';
+import { Dictionary } from 'lodash';
+import { ConnectionWizardService } from '../connection-wizard.service';
+
+@Component({
+ selector: 'from-node-step',
+ templateUrl: './from-node-step.component.html'
+})
+
+export class FromNodeStepComponent implements IStepComponent, OnInit{
+
+ optionalRequirementsMap: Dictionary<Requirement[]>;
+ optionalCapabilitiesMap: Dictionary<Capability[]>;
+
+ constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) {}
+
+ ngOnInit() {
+ this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(true);
+ this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(false);
+ }
+
+ preventNext = (): boolean => {
+ return !this.connectWizardService.selectedMatch || (!this.connectWizardService.selectedMatch.capability && !this.connectWizardService.selectedMatch.requirement);
+ }
+
+ preventBack = (): boolean => {
+ return true;
+ }
+
+ private updateSelectedReqOrCap = (selected: Requirement|Capability): void => {
+ if (!selected) {
+ this.connectWizardService.selectedMatch = null;
+ } else if (selected instanceof Requirement) {
+ this.connectWizardService.selectedMatch = new Match(<Requirement>selected, null, true, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId, null);
+ } else {
+ this.connectWizardService.selectedMatch = new Match(null, <Capability>selected , false, null, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId);
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.html
similarity index 99%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.html
index 293ebf9..a817759 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.html
@@ -13,8 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
<div class="title">
<span class="capability-name">
{{(connectWizardService.selectedMatch.capability && connectWizardService.selectedMatch.capability.getTitle()) || connectWizardService.selectedMatch.relationship.relation.capability}}
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.less
similarity index 81%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.less
index 8e9e07c..c8ad4d3 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.less
@@ -1,4 +1,4 @@
-@import '../../../../../assets/styles/variables';
+@import '../../../../../../../assets/styles/variables';
.title{
margin-bottom: 20px;
.capability-name-label{
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.ts
similarity index 86%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.ts
index 946d185..2c12e0d 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/properties-step/properties-step.component.ts
@@ -7,10 +7,10 @@
import {Component, Inject, forwardRef} from '@angular/core';
import {IStepComponent} from "app/models"
import {ConnectionWizardService} from "../connection-wizard.service";
-import {PropertyFEModel} from "../../../../models/properties-inputs/property-fe-model";
-import {InstanceFePropertiesMap} from "../../../../models/properties-inputs/property-fe-map";
-import {PropertiesUtils} from "../../properties-assignment/services/properties.utils";
-import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service";
+import {PropertyFEModel} from "app/models/properties-inputs/property-fe-model";
+import {InstanceFePropertiesMap} from "app/models/properties-inputs/property-fe-map";
+import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils";
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
@Component({
selector: 'properties-step',
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/__snapshots__/to-node-step.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/__snapshots__/to-node-step.component.spec.ts.snap
new file mode 100644
index 0000000..ea587bc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/__snapshots__/to-node-step.component.spec.ts.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`to-node-step component should match current snapshot 1`] = `
+<to-node-step
+ connectWizardService={[Function Object]}
+ optionalCapabilitiesMap={[Function Object]}
+ optionalRequirementsMap={[Function Object]}
+ preventBack={[Function Function]}
+ preventNext={[Function Function]}
+ updateSelectedReqOrCap={[Function Function]}
+>
+ <select-requirement-or-capability />
+</to-node-step>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.html
similarity index 93%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.html
index 775a1a7..4892b7f 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.html
@@ -13,13 +13,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap"
[optionalCapabilitiesMap]="optionalCapabilitiesMap"
[selectedReqOrCapModel]="connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.capability : connectWizardService.selectedMatch.requirement"
[selectedReqOrCapOption]="displayRequirementsOrCapabilities"
- [currentComponent]="connectWizardService.currentComponent"
[componentInstanceId]="connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId"
(updateSelectedReqOrCap)="updateSelectedReqOrCap($event)">
</select-requirement-or-capability>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.spec.ts
new file mode 100644
index 0000000..9d453f2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.spec.ts
@@ -0,0 +1,71 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {ToNodeStepComponent} from "./to-node-step.component";
+import {ConnectionWizardService} from "../connection-wizard.service";
+import {ConfigureFn, configureTests} from "../../../../../../../jest/test-config.helper";
+import {Match} from "../../../../../../models/graph/match-relation";
+
+
+describe('to-node-step component', () => {
+
+ let fixture: ComponentFixture<ToNodeStepComponent>;
+ let connectionWizardServiceMock: Partial<ConnectionWizardService>;
+
+ beforeEach(
+ async(() => {
+
+ connectionWizardServiceMock = {
+ // selectedMatch: new Match(null, null, true, '',''),
+ selectedMatch: {
+ isFromTo: false
+ },
+ getOptionalRequirementsByInstanceUniqueId: jest.fn().mockReturnValue(5),
+ getOptionalCapabilitiesByInstanceUniqueId: jest.fn().mockReturnValue(10)
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [ToNodeStepComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: ConnectionWizardService, useValue: connectionWizardServiceMock}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(ToNodeStepComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should test the ngOnInit with isFromTo = false', () => {
+ const component = TestBed.createComponent(ToNodeStepComponent);
+ let service = TestBed.get(ConnectionWizardService);
+ service.selectedMatch.isFromTo = false;
+ component.componentInstance.ngOnInit();
+ expect(component.componentInstance.displayRequirementsOrCapabilities).toEqual("Requirement");
+ expect(connectionWizardServiceMock.getOptionalRequirementsByInstanceUniqueId).toHaveBeenCalledWith(false, connectionWizardServiceMock.selectedMatch.capability);
+ expect(component.componentInstance.optionalRequirementsMap).toEqual(5);
+ expect(component.componentInstance.optionalCapabilitiesMap).toEqual({});
+ });
+
+
+ it('should test the ngOnInit with isFromTo = true', () => {
+ const component = TestBed.createComponent(ToNodeStepComponent);
+ let service = TestBed.get(ConnectionWizardService);
+ service.selectedMatch.isFromTo = true;
+ component.componentInstance.ngOnInit();
+ expect(component.componentInstance.displayRequirementsOrCapabilities).toEqual("Capability");
+ expect(connectionWizardServiceMock.getOptionalCapabilitiesByInstanceUniqueId).toHaveBeenCalledWith(true, connectionWizardServiceMock.selectedMatch.requirement);
+ expect(component.componentInstance.optionalCapabilitiesMap).toEqual(10);
+ expect(component.componentInstance.optionalRequirementsMap).toEqual({});
+ });
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.ts
similarity index 91%
rename from catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.ts
index ea3b129..67dc381 100644
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/connection-wizard/to-node-step/to-node-step.component.ts
@@ -2,10 +2,10 @@
import {IStepComponent} from "app/models"
import {Dictionary} from "lodash";
import {ConnectionWizardService} from "../connection-wizard.service";
-import {Match} from "../../../../models/graph/match-relation";
-import {Requirement} from "../../../../models/requirement";
-import {Capability} from "../../../../models/capability";
-import {PropertyModel} from "../../../../models/properties";
+import {Match} from "app/models/graph/match-relation";
+import {Requirement} from "app/models/requirement";
+import {Capability} from "app/models/capability";
+import {PropertyModel} from "app/models/properties";
@Component({
selector: 'to-node-step',
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap
new file mode 100644
index 0000000..094f41b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact form component should match current snapshot of artifact form component 1`] = `
+<link-row
+ source={[Function Array]}
+ srcCP={[Function Array]}
+ target={[Function Array]}
+ targetCP={[Function Array]}
+>
+ <ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkSrc"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkSrcCP"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkTarget"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkTargetCP"
+ /><div
+ class="cell remove"
+ data-tests-id="removeLnk"
+ >
+
+ </div>
+</link-row>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less
similarity index 78%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less
index beec9bd..2a1d0d9 100644
--- a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less
@@ -1,4 +1,4 @@
-@import './../../../../../assets/styles/variables.less';
+@import './../../../../../../../assets/styles/variables.less';
.remove {
display: flex;
align-items: center;
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts
new file mode 100644
index 0000000..5cbad6e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts
@@ -0,0 +1,478 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {CacheService} from "../../../../../services/cache.service";
+import {ConfigureFn, configureTests} from "../../../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {LinkRowComponent} from "./link-row.component";
+import {DropdownValue} from "../../../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {MapItemData, ServicePathMapItem} from "../../../../../../models/graph/nodes-and-links-map";
+
+describe('artifact form component', () => {
+
+ let fixture: ComponentFixture<LinkRowComponent>;
+ let cacheServiceMock: Partial<CacheService>;
+
+ beforeEach(
+ async(() => {
+
+
+ cacheServiceMock = {
+ contains: jest.fn(),
+ remove: jest.fn(),
+ set: jest.fn(),
+ get: jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [LinkRowComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: []
+ ,
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(LinkRowComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot of artifact form component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+
+ it('ngOnChanges() -> in case data exist -> call to parseInitialData()' ,() => {
+ // init values / mock functions
+ let data = 'something';
+ fixture.componentInstance.parseInitialData = jest.fn();
+ fixture.componentInstance.data = data;
+
+ // call to the tested function
+ fixture.componentInstance.ngOnChanges();
+
+ // expect that
+ expect(fixture.componentInstance.parseInitialData).toHaveBeenCalledWith(data);
+ });
+
+ it('onSourceSelected() -> in case id -> srcCP, link.fromCP, link.toNode, link.toCP, target, targetCP should be updated accordingly' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let data = 'data';
+ let link = {
+ fromCP:'testVal',
+ toNode:'testVal',
+ toCP:'testVal'
+ }
+ let target = ['val1', 'val2'];
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.data = data;
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.target = target;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onSourceSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.findOptions).toHaveBeenCalledWith(data, id);
+ expect(fixture.componentInstance.srcCP).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.fromCP).toBe('');
+ expect(fixture.componentInstance.link.toNode).toBe('');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+ expect(fixture.componentInstance.target.length).toBe(0);
+ expect(fixture.componentInstance.targetCP.length).toBe(0);
+ });
+
+ it('onSourceSelected() -> in case id undefined -> No Change to srcCP, link.fromCP, link.toNode, link.toCP, target, targetCP' ,() => {
+ // init values / mock functions
+ let id;
+ let data = 'data';
+ let link = {
+ fromCP:'testVal',
+ toNode:'testVal',
+ toCP:'testVal'
+ }
+ let target = ['val1', 'val2'];
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.data = data;
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.target = target;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onSourceSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.fromCP).toBe(link.fromCP);
+ expect(fixture.componentInstance.link.toNode).toBe(link.toNode);
+ expect(fixture.componentInstance.link.toCP).toBe(link.toCP);
+ expect(fixture.componentInstance.target.length).toBe(2);
+ expect(fixture.componentInstance.target[0]).toBe('val1')
+ expect(fixture.componentInstance.targetCP.length).toBe(2);
+ expect(fixture.componentInstance.targetCP[1]).toBe('val2');
+ });
+
+ it('onSrcCPSelected() -> in case id -> Verify target, link.fromCPOriginId, link.toNode, link.toCP, targetCP.length' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ fromNode:'testVal',
+ toCPOriginId: 'initValue_ShouldBeChanged'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+
+ // call to the tested function
+ fixture.componentInstance.onSrcCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.target).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.fromCPOriginId).toBe(option2.data.ownerId);
+ expect(fixture.componentInstance.link.toNode).toBe('');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+ expect(fixture.componentInstance.targetCP.length).toBe(0);
+
+ });
+
+ it('onSrcCPSelected() -> in case id undefined -> Verify target, link.fromCPOriginId, link.toNode, link.toCP, targetCP.length' ,() => {
+ // init values / mock functions
+ let id;
+
+ let targetInput:Array<DropdownValue> = [{value:'Value', label:'Label', hidden:true, selected:true}];
+
+ let linkInput = {
+ fromCPOriginId:'expectedLinkFromCPOriginId',
+ toNode:'expectedLinkToNode',
+ toCP:'expectedLinkToCP',
+ // Link Object
+ canEdit:true,
+ canRemove:true,
+ isFirst:true,
+ // ForwardingPathLink Object
+ ownerId:'',
+ fromNode:'',
+ fromCP:'',
+ toCPOriginId:''
+ }
+
+ fixture.componentInstance.target = targetInput;
+ fixture.componentInstance.link = linkInput;
+ fixture.componentInstance.targetCP = targetInput;
+
+
+ // call to the tested function
+ fixture.componentInstance.onSrcCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.target).toBe(targetInput);
+ expect(fixture.componentInstance.link.fromCPOriginId).toBe('expectedLinkFromCPOriginId');
+ expect(fixture.componentInstance.link.toNode).toBe('expectedLinkToNode');
+ expect(fixture.componentInstance.link.toCP).toBe('expectedLinkToCP');
+ expect(fixture.componentInstance.targetCP.length).toBe(1);
+ });
+
+ it('onTargetSelected() -> in case id -> Verify targetCP & link.toCP' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ toCP:'testVal'
+ }
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onTargetSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.targetCP).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+
+ });
+
+ it('onTargetSelected() -> in case id undefined -> Verify targetCP & link.toCP' ,() => {
+ // init values / mock functions
+ let id;
+ let link = {
+ toCP:'toCP_testVal'
+ }
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onTargetSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.targetCP.length).toBe(2);
+ expect(fixture.componentInstance.targetCP).toEqual(['val1', 'val2']);
+ expect(fixture.componentInstance.link.toCP).toBe('toCP_testVal');
+ });
+
+ it('onTargetCPSelected() -> in case id -> Validate toCPOriginId' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ toNode:'testVal',
+ toCPOriginId: 'initValue_ShouldBeChanged'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+
+ // call to the tested function
+ fixture.componentInstance.onTargetCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.toCPOriginId).toBe(option2.data.ownerId);
+ });
+
+ it('onTargetCPSelected() -> in case id undefined -> Validate toCPOriginId' ,() => {
+ // init values / mock functions
+ let id;
+ let link = {
+ toNode:'testVal',
+ toCPOriginId: 'initValue_ShouldRemain'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+
+ // call to the tested function
+ fixture.componentInstance.onTargetCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.toCPOriginId).toBe('initValue_ShouldRemain');
+ });
+
+
+ it('findOptions() -> in case item.data.options -> Validate return item.data.options' ,() => {
+ // init values / mock functions
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const innerServicePathItem: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ const mapItemData1: MapItemData = { id: 'mapItemData1_id', name: 'mapItemData1_name', options: [innerServicePathItem]};
+
+ const servicePathItem: ServicePathMapItem = { id: 'servicePathItem_id', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem];
+
+ let nodeOrCPId: string = servicePathItem.id;
+
+ // call to the tested function
+ let res = fixture.componentInstance.findOptions(arrServicePathItems, nodeOrCPId);
+
+ // expect that
+ expect(res).toEqual([innerServicePathItem]);
+ });
+
+ it('findOptions() -> in case NOT item || item.data || item.data.options -> Validate return null' ,() => {
+ // init values / mock functions
+ let item = [{
+ // data: {
+ data:{
+ name:'data_name',
+ id: 'data_id'
+ },
+ name:'name',
+ id: 'id'
+ // }
+ }];
+ let items: Array<ServicePathMapItem> = item;
+ let nodeOrCPId: string = 'someString';
+
+ // call to the tested function
+ let res = fixture.componentInstance.findOptions(items, nodeOrCPId);
+
+ // expect that
+ expect(res).toBe(null);
+ });
+
+ it('convertValuesToDropDownOptions() -> Verify that the result is sorted' ,() => {
+ // init values / mock functions
+ const mapItemData1: MapItemData = { id: 'Z_ID', name: 'Z_NAME'};
+ const servicePathItem1: ServicePathMapItem = { id: 'Z_servicePathItem_id', data: mapItemData1 };
+
+ const mapItemData2: MapItemData = { id: 'A_ID', name: 'A_NAME'};
+ const servicePathItem2: ServicePathMapItem = { id: 'A_servicePathItem_id', data: mapItemData2 };
+
+ const mapItemData3: MapItemData = { id: 'M_ID', name: 'M_NAME'};
+ const servicePathItem3: ServicePathMapItem = { id: 'M_servicePathItem_id', data: mapItemData3 };
+
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1, servicePathItem2, servicePathItem3];
+
+ // call to the tested function
+ let res = fixture.componentInstance.convertValuesToDropDownOptions(arrServicePathItems);
+
+ // expect that
+ expect(res.length).toBe(3);
+ expect(res[0].value).toBe("A_servicePathItem_id");
+ expect(res[0].label).toBe("A_NAME");
+ expect(res[1].value).toBe("M_servicePathItem_id");
+ expect(res[1].label).toBe("M_NAME");
+ expect(res[2].value).toBe("Z_servicePathItem_id");
+ expect(res[2].label).toBe("Z_NAME");
+
+ });
+
+ it('parseInitialData() -> link.fromNode Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode";
+ const label = "expected_label_fromNode"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+ it('parseInitialData() -> link.fromNode & link.fromCP Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal',
+ fromCP: 'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode_and_fromCP";
+ const label = "expected_label_fromNode_and_fromCP"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+
+ it('parseInitialData() -> link.fromNode & link.fromCP & link.toNode Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal',
+ fromCP: 'testVal',
+ toNode: 'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode_and_fromCP_and_toNode";
+ const label = "expected_label_fromNode_and_fromCP_and_toNode"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts
similarity index 98%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts
index e4fc1d4..83c30b1 100644
--- a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link-row.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts
@@ -2,6 +2,7 @@
import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
import {Link} from './link.model';
import {ServicePathMapItem} from "app/models/graph/nodes-and-links-map";
+import * as _ from "lodash";
@Component({
selector: 'link-row',
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link.model.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/link-row/link.model.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html
similarity index 99%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html
index cc14b49..db0d912 100644
--- a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="service-path-creator">
<form class="w-sdc-form">
<div class="i-sdc-form-item" >
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less
similarity index 92%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less
index 5c9e53e..2a3efbd 100644
--- a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less
@@ -1,4 +1,4 @@
-@import './../../../../assets/styles/variables.less';
+@import './../../../../../../assets/styles/variables.less';
.service-path-creator {
font-family: @font-opensans-regular;
.separator-buttons {
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts
similarity index 93%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts
index bffb1c5..17c2081 100644
--- a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts
@@ -25,6 +25,7 @@
import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
import {ForwardingPathLink} from "app/models/forwarding-path-link";
import {ServicePathMapItem} from "app/models/graph/nodes-and-links-map";
+import {CompositionService} from "app/ng2/pages/composition/composition.service";
@Component({
selector: 'service-path-creator',
@@ -43,7 +44,8 @@
forwardingPath:ForwardingPath;
//isExtendAllowed:boolean = false;
- constructor(private serviceService: ServiceServiceNg2) {
+ constructor(private serviceService: ServiceServiceNg2,
+ private compositionService: CompositionService) {
this.forwardingPath = new ForwardingPath();
this.links = [new Link(new ForwardingPathLink('', '', '', '', '', ''), true, false, true)];
this.headers = ['Source', 'Source Connection Point', 'Target', 'Target Connection Point', ' '];
@@ -57,7 +59,7 @@
}
ngOnInit() {
- this.serviceService.getNodesAndLinksMap(this.input.service).subscribe((res:any) => {
+ this.serviceService.getNodesAndLinksMap(this.input.serviceId).subscribe((res:any) => {
this.linksMap = res;
});
this.processExistingPath();
@@ -66,7 +68,7 @@
private processExistingPath() {
if (this.input.pathId) {
- let forwardingPath = <ForwardingPath>{...this.input.service.forwardingPaths[this.input.pathId]};
+ let forwardingPath = <ForwardingPath>{...this.compositionService.forwardingPaths[this.input.pathId]};
this.forwardingPath.name = forwardingPath.name;
this.forwardingPath.destinationPortNumber = forwardingPath.destinationPortNumber;
this.forwardingPath.protocol = forwardingPath.protocol;
diff --git a/catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/service-path-creator/service-path-creator.module.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.html
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.less
similarity index 86%
rename from catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.less
index f3cb4a3..f618d6b 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.less
@@ -1,4 +1,4 @@
-@import './../../../../../assets/styles/variables.less';
+@import './../../../../../../assets/styles/variables.less';
.service-path-selector {
margin: 10px 35px 10px 0;
display: flex;
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.ts
new file mode 100644
index 0000000..0dba906
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.component.ts
@@ -0,0 +1,142 @@
+import {Component, Input, KeyValueDiffer, IterableDiffers, KeyValueDiffers, DoCheck} from '@angular/core';
+import {Service} from "app/models/components/service";
+import {TranslateService} from "app/ng2/shared/translator/translate.service";
+import {ForwardingPath} from "app/models/forwarding-path";
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {CompositionService} from "app/ng2/pages/composition/composition.service";
+import {EventListenerService} from "app/services/event-listener-service";
+import {GRAPH_EVENTS} from "app/utils/constants";
+
+@Component({
+ selector: 'service-path-selector',
+ templateUrl: './service-path-selector.component.html',
+ styleUrls: ['service-path-selector.component.less']
+})
+
+export class ServicePathSelectorComponent {
+
+ defaultSelectedId: string;
+ hideAllValue: string;
+ hideAllId: string = '0';
+ showAllValue: string;
+ showAllId: string = '1';
+
+ paths: Array<ForwardingPath> = [];
+ dropdownOptions: Array<DropdownValue>;
+ differ: KeyValueDiffer<string, ForwardingPath>;
+
+ @Input() drawPath: Function;
+ @Input() deletePaths: Function;
+ @Input() selectedPathId: string;
+
+ constructor(private differs: KeyValueDiffers,
+ private translateService: TranslateService,
+ private compositionService: CompositionService,
+ private eventListenerService: EventListenerService
+ ) {
+
+ this.defaultSelectedId = this.hideAllId;
+ this.convertPathsToDropdownOptions();
+
+ this.translateService.languageChangedObservable.subscribe(lang => {
+ this.hideAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_HIDE_ALL_VALUE");
+ this.showAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_SHOW_ALL_VALUE");
+ this.convertPathsToDropdownOptions();
+ });
+
+ }
+
+ ngOnInit(): void {
+
+ this.selectedPathId = this.defaultSelectedId;
+ this.differ = this.differs.find(this.compositionService.forwardingPaths).create();
+ this.updatePaths();
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_SERVICE_PATH_CREATED, (createdId) => {
+ this.selectedPathId = createdId;
+ this.updatePaths();
+ } )
+
+ }
+
+ updatePaths(): void {
+
+ const pathsChanged = this.differ.diff(this.compositionService.forwardingPaths);
+
+ if (pathsChanged) {
+ let oldPaths = _.cloneDeep(this.paths);
+ this.populatePathsFromService();
+
+ if (!(_.isEqual(oldPaths, this.paths))) {
+ this.convertPathsToDropdownOptions();
+
+ let temp = this.selectedPathId;
+ this.selectedPathId = '-1';
+
+ setTimeout(() => {
+ this.selectedPathId = temp;
+ this.onSelectPath();
+ }, 0);
+ }
+ }
+
+ }
+
+ populatePathsFromService(): void {
+
+ this.paths = [];
+
+ _.forEach(this.compositionService.forwardingPaths, path => {
+ this.paths.push(path);
+ });
+ this.paths.sort((a: ForwardingPath, b: ForwardingPath) => {
+ return a.name.localeCompare(b.name);
+ });
+
+ }
+
+ convertPathsToDropdownOptions(): void {
+
+ let result = [
+ new DropdownValue(this.hideAllId, this.hideAllValue),
+ new DropdownValue(this.showAllId, this.showAllValue)
+ ];
+
+ _.forEach(this.paths, (value: ForwardingPath) => {
+ result[result.length] = new DropdownValue(value.uniqueId, value.name);
+ });
+
+ this.dropdownOptions = result;
+
+ }
+
+ onSelectPath = (): void => {
+
+ if (this.selectedPathId !== '-1') {
+ this.deletePaths();
+
+ switch (this.selectedPathId) {
+ case this.hideAllId:
+ break;
+
+ case this.showAllId:
+ _.forEach(this.paths, path =>
+ this.drawPath(path)
+ );
+ break;
+
+ default:
+ let path = this.paths.find(path =>
+ path.uniqueId === this.selectedPathId
+ );
+ if (!path) {
+ this.selectedPathId = this.defaultSelectedId;
+ this.onSelectPath(); // currently does nothing in default case, but if one day it does, we want the selection to behave accordingly.
+ break;
+ }
+ this.drawPath(path);
+ break;
+ }
+ }
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.module.ts
similarity index 75%
rename from catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.module.ts
index c07061c..6782c88 100644
--- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-selector/service-path-selector.module.ts
@@ -2,6 +2,7 @@
import {CommonModule} from "@angular/common";
import {ServicePathSelectorComponent} from "./service-path-selector.component";
import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import {CompositionService} from "app/ng2/pages/composition/composition.service";
@NgModule({
declarations: [
@@ -11,11 +12,11 @@
CommonModule,
UiElementsModule
],
- exports: [],
+ exports: [ServicePathSelectorComponent],
entryComponents: [
ServicePathSelectorComponent
],
- providers: []
+ providers: [CompositionService]
})
export class ServicePathSelectorModule {
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.html
similarity index 62%
rename from catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.html
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.html
index 33a0090..39c4191 100644
--- a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.html
@@ -1,19 +1,3 @@
-<!--
- ~ 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="service-path-list">
<div class="add-path-link" *ngIf="!isViewOnly"><a (click)="onAddServicePath()" data-tests-id="add-service-path-lnk" >+ Add Flow</a></div>
<div class="generic-table table-container" >
diff --git a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.less
similarity index 84%
rename from catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.less
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.less
index 291119f..17f7092 100644
--- a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.less
@@ -1,4 +1,4 @@
-@import './../../../../assets/styles/variables.less';
+@import './../../../../../../assets/styles/variables.less';
.add-path-link {
display: flex;
diff --git a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.ts
similarity index 85%
rename from catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.ts
index 1625ab4..81abe42 100644
--- a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component.ts
@@ -24,6 +24,7 @@
import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
import {ModalService} from "app/ng2/services/modal.service";
import {ModalComponent} from "app/ng2/components/ui/modal/modal.component";
+import {CompositionService} from "app/ng2/pages/composition/composition.service";
@Component({
selector: 'service-paths-list',
@@ -31,7 +32,7 @@
styleUrls:['service-paths-list.component.less'],
providers: [ServiceServiceNg2, ModalService]
})
-export default class ServicePathsListComponent {
+export class ServicePathsListComponent {
modalInstance: ComponentRef<ModalComponent>;
headers: Array<string> = [];
paths: Array<ForwardingPath> = [];
@@ -40,12 +41,13 @@
onEditServicePath: Function;
isViewOnly: boolean;
- constructor(private serviceService:ServiceServiceNg2) {
+ constructor(private serviceService:ServiceServiceNg2,
+ private compositionService: CompositionService) {
this.headers = ['Flow Name','Actions'];
}
ngOnInit() {
- _.forEach(this.input.service.forwardingPaths, (path: ForwardingPath)=> {
+ _.forEach(this.compositionService.forwardingPaths, (path: ForwardingPath)=> {
this.paths[this.paths.length] = path;
});
this.paths.sort((a:ForwardingPath, b:ForwardingPath)=> {
@@ -57,8 +59,8 @@
}
deletePath = (id:string):void => {
- this.serviceService.deleteServicePath(this.input.service, id).subscribe((res:any) => {
- delete this.input.service.forwardingPaths[id];
+ this.serviceService.deleteServicePath(this.input.serviceId, id).subscribe((res:any) => {
+ delete this.compositionService.forwardingPaths[id];
this.paths = this.paths.filter(function(path){
return path.uniqueId !== id;
});
diff --git a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.module.ts
similarity index 81%
rename from catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.module.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.module.ts
index c236934..5121627 100644
--- a/catalog-ui/src/app/ng2/pages/service-paths-list/service-paths-list.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-paths-list/service-paths-list.module.ts
@@ -1,6 +1,6 @@
import { NgModule } from "@angular/core";
import {CommonModule} from "@angular/common";
-import ServicePathsListComponent from "./service-paths-list.component";
+import { ServicePathsListComponent } from "./service-paths-list.component";
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-general-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-general-utils.ts
new file mode 100644
index 0000000..bc8bd69
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-general-utils.ts
@@ -0,0 +1,268 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import {ComponentInstance, Match, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models";
+import {Dictionary, GraphUIObjects} from "app/utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {CommonGraphUtils} from "../common/common-graph-utils";
+import {Injectable} from "@angular/core";
+import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
+import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service";
+import {RequirementsGroup} from "app/models/requirement";
+import {CapabilitiesGroup} from "app/models/capability";
+import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
+import {CompositionService} from "../../composition.service";
+import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
+import {NotificationsService} from "onap-ui-angular/dist/notifications/services/notifications.service";
+import {NotificationSettings} from "onap-ui-angular/dist/notifications/utilities/notification.config";
+
+export interface RequirementAndCapabilities {
+ capabilities: CapabilitiesGroup;
+ requirements: RequirementsGroup;
+}
+
+@Injectable()
+export class CompositionGraphGeneralUtils {
+
+ public componentRequirementsAndCapabilitiesCaching = new Dictionary<string, RequirementAndCapabilities>();
+
+ constructor(private commonGraphUtils: CommonGraphUtils,
+ private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
+ private queueServiceUtils: QueueServiceUtils,
+ private componentService: ComponentServiceNg2,
+ private topologyTemplateService: TopologyTemplateService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService) {
+ }
+
+ /**
+ * Get the offset for the link creation Menu
+ * @param point
+ * @returns {Cy.Position}
+ */
+ public calcMenuOffset: Function = (point: Cy.Position): Cy.Position => {
+ point.x = point.x + 60;
+ point.y = point.y + 105;
+ return point;
+ };
+
+ /**
+ * return the top left position of the link menu
+ * @param cy
+ * @param targetNodePosition
+ * @returns {Cy.Position}
+ */
+ public getLinkMenuPosition = (cy: Cy.Instance, targetNodePosition: Cy.Position) => {
+ let menuPosition: Cy.Position = this.calcMenuOffset(targetNodePosition); //get the link mid point
+ if ($(document.body).height() < menuPosition.y + GraphUIObjects.LINK_MENU_HEIGHT + $(document.getElementsByClassName('sdc-composition-graph-wrapper')).offset().top) { // if position menu is overflow bottom
+ menuPosition.y = $(document.body).height() - GraphUIObjects.TOP_HEADER_HEIGHT - GraphUIObjects.LINK_MENU_HEIGHT;
+ }
+ return menuPosition;
+ };
+
+ public zoomGraphTo = (cy: Cy.Instance, zoomLevel: number): void => {
+ let zy = cy.height() / 2;
+ let zx = cy.width() / 2;
+ cy.zoom({
+ level: zoomLevel,
+ renderedPosition: {x: zx, y: zy}
+ });
+ }
+
+ //saves the current zoom, and then sets a temporary maximum zoom for zoomAll, and then reverts to old value
+ public zoomAllWithMax = (cy: Cy.Instance, maxZoom: number): void => {
+
+ let oldMaxZoom: number = cy.maxZoom();
+
+ cy.maxZoom(maxZoom);
+ this.zoomAll(cy);
+ cy.maxZoom(oldMaxZoom);
+
+ };
+
+ //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph
+ public zoomAll = (cy: Cy.Instance, nodes?: Cy.CollectionNodes): void => {
+
+ if (!nodes || !nodes.length) {
+ nodes = cy.nodes();
+ }
+
+ cy.resize();
+ cy.animate({
+ fit: {eles: nodes, padding: 20},
+ center: {eles: nodes}
+ }, {duration: 400});
+ };
+
+ /**
+ * will return true/false if two nodes overlapping
+ *
+ * @param graph node
+ */
+ private isNodesOverlapping(node: Cy.CollectionFirstNode, draggedNode: Cy.CollectionFirstNode): boolean {
+
+ let nodeBoundingBox: Cy.BoundingBox = node.renderedBoundingBox();
+ let secondNodeBoundingBox: Cy.BoundingBox = draggedNode.renderedBoundingBox();
+
+ return this.isBBoxOverlapping(nodeBoundingBox, secondNodeBoundingBox);
+ }
+
+ /**
+ * Checks whether the bounding boxes of two nodes are overlapping on any side
+ * @param nodeOneBBox
+ * @param nodeTwoBBox
+ * @returns {boolean}
+ */
+ private isBBoxOverlapping(nodeOneBBox: Cy.BoundingBox, nodeTwoBBox: Cy.BoundingBox) {
+ return (((nodeOneBBox.x1 < nodeTwoBBox.x1 && nodeOneBBox.x2 > nodeTwoBBox.x1) ||
+ (nodeOneBBox.x1 < nodeTwoBBox.x2 && nodeOneBBox.x2 > nodeTwoBBox.x2) ||
+ (nodeTwoBBox.x1 < nodeOneBBox.x1 && nodeTwoBBox.x2 > nodeOneBBox.x2)) &&
+ ((nodeOneBBox.y1 < nodeTwoBBox.y1 && nodeOneBBox.y2 > nodeTwoBBox.y1) ||
+ (nodeOneBBox.y1 < nodeTwoBBox.y2 && nodeOneBBox.y2 > nodeTwoBBox.y2) ||
+ (nodeTwoBBox.y1 < nodeOneBBox.y1 && nodeTwoBBox.y2 > nodeOneBBox.y2)))
+ }
+
+ /**
+ * Checks whether a specific topologyTemplate instance can be hosted on the UCPE instance
+ * @param cy - Cytoscape instance
+ * @param fromUcpeInstance
+ * @param toComponentInstance
+ * @returns {Match}
+ */
+ public canBeHostedOn(cy: Cy.Instance, fromUcpeInstance: ComponentInstance, toComponentInstance: ComponentInstance): Match {
+
+ let matches: Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromUcpeInstance, toComponentInstance, this.getAllCompositionCiLinks(cy));
+ let hostedOnMatch: Match = _.find(matches, (match: Match) => {
+ return match.requirement.capability.toLowerCase() === 'tosca.capabilities.container';
+ });
+
+ return hostedOnMatch;
+ };
+
+ /**
+ * Checks whether node can be dropped into UCPE
+ * @param cy
+ * @param nodeToInsert
+ * @param ucpeNode
+ * @returns {boolean}
+ */
+ private isValidDropInsideUCPE(cy: Cy.Instance, nodeToInsert: ComponentInstance, ucpeNode: ComponentInstance): boolean {
+
+ let hostedOnMatch: Match = this.canBeHostedOn(cy, ucpeNode, nodeToInsert);
+ let result: boolean = !angular.isUndefined(hostedOnMatch) || nodeToInsert.isVl(); //group validation
+ return result;
+
+ };
+
+ /**
+ * For drops from palette, checks whether the node can be dropped. If node is being held over another node, check if capable of hosting
+ * @param cy
+ * @param pseudoNodeBBox
+ * @param paletteComponentInstance
+ * @returns {boolean}
+ */
+ public isPaletteDropValid(cy: Cy.Instance, pseudoNodeBBox: Cy.BoundingBox) {
+
+ let illegalOverlappingNodes = _.filter(cy.nodes("[isSdcElement]"), (graphNode: Cy.CollectionFirstNode) => {
+ if (this.isBBoxOverlapping(pseudoNodeBBox, graphNode.renderedBoundingBox())) {
+ return true;
+ }
+ return false;
+ });
+
+ return illegalOverlappingNodes.length === 0;
+ }
+
+ /**
+ * will return true/false if a drop of a single node is valid
+ *
+ * @param graph node
+ */
+ public isValidDrop(cy: Cy.Instance, draggedNode: Cy.CollectionFirstNode): boolean {
+
+ let illegalOverlappingNodes = _.filter(cy.nodes("[isSdcElement]"), (graphNode: Cy.CollectionFirstNode) => { //all sdc nodes, removing child nodes (childe node allways collaps
+
+ if (draggedNode.data().isUcpe && (graphNode.isChild() || graphNode.data().isInsideGroup)) { //ucpe cps always inside ucpe, no overlapping
+ return false;
+ }
+ if (draggedNode.data().isInsideGroup && (!draggedNode.active() || graphNode.data().isUcpe)) {
+ return false;
+ }
+
+ if (!draggedNode.data().isUcpe && !(draggedNode.data() instanceof CompositionCiNodeUcpeCp) && graphNode.data().isUcpe) { //case we are dragging a node into UCPE
+ let isEntirelyInUCPE: boolean = this.commonGraphUtils.isFirstBoxContainsInSecondBox(draggedNode.renderedBoundingBox(), graphNode.renderedBoundingBox());
+ if (isEntirelyInUCPE) {
+ if (this.isValidDropInsideUCPE(cy, draggedNode.data().componentInstance, graphNode.data().componentInstance)) { //if this is valid insert into ucpe, we return false - no illegal overlapping nodes
+ return false;
+ }
+ }
+ }
+ return graphNode.data().id !== draggedNode.data().id && this.isNodesOverlapping(draggedNode, graphNode);
+
+ });
+ // return false;
+ return illegalOverlappingNodes.length === 0;
+ };
+
+ /**
+ * will return true/false if the move of the nodes is valid (no node overlapping and verifying if insert into UCPE is valid)
+ *
+ * @param nodesArray - the selected drags nodes
+ */
+ public isGroupValidDrop(cy: Cy.Instance, nodesArray: Cy.CollectionNodes): boolean {
+ let filterDraggedNodes = nodesArray.filter('[?isDraggable]');
+ let isValidDrop = _.every(filterDraggedNodes, (node: Cy.CollectionFirstNode) => {
+ return this.isValidDrop(cy, node);
+
+ });
+ return isValidDrop;
+ };
+
+ /**
+ * get all links in diagram
+ * @param cy
+ * @returns {any[]|boolean[]}
+ */
+ public getAllCompositionCiLinks = (cy: Cy.Instance): Array<CompositionCiLinkBase> => {
+ return _.map(cy.edges("[isSdcElement]"), (edge: Cy.CollectionEdges) => {
+ return edge.data();
+ });
+ };
+
+ /**
+ *
+ * @param blockAction - true/false if this is a block action
+ * @param instances
+ * @param component
+ */
+ public pushMultipleUpdateComponentInstancesRequestToQueue = (instances: Array<ComponentInstance>): void => {
+ this.queueServiceUtils.addNonBlockingUIAction(() => {
+ return new Promise<boolean>((resolve, reject) => {
+ let uniqueId = this.workspaceService.metadata.uniqueId;
+ let topologyType = this.workspaceService.metadata.componentType;
+ this.topologyTemplateService.updateMultipleComponentInstances(uniqueId, topologyType, instances).subscribe(instancesResult => {
+ this.compositionService.updateComponentInstances(instancesResult);
+ resolve(true);
+ });
+ });
+ });
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-links-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-links-utils.ts
new file mode 100644
index 0000000..6035d05
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-links-utils.ts
@@ -0,0 +1,342 @@
+/*-
+ * ============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 obarda on 6/28/2016.
+ */
+import * as _ from "lodash";
+import {GraphUIObjects} from "app/utils";
+import {
+ Match,
+ CompositionCiNodeBase,
+ RelationshipModel,
+ ConnectRelationModel,
+ LinksFactory,
+ Component,
+ LinkMenu,
+ Point,
+ CompositionCiLinkBase,
+ Requirement,
+ Capability,
+ Relationship,
+ ComponentInstance
+} from "app/models";
+import {CommonGraphUtils} from "../common/common-graph-utils";
+import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
+import {Injectable} from "@angular/core";
+import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
+import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
+import {SdcUiServices} from "onap-ui-angular";
+import {CompositionService} from "../../composition.service";
+import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
+
+@Injectable()
+export class CompositionGraphLinkUtils {
+
+ constructor(private linksFactory: LinksFactory,
+ private generalGraphUtils: CompositionGraphGeneralUtils,
+ private commonGraphUtils: CommonGraphUtils,
+ private queueServiceUtils: QueueServiceUtils,
+ private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
+ private topologyTemplateService: TopologyTemplateService,
+ private loaderService: SdcUiServices.LoaderService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService) {
+
+
+ }
+
+ /**
+ * Delete the link on server and then remove it from graph
+ * @param component
+ * @param releaseLoading - true/false release the loader when finished
+ * @param link - the link to delete
+ */
+ public deleteLink = (cy: Cy.Instance, component: Component, releaseLoading: boolean, link: Cy.CollectionEdges) => {
+
+ this.loaderService.activate();
+ this.queueServiceUtils.addBlockingUIAction(() => {
+ this.topologyTemplateService.deleteRelation(this.workspaceService.metadata.uniqueId, this.workspaceService.metadata.componentType, link.data().relation).subscribe((deletedRelation) => {
+ this.compositionService.deleteRelation(deletedRelation);
+ cy.remove(link);
+ this.loaderService.deactivate();
+ }, (error) => {this.loaderService.deactivate()});
+ });
+ };
+
+ /**
+ * create the link on server and than draw it on graph
+ * @param link - the link to create
+ * @param cy
+ * @param component
+ */
+ public createLink = (link: CompositionCiLinkBase, cy: Cy.Instance): void => {
+
+ this.loaderService.activate();
+ link.updateLinkDirection();
+
+ this.queueServiceUtils.addBlockingUIAction(() => {
+ this.topologyTemplateService.createRelation(this.workspaceService.metadata.uniqueId, this.workspaceService.metadata.componentType, link.relation).subscribe((relation) => {
+ link.setRelation(relation);
+ this.insertLinkToGraph(cy, link);
+ this.compositionService.addRelation(relation);
+ this.loaderService.deactivate();
+ }, (error) => {this.loaderService.deactivate()})
+ });
+ };
+
+ private createSimpleLink = (match: Match, cy: Cy.Instance): void => {
+ let newRelation: RelationshipModel = match.matchToRelationModel();
+ let linkObg: CompositionCiLinkBase = this.linksFactory.createGraphLink(cy, newRelation, newRelation.relationships[0]);
+ this.createLink(linkObg, cy);
+ };
+
+ public createLinkFromMenu = (cy: Cy.Instance, chosenMatch: Match): void => {
+
+ if (chosenMatch) {
+ if (chosenMatch && chosenMatch instanceof Match) {
+ this.createSimpleLink(chosenMatch, cy);
+ }
+ }
+ }
+
+ /**
+ * open the connect link menu if the link drawn is valid - match requirements & capabilities
+ * @param cy
+ * @param fromNode
+ * @param toNode
+ * @returns {any}
+ */
+ public onLinkDrawn(cy: Cy.Instance, fromNode: Cy.CollectionFirstNode, toNode: Cy.CollectionFirstNode): ConnectRelationModel {
+
+ let linkModel: Array<CompositionCiLinkBase> = this.generalGraphUtils.getAllCompositionCiLinks(cy);
+
+ let possibleRelations: Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromNode.data().componentInstance,
+ toNode.data().componentInstance, linkModel);
+
+ //if found possibleRelations between the nodes we create relation menu directive and open the link menu
+ if (possibleRelations.length) {
+ // let menuPosition = this.generalGraphUtils.getLinkMenuPosition(cy, toNode.renderedPoint());
+ return new ConnectRelationModel(fromNode.data(), toNode.data(), possibleRelations);
+ }
+ return null;
+ };
+
+ private handlePathLink(cy: Cy.Instance, event: Cy.EventObject) {
+ let linkData = event.cyTarget.data();
+ let selectedPathId = linkData.pathId;
+ let pathEdges = cy.collection(`[pathId='${selectedPathId}']`);
+ if (pathEdges.length > 1) {
+ setTimeout(() => {
+ pathEdges.select();
+ }, 0);
+ }
+ }
+
+ private handleVLLink(event: Cy.EventObject) {
+ let vl: Cy.CollectionNodes = event.cyTarget[0].target('.vl-node');
+ let connectedEdges: Cy.CollectionEdges = vl.connectedEdges(`[type!="${CompositionCiServicePathLink.LINK_TYPE}"]`);
+ if (vl.length && connectedEdges.length > 1) {
+ setTimeout(() => {
+ vl.select();
+ connectedEdges.select();
+ }, 0);
+ }
+ }
+
+
+ /**
+ * Handles click event on links.
+ * If one edge selected: do nothing.
+ * Two or more edges: first click - select all, secondary click - select single.
+ * @param cy
+ * @param event
+ */
+ public handleLinkClick(cy: Cy.Instance, event: Cy.EventObject) {
+ if (cy.$('edge:selected').length > 1 && event.cyTarget[0].selected()) {
+ cy.$(':selected').unselect();
+ } else {
+ if (event.cyTarget[0].data().type === CompositionCiServicePathLink.LINK_TYPE) {
+ this.handlePathLink(cy, event);
+ }
+ else {
+ this.handleVLLink(event);
+ }
+ }
+ }
+
+
+ /**
+ * Calculates the position for the menu that modifies an existing link
+ * @param event
+ * @param elementWidth
+ * @param elementHeight
+ * @returns {Point}
+ */
+ public calculateLinkMenuPosition(event, elementWidth, elementHeight): Point {
+ let point: Point = new Point(event.originalEvent.clientX, event.originalEvent.clientY);
+ if (event.originalEvent.view.screen.height - elementHeight < point.y) {
+ point.y = event.originalEvent.view.screen.height - elementHeight;
+ }
+ if (event.originalEvent.view.screen.width - elementWidth < point.x) {
+ point.x = event.originalEvent.view.screen.width - elementWidth;
+ }
+ return point;
+ };
+
+
+ /**
+ * Gets the menu that is displayed when you click an existing link.
+ * @param link
+ * @param event
+ * @returns {LinkMenu}
+ */
+ public getModifyLinkMenu(link: Cy.CollectionFirstEdge, event: Cy.EventObject): LinkMenu {
+ let point: Point = this.calculateLinkMenuPosition(event, GraphUIObjects.MENU_LINK_VL_WIDTH_OFFSET, GraphUIObjects.MENU_LINK_VL_HEIGHT_OFFSET);
+ let menu: LinkMenu = new LinkMenu(point, true, link);
+ return menu;
+ };
+
+ /**
+ * Returns relation source and target nodes.
+ * @param nodes - all nodes in graph in order to find the edge connecting the two nodes
+ * @param fromNodeId
+ * @param toNodeId
+ * @returns [source, target] array of source node and target node.
+ */
+ public getRelationNodes(nodes: Cy.CollectionNodes, fromNodeId: string, toNodeId: string) {
+ return [
+ _.find(nodes, (node: Cy.CollectionFirst) => node.data().id === fromNodeId),
+ _.find(nodes, (node: Cy.CollectionFirst) => node.data().id === toNodeId)
+ ];
+ }
+
+
+ /**
+ * go over the relations and draw links on the graph
+ * @param cy
+ * @param getRelationRequirementCapability - function to get requirement and capability of a relation
+ */
+ public initGraphLinks(cy: Cy.Instance, relations: RelationshipModel[]) {
+ if (relations) {
+ _.forEach(relations, (relationshipModel: RelationshipModel) => {
+ _.forEach(relationshipModel.relationships, (relationship: Relationship) => {
+ let linkToCreate = this.linksFactory.createGraphLink(cy, relationshipModel, relationship);
+ this.insertLinkToGraph(cy, linkToCreate);
+ });
+ });
+ }
+ }
+
+ /**
+ * Add link to graph - only draw the link
+ * @param cy
+ * @param link
+ * @param getRelationRequirementCapability
+ */
+ public insertLinkToGraph = (cy: Cy.Instance, link: CompositionCiLinkBase) => {
+ const relationNodes = this.getRelationNodes(cy.nodes(), link.source, link.target);
+ const sourceNode: CompositionCiNodeBase = relationNodes[0] && relationNodes[0].data();
+ const targetNode: CompositionCiNodeBase = relationNodes[1] && relationNodes[1].data();
+ if ((sourceNode && !sourceNode.certified) || (targetNode && !targetNode.certified)) {
+ link.classes = 'not-certified-link';
+ }
+ let linkElement = cy.add({
+ group: 'edges',
+ data: link,
+ classes: link.classes
+ });
+
+ const getLinkRequirementCapability = () =>
+ this.getRelationRequirementCapability(link.relation.relationships[0], sourceNode.componentInstance, targetNode.componentInstance);
+ this.commonGraphUtils.initLinkTooltip(linkElement, link.relation.relationships[0], getLinkRequirementCapability);
+ };
+
+ public syncComponentByRelation(relation: RelationshipModel) {
+ let componentInstances = this.compositionService.getComponentInstances();
+ relation.relationships.forEach((rel) => {
+ if (rel.capability) {
+ const toComponentInstance: ComponentInstance = componentInstances.find((inst) => inst.uniqueId === relation.toNode);
+ const toComponentInstanceCapability: Capability = toComponentInstance.findCapability(
+ rel.capability.type, rel.capability.uniqueId, rel.capability.ownerId, rel.capability.name);
+ const isCapabilityFulfilled: boolean = rel.capability.isFulfilled();
+ if (isCapabilityFulfilled && toComponentInstanceCapability) {
+ // if capability is fulfilled and in component, then remove it
+ console.log('Capability is fulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
+ toComponentInstance.capabilities[rel.capability.type].splice(
+ toComponentInstance.capabilities[rel.capability.type].findIndex((cap) => cap === toComponentInstanceCapability), 1
+ )
+ } else if (!isCapabilityFulfilled && !toComponentInstanceCapability) {
+ // if capability is unfulfilled and not in component, then add it
+ console.log('Capability is unfulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
+ toComponentInstance.capabilities[rel.capability.type].push(rel.capability);
+ }
+ }
+ if (rel.requirement) {
+ const fromComponentInstance: ComponentInstance = componentInstances.find((inst) => inst.uniqueId === relation.fromNode);
+ const fromComponentInstanceRequirement: Requirement = fromComponentInstance.findRequirement(
+ rel.requirement.capability, rel.requirement.uniqueId, rel.requirement.ownerId, rel.requirement.name);
+ const isRequirementFulfilled: boolean = rel.requirement.isFulfilled();
+ if (isRequirementFulfilled && fromComponentInstanceRequirement) {
+ // if requirement is fulfilled and in component, then remove it
+ console.log('Requirement is fulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
+ fromComponentInstance.requirements[rel.requirement.capability].splice(
+ fromComponentInstance.requirements[rel.requirement.capability].findIndex((req) => req === fromComponentInstanceRequirement), 1
+ )
+ } else if (!isRequirementFulfilled && !fromComponentInstanceRequirement) {
+ // if requirement is unfulfilled and not in component, then add it
+ console.log('Requirement is unfulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
+ fromComponentInstance.requirements[rel.requirement.capability].push(rel.requirement);
+ }
+ }
+ });
+ }
+
+ public getRelationRequirementCapability(relationship: Relationship, sourceNode: ComponentInstance, targetNode: ComponentInstance): Promise<{ requirement: Requirement, capability: Capability }> {
+ // try find the requirement and capability in the source and target component instances:
+ let capability: Capability = targetNode.findCapability(undefined,
+ relationship.relation.capabilityUid,
+ relationship.relation.capabilityOwnerId,
+ relationship.relation.capability);
+ let requirement: Requirement = sourceNode.findRequirement(undefined,
+ relationship.relation.requirementUid,
+ relationship.relation.requirementOwnerId,
+ relationship.relation.requirement);
+
+ return new Promise<{ requirement: Requirement, capability: Capability }>((resolve, reject) => {
+ if (capability && requirement) {
+ resolve({capability, requirement});
+ }
+ else {
+ // if requirement and/or capability is missing, then fetch the full relation with its requirement and capability:
+ this.topologyTemplateService.fetchRelation(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, relationship.relation.id).subscribe((fetchedRelation) => {
+ this.syncComponentByRelation(fetchedRelation);
+ resolve({
+ capability: capability || fetchedRelation.relationships[0].capability,
+ requirement: requirement || fetchedRelation.relationships[0].requirement
+ });
+ }, reject);
+ }
+ });
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.spec.ts
new file mode 100644
index 0000000..9dcc47f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.spec.ts
@@ -0,0 +1,158 @@
+import { TestBed } from '@angular/core/testing';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Rx';
+import CollectionNodes = Cy.CollectionNodes;
+import { Mock } from 'ts-mockery';
+import { ComponentInstance } from '../../../../../models';
+import { ComponentMetadata } from '../../../../../models/component-metadata';
+import { Resource } from '../../../../../models/components/resource';
+import { CompositionCiNodeCp } from '../../../../../models/graph/nodes/composition-graph-nodes/composition-ci-node-cp';
+import { CompositionCiNodeVl } from '../../../../../models/graph/nodes/composition-graph-nodes/composition-ci-node-vl';
+import { EventListenerService } from '../../../../../services';
+import CollectionEdges = Cy.CollectionEdges;
+import { GRAPH_EVENTS } from '../../../../../utils/constants';
+import { ServiceServiceNg2 } from '../../../../services/component-services/service.service';
+import { TopologyTemplateService } from '../../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../../services/responses/component-generic-response';
+import { QueueServiceUtils } from '../../../../utils/queue-service-utils';
+import { WorkspaceService } from '../../../workspace/workspace.service';
+import { CompositionService } from '../../composition.service';
+import { CommonGraphUtils } from '../common/common-graph-utils';
+import { CompositionGraphGeneralUtils } from './composition-graph-general-utils';
+import { CompositionGraphNodesUtils } from './composition-graph-nodes-utils';
+
+describe('composition graph nodes utils', () => {
+
+ const CP_TO_DELETE_ID = 'cp1';
+ const VL_TO_DELETE_ID = 'vl';
+ const CP2_ID = 'cp2';
+
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let service: CompositionGraphNodesUtils;
+ let topologyServiceMock: TopologyTemplateService;
+ let queueServiceMock: QueueServiceUtils;
+ let workspaceServiceMock: WorkspaceService;
+ let compositionServiceMock: CompositionService;
+ let eventListenerServiceMock: EventListenerService;
+ const cpInstanceMock: ComponentInstance = Mock.of<ComponentInstance>({
+ uniqueId: CP_TO_DELETE_ID,
+ isVl: () => false
+ });
+ const vlInstanceMock: ComponentInstance = Mock.of<ComponentInstance>({
+ uniqueId: VL_TO_DELETE_ID,
+ isVl: () => true
+ });
+ const cp2InstanceMock: ComponentInstance = Mock.of<ComponentInstance>({
+ uniqueId: CP2_ID,
+ isVl: () => false
+ });
+
+ const cyMock = Mock.of<Cy.Instance>({
+ remove: jest.fn(),
+ collection: jest.fn()
+ });
+
+ const serviceServiceMock = Mock.of<ServiceServiceNg2>({
+ getComponentCompositionData : () => Observable.of(Mock.of<ComponentGenericResponse>())
+ });
+
+ // Instances on the graph cp, vl, cp2
+ const cp = Mock.from<CompositionCiNodeCp>({ id: CP_TO_DELETE_ID, componentInstance: cpInstanceMock });
+ const vl = Mock.from<CompositionCiNodeVl>({ id: VL_TO_DELETE_ID, componentInstance: vlInstanceMock });
+ const cp2 = Mock.from<CompositionCiNodeCp>({ id: CP2_ID, componentInstance: cp2InstanceMock });
+
+ beforeEach(() => {
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ topologyServiceMock = Mock.of<TopologyTemplateService>({
+ deleteComponentInstance : () => Observable.of(cpInstanceMock)
+ });
+
+ queueServiceMock = Mock.of<QueueServiceUtils>({
+ addBlockingUIAction : ( (f) => f() )
+ });
+
+ workspaceServiceMock = Mock.of<WorkspaceService>({
+ metadata: Mock.of<ComponentMetadata>( { uniqueId: 'topologyTemplateUniqueId' } )
+ });
+
+ compositionServiceMock = Mock.of<CompositionService>({
+ deleteComponentInstance : jest.fn()
+ });
+
+ eventListenerServiceMock = Mock.of<EventListenerService>({
+ notifyObservers : jest.fn()
+ });
+
+ TestBed.configureTestingModule({
+ imports: [],
+ providers: [
+ CompositionGraphNodesUtils,
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: TopologyTemplateService, useValue: topologyServiceMock},
+ {provide: CompositionService, useValue: compositionServiceMock},
+ {provide: CompositionGraphGeneralUtils, useValue: {}},
+ {provide: CommonGraphUtils, useValue: {}},
+ {provide: EventListenerService, useValue: eventListenerServiceMock},
+ {provide: QueueServiceUtils, useValue: queueServiceMock},
+ {provide: ServiceServiceNg2, useValue: serviceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock}
+ ]
+ });
+ service = TestBed.get(CompositionGraphNodesUtils);
+ });
+
+ it('When a CP is deleted which is connected to a VL that has another leg to another CP, the VL is deleted as well', () => {
+ // Prepare a VL that is connected to both CP and CP2
+ const vlToDelete = Mock.of<CollectionNodes>({
+ data: () => vl,
+ connectedEdges: () => Mock.of<CollectionEdges>({
+ length: 2,
+ connectedNodes: () => [cp, cp2] as CollectionNodes
+ })
+ });
+
+ // Prepare a CP which is connected to a VL
+ const cpToDelete = Mock.of<CollectionNodes>({
+ data: () => cp,
+ connectedEdges: () => Mock.of<CollectionEdges>({
+ length: 1,
+ connectedNodes: () => [vlToDelete] as CollectionNodes
+ })
+ });
+ service.deleteNode(cyMock, Mock.of<Resource>(), cpToDelete);
+ expect(compositionServiceMock.deleteComponentInstance).toHaveBeenCalledWith(CP_TO_DELETE_ID);
+ expect(eventListenerServiceMock.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, VL_TO_DELETE_ID);
+ expect(eventListenerServiceMock.notifyObservers).toHaveBeenLastCalledWith(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, CP_TO_DELETE_ID);
+ expect(cyMock.remove).toHaveBeenCalled();
+ });
+
+ it('When a CP is deleted which is solely connected to another VL the VL is not deleted', () => {
+ // Prepare a VL that is connected only to 1 CP
+ const vlToDelete = Mock.of<CollectionNodes>({
+ data: () => vl,
+ connectedEdges: () => Mock.of<CollectionEdges>({
+ length: 1,
+ connectedNodes: () => [cp] as CollectionNodes
+ })
+ });
+
+ // Prepare a CP which is connected to a VL
+ const cpToDelete = Mock.of<CollectionNodes>({
+ data: () => cp,
+ connectedEdges: () => Mock.of<CollectionEdges>({
+ length: 1,
+ connectedNodes: () => [vlToDelete] as CollectionNodes
+ })
+ });
+ service.deleteNode(cyMock, Mock.of<Resource>(), cpToDelete);
+ expect(compositionServiceMock.deleteComponentInstance).toHaveBeenCalledWith(CP_TO_DELETE_ID);
+ expect(eventListenerServiceMock.notifyObservers).toHaveBeenLastCalledWith(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, CP_TO_DELETE_ID);
+ expect(eventListenerServiceMock.notifyObservers).toHaveBeenCalledTimes(1);
+ expect(cyMock.remove).toHaveBeenCalled();
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.ts
new file mode 100644
index 0000000..ea876c6
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-nodes-utils.ts
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { Component as TopologyTemplate } from 'app/models';
+import {
+ ComponentInstance,
+ CompositionCiNodeVl, Service
+} from 'app/models';
+import { CompositionCiServicePathLink } from 'app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ServiceGenericResponse } from 'app/ng2/services/responses/service-generic-response';
+import { QueueServiceUtils } from 'app/ng2/utils/queue-service-utils';
+import { EventListenerService } from 'app/services';
+import { GRAPH_EVENTS } from 'app/utils';
+import * as _ from 'lodash';
+import { SdcUiServices } from 'onap-ui-angular';
+import { CompositionService } from '../../composition.service';
+import { CommonGraphUtils } from '../common/common-graph-utils';
+import { CompositionGraphGeneralUtils } from './composition-graph-general-utils';
+
+/**
+ * Created by obarda on 11/9/2016.
+ */
+@Injectable()
+export class CompositionGraphNodesUtils {
+ constructor(private generalGraphUtils: CompositionGraphGeneralUtils,
+ private commonGraphUtils: CommonGraphUtils,
+ private eventListenerService: EventListenerService,
+ private queueServiceUtils: QueueServiceUtils,
+ private serviceService: ServiceServiceNg2,
+ private loaderService: SdcUiServices.LoaderService,
+ private compositionService: CompositionService,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService) {
+ }
+
+ /**
+ * Returns component instances for all nodes passed in
+ * @param nodes - Cy nodes
+ * @returns {any[]}
+ */
+ public getAllNodesData(nodes: Cy.CollectionNodes) {
+ return _.map(nodes, (node: Cy.CollectionFirstNode) => {
+ return node.data();
+ });
+ }
+
+ public highlightMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string) => {
+
+ cy.batch(() => {
+ cy.nodes("[name !@^= '" + nameToMatch + "']").style({'background-image-opacity': 0.4});
+ cy.nodes("[name @^= '" + nameToMatch + "']").style({'background-image-opacity': 1});
+ });
+
+ }
+
+ // Returns all nodes whose name starts with searchTerm
+ public getMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string): Cy.CollectionNodes => {
+ return cy.nodes("[name @^= '" + nameToMatch + "']");
+ }
+
+ /**
+ * Deletes component instances on server and then removes it from the graph as well
+ * @param cy
+ * @param component
+ * @param nodeToDelete
+ */
+ public deleteNode(cy: Cy.Instance, component: TopologyTemplate, nodeToDelete: Cy.CollectionNodes): void {
+
+ this.loaderService.activate();
+ const onSuccess: (response: ComponentInstance) => void = (response: ComponentInstance) => {
+ // check whether the node is connected to any VLs that only have one other connection. If so, delete that VL as well
+ this.loaderService.deactivate();
+ this.compositionService.deleteComponentInstance(response.uniqueId);
+
+ const nodeToDeleteIsNotVl = nodeToDelete.data().componentInstance && !(nodeToDelete.data().componentInstance.isVl());
+ if (nodeToDeleteIsNotVl) {
+ const connectedVls: Cy.CollectionFirstNode[] = this.getConnectedVlToNode(nodeToDelete);
+ this.handleConnectedVlsToDelete(connectedVls);
+ }
+
+ // check whether there is a service path going through this node, and if so clean it from the graph.
+ const nodeId = nodeToDelete.data().id;
+ const connectedPathLinks = cy.collection(`[type="${CompositionCiServicePathLink.LINK_TYPE}"][source="${nodeId}"], [type="${CompositionCiServicePathLink.LINK_TYPE}"][target="${nodeId}"]`);
+ _.forEach(connectedPathLinks, (link, key) => {
+ cy.remove(`[pathId="${link.data().pathId}"]`);
+ });
+
+ // update service path list
+ this.serviceService.getComponentCompositionData(component).subscribe((serviceResponse: ServiceGenericResponse) => {
+ (component as Service).forwardingPaths = serviceResponse.forwardingPaths;
+ });
+
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, nodeId);
+
+ // update UI
+ cy.remove(nodeToDelete);
+ };
+
+ const onFailed: (response: any) => void = (response: any) => {
+ this.loaderService.deactivate();
+ };
+
+ this.queueServiceUtils.addBlockingUIAction(
+ () => {
+ const uniqueId = this.workspaceService.metadata.uniqueId;
+ const componentType = this.workspaceService.metadata.componentType;
+ this.topologyTemplateService.deleteComponentInstance(componentType, uniqueId, nodeToDelete.data().componentInstance.uniqueId).subscribe(onSuccess, onFailed);
+ }
+ );
+ }
+
+ /**
+ * Finds all VLs connected to a single node
+ * @param node
+ * @returns {Array<Cy.CollectionFirstNode>}
+ */
+ public getConnectedVlToNode = (node: Cy.CollectionNodes): Cy.CollectionFirstNode[] => {
+ const connectedVls: Cy.CollectionFirstNode[] = new Array<Cy.CollectionFirstNode>();
+ _.forEach(node.connectedEdges().connectedNodes(), (connectedNode: Cy.CollectionFirstNode) => {
+ const connectedNodeIsVl = connectedNode.data().componentInstance.isVl();
+ if (connectedNodeIsVl) {
+ connectedVls.push(connectedNode);
+ }
+ });
+ return connectedVls;
+ }
+
+ /**
+ * Delete all VLs that have only two connected nodes (this function is called when deleting a node)
+ * @param connectedVls
+ */
+ public handleConnectedVlsToDelete = (connectedVls: Cy.CollectionFirstNode[]) => {
+ _.forEach(connectedVls, (vlToDelete: Cy.CollectionNodes) => {
+
+ if (vlToDelete.connectedEdges().length === 2) { // if vl connected only to 2 nodes need to delete the vl
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, vlToDelete.data().componentInstance.uniqueId);
+ }
+ });
+ }
+
+ /**
+ * This function will update nodes position.
+ * @param cy
+ * @param component
+ * @param nodesMoved - the node/multiple nodes now moved by the user
+ */
+ public onNodesPositionChanged = (cy: Cy.Instance, component: TopologyTemplate, nodesMoved: Cy.CollectionNodes): void => {
+
+ if (nodesMoved.length === 0) {
+ return;
+ }
+
+ const isValidMove: boolean = this.generalGraphUtils.isGroupValidDrop(cy, nodesMoved);
+ if (isValidMove) {
+
+ const instancesToUpdate: ComponentInstance[] = new Array<ComponentInstance>();
+
+ _.each(nodesMoved, (node: Cy.CollectionFirstNode) => { // update all nodes new position
+
+ // update position
+ const newPosition: Cy.Position = this.commonGraphUtils.getNodePosition(node);
+ node.data().componentInstance.updatePosition(newPosition.x, newPosition.y);
+ instancesToUpdate.push(node.data().componentInstance);
+
+ });
+
+ if (instancesToUpdate.length > 0) {
+ this.generalGraphUtils.pushMultipleUpdateComponentInstancesRequestToQueue(instancesToUpdate);
+ }
+ } else {
+ // reset nodes position
+ nodesMoved.positions((i, node) => {
+ return {
+ x: +node.data().componentInstance.posX,
+ y: +node.data().componentInstance.posY
+ };
+ });
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-palette-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-palette-utils.ts
new file mode 100644
index 0000000..1776c2f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-palette-utils.ts
@@ -0,0 +1,233 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {Injectable} from "@angular/core";
+import {CompositionGraphGeneralUtils, RequirementAndCapabilities} from "./composition-graph-general-utils";
+import {CommonGraphUtils} from "../common/common-graph-utils";
+import {EventListenerService} from "../../../../../services/event-listener-service";
+import {ResourceNamePipe} from "app/ng2/pipes/resource-name.pipe";
+import {ComponentInstanceFactory} from "app/utils/component-instance-factory";
+import {GRAPH_EVENTS, GraphUIObjects} from "app/utils/constants";
+import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
+import {DndDropEvent} from "ngx-drag-drop/ngx-drag-drop";
+import {SdcUiServices} from "onap-ui-angular"
+import { Component as TopologyTemplate, NodesFactory, CapabilitiesGroup, RequirementsGroup,
+ CompositionCiNodeBase, ComponentInstance, LeftPaletteComponent, Point } from "app/models";
+import {CompositionService} from "../../composition.service";
+import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
+import { QueueServiceUtils } from "app/ng2/utils/queue-service-utils";
+import {ComponentGenericResponse} from "../../../../services/responses/component-generic-response";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {CompositionGraphNodesUtils} from "./index";
+
+@Injectable()
+export class CompositionGraphPaletteUtils {
+
+ constructor(private generalGraphUtils:CompositionGraphGeneralUtils,
+ private nodesFactory:NodesFactory,
+ private commonGraphUtils:CommonGraphUtils,
+ private queueServiceUtils:QueueServiceUtils,
+ private eventListenerService:EventListenerService,
+ private topologyTemplateService: TopologyTemplateService,
+ private loaderService: SdcUiServices.LoaderService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
+ private nodesGraphUtils: CompositionGraphNodesUtils) {
+ }
+
+ /**
+ *
+ * @param Calculate matching nodes, highlight the matching nodes and fade the non matching nodes
+ * @param leftPaletteComponent
+ * @param _cy
+ * @returns void
+ * @private
+ */
+
+ public onComponentHoverIn = (leftPaletteComponent: LeftPaletteComponent, _cy: Cy.Instance) => {
+ const nodesData = this.nodesGraphUtils.getAllNodesData(_cy.nodes());
+ const nodesLinks = this.generalGraphUtils.getAllCompositionCiLinks(_cy);
+
+ if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(leftPaletteComponent.uniqueId)) {
+ const reqAndCap: RequirementAndCapabilities = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(leftPaletteComponent.uniqueId);
+ const filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodesToComponentInstance(
+ { uniqueId: leftPaletteComponent.uniqueId, requirements: reqAndCap.requirements, capabilities: reqAndCap.capabilities} as ComponentInstance, nodesData, nodesLinks);
+
+ this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, _cy);
+ this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, _cy);
+ } else {
+
+ this.topologyTemplateService.getCapabilitiesAndRequirements(leftPaletteComponent.componentType, leftPaletteComponent.uniqueId).subscribe((response: ComponentGenericResponse) => {
+ let reqAndCap: RequirementAndCapabilities = {
+ capabilities: response.capabilities,
+ requirements: response.requirements
+ }
+ this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, reqAndCap);
+ });
+ }
+ }
+
+ /**
+ * Calculate the dragged element (html element) position on canvas
+ * @param cy
+ * @param event
+ * @param position
+ * @returns {Cy.BoundingBox}
+ * @private
+ */
+ private _getNodeBBox(cy:Cy.Instance, event:DragEvent, position?:Cy.Position, eventPosition?: Point) {
+ let bbox = <Cy.BoundingBox>{};
+ if (!position) {
+ position = event ? this.commonGraphUtils.getCytoscapeNodePosition(cy, event) : eventPosition;
+ }
+ let cushionWidth:number = 40;
+ let cushionHeight:number = 40;
+
+ bbox.x1 = position.x - cushionWidth / 2;
+ bbox.y1 = position.y - cushionHeight / 2;
+ bbox.x2 = position.x + cushionWidth / 2;
+ bbox.y2 = position.y + cushionHeight / 2;
+ return bbox;
+ }
+
+ /**
+ * Create the component instance, update data from parent component in the left palette and notify on_insert_to_ucpe if component was dragg into ucpe
+ * @param cy
+ * @param fullComponent
+ * @param event
+ * @param component
+ */
+ private _createComponentInstanceOnGraphFromPaletteComponent(cy:Cy.Instance, fullComponent:LeftPaletteComponent, event:DragEvent) {
+
+ let componentInstanceToCreate:ComponentInstance = ComponentInstanceFactory.createComponentInstanceFromComponent(fullComponent);
+ let cytoscapePosition:Cy.Position = this.commonGraphUtils.getCytoscapeNodePosition(cy, event);
+ componentInstanceToCreate.posX = cytoscapePosition.x;
+ componentInstanceToCreate.posY = cytoscapePosition.y;
+
+ let onFailedCreatingInstance:(error:any) => void = (error:any) => {
+ this.loaderService.deactivate();
+ };
+
+ //on success - update node data
+ let onSuccessCreatingInstance = (createInstance:ComponentInstance):void => {
+
+ this.loaderService.deactivate();
+ this.compositionService.addComponentInstance(createInstance);
+ createInstance.name = ResourceNamePipe.getDisplayName(createInstance.name);
+ createInstance.requirements = new RequirementsGroup(createInstance.requirements);
+ createInstance.capabilities = new CapabilitiesGroup(createInstance.capabilities);
+ createInstance.componentVersion = fullComponent.version;
+ createInstance.icon = fullComponent.icon;
+ createInstance.setInstanceRC();
+
+ let newNode:CompositionCiNodeBase = this.nodesFactory.createNode(createInstance);
+ this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, newNode);
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE);
+ };
+
+ this.queueServiceUtils.addBlockingUIAction(() => {
+ let uniqueId = this.workspaceService.metadata.uniqueId;
+ let componentType = this.workspaceService.metadata.componentType;
+ this.topologyTemplateService.createComponentInstance(componentType, uniqueId, componentInstanceToCreate).subscribe(onSuccessCreatingInstance, onFailedCreatingInstance);
+
+ });
+ }
+ //
+ // /**
+ // * Thid function applay red/green background when component dragged from palette
+ // * @param cy
+ // * @param event
+ // * @param dragElement
+ // * @param dragComponent
+ // */
+ // public onComponentDrag(cy:Cy.Instance, event) {
+ // let draggedElement = document.getElementById("draggable_element");
+ // // event.dataTransfer.setDragImage(draggableElement, 0, 0);
+ // if (event.clientX < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || event.clientY < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
+ // draggedElement.className = 'invalid-drag';
+ // event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
+ // return;
+ // }
+ //
+ // let offsetPosition = {
+ // x: event.clientX - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
+ // y: event.clientY - GraphUIObjects.DIAGRAM_HEADER_OFFSET
+ // };
+ // let bbox = this._getNodeBBox(cy, event, offsetPosition);
+ //
+ // if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
+ // draggedElement.className = 'valid-drag';
+ // event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
+ // // event.dataTransfer.setDragImage(draggedElement, 0, 0);
+ // // event.dataTransfer.setDragImage(draggedElement, 0, 0);
+ //
+ // } else {
+ // draggedElement.className = 'invalid-drag';
+ // event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
+ // }
+ // }
+
+ public isDragValid(cy:Cy.Instance, position: Point):boolean {
+ if (position.x < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || position.y < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
+ return false;
+ }
+
+ let offsetPosition = {
+ x: position.x - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
+ y: position.y - GraphUIObjects.DIAGRAM_HEADER_OFFSET
+ };
+ let bbox = this._getNodeBBox(cy, null, offsetPosition, position);
+
+ if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ /**
+ * This function is called when after dropping node on canvas
+ * Check if the capability & requirements fulfilled and if not get from server
+ * @param cy
+ * @param dragEvent
+ * @param component
+ */
+ public addNodeFromPalette(cy:Cy.Instance, dragEvent:DndDropEvent) {
+ this.loaderService.activate();
+
+ let draggedComponent:LeftPaletteComponent = dragEvent.data;
+
+ if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(draggedComponent.uniqueId)) {
+ let fullComponent = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(draggedComponent.uniqueId);
+ draggedComponent.capabilities = fullComponent.capabilities;
+ draggedComponent.requirements = fullComponent.requirements;
+ this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
+
+ } else {
+
+ this.topologyTemplateService.getFullComponent(draggedComponent.componentType, draggedComponent.uniqueId).subscribe((topologyTemplate:TopologyTemplate) => {
+ draggedComponent.capabilities = topologyTemplate.capabilities;
+ draggedComponent.requirements = topologyTemplate.requirements;
+ this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
+ });
+ }
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-service-path-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-service-path-utils.ts
new file mode 100644
index 0000000..bc124fe
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-service-path-utils.ts
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils";
+import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service';
+import {Service} from "app/models/components/service";
+import {ForwardingPath} from "app/models/forwarding-path";
+import {ForwardingPathLink} from "app/models/forwarding-path-link";
+import {ComponentRef, Injectable} from "@angular/core";
+import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
+import {SdcUiServices} from "onap-ui-angular";
+import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
+import {ServicePathsListComponent} from "app/ng2/pages/composition/graph/service-paths-list/service-paths-list.component";
+import {ButtonModel, ModalModel} from "app/models";
+import {ServicePathCreatorComponent} from "app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component";
+import {ModalService} from "app/ng2/services/modal.service";
+import {ModalComponent} from "app/ng2/components/ui/modal/modal.component";
+import {Select, Store} from "@ngxs/store";
+import {WorkspaceState} from "app/ng2/store/states/workspace.state";
+import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
+import {CompositionService} from "../../composition.service";
+import {CommonGraphUtils} from "../common/common-graph-utils";
+import {GRAPH_EVENTS} from "app/utils/constants";
+import {EventListenerService} from "app/services/event-listener-service";
+
+@Injectable()
+export class ServicePathGraphUtils {
+
+ constructor(
+ private generalGraphUtils: CompositionGraphGeneralUtils,
+ private serviceService: ServiceServiceNg2,
+ private commonGraphUtils: CommonGraphUtils,
+ private loaderService: SdcUiServices.LoaderService,
+ private queueServiceUtils: QueueServiceUtils,
+ private modalService: ModalService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private store:Store,
+ private eventListenerService: EventListenerService
+ ) {
+ }
+
+ private isViewOnly = (): boolean => {
+ return this.store.selectSnapshot(state => state.workspace.isViewOnly);
+ }
+ private modalInstance: ComponentRef<ModalComponent>;
+
+ public deletePathsFromGraph(cy: Cy.Instance) {
+ cy.remove(`[type="${CompositionCiServicePathLink.LINK_TYPE}"]`);
+ }
+
+ public drawPath(cy: Cy.Instance, forwardingPath: ForwardingPath) {
+ let pathElements = forwardingPath.pathElements.listToscaDataDefinition;
+
+ _.forEach(pathElements, (link: ForwardingPathLink) => {
+ let data: CompositionCiServicePathLink = new CompositionCiServicePathLink(link);
+ data.source = _.find(
+ this.compositionService.componentInstances,
+ instance => instance.name === data.forwardingPathLink.fromNode
+ ).uniqueId;
+ data.target = _.find(
+ this.compositionService.componentInstances,
+ instance => instance.name === data.forwardingPathLink.toNode
+ ).uniqueId;
+ data.pathId = forwardingPath.uniqueId;
+ data.pathName = forwardingPath.name;
+ this.commonGraphUtils.insertServicePathLinkToGraph(cy, data);
+ });
+ }
+
+ public createOrUpdateServicePath = (path: any): void => {
+ this.loaderService.activate();
+
+ let onSuccess: (response: ForwardingPath) => void = (response: ForwardingPath) => {
+ this.loaderService.deactivate();
+ this.compositionService.forwardingPaths[response.uniqueId] = response;
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_SERVICE_PATH_CREATED, response.uniqueId)
+ };
+
+ this.queueServiceUtils.addBlockingUIAction(
+ () => this.serviceService.createOrUpdateServicePath(this.workspaceService.metadata.uniqueId, path).subscribe(onSuccess
+ , (error) => {this.loaderService.deactivate()})
+ );
+ };
+
+ public onCreateServicePath = (): void => {
+ // this.showServicePathMenu = false;
+ let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.modalService.closeCurrentModal);
+ let saveButton: ButtonModel = new ButtonModel('Create', 'blue', this.createPath, this.getDisabled);
+ let modalModel: ModalModel = new ModalModel('l', 'Create Service Flow', '', [saveButton, cancelButton], 'standard', true);
+ this.modalInstance = this.modalService.createCustomModal(modalModel);
+ this.modalService.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {serviceId: this.workspaceService.metadata.uniqueId});
+ this.modalInstance.instance.open();
+ };
+
+ public onListServicePath = (): void => {
+ // this.showServicePathMenu = false;
+ let cancelButton: ButtonModel = new ButtonModel('Close', 'outline white', this.modalService.closeCurrentModal);
+ let modalModel: ModalModel = new ModalModel('md', 'Service Flows List', '', [cancelButton], 'standard', true);
+ this.modalInstance = this.modalService.createCustomModal(modalModel);
+ this.modalService.addDynamicContentToModal(this.modalInstance, ServicePathsListComponent, {
+ serviceId: this.workspaceService.metadata.uniqueId,
+ onCreateServicePath: this.onCreateServicePath,
+ onEditServicePath: this.onEditServicePath,
+ isViewOnly: this.isViewOnly()
+ });
+ this.modalInstance.instance.open();
+ };
+
+ public onEditServicePath = (id: string): void => {
+ let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.modalService.closeCurrentModal);
+ let saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createPath, this.getDisabled);
+ let modalModel: ModalModel = new ModalModel('l', 'Edit Path', '', [saveButton, cancelButton], 'standard', true);
+ this.modalInstance = this.modalService.createCustomModal(modalModel);
+ this.modalService.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {
+ serviceId: this.workspaceService.metadata.uniqueId,
+ pathId: id
+ });
+ this.modalInstance.instance.open();
+ };
+
+ public getDisabled = (): boolean => {
+ return this.isViewOnly() || !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
+ };
+
+ public createPath = (): void => {
+ this.createOrUpdateServicePath(this.modalInstance.instance.dynamicContent.instance.createServicePathData());
+ this.modalService.closeCurrentModal();
+ };
+}
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-zone-utils.ts
similarity index 68%
rename from catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts
rename to catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-zone-utils.ts
index cf6c7e3..9e97ec0 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-zone-utils.ts
@@ -1,21 +1,32 @@
-import { PolicyInstance } from "app/models/graph/zones/policy-instance";
-import { ZoneInstance, ZoneInstanceType, ZoneInstanceAssignmentType } from "app/models/graph/zones/zone-instance";
-import { Zone } from "app/models/graph/zones/zone";
-import { DynamicComponentService } from "app/ng2/services/dynamic-component.service";
-import { PaletteAnimationComponent } from "app/ng2/components/ui/palette-animation/palette-animation.component";
-import { Point, LeftPaletteMetadataTypes, Component } from "../../../../models";
-import { CanvasHandleTypes } from "app/utils";
-import { PoliciesService } from "../../../../ng2/services/policies.service";
-import { Observable } from "rxjs";
-import { GroupsService } from "../../../../ng2/services/groups.service";
-import { GroupInstance } from "app/models/graph/zones/group-instance";
+import {
+ Point,
+ PolicyInstance,
+ Zone,
+ LeftPaletteMetadataTypes,
+ ZoneInstance,
+ ZoneInstanceType,
+ ZoneInstanceAssignmentType
+} from "app/models";
+import {CanvasHandleTypes} from "app/utils";
+import {Observable} from "rxjs";
+import {GroupInstance} from "app/models/graph/zones/group-instance";
+import {Injectable} from "@angular/core";
+import {DynamicComponentService} from "app/ng2/services/dynamic-component.service";
+import {PoliciesService} from "app/ng2/services/policies.service";
+import {GroupsService} from "app/ng2/services/groups.service";
+import {Store} from "@ngxs/store";
+import {CompositionService} from "../../composition.service";
+import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
+import { PaletteAnimationComponent } from "app/ng2/pages/composition/palette/palette-animation/palette-animation.component";
-
+@Injectable()
export class CompositionGraphZoneUtils {
constructor(private dynamicComponentService: DynamicComponentService,
- private policiesService: PoliciesService,
- private groupsService: GroupsService) {
+ private policiesService: PoliciesService,
+ private groupsService: GroupsService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService) {
}
@@ -41,19 +52,22 @@
}
};
- public initZoneInstances(zones: Array<Zone>, component: Component) {
- if (component.groupInstances && component.groupInstances.length) {
+ public initZoneInstances(zones: Array<Zone>) {
+
+ if (this.compositionService.groupInstances && this.compositionService.groupInstances.length) {
this.showZone(zones[ZoneInstanceType.GROUP]);
- _.forEach(component.groupInstances, (group: GroupInstance) => {
- let newInstance = new ZoneInstance(group, component);
+ zones[ZoneInstanceType.GROUP].instances = [];
+ _.forEach(this.compositionService.groupInstances, (group: GroupInstance) => {
+ let newInstance = new ZoneInstance(group, this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId);
this.addInstanceToZone(zones[ZoneInstanceType.GROUP], newInstance);
});
}
- if (component.policies && component.policies.length) {
+ if (this.compositionService.policies && this.compositionService.policies.length) {
this.showZone(zones[ZoneInstanceType.POLICY]);
- _.forEach(component.policies, (policy: PolicyInstance) => {
- let newInstance = new ZoneInstance(policy, component);
+ zones[ZoneInstanceType.POLICY].instances = [];
+ _.forEach(this.compositionService.policies, (policy: PolicyInstance) => {
+ let newInstance = new ZoneInstance(policy, this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId);
this.addInstanceToZone(zones[ZoneInstanceType.POLICY], newInstance);
});
@@ -82,18 +96,19 @@
});
};
- public createZoneInstanceFromLeftPalette = (zoneType: ZoneInstanceType, component: Component, paletteComponentType: string): Observable<ZoneInstance> => {
+ public createZoneInstanceFromLeftPalette = (zoneType: ZoneInstanceType, paletteComponentType: string): Observable<ZoneInstance> => {
+
if (zoneType === ZoneInstanceType.POLICY) {
- return this.policiesService.createPolicyInstance(component.componentType, component.uniqueId, paletteComponentType).map(response => {
+ return this.policiesService.createPolicyInstance(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, paletteComponentType).map(response => {
let newInstance = new PolicyInstance(response);
- component.policies.push(newInstance);
- return new ZoneInstance(newInstance, component);
+ this.compositionService.addPolicyInstance(newInstance);
+ return new ZoneInstance(newInstance, this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId);
});
} else if (zoneType === ZoneInstanceType.GROUP) {
- return this.groupsService.createGroupInstance(component.componentType, component.uniqueId, paletteComponentType).map(response => {
+ return this.groupsService.createGroupInstance(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, paletteComponentType).map(response => {
let newInstance = new GroupInstance(response);
- component.groupInstances.push(newInstance);
- return new ZoneInstance(newInstance, component);
+ this.compositionService.addGroupInstance(newInstance);
+ return new ZoneInstance(newInstance, this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId);
});
}
}
@@ -187,9 +202,3 @@
}
};
}
-
-CompositionGraphZoneUtils.$inject = [
- 'DynamicComponentService',
- 'PoliciesServiceNg2',
- 'GroupsServiceNg2'
-];
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/index.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/index.ts
new file mode 100644
index 0000000..e7f11af
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/index.ts
@@ -0,0 +1,29 @@
+/**
+ * Created by ob0695 on 6/3/2018.
+ */
+// export * from './composition-graph-general-utils';
+// export * from './composition-graph-links-utils';
+// export * from './composition-graph-nodes-utils';
+// export * from './composition-graph-palette-utils';
+// export * from './composition-graph-service-path-utils';
+// export * from './composition-graph-zone-utils';
+
+
+import {CompositionGraphGeneralUtils} from './composition-graph-general-utils';
+import {CompositionGraphNodesUtils} from './composition-graph-nodes-utils';
+import {MatchCapabilitiesRequirementsUtils} from './match-capability-requierment-utils'
+import {CompositionGraphPaletteUtils} from './composition-graph-palette-utils';
+import {CompositionGraphZoneUtils} from './composition-graph-zone-utils';
+import {ServicePathGraphUtils} from './composition-graph-service-path-utils';
+import {CompositionGraphLinkUtils} from "./composition-graph-links-utils";
+
+
+export {
+ CompositionGraphGeneralUtils,
+ CompositionGraphLinkUtils,
+ CompositionGraphNodesUtils,
+ MatchCapabilitiesRequirementsUtils,
+ CompositionGraphPaletteUtils,
+ CompositionGraphZoneUtils,
+ ServicePathGraphUtils
+};
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.spec.ts
new file mode 100644
index 0000000..dbfc3e7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.spec.ts
@@ -0,0 +1,342 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Mock } from 'ts-mockery';
+import {
+ CapabilitiesGroup,
+ Capability, ComponentInstance, CompositionCiLinkBase, CompositionCiNodeBase, CompositionCiNodeCp,
+ CompositionCiNodeVf, CompositionCiNodeVl,
+ Requirement, RequirementsGroup
+} from '../../../../../models';
+import { MatchCapabilitiesRequirementsUtils } from './match-capability-requierment-utils';
+
+describe('match capability requirements utils service ', () => {
+
+ const bindableReq = Mock.of<Requirement>({
+ capability : 'tosca.capabilities.network.Bindable',
+ name: 'virtualBinding',
+ relationship: 'tosca.relationships.network.BindsTo',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualBinding',
+ ownerId : 'extcp0',
+ ownerName : 's'
+ });
+
+ const virtualLinkReq = Mock.of<Requirement>({
+ capability: 'tosca.capabilities.network.Linkable',
+ name: 'virtualLink',
+ relationship: 'tosca.relationships.network.LinksTo',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualLink',
+ ownerId : '',
+ ownerName : 's'
+ });
+
+ const storeAttachmentReq = Mock.of<Requirement>({
+ capability: 'tosca.capabilities.Attachment',
+ name: 'local_storage',
+ relationship: 'tosca.relationships.AttachesTo',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.local_storage',
+ node: 'tosca.nodes.BlockStorage',
+ ownerId : '',
+ ownerName : 's'
+ });
+
+ const vlAttachmentReq = Mock.of<Requirement>({
+ capability: 'tosca.capabilities.Attachment',
+ name: 'local_storage',
+ relationship: 'tosca.relationships.AttachesTo',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.local_storage',
+ node: 'tosca.nodes.BlockStorage',
+ ownerId : '',
+ ownerName : 's'
+ });
+
+ const extVirtualLinkReq = Mock.of<Requirement>({
+ capability: 'tosca.capabilities.network.Linkable',
+ name: 'external_virtualLink',
+ relationship: 'tosca.relationships.network.LinksTo',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.external_virtualLink'
+ });
+
+ const dependencyReq = Mock.of<Requirement>({
+ capability: 'tosca.capabilities.Node',
+ name: 'dependency',
+ relationship: 'tosca.relationships.DependsOn',
+ uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.dependency'
+ });
+
+ const featureCap = Mock.of<Capability>({
+ type: 'tosca.capabilities.Node',
+ name: 'feature',
+ uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.feature',
+ maxOccurrences: 'UNBOUNDED',
+ minOccurrences: '1'
+ });
+
+ const internalConnPointCap = Mock.of<Capability>({
+ type: 'tosca.capabilities.Node',
+ name: 'internal_connectionPoint',
+ capabilitySources : ['org.openecomp.resource.cp.extCP'],
+ uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.internal_connectionPoint',
+ maxOccurrences: 'UNBOUNDED',
+ minOccurrences: '1'
+ });
+
+ const blockStoreAttachmentCap = Mock.of<Capability>({
+ type: 'tosca.capabilities.Attachment',
+ name: 'attachment',
+ capabilitySources: ['tosca.nodes.BlockStorage'],
+ uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.attachment',
+ maxOccurrences: 'UNBOUNDED',
+ minOccurrences: '1'
+ });
+
+ const bindingCap = Mock.of<Capability>({
+ type: 'tosca.capabilities.network.Bindable',
+ name: 'binding',
+ capabilitySources: ['tosca.nodes.Compute'],
+ uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.binding',
+ maxOccurrences: 'UNBOUNDED',
+ minOccurrences: '1',
+ });
+
+ const linkableCap = Mock.of<Capability>({
+ type: 'tosca.capabilities.network.Linkable',
+ capabilitySources: ['org.openecomp.resource.vl.extVL'],
+ uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.virtual_linkable',
+ maxOccurrences: 'UNBOUNDED',
+ minOccurrences: '1'
+ });
+
+ const nodeCompute = Mock.of<CompositionCiNodeVf>({
+ name: 'Compute 0',
+ componentInstance: Mock.of<ComponentInstance>({
+ componentName: 'Compute',
+ uniqueId : 'compute0',
+ requirements: Mock.of<RequirementsGroup>({
+ 'tosca.capabilities.Node' : [ dependencyReq ],
+ 'tosca.capabilities.Attachment' : [ storeAttachmentReq ]
+ }),
+ capabilities: Mock.of<CapabilitiesGroup>({
+ 'tosca.capabilities.network.Bindable' : [ bindingCap ],
+ 'tosca.capabilities.Node' : [ featureCap ]
+ })
+ })
+ });
+
+ const nodeBlockStorage = Mock.of<CompositionCiNodeVf>({
+ name: 'BlockStorage 0',
+ componentInstance: Mock.of<ComponentInstance>({
+ componentName: 'BlockStorage',
+ uniqueId : 'blockstorage0',
+ requirements: Mock.of<RequirementsGroup>({
+ 'tosca.capabilities.Node' : [ dependencyReq ]
+ }),
+ capabilities: Mock.of<CapabilitiesGroup>({
+ 'tosca.capabilities.Attachment' : [ blockStoreAttachmentCap ],
+ 'tosca.capabilities.Node' : [ featureCap ]
+ })
+ })
+ });
+
+ const nodeVl = Mock.of<CompositionCiNodeVl>({
+ name: 'ExtVL 0',
+ componentInstance: Mock.of<ComponentInstance>({
+ componentName: 'BlockStorage',
+ uniqueId : 'extvl0',
+ requirements: Mock.of<RequirementsGroup>({
+ 'tosca.capabilities.Node' : [ dependencyReq ]
+ }),
+ capabilities: Mock.of<CapabilitiesGroup>({
+ 'tosca.capabilities.network.Linkable' : [ linkableCap ],
+ 'tosca.capabilities.Node' : [ featureCap ]
+ })
+ })
+ });
+
+ const nodeCp = Mock.of<CompositionCiNodeCp>({
+ name: 'ExtCP 0',
+ componentInstance: Mock.of<ComponentInstance>({
+ componentName: 'ExtCP',
+ uniqueId : 'extcp0',
+ requirements: Mock.of<RequirementsGroup>({
+ 'tosca.capabilities.network.Linkable' : [ virtualLinkReq ],
+ 'tosca.capabilities.network.Bindable' : [ bindableReq ]
+ }),
+ capabilities: Mock.of<CapabilitiesGroup>({
+ 'tosca.capabilities.Node' : [ featureCap ]
+ })
+ })
+ });
+
+ let service: MatchCapabilitiesRequirementsUtils;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [],
+ providers: [MatchCapabilitiesRequirementsUtils]
+ });
+
+ service = TestBed.get(MatchCapabilitiesRequirementsUtils);
+ });
+
+ it('match capability requirements utils should be defined', () => {
+ console.log(JSON.stringify(service));
+ expect(service).toBeDefined();
+ });
+
+ describe('isMatch function ', () => {
+
+ it('capability type not equal to requirement capability, match is false', () => {
+ const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable11'});
+ const capability = Mock.of<Capability>({type: 'tosca.capabilities.network.Linkable'});
+ expect(service.isMatch(requirement, capability)).toBeFalsy();
+ });
+
+ it('capability type equal to requirement capability and requirement node not exist, match is true', () => {
+ const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable'});
+ const capability = Mock.of<Capability>({type: 'tosca.capabilities.network.Linkable'});
+ expect(service.isMatch(requirement, capability)).toBeTruthy();
+ });
+
+ it('is match - capability type equal to requirement capability and requirement node exist and includes in capability sources, match is true', () => {
+ const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable', node: 'node1'});
+ const capability = Mock.of<Capability>({
+ type: 'tosca.capabilities.network.Linkable',
+ capabilitySources: ['node1', 'node2', 'node3']
+ });
+ expect(service.isMatch(requirement, capability)).toBeTruthy();
+ });
+
+ it('no match - capability type equal to requirement capability and requirement node but not includes in capability sources, match is false', () => {
+ const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable', node: 'node4'});
+ const capability = Mock.of<Capability>({
+ type: 'tosca.capabilities.network.Linkable',
+ capabilitySources: ['node1', 'node2', 'node3']
+ });
+ expect(service.isMatch(requirement, capability)).toBeFalsy();
+ });
+ });
+
+ describe('hasUnfulfilledRequirementContainingMatch function ', () => {
+
+ it('node have no componentInstance, return false', () => {
+ const node = Mock.of<CompositionCiNodeVf>({componentInstance: undefined});
+ expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
+ });
+
+ it('node have componentInstance data but no unfulfilled requirements, return false', () => {
+ const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([]);
+ expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
+ });
+
+ it('node have componentInstance data and unfulfilled requirements but no match found, return false', () => {
+ const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
+ jest.spyOn(service, 'containsMatch').mockReturnValue(false);
+ expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
+ });
+
+ it('node have componentInstance data with unfulfilled requirements and match found, return true', () => {
+ const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
+ jest.spyOn(service, 'containsMatch').mockReturnValue(true);
+ expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeTruthy();
+ });
+ });
+
+ describe('getMatches function ', () => {
+ let fromId: string;
+ let toId: string;
+
+ beforeEach(() => {
+ fromId = 'from_id';
+ toId = 'to_id';
+ });
+
+ it('node have no unfulfilled requirements, return empty match array', () => {
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([]);
+ expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
+ });
+
+ it('node have unfulfilled requirements but no capabilities, return empty match array', () => {
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
+ expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
+ });
+
+ it('node have unfulfilled requirements and capabilities but no match found, return empty match array', () => {
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
+ jest.spyOn(service, 'isMatch').mockReturnValue(false);
+ expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
+ });
+
+ it('node have 2 unfulfilled requirements and 2 capabilities and match found, return 4 matches', () => {
+ jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
+ const capabilities = {aaa: Mock.of<Capability>(), bbb: Mock.of<Capability>()};
+ jest.spyOn(service, 'isMatch').mockReturnValue(true);
+ expect(service.getMatches({}, capabilities, [], fromId, toId, true)).toHaveLength(4);
+ });
+ });
+
+ describe('Find matching nodes ===>', () => {
+
+ it('should find matching nodes with component instance', () => {
+ const nodes = [ nodeBlockStorage, nodeCompute, nodeVl ];
+ let matchingNodes: any;
+
+ // Compute can connect to Block Store
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeCompute.componentInstance, nodes, []);
+ expect(matchingNodes).toHaveLength(1);
+ expect(matchingNodes).toContain(nodeBlockStorage);
+
+ // Block Storage can connect to Compute
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeBlockStorage.componentInstance, nodes, []);
+ expect(matchingNodes).toHaveLength(1);
+ expect(matchingNodes).toContain(nodeCompute);
+
+ // Vl has no matches
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeVl.componentInstance, nodes, []);
+ expect(matchingNodes).toHaveLength(0);
+
+ // CP should be able to connect to VL and Compute
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, []);
+ expect(matchingNodes).toHaveLength(2);
+ expect(matchingNodes).toContain(nodeCompute);
+ expect(matchingNodes).toContain(nodeVl);
+ });
+
+ it('try with empty list of nodes', () => {
+ const nodes = [ ];
+ let matchingNodes: any;
+
+ // Compute can connect to Block Store
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeCompute.componentInstance, nodes, []);
+ expect(matchingNodes).toHaveLength(0);
+ });
+
+ it('should detect fulfilled connection with compute node', () => {
+ const nodes = [ nodeBlockStorage, nodeCompute, nodeVl ];
+ let matchingNodes: any;
+ const link = {
+ relation: {
+ fromNode: 'extcp0',
+ toNode: 'compute0',
+ relationships: [{
+ relation: {
+ requirementOwnerId: 'extcp0',
+ requirement: 'virtualBinding',
+ relationship: {
+ type: 'tosca.relationships.network.BindsTo'
+ }
+
+ }
+ }]
+ }
+ };
+
+ const links = [link];
+ // CP should be able to connect to VL only since it already has a link with compute
+ matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, links as CompositionCiLinkBase[]);
+ expect(matchingNodes).toHaveLength(1);
+ expect(matchingNodes).toContain(nodeVl);
+ });
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.ts
new file mode 100644
index 0000000..c3a1286
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.ts
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+import { Injectable } from '@angular/core';
+import {
+ CapabilitiesGroup, Capability, ComponentInstance, CompositionCiLinkBase,
+ CompositionCiNodeBase, Match, Requirement, RequirementsGroup
+} from 'app/models';
+import * as _ from 'lodash';
+
+/**
+ * Created by obarda on 1/1/2017.
+ */
+@Injectable()
+export class MatchCapabilitiesRequirementsUtils {
+
+ /**
+ * Shows + icon in corner of each node passed in
+ * @param filteredNodesData
+ * @param cy
+ */
+ public highlightMatchingComponents(filteredNodesData, cy: Cy.Instance) {
+ _.each(filteredNodesData, (data: any) => {
+ const node = cy.getElementById(data.id);
+ cy.emit('showhandle', [node]);
+ });
+ }
+
+ /**
+ * Adds opacity to each node that cannot be linked to hovered node
+ * @param filteredNodesData
+ * @param nodesData
+ * @param cy
+ * @param hoveredNodeData
+ */
+ public fadeNonMachingComponents(filteredNodesData, nodesData, cy: Cy.Instance, hoveredNodeData?) {
+ const fadeNodes = _.xorWith(nodesData, filteredNodesData, (node1, node2) => {
+ return node1.id === node2.id;
+ });
+ if (hoveredNodeData) {
+ _.remove(fadeNodes, hoveredNodeData);
+ }
+ cy.batch(() => {
+ _.each(fadeNodes, (node) => {
+ cy.getElementById(node.id).style({'background-image-opacity': 0.4});
+ });
+ });
+ }
+
+ /**
+ * Resets all nodes to regular opacity
+ * @param cy
+ */
+ public resetFadedNodes(cy: Cy.Instance) {
+ cy.batch(() => {
+ cy.nodes().style({'background-image-opacity': 1});
+ });
+ }
+
+ public getMatchedRequirementsCapabilities(fromComponentInstance: ComponentInstance,
+ toComponentInstance: ComponentInstance,
+ links: CompositionCiLinkBase[]): Match[] {
+ const fromToMatches: Match[] = this.getMatches(fromComponentInstance.requirements,
+ toComponentInstance.capabilities,
+ links,
+ fromComponentInstance.uniqueId,
+ toComponentInstance.uniqueId, true);
+ const toFromMatches: Match[] = this.getMatches(toComponentInstance.requirements,
+ fromComponentInstance.capabilities,
+ links,
+ toComponentInstance.uniqueId,
+ fromComponentInstance.uniqueId, false);
+
+ return fromToMatches.concat(toFromMatches);
+ }
+
+ /***** REFACTORED FUNCTIONS START HERE *****/
+
+ public getMatches(requirements: RequirementsGroup, capabilities: CapabilitiesGroup, links: CompositionCiLinkBase[],
+ fromId: string, toId: string, isFromTo: boolean): Match[] {
+ const matches: Match[] = [];
+ const unfulfilledReqs = this.getUnfulfilledRequirements(fromId, requirements, links);
+ _.forEach(unfulfilledReqs, (req) => {
+ _.forEach(_.flatten(_.values(capabilities)), (capability: Capability) => {
+ if (this.isMatch(req, capability)) {
+ if (isFromTo) {
+ matches.push(new Match(req, capability, isFromTo, fromId, toId));
+ } else {
+ matches.push(new Match(req, capability, isFromTo, toId, fromId));
+ }
+ }
+ });
+ });
+ return matches;
+ }
+
+ public getUnfulfilledRequirements = (fromNodeId: string, requirements: RequirementsGroup, links: CompositionCiLinkBase[]): Requirement[] => {
+ const requirementArray: Requirement[] = [];
+ _.forEach(_.flatten(_.values(requirements)), (requirement: Requirement) => {
+ const reqFulfilled = this.isRequirementFulfilled(fromNodeId, requirement, links);
+ if (requirement.name !== 'dependency' && requirement.parentName !== 'dependency' && !reqFulfilled) {
+ requirementArray.push(requirement);
+ }
+ });
+ return requirementArray;
+ }
+
+ /**
+ * Returns true if there is a match between the capabilities and requirements that are passed in
+ * @param requirements
+ * @param capabilities
+ * @returns {boolean}
+ */
+ public containsMatch = (requirements: Requirement[], capabilities: CapabilitiesGroup): boolean => {
+ return _.some(requirements, (req: Requirement) => {
+ return _.some(_.flatten(_.values(capabilities)), (capability: Capability) => {
+ return this.isMatch(req, capability);
+ });
+ });
+ }
+
+ public hasUnfulfilledRequirementContainingMatch = (node: CompositionCiNodeBase, componentRequirements: Requirement[], capabilities: CapabilitiesGroup, links: CompositionCiLinkBase[]) => {
+ if (node && node.componentInstance) {
+ // Check if node has unfulfilled requirement that can be filled by component (#2)
+ const nodeRequirements: Requirement[] = this.getUnfulfilledRequirements(node.componentInstance.uniqueId, node.componentInstance.requirements, links);
+ if (!nodeRequirements.length) {
+ return false;
+ }
+ if (this.containsMatch(nodeRequirements, capabilities)) {
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns array of nodes that can connect to the component.
+ * In order to connect, one of the following conditions must be met:
+ * 1. component has an unfulfilled requirement that matches a node's capabilities
+ * 2. node has an unfulfilled requirement that matches the component's capabilities
+ * 3. vl is passed in which has the capability to fulfill requirement from component and requirement on node.
+ */
+ public findMatchingNodesToComponentInstance(componentInstance: ComponentInstance, nodeDataArray: CompositionCiNodeBase[], links: CompositionCiLinkBase[]): any[] {
+ return _.filter(nodeDataArray, (node: CompositionCiNodeBase) => {
+ const matchedRequirementsCapabilities = this.getMatchedRequirementsCapabilities(node.componentInstance, componentInstance, links);
+ return matchedRequirementsCapabilities && matchedRequirementsCapabilities.length > 0;
+ });
+ }
+
+ public isMatch(requirement: Requirement, capability: Capability): boolean {
+ if (capability.type === requirement.capability) {
+ if (requirement.node) {
+ if (_.includes(capability.capabilitySources, requirement.node)) {
+ return true;
+ }
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private isRequirementFulfilled(fromNodeId: string, requirement: any, links: CompositionCiLinkBase[]): boolean {
+ return _.some(links, {
+ relation: {
+ fromNode: fromNodeId,
+ relationships: [{
+ relation: {
+ requirementOwnerId: requirement.ownerId,
+ requirement: requirement.name,
+ relationship: {
+ type: requirement.relationship
+ }
+
+ }
+ }]
+ }
+ });
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/__snapshots__/palette.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/palette/__snapshots__/palette.component.spec.ts.snap
new file mode 100644
index 0000000..74517e1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/__snapshots__/palette.component.spec.ts.snap
@@ -0,0 +1,51 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`palette component should match current snapshot of palette component 1`] = `
+<composition-palette
+ buildPaletteByCategories={[Function Function]}
+ compositionPaletteService={[Function Object]}
+ eventListenerService={[Function Object]}
+ numberOfElements="0"
+ onDragStart={[Function Function]}
+ onDraggableMoved={[Function Function]}
+ onDrop={[Function Function]}
+ onMouseOut={[Function Function]}
+ onMouseOver={[Function Function]}
+ onSearchChanged={[Function Function]}
+ position={[Function Point]}
+>
+ <div
+ class="composition-palette-component"
+ >
+ <div
+ class="palette-elements-count"
+ >
+ Elements
+ <span
+ class="palette-elements-count-value"
+ >
+
+ </span>
+ </div>
+ <sdc-filter-bar
+ placeholder="Search..."
+ testid="searchAsset"
+ />
+ <div
+ class="palette-elements-list"
+ >
+ <sdc-loader
+ name="palette-loader"
+ testid="palette-loader"
+ />
+
+
+ </div>
+ </div><div
+ dnddropzone=""
+ id="draggable_element"
+ >
+
+ </div>
+</composition-palette>
+`;
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html b/catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.html
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less b/catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.less
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.less
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.ts
similarity index 95%
rename from catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.ts
index 7e45b9e..a445c87 100644
--- a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.component.ts
@@ -24,7 +24,7 @@
import { EventListenerService } from 'app/services';
import { GRAPH_EVENTS } from 'app/utils';
import { Point } from 'app/models';
-import { ZoneInstanceType, ZoneInstance } from '../../../../models/graph/zones/zone-instance';
+import { ZoneInstanceType, ZoneInstance } from 'app/models/graph/zones/zone-instance';
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.module.ts
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-animation/palette-animation.module.ts
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/__snapshots__/palette-element.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/__snapshots__/palette-element.component.spec.ts.snap
new file mode 100644
index 0000000..40df575
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/__snapshots__/palette-element.component.spec.ts.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`palette element component should match current snapshot of palette element component 1`] = `
+<palette-element>
+ <div
+ class="palette-element"
+ >
+ <sdc-element-icon
+ class="palette-element-icon"
+ />
+ <div
+ class="palette-element-text"
+ >
+ <div
+ class="palette-element-name"
+ sdc-tooltip=""
+ >
+
+ </div>
+ <span>
+ V.
+ </span>
+ <span>
+
+ </span>
+ </div>
+ </div>
+</palette-element>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.html b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.html
new file mode 100644
index 0000000..3a6be5d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.html
@@ -0,0 +1,11 @@
+<div class="palette-element" >
+ <sdc-element-icon class="palette-element-icon" [iconName]="paletteElement.icon"
+ [elementType]="paletteElement.componentSubType"[uncertified]="this.paletteElement.certifiedIconClass"></sdc-element-icon>
+ <div class="palette-element-text">
+ <div class="palette-element-name" sdc-tooltip
+ tooltip-text='{{paletteElement.name | resourceName}}'>{{paletteElement.name | resourceName}}
+ </div>
+ <span> V.{{paletteElement.version}}</span>
+ <span>{{paletteElement.componentSubType}}</span>
+ </div>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.less b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.less
new file mode 100644
index 0000000..e9c3253
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.less
@@ -0,0 +1,32 @@
+@import "./../../../../../../assets/styles/override";
+.palette-element {
+ cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ max-height: 65px;
+ border-bottom: 1px solid @sdcui_color_silver;
+ padding: 10px;
+ align-items: center;
+ .palette-element-icon {
+ min-width: 45px;
+ text-align: center;
+ }
+
+ .palette-element-text {
+ display: flex;
+ flex-direction: column;
+ font-size: 13px;
+ line-height: 15px;
+ padding-left: 10px;
+ font-family: OpenSans-Regular, sans-serif;
+ overflow: hidden;
+
+ .palette-element-name {
+ color: @sdcui_color_dark-gray;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.spec.ts
new file mode 100644
index 0000000..64ed45b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.spec.ts
@@ -0,0 +1,30 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {ConfigureFn, configureTests} from "../../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {PaletteElementComponent} from "./palette-element.component";
+import {ResourceNamePipe} from "../../../../pipes/resource-name.pipe";
+
+describe('palette element component', () => {
+
+ let fixture: ComponentFixture<PaletteElementComponent>;
+
+ beforeEach(
+ async(() => {
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [PaletteElementComponent, ResourceNamePipe],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(PaletteElementComponent);
+ });
+ })
+ );
+
+ it('should match current snapshot of palette element component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.ts
similarity index 69%
rename from catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.ts
index 41f24dc..9e9e5a2 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-element/palette-element.component.ts
@@ -1,3 +1,6 @@
+/**
+ * Created by ob0695 on 6/28/2018.
+ */
/*-
* ============LICENSE_START=======================================================
* SDC
@@ -7,9 +10,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.
@@ -18,17 +21,15 @@
* ============LICENSE_END=========================================================
*/
-'use strict';
-import {ICompositionViewModelScope} from "../../composition-view-model";
+import {Component, Input} from "@angular/core";
+import {LeftPaletteComponent} from "app/models/components/displayComponent";
-interface IStructureViewModel extends ICompositionViewModelScope {
-}
+@Component({
+ selector: 'palette-element',
+ templateUrl: './palette-element.component.html',
+ styleUrls: ['./palette-element.component.less']
+})
+export class PaletteElementComponent {
-export class StructureViewModel {
- static '$inject' = [
- '$scope'
- ];
-
- constructor(private $scope:IStructureViewModel) {
- }
+ @Input() paletteElement: LeftPaletteComponent;
}
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html b/catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.html
similarity index 92%
rename from catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.html
index 11261e9..86847eb 100644
--- a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.html
@@ -23,3 +23,8 @@
<div class="popup-panel-title">{{panelTitle}}</div>
</div>
</div>
+<!--<popup-menu-list [menuItemsData]="getMenuItems()">-->
+
+
+
+<!--</popup-menu-list>-->
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less b/catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.less
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.less
diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.ts
similarity index 79%
rename from catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.ts
index a10ca7d..5d98fc7 100644
--- a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette-popup-panel/palette-popup-panel.component.ts
@@ -1,8 +1,8 @@
import {Component, OnInit} from '@angular/core';
-import {GRAPH_EVENTS} from "app/utils";
+import {GRAPH_EVENTS, SdcElementType} from "app/utils";
import {LeftPaletteComponent, Point} from "app/models";
import {EventListenerService} from "app/services";
-import {LeftPaletteMetadataTypes} from "../../../../models/components/displayComponent";
+import {LeftPaletteMetadataTypes} from "app/models/components/displayComponent";
@Component({
selector: 'app-palette-popup-panel',
@@ -29,6 +29,18 @@
this.isShowPanel = true;
}
+ public getMenuItems = () => {
+ return [{
+ text: 'Delete',
+ iconName: 'trash-o',
+ iconType: 'common',
+ iconMode: 'secondary',
+ iconSize: 'small',
+ type: '',
+ action: () => this.addZoneInstance()
+ }];
+ }
+
public onMouseLeave() {
this.isShowPanel = false;
}
@@ -43,9 +55,7 @@
private registerObserverCallbacks() {
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL,
- (component: Component, displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => {
-
- this.component = component;
+ (displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => {
this.showPopupPanel(displayComponent, sectionElem);
});
@@ -60,12 +70,12 @@
};
private setPopupPanelTitle(component: LeftPaletteComponent): void {
- if (component.categoryType === LeftPaletteMetadataTypes.Group) {
+ if (component.componentSubType === SdcElementType.GROUP) {
this.panelTitle = "Add Group";
return;
}
- if (component.categoryType === LeftPaletteMetadataTypes.Policy) {
+ if (component.componentSubType === SdcElementType.POLICY) {
this.panelTitle = "Add Policy";
return;
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.html b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.html
new file mode 100644
index 0000000..7963dd1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.html
@@ -0,0 +1,41 @@
+<div class="composition-palette-component">
+ <div class="palette-elements-count">Elements
+ <span class="palette-elements-count-value">{{numberOfElements}}</span>
+ </div>
+
+ <sdc-filter-bar placeholder="Search..." (valueChange)="onSearchChanged($event)" testId="searchAsset"></sdc-filter-bar>
+
+ <div class="palette-elements-list">
+ <sdc-loader [global]="false" name="palette-loader" testId="palette-loader" [active]="this.isPaletteLoading" [class.inactive]="!this.isPaletteLoading"></sdc-loader>
+ <div *ngIf="numberOfElements === 0 && searchText" class="no-elements-found">No Elements Found</div>
+ <sdc-accordion *ngFor="let mapByCategory of paletteElements | keyValue; let first = first" [attr.data-tests-id]="'leftPalette.category.'+mapByCategory.key" [title]="mapByCategory.key" [css-class]="'palette-category'">
+ <div *ngFor="let mapBySubCategory of mapByCategory.value | keyValue">
+ <div class="palette-subcategory">{{mapBySubCategory.key}}</div>
+ <ng-container *ngIf="!(isViewOnly$ | async)">
+ <div *ngFor="let paletteElement of mapBySubCategory.value"
+ [dndDraggable]="paletteElement"
+ [dndDisableIf]="paletteElement.componentSubType == 'GROUP' && paletteElement.componentSubType == 'POLICY'"
+ (dndStart)="onDragStart($event, paletteElement)"
+ (drag)="onDraggableMoved($event)"
+ [dndEffectAllowed]="'copyMove'"
+ (mouseenter)="onMouseOver($event, paletteElement)"
+ (mouseleave)="onMouseOut(paletteElement)"
+ [attr.data-tests-id]="paletteElement.name">
+ <palette-element [paletteElement]="paletteElement"></palette-element>
+ </div>
+ </ng-container>
+ <ng-container *ngIf="(isViewOnly$ | async)">
+ <div *ngFor="let paletteElement of mapBySubCategory.value"
+ [attr.data-tests-id]="paletteElement.name">
+ <palette-element [paletteElement]="paletteElement"></palette-element>
+ </div>
+ </ng-container>
+ </div>
+ </sdc-accordion>
+ </div>
+</div>
+
+<div id="draggable_element" dndDropzone (dndDrop)="onDrop($event)" [dndAllowExternal]="true">
+ <sdc-element-icon *ngIf="paletteDraggedElement" [iconName]="paletteDraggedElement.icon"
+ [elementType]="paletteDraggedElement.componentSubType" [uncertified]="paletteDraggedElement.certifiedIconClass"></sdc-element-icon>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.less b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.less
new file mode 100644
index 0000000..37461ba
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.less
@@ -0,0 +1,84 @@
+@import "./../../../../../assets/styles/override";
+
+:host(composition-palette) {
+ display:flex;
+ flex: 0 0 244px;
+}
+
+sdc-loader.inactive {
+ display:none;
+}
+
+:host ::ng-deep .sdc-filter-bar .sdc-input {
+ margin-bottom:0px;
+}
+:host ::ng-deep .sdc-loader-wrapper {
+ position:static;
+}
+
+.composition-palette-component {
+ background-color: @sdcui_color_white;
+ overflow-y: auto;
+ overflow-x: hidden;
+ display: flex;
+ flex-direction: column;
+ position:relative;
+ width: 244px;
+ box-shadow: 7px -3px 6px -8px @sdcui_color_gray;
+
+ .palette-elements-count {
+ background-color: @sdcui_color_gray;
+ line-height: 40px;
+ padding: 0 17px;
+ color: @sdcui_color_white;
+ .palette-elements-count-value {
+ float: right;
+ }
+ }
+
+ .palette-elements-list {
+
+ .no-elements-found {
+ padding-left: 40px;
+ }
+ /deep/ .palette-category {
+ display: flex;
+ margin: 0px;
+ .sdc-accordion-header {
+ background-color: @sdcui_color_silver;
+ margin: 0px;
+ line-height: 40px;
+ padding: 0px 10px;
+ }
+ .sdc-accordion-body {
+ padding: 0px;
+ }
+ }
+ .palette-subcategory {
+ padding: 0 10px;
+ background-color: @sdcui_color_lighter-silver;
+ line-height: 35px;
+ }
+ }
+}
+
+#draggable_element {
+ display: inline-block;
+ border-radius: 50%;
+ background: transparent;
+ position: absolute;
+ top: -9999px;
+ left: 0;
+ z-index: 100;
+}
+
+.invalid-drag {
+ border: 7px solid @red-shadow;
+}
+
+.valid-drag {
+ border: 7px solid @green-shadow;
+}
+
+@green-shadow: rgba(29, 154, 149, 0.3);
+@red-shadow: rgba(218, 31, 61, 0.3);
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.spec.ts
new file mode 100644
index 0000000..efa9cd3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.spec.ts
@@ -0,0 +1,102 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {CompositionPaletteService} from "./services/palette.service";
+import {EventListenerService} from "../../../../services/event-listener-service";
+import {PaletteElementComponent} from "./palette-element/palette-element.component";
+import {PaletteComponent} from "./palette.component";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {GRAPH_EVENTS} from "../../../../utils/constants";
+import {KeyValuePipe} from "../../../pipes/key-value.pipe";
+import {ResourceNamePipe} from "../../../pipes/resource-name.pipe";
+import {LeftPaletteComponent} from "../../../../models/components/displayComponent";
+import {Observable} from "rxjs/Observable";
+import {leftPaletteElements} from "../../../../../jest/mocks/left-paeltte-elements.mock";
+import {NgxsModule, Select} from '@ngxs/store';
+import { WorkspaceState } from 'app/ng2/store/states/workspace.state';
+
+
+describe('palette component', () => {
+
+ const mockedEvent = <MouseEvent>{ target: {} }
+ let fixture: ComponentFixture<PaletteComponent>;
+ let eventServiceMock: Partial<EventListenerService>;
+ let compositionPaletteMockService: Partial<CompositionPaletteService>;
+
+ beforeEach(
+ async(() => {
+ eventServiceMock = {
+ notifyObservers: jest.fn()
+ }
+ compositionPaletteMockService = {
+ subscribeToLeftPaletteElements: jest.fn().mockImplementation(()=> Observable.of(leftPaletteElements)),
+ getLeftPaletteElements: jest.fn().mockImplementation(()=> leftPaletteElements)
+ }
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [PaletteComponent, PaletteElementComponent, KeyValuePipe, ResourceNamePipe],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: CompositionPaletteService, useValue: compositionPaletteMockService},
+ {provide: EventListenerService, useValue: eventServiceMock}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(PaletteComponent);
+ });
+ })
+ );
+
+ it('should match current snapshot of palette component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should call on palette component hover in event', () => {
+ let paletteObject = <LeftPaletteComponent>{categoryType: 'COMPONENT'};
+ fixture.componentInstance.onMouseOver(mockedEvent, paletteObject);
+ expect(eventServiceMock.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, paletteObject);
+ });
+
+ it('should call on palette component hover out event', () => {
+ let paletteObject = <LeftPaletteComponent>{categoryType: 'COMPONENT'};
+ fixture.componentInstance.onMouseOut(paletteObject);
+ expect(eventServiceMock.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT);
+ });
+
+ it('should call show popup panel event', () => {
+ let paletteObject = <LeftPaletteComponent>{categoryType: 'GROUP'};
+ fixture.componentInstance.onMouseOver(mockedEvent, paletteObject);
+ expect(eventServiceMock.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, paletteObject, mockedEvent.target);
+ });
+
+ it('should call hide popup panel event', () => {
+ let paletteObject = <LeftPaletteComponent>{categoryType: 'GROUP'};
+ fixture.componentInstance.onMouseOut(paletteObject);
+ expect(eventServiceMock.notifyObservers).toHaveBeenCalledWith(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL);
+ });
+
+ it('should build Palette By Categories without searchText', () => {
+ fixture.componentInstance.buildPaletteByCategories();
+ expect(fixture.componentInstance.paletteElements["Generic"]["Network"].length).toBe(5);
+ expect(fixture.componentInstance.paletteElements["Generic"]["Network"][0].searchFilterTerms).toBe("extvirtualmachineinterfacecp external port for virtual machine interface extvirtualmachineinterfacecp 3.0");
+ expect(fixture.componentInstance.paletteElements["Generic"]["Network"][1].searchFilterTerms).toBe("newservice2 asdfasdfa newservice2 0.3");
+
+ expect(fixture.componentInstance.paletteElements["Generic"]["Configuration"].length).toBe(1);
+ expect(fixture.componentInstance.paletteElements["Generic"]["Configuration"][0].systemName).toBe("Extvirtualmachineinterfacecp");
+ });
+
+ it('should build Palette By Categories with searchText', () => {
+ fixture.componentInstance.buildPaletteByCategories("testVal");
+ expect(fixture.componentInstance.paletteElements["Generic"]["Network"].length).toBe(1);
+ expect(fixture.componentInstance.paletteElements["Generic"]["Network"][0].searchFilterTerms).toBe("testVal and other values");
+ });
+
+ it('should change numbers of elements', () => {
+ fixture.componentInstance.buildPaletteByCategories();
+ expect(fixture.componentInstance.numberOfElements).toEqual(6);
+ fixture.componentInstance.buildPaletteByCategories("testVal");
+ expect(fixture.componentInstance.numberOfElements).toEqual(1);
+ });
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.ts
new file mode 100644
index 0000000..02d270b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette.component.ts
@@ -0,0 +1,172 @@
+/**
+ * Created by ob0695 on 6/28/2018.
+ */
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Component, HostListener } from '@angular/core';
+import { Select } from '@ngxs/store';
+import { LeftPaletteComponent, LeftPaletteMetadataTypes } from 'app/models/components/displayComponent';
+import { Point } from 'app/models/graph/point';
+import { WorkspaceState } from 'app/ng2/store/states/workspace.state';
+import Dictionary = _.Dictionary;
+import { EventListenerService } from 'app/services/event-listener-service';
+import { GRAPH_EVENTS } from 'app/utils/constants';
+import { DndDropEvent } from 'ngx-drag-drop/ngx-drag-drop';
+import { CompositionPaletteService } from './services/palette.service';
+import {PolicyMetadata} from "../../../../models/policy-metadata";
+import {GenericBrowserDomAdapter} from "@angular/platform-browser/src/browser/generic_browser_adapter";
+
+@Component({
+ selector: 'composition-palette',
+ templateUrl: './palette.component.html',
+ styleUrls: ['./palette.component.less']
+})
+export class PaletteComponent {
+
+ constructor(private compositionPaletteService: CompositionPaletteService, private eventListenerService: EventListenerService) {}
+
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+ private paletteElements: Dictionary<Dictionary<LeftPaletteComponent[]>>;
+ public numberOfElements: number = 0;
+ public isPaletteLoading: boolean;
+ private paletteDraggedElement: LeftPaletteComponent;
+ public position: Point = new Point();
+
+ ngOnInit() {
+ this.isPaletteLoading = true;
+
+ this.compositionPaletteService.subscribeToLeftPaletteElements((leftPaletteElementsResponse) => {
+ this.paletteElements = leftPaletteElementsResponse;
+ this.numberOfElements = this.countLeftPalleteElements(this.paletteElements);
+ this.isPaletteLoading = false;
+ }, () => {
+ this.isPaletteLoading = false;
+ });
+
+ }
+
+ public buildPaletteByCategories = (searchText?: string) => { // create nested by category & subcategory, filtered by search parans
+ // Flat the object and run on its leaves
+ if (searchText) {
+ searchText = searchText.toLowerCase();
+ const paletteElementsAfterSearch = {};
+ this.paletteElements = this.compositionPaletteService.getLeftPaletteElements();
+ for (const category in this.paletteElements) {
+ for (const subCategory in this.paletteElements[category]) {
+ const subCategoryToCheck = this.paletteElements[category][subCategory];
+ const res = subCategoryToCheck.filter((item) => item.searchFilterTerms.toLowerCase().indexOf(searchText) >= 0)
+ if (res.length > 0) {
+ paletteElementsAfterSearch[category] = {};
+ paletteElementsAfterSearch[category][subCategory] = res;
+ }
+ }
+ }
+ this.paletteElements = paletteElementsAfterSearch;
+ } else {
+ this.paletteElements = this.compositionPaletteService.getLeftPaletteElements();
+ }
+ this.numberOfElements = this.countLeftPalleteElements(this.paletteElements);
+ }
+
+ public onSearchChanged = (searchText: string) => {
+
+ if (this.compositionPaletteService.getLeftPaletteElements()) {
+ this.buildPaletteByCategories(searchText);
+ }
+ }
+
+ private countLeftPalleteElements(leftPalleteElements: Dictionary<Dictionary<LeftPaletteComponent[]>>) {
+ // Use _ & flat map
+ let counter = 0;
+ for (const category in leftPalleteElements) {
+ for (const subCategory in leftPalleteElements[category]) {
+ counter += leftPalleteElements[category][subCategory].length;
+ }
+ }
+ return counter;
+ }
+
+ private isGroupOrPolicy(component: LeftPaletteComponent): boolean {
+ if (component &&
+ (component.categoryType === LeftPaletteMetadataTypes.Group ||
+ component.categoryType === LeftPaletteMetadataTypes.Policy)) {
+ return true;
+ }
+ return false;
+ }
+ @HostListener('document:dragover', ['$event'])
+ public onDrag(event) {
+ this.position.x = event.clientX;
+ this.position.y = event.clientY;
+ }
+
+ //---------------------------------------Palette Events-----------------------------------------//
+
+ public onDraggableMoved = (event:DragEvent) => {
+ let draggedElement = document.getElementById("draggable_element");
+ draggedElement.style.top = (this.position.y - 80) + "px";
+ draggedElement.style.left = (this.position.x - 30) + "px";
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, this.position);
+ }
+
+ public onDragStart = (event, draggedElement:LeftPaletteComponent) => { // Applying the dragged svg component to the draggable element
+
+ this.paletteDraggedElement = draggedElement;
+ event.dataTransfer.dropEffect = "copy";
+ let hiddenImg = document.createElement("span");
+ event.dataTransfer.setDragImage(hiddenImg, 0, 0);
+ }
+
+
+ public onDrop = (event:DndDropEvent) => {
+ let draggedElement = document.getElementById("draggable_element");
+ draggedElement.style.top = "-9999px";
+ if(draggedElement.classList.contains('valid-drag')) {
+ if(!event.data){
+ event.data = this.paletteDraggedElement;
+ }
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DROP, event);
+ } else {
+ console.log("INVALID drop");
+ }
+ this.paletteDraggedElement = undefined;
+
+ }
+
+ public onMouseOver = (sectionElem:MouseEvent, displayComponent:LeftPaletteComponent) => {
+ console.debug("On palette element MOUSE HOVER: ", displayComponent);
+ if (this.isGroupOrPolicy(displayComponent)) {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, displayComponent, sectionElem.target);
+ } else {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent);
+ }
+ };
+
+ public onMouseOut = (displayComponent:LeftPaletteComponent) => {
+ console.debug("On palette element MOUSE OUT: ", displayComponent);
+ if (this.isGroupOrPolicy(displayComponent)) {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL);
+ } else {
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT);
+ }
+ };
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/palette.module.ts b/catalog-ui/src/app/ng2/pages/composition/palette/palette.module.ts
new file mode 100644
index 0000000..aeb4c4c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/palette.module.ts
@@ -0,0 +1,25 @@
+import { NgModule } from "@angular/core";
+import { CompositionPaletteService } from "./services/palette.service";
+import { PaletteComponent } from "./palette.component";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import { GlobalPipesModule } from "app/ng2/pipes/global-pipes.module";
+import { CommonModule } from "@angular/common";
+import { DndModule } from "ngx-drag-drop";
+import {PaletteElementComponent} from "./palette-element/palette-element.component";
+import {EventListenerService} from "app/services/event-listener-service";
+import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+
+@NgModule({
+ declarations: [PaletteComponent, PaletteElementComponent],
+ imports: [CommonModule, SdcUiComponentsModule, GlobalPipesModule, UiElementsModule, DndModule],
+ exports: [PaletteComponent],
+ entryComponents: [PaletteComponent],
+ providers: [CompositionPaletteService, EventListenerService]
+})
+export class PaletteModule {
+
+ constructor() {
+
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.spec.ts b/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.spec.ts
new file mode 100644
index 0000000..3a660c1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.spec.ts
@@ -0,0 +1,41 @@
+import {TestBed} from "@angular/core/testing";
+import {CompositionPaletteService} from "./palette.service";
+import {ISdcConfig, SdcConfigToken} from "../../../../config/sdc-config.config";
+import {WorkspaceService} from "../../../../pages/workspace/workspace.service";
+import { HttpClient } from "@angular/common/http";
+describe('palette component', () => {
+
+ let service: CompositionPaletteService;
+
+ let httpServiceMock: Partial<HttpClient> = {
+ get: jest.fn()
+ }
+
+ let sdcConfigToken: Partial<ISdcConfig> = {
+ "api": {
+ "root": ''
+ }
+ }
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [],
+ providers: [CompositionPaletteService,
+ {provide: HttpClient, useValue: httpServiceMock},
+ {provide: SdcConfigToken, useValue: sdcConfigToken},
+ {provide: WorkspaceService, useValue{}}
+ ]
+ });
+
+ service = TestBed.get(CompositionPaletteService);
+ });
+
+ it('should create an instance', () => {
+ expect(service).toBeDefined();
+ });
+
+ // it('should create an instance2', async () => {
+ // expect(await service.subscribeToLeftPaletteElements("resources")).toEqual([]);
+ // });
+});
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.ts b/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.ts
new file mode 100644
index 0000000..7587c52
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/palette/services/palette.service.ts
@@ -0,0 +1,98 @@
+import { HttpClient, HttpParams } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { LeftPaletteComponent, LeftPaletteMetadataTypes } from 'app/models/components/displayComponent';
+import { GroupMetadata } from 'app/models/group-metadata';
+import { PolicyMetadata } from 'app/models/policy-metadata';
+import { SdcConfigToken } from 'app/ng2/config/sdc-config.config';
+import { ISdcConfig } from 'app/ng2/config/sdc-config.config.factory';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import 'rxjs/add/observable/forkJoin';
+import { Observable } from 'rxjs/Rx';
+import Dictionary = _.Dictionary;
+
+
+
+@Injectable()
+export class CompositionPaletteService {
+
+ protected baseUrl = '';
+
+ private leftPaletteComponents: Dictionary<Dictionary<LeftPaletteComponent[]>>;
+ private facadeUrl: string;
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig, private workspaceService: WorkspaceService) {
+ this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
+ this.facadeUrl = sdcConfig.api.uicache_root + sdcConfig.api.GET_uicache_left_palette;
+
+ }
+
+ public subscribeToLeftPaletteElements(next, error) {
+
+ let params = new HttpParams();
+ params = params.append('internalComponentType', this.workspaceService.getMetadataType());
+
+ const loadInstances = this.http.get(this.facadeUrl, {params});
+ const loadGroups = this.http.get(this.baseUrl + 'groupTypes', {params});
+ const loadPolicies = this.http.get(this.baseUrl + 'policyTypes', {params});
+
+ Observable.forkJoin(
+ loadInstances, loadGroups, loadPolicies
+ ).subscribe( ([resInstances, resGrouops, resPolicies]) => {
+ const combinedDictionary = this.combineResoponses(resInstances, resGrouops, resPolicies);
+ this.leftPaletteComponents = combinedDictionary;
+ next(this.leftPaletteComponents);
+ });
+ }
+
+ public getLeftPaletteElements = (): Dictionary<Dictionary<LeftPaletteComponent[]>> => {
+ return this.leftPaletteComponents;
+ }
+
+
+ public convertPoliciesOrGroups = (paletteListResult, type: string ) => {
+ const components: LeftPaletteComponent[] = [];
+
+ if (type === 'Policies') {
+ _.forEach(paletteListResult, (policyMetadata: PolicyMetadata) => {
+ components.push(new LeftPaletteComponent(LeftPaletteMetadataTypes.Policy, policyMetadata));
+ });
+ return {
+ Policies: components
+ };
+ }
+
+ if (type === 'Groups') {
+ _.forEach(paletteListResult, (groupMetadata: GroupMetadata) => {
+ const item = new LeftPaletteComponent(LeftPaletteMetadataTypes.Group, groupMetadata);
+ components.push(item);
+ });
+ return {
+ Groups: components
+ };
+ }
+
+ return {};
+ }
+
+ private combineResoponses(resInstances: object, resGrouops: object, resPolicies: object) {
+ const retValObject = {};
+ // Generic will be the 1st category in the left Pallete
+ if (resInstances['Generic']) {
+ retValObject['Generic'] = resInstances['Generic'];
+ }
+ // Add all other categories
+ for (const category in resInstances) {
+ if (category === 'Generic') {
+ continue;
+ }
+ retValObject[category] = resInstances[category];
+ }
+
+ // Add Groups
+ retValObject["Groups"] = this.convertPoliciesOrGroups(resGrouops, 'Groups');
+
+ // Add policies
+ retValObject["Policies"] = this.convertPoliciesOrGroups(resPolicies, 'Policies');
+
+ return retValObject;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/__snapshots__/composition-panel.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/panel/__snapshots__/composition-panel.component.spec.ts.snap
new file mode 100644
index 0000000..5f10806
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/__snapshots__/composition-panel.component.spec.ts.snap
@@ -0,0 +1,18 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`composition-panel component should match current snapshot of composition-panel component. 1`] = `
+<ng2-composition-panel
+ activatePreviousActiveTab={[Function Function]}
+ classes={[Function String]}
+ initTabs={[Function Function]}
+ isComponentInstanceSelected={[Function Function]}
+ isConfiguration={[Function Function]}
+ isPNF={[Function Function]}
+ selectedComponentIsServiceProxyInstance={[Function Function]}
+ setActive={[Function Function]}
+ store={[Function Store]}
+ toggleSidebarDisplay={[Function Function]}
+>
+
+</ng2-composition-panel>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html
new file mode 100644
index 0000000..bd90b9a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html
@@ -0,0 +1,21 @@
+<panel-wrapper-component *ngIf="compositionState$ | async as state"> <!-- HEADER -->
+
+ <ng2-composition-panel-header [isViewOnly]="state.isViewOnly"
+ [selectedComponent]="state.selectedComponent"></ng2-composition-panel-header>
+
+ <!-- TABS -->
+ <div class="component-details-panel-tabs">
+ <sdc-loader [global]="false" name="panel" testId="panel-loader" [active]="state.panelLoading"></sdc-loader>
+ <sdc-tabs (selectedTab)="setActive($event)" [iconsSize]="'large'">
+ <sdc-tab *ngFor="let tab of tabs" [titleIcon]="tab.titleIcon" [active]="tab.isActive"
+ [tooltipText]="tab.tooltipText">
+ <panel-tab [isActive]="tab.isActive" [component]="selectedComponent"
+ [componentType]="state.selectedComponentType" [isViewOnly]="isViewOnly$ | async"
+ [input]="tab.input" [panelTabType]="tab.component"></panel-tab>
+ </sdc-tab>
+ </sdc-tabs>
+ </div>
+
+</panel-wrapper-component>
+
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.less
new file mode 100644
index 0000000..776ef68
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.less
@@ -0,0 +1,27 @@
+@import '../../../../../assets/styles/variables';
+@import '../../../../../assets/styles/mixins_old';
+
+:host ::ng-deep .sdc-loader-wrapper {
+ position:static;
+}
+
+.component-details-panel-tabs {
+ flex: 1;
+ display:flex;
+ overflow:hidden;
+ }
+
+.component-details-panel-tabs /deep/ sdc-tabs {
+ display:flex;
+ flex-direction:column;
+
+ /deep/ sdc-tab {
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ }
+ .svg-icon-wrapper.label-placement-left .svg-icon-label {
+ margin-right: 0;
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts
new file mode 100644
index 0000000..25a0c72
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts
@@ -0,0 +1,228 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { NgxsModule, Store } from '@ngxs/store';
+import { Observable } from 'rxjs';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { Service } from '../../../../models/components/service';
+import { Resource } from '../../../../models/components/resource';
+import { GroupInstance } from '../../../../models/graph/zones/group-instance';
+import { PolicyInstance } from '../../../../models/graph/zones/policy-instance';
+import { ArtifactGroupType, ResourceType } from '../../../../utils/constants';
+import { WorkspaceState } from '../../../store/states/workspace.state';
+import { CompositionPanelComponent } from './composition-panel.component';
+import { ArtifactsTabComponent } from './panel-tabs/artifacts-tab/artifacts-tab.component';
+import { GroupMembersTabComponent } from './panel-tabs/group-members-tab/group-members-tab.component';
+import { GroupOrPolicyPropertiesTab } from './panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component';
+import { InfoTabComponent } from './panel-tabs/info-tab/info-tab.component';
+import { PolicyTargetsTabComponent } from './panel-tabs/policy-targets-tab/policy-targets-tab.component';
+import { PropertiesTabComponent } from './panel-tabs/properties-tab/properties-tab.component';
+import { ReqAndCapabilitiesTabComponent } from './panel-tabs/req-capabilities-tab/req-capabilities-tab.component';
+
+describe('composition-panel component', () => {
+
+ let fixture: ComponentFixture<CompositionPanelComponent>;
+ let store: Store;
+
+ const tabs = {
+ infoTab : {titleIcon: 'info-circle', component: InfoTabComponent, input: {}, isActive: true, tooltipText: 'Information'},
+ policyProperties: {
+ titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'policy'}, isActive: false, tooltipText: 'Properties'
+ },
+ policyTargets: {titleIcon: 'inputs-o', component: PolicyTargetsTabComponent, input: {}, isActive: false, tooltipText: 'Targets'},
+ groupMembers: {titleIcon: 'inputs-o', component: GroupMembersTabComponent, input: {}, isActive: false, tooltipText: 'Members'},
+ groupProperties: {
+ titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'group'}, isActive: false, tooltipText: 'Properties'
+ },
+ deploymentArtifacts: {
+ titleIcon: 'deployment-artifacts-o', component: ArtifactsTabComponent,
+ input: { type: ArtifactGroupType.DEPLOYMENT}, isActive: false, tooltipText: 'Deployment Artifacts'
+ },
+ apiArtifacts: {
+ titleIcon: 'api-o', component: ArtifactsTabComponent,
+ input: { type: ArtifactGroupType.SERVICE_API}, isActive: false, tooltipText: 'API Artifacts'
+ },
+ infoArtifacts: {
+ titleIcon: 'info-square-o', component: ArtifactsTabComponent,
+ input: { type: ArtifactGroupType.INFORMATION}, isActive: false, tooltipText: 'Information Artifacts'
+ },
+ properties: {
+ titleIcon: 'settings-o', component: PropertiesTabComponent,
+ input: {title: 'Properties and Attributes'}, isActive: false, tooltipText: 'Properties'
+ },
+ reqAndCapabilities : {
+ titleIcon: 'req-capabilities-o', component: ReqAndCapabilitiesTabComponent, input: {},
+ isActive: false, tooltipText: 'Requirements and Capabilities'
+ },
+ inputs: {titleIcon: 'inputs-o', component: PropertiesTabComponent, input: {title: 'Inputs'}, isActive: false, tooltipText: 'Inputs'},
+ settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'},
+ };
+
+ beforeEach(
+ async(() => {
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [CompositionPanelComponent],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(CompositionPanelComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it('When PolicyInstance Selected => Expect (info, policyTargets and policyProperties) tabs appear', () => {
+
+ const testInstance = new PolicyInstance();
+
+ fixture.componentInstance.initTabs(testInstance);
+
+ expect (fixture.componentInstance.tabs.length).toBe(3);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.policyTargets);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.policyProperties);
+ });
+
+ it('should match current snapshot of composition-panel component.', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('When Topology Template is Service and no instance is selected Expect (info, deployment, inputs, info and api)', () => {
+
+ const selectedComponent: Service = new Service(null, null);
+ selectedComponent.isResource = jest.fn(() => false);
+ selectedComponent.isService = jest.fn(() => true );
+
+ fixture.componentInstance.store.select = jest.fn(() => Observable.of(selectedComponent));
+
+ // const pnfMock = Mock.of<Service>({ isResource : () => false });
+ fixture.componentInstance.topologyTemplate = selectedComponent;
+
+ // Call ngOnInit
+ fixture.componentInstance.ngOnInit();
+
+ // Expect that
+ expect (fixture.componentInstance.tabs.length).toBe(5);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.deploymentArtifacts);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.inputs);
+ expect (fixture.componentInstance.tabs[3]).toEqual(tabs.infoArtifacts);
+ expect (fixture.componentInstance.tabs[4]).toEqual(tabs.apiArtifacts);
+
+ });
+
+ it('When Topology Template is Resource and no instance is selected Expect (info, deployment, inputs, info and api)', () => {
+
+ const selectedComponent: Service = new Service(null, null);
+ selectedComponent.isResource = jest.fn(() => true);
+ selectedComponent.isService = jest.fn(() => false );
+
+ fixture.componentInstance.store.select = jest.fn(() => Observable.of(selectedComponent));
+
+ fixture.componentInstance.topologyTemplate = selectedComponent;
+
+ // Call ngOnInit
+ fixture.componentInstance.ngOnInit();
+
+ // Expect that
+ expect (fixture.componentInstance.tabs.length).toBe(5);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.deploymentArtifacts);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.properties);
+ expect (fixture.componentInstance.tabs[3]).toEqual(tabs.infoArtifacts);
+ expect (fixture.componentInstance.tabs[4]).toEqual(tabs.reqAndCapabilities);
+
+ });
+
+ it('When Topology Template is Service and proxyService instance is selected ' +
+ 'Expect (info, deployment, inputs, info and api)', () => {
+
+ const selectedComponent: Service = new Service(null, null);
+ selectedComponent.isResource = jest.fn(() => false);
+ selectedComponent.isService = jest.fn(() => true );
+
+ fixture.componentInstance.store.select = jest.fn(() => Observable.of(selectedComponent));
+ fixture.componentInstance.selectedComponentIsServiceProxyInstance = jest.fn(() => true);
+
+ // const pnfMock = Mock.of<Service>({ isResource : () => false });
+ fixture.componentInstance.topologyTemplate = selectedComponent;
+
+ // Call ngOnInit
+ fixture.componentInstance.ngOnInit();
+
+ // Expect that
+ expect (fixture.componentInstance.tabs.length).toBe(5);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.properties);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.reqAndCapabilities);
+
+ });
+
+ it('When Topology Template is Resource and VL is selected ' +
+ 'Expect (info, deployment, inputs, info and api)', () => {
+
+ const topologyTemplate: Resource = new Resource(null, null);
+ topologyTemplate.isResource = jest.fn(() => true);
+ topologyTemplate.isService = jest.fn(() => false );
+
+ const vlMock = Mock.of<Resource>({ resourceType : 'VL', isResource : () => true, isService : () => false });
+ fixture.componentInstance.store.select = jest.fn(() => Observable.of(vlMock));
+
+ fixture.componentInstance.topologyTemplate = topologyTemplate;
+
+ // Call ngOnInit
+ fixture.componentInstance.ngOnInit();
+
+ // Expect that
+ expect (fixture.componentInstance.tabs.length).toBe(5);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.deploymentArtifacts);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.properties);
+ expect (fixture.componentInstance.tabs[3]).toEqual(tabs.infoArtifacts);
+ expect (fixture.componentInstance.tabs[4]).toEqual(tabs.reqAndCapabilities);
+
+ });
+
+ it('When Topology Template is Service and VL is selected ' +
+ 'Expect (info, deployment, inputs, info and api)', () => {
+
+ const topologyTemplate: Service = new Service(null, null);
+ topologyTemplate.isResource = jest.fn(() => true);
+ topologyTemplate.isService = jest.fn(() => false );
+
+ const vlMock = Mock.of<Resource>({ resourceType : 'VL', isResource : () => true, isService : () => false });
+ fixture.componentInstance.store.select = jest.fn(() => Observable.of(vlMock));
+
+ fixture.componentInstance.topologyTemplate = topologyTemplate;
+
+ // Call ngOnInit
+ fixture.componentInstance.ngOnInit();
+
+ // Expect that
+ expect (fixture.componentInstance.tabs.length).toBe(5);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.deploymentArtifacts);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.properties);
+ expect (fixture.componentInstance.tabs[3]).toEqual(tabs.infoArtifacts);
+ expect (fixture.componentInstance.tabs[4]).toEqual(tabs.reqAndCapabilities);
+
+ });
+
+ it('When GroupInstance Selected => Expect (info, groupMembers and groupProperties) tabs appear.', () => {
+
+ const testInstance = new GroupInstance();
+ fixture.componentInstance.initTabs(testInstance);
+
+ expect (fixture.componentInstance.tabs.length).toBe(3);
+ expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
+ expect (fixture.componentInstance.tabs[1]).toEqual(tabs.groupMembers);
+ expect (fixture.componentInstance.tabs[2]).toEqual(tabs.groupProperties);
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts
new file mode 100644
index 0000000..c5ea41b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts
@@ -0,0 +1,171 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Component, HostBinding, Input } from '@angular/core';
+import { Select, Store } from '@ngxs/store';
+import { Component as TopologyTemplate, ComponentInstance, FullComponentInstance, GroupInstance, PolicyInstance, Resource, Service } from 'app/models';
+import { ArtifactsTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component';
+import { GroupMembersTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component';
+import { GroupOrPolicyPropertiesTab } from 'app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component';
+import { InfoTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component';
+import { PolicyTargetsTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component';
+import { PropertiesTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component';
+import { ReqAndCapabilitiesTabComponent } from 'app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component';
+import { ComponentType, ResourceType } from 'app/utils';
+import * as _ from 'lodash';
+import { Subscription } from 'rxjs';
+import { Observable } from 'rxjs/Observable';
+import { ArtifactGroupType, COMPONENT_FIELDS } from '../../../../utils/constants';
+import { WorkspaceState } from '../../../store/states/workspace.state';
+import { OnSidebarOpenOrCloseAction } from '../common/store/graph.actions';
+import { CompositionStateModel, GraphState } from '../common/store/graph.state';
+import { ServiceConsumptionTabComponent } from './panel-tabs/service-consumption-tab/service-consumption-tab.component';
+import { ServiceDependenciesTabComponent } from './panel-tabs/service-dependencies-tab/service-dependencies-tab.component';
+
+const tabs = {
+ infoTab : {titleIcon: 'info-circle', component: InfoTabComponent, input: {}, isActive: true, tooltipText: 'Information'},
+ policyProperties: {titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'policy'}, isActive: false, tooltipText: 'Properties'},
+ policyTargets: {titleIcon: 'inputs-o', component: PolicyTargetsTabComponent, input: {}, isActive: false, tooltipText: 'Targets'},
+ groupMembers: {titleIcon: 'inputs-o', component: GroupMembersTabComponent, input: {}, isActive: false, tooltipText: 'Members'},
+ groupProperties: {titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'group'}, isActive: false, tooltipText: 'Properties'},
+ deploymentArtifacts: {titleIcon: 'deployment-artifacts-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.DEPLOYMENT}, isActive: false, tooltipText: 'Deployment Artifacts'},
+ apiArtifacts: {titleIcon: 'api-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.SERVICE_API}, isActive: false, tooltipText: 'API Artifacts'},
+ infoArtifacts: {titleIcon: 'info-square-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.INFORMATION}, isActive: false, tooltipText: 'Information Artifacts'},
+ properties: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {title: 'Properties and Attributes'}, isActive: false, tooltipText: 'Properties'},
+ reqAndCapabilities : { titleIcon: 'req-capabilities-o', component: ReqAndCapabilitiesTabComponent, input: {}, isActive: false, tooltipText: 'Requirements and Capabilities'},
+ inputs: {titleIcon: 'inputs-o', component: PropertiesTabComponent, input: {title: 'Inputs'}, isActive: false, tooltipText: 'Inputs'},
+ settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'},
+ consumption: {titleIcon: 'api-o', component: ServiceConsumptionTabComponent, input: {title: 'OPERATION CONSUMPTION'}, isActive: false, tooltipText: 'Service Consumption'},
+ dependencies: {titleIcon: 'archive', component: ServiceDependenciesTabComponent, input: {title: 'SERVICE DEPENDENCIES'}, isActive: false, tooltipText: 'Service Dependencies'}
+};
+
+@Component({
+ selector: 'ng2-composition-panel',
+ templateUrl: './composition-panel.component.html',
+ styleUrls: ['./composition-panel.component.less', './panel-tabs/panel-tabs.less'],
+})
+export class CompositionPanelComponent {
+
+ @Input() topologyTemplate: TopologyTemplate;
+ @HostBinding('class') classes = 'component-details-panel';
+ @Select(GraphState) compositionState$: Observable<CompositionStateModel>;
+ @Select(GraphState.withSidebar) withSidebar$: boolean;
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+ tabs: any[];
+ subscription: Subscription;
+
+ private selectedComponent;
+
+ constructor(public store: Store) {
+ }
+
+ ngOnInit() {
+ this.subscription = this.store.select(GraphState.getSelectedComponent).subscribe((component) => {
+ this.selectedComponent = component;
+ this.initTabs(component);
+ this.activatePreviousActiveTab();
+ });
+ }
+
+ ngOnDestroy() {
+ if (this.subscription) {
+ this.subscription.unsubscribe();
+ }
+ }
+
+ public setActive = (tabToSelect) => {
+ this.tabs.map((tab) => tab.isActive = (tab.titleIcon === tabToSelect.titleIcon) ? true : false);
+ }
+
+ public activatePreviousActiveTab = () => { // sets the info tab to active if no other tab selected
+
+ this.setActive(this.tabs.find((tab) => tab.isActive) || tabs.infoTab);
+
+ }
+
+ private initTabs = (component) => {
+ this.tabs = [];
+
+ // Information
+ this.tabs.push(tabs.infoTab);
+
+ if (component instanceof PolicyInstance) {
+ this.tabs.push(tabs.policyTargets);
+ this.tabs.push(tabs.policyProperties);
+ return;
+ }
+
+ if (component instanceof GroupInstance) {
+ this.tabs.push(tabs.groupMembers);
+ this.tabs.push(tabs.groupProperties);
+ return;
+ }
+
+ // Deployment artifacts
+ if (!this.isPNF() && !this.isConfiguration() && !this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.deploymentArtifacts);
+ }
+
+ // Properties or Inputs
+ if (component.isResource() || this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.properties);
+ } else {
+ this.tabs.push(tabs.inputs);
+ }
+
+ if (!this.isConfiguration() && !this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.infoArtifacts);
+ }
+
+ if (!(component.isService()) || this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.reqAndCapabilities);
+ }
+
+ if (component.isService() && !this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.apiArtifacts);
+ }
+ if (component.isService() && this.selectedComponentIsServiceProxyInstance()) {
+ this.tabs.push(tabs.consumption);
+ this.tabs.push(tabs.dependencies);
+ }
+
+ }
+
+ private toggleSidebarDisplay = () => {
+ // this.withSidebar = !this.withSidebar;
+ this.store.dispatch(new OnSidebarOpenOrCloseAction());
+ }
+
+ private isPNF = (): boolean => {
+ return this.topologyTemplate.isResource() && (this.topologyTemplate as Resource).resourceType === ResourceType.PNF;
+ }
+
+ private isConfiguration = (): boolean => {
+ return this.topologyTemplate.isResource() && (this.topologyTemplate as Resource).resourceType === ResourceType.CONFIGURATION;
+ }
+
+ private isComponentInstanceSelected = (): boolean => {
+ return this.selectedComponent instanceof FullComponentInstance;
+ }
+
+ private selectedComponentIsServiceProxyInstance = (): boolean => {
+ return this.isComponentInstanceSelected() && this.selectedComponent.isServiceProxy();
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts
new file mode 100644
index 0000000..0fd1e51
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+import { NgModule } from "@angular/core";
+import { FormsModule } from "@angular/forms";
+import { BrowserModule } from "@angular/platform-browser";
+import { CompositionPanelComponent } from "./composition-panel.component";
+import { CompositionPanelHeaderModule } from "app/ng2/pages/composition/panel/panel-header/panel-header.module";
+import { SdcUiComponentsModule, SdcUiServices } from "onap-ui-angular";
+// import { SdcUiServices } from "onap-ui-angular/";
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { AddElementsModule } from "../../../components/ui/modal/add-elements/add-elements.module";
+import { TranslateModule } from "app/ng2/shared/translator/translate.module";
+import { InfoTabComponent } from './panel-tabs/info-tab/info-tab.component';
+import { PanelTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/panel-tab.component";
+import { ArtifactsTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component";
+import { PropertiesTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component";
+import { ReqAndCapabilitiesTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component";
+import { RequirementListComponent } from "app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component";
+import { PolicyTargetsTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component";
+import { GroupMembersTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component";
+import { GroupOrPolicyPropertiesTab } from "app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component";
+import { GlobalPipesModule } from "app/ng2/pipes/global-pipes.module";
+import {ModalModule} from "../../../components/ui/modal/modal.module";
+import {EnvParamsComponent} from "../../../components/forms/env-params/env-params.component";
+import {ModalsModule} from "../../../components/modals/modals.module";
+// import {EnvParamsModule} from "../../../components/forms/env-params/env-params.module";
+import { NgxDatatableModule } from "@swimlane/ngx-datatable";
+import {EnvParamsModule} from "../../../components/forms/env-params/env-params.module";
+import { ServiceConsumptionTabComponent } from "./panel-tabs/service-consumption-tab/service-consumption-tab.component";
+import { ServiceDependenciesTabComponent } from "./panel-tabs/service-dependencies-tab/service-dependencies-tab.component";
+import { ServiceDependenciesModule } from "../../../components/logic/service-dependencies/service-dependencies.module";
+import { ServiceConsumptionModule } from "../../../components/logic/service-consumption/service-consumption.module";
+
+
+
+@NgModule({
+ declarations: [
+ CompositionPanelComponent,
+ PolicyTargetsTabComponent,
+ GroupOrPolicyPropertiesTab,
+ GroupMembersTabComponent,
+ InfoTabComponent,
+ PanelTabComponent,
+ ArtifactsTabComponent,
+ PropertiesTabComponent,
+ ReqAndCapabilitiesTabComponent,
+ ServiceConsumptionTabComponent,
+ ServiceDependenciesTabComponent,
+ RequirementListComponent,
+ EnvParamsComponent
+ ],
+ imports: [
+ GlobalPipesModule,
+ BrowserModule,
+ FormsModule,
+ CompositionPanelHeaderModule,
+ SdcUiComponentsModule,
+ UiElementsModule,
+ AddElementsModule,
+ TranslateModule,
+ NgxDatatableModule,
+ ServiceDependenciesModule,
+ ServiceConsumptionModule
+ // EnvParamsModule
+ ],
+ entryComponents: [
+ CompositionPanelComponent,
+ PolicyTargetsTabComponent,
+ GroupOrPolicyPropertiesTab,
+ GroupMembersTabComponent,
+ InfoTabComponent,
+ ArtifactsTabComponent,
+ PropertiesTabComponent,
+ ReqAndCapabilitiesTabComponent,
+ ServiceConsumptionTabComponent,
+ ServiceDependenciesTabComponent,
+ RequirementListComponent,
+ PanelTabComponent,
+ EnvParamsComponent
+ ],
+ exports: [
+ CompositionPanelComponent
+ // EnvParamsModule
+ ],
+ providers: [SdcUiServices.ModalService]
+})
+export class CompositionPanelModule {
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.html
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.html
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.html
diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.less
similarity index 100%
rename from catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.less
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.less
diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.ts
similarity index 68%
rename from catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.ts
index 08bc058..9c4aab2 100644
--- a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.ts
@@ -1,11 +1,11 @@
import { Component, Input } from "@angular/core";
@Component({
- selector: 'value-edit',
- templateUrl: './value-edit.component.html',
- styleUrls: ['./value-edit.component.less']
+ selector: 'edit-name-modal',
+ templateUrl: './edit-name-modal.component.html',
+ styleUrls: ['./edit-name-modal.component.less']
})
-export class ValueEditComponent {
+export class EditNameModalComponent {
@Input() name:String;
@Input() validityChangedCallback: Function;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html
index 67c8238..d9c5619 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.html
@@ -1,30 +1,23 @@
-<!--
- ~ 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="component-details-panel-header" data-tests-id="w-sdc-designer-sidebar-head">
-
+<div *ngIf="selectedComponent" class="component-details-panel-header" data-tests-id="w-sdc-designer-sidebar-head">
<div class="icon">
- <div class="large {{iconClassName}}">
- <div [ngClass]="{'non-certified': nonCertified}" tooltip="Not certified"></div>
- </div>
+ <div *ngIf="iconClassName; else svgIcon" class="large {{iconClassName}}"></div>
+ <ng-template #svgIcon>
+ <sdc-element-icon
+ [elementType]="selectedComponent.componentType === 'RESOURCE' ? selectedComponent.resourceType: (selectedComponent.originType || selectedComponent.componentType)"
+ [iconName]="selectedComponent.icon"
+ [uncertified]="!isTopologyTemplateSelected && selectedComponent.lifecycleState && 'CERTIFIED' !== selectedComponent.lifecycleState"></sdc-element-icon>
+ </ng-template>
</div>
- <div class="title" data-tests-id="selectedCompTitle" tooltip="​{{name}}">{{name}}</div>
+ <div class="title" data-tests-id="selectedCompTitle" tooltip="​{{selectedComponent.name}}">
+ {{selectedComponent.name}}
+ </div>
- <svg-icon-label *ngIf="!isViewOnly" name="edit-file-o" clickable="true" size="small" class="rename-instance" data-tests-id="renameInstance" (click)="renameInstance()"></svg-icon-label>
- <svg-icon-label *ngIf="!isViewOnly" name="trash-o" clickable="true" size="small" class="delete-instance" data-tests-id="deleteInstance" (click)="deleteInstance()"></svg-icon-label>
-
+ <svg-icon-label *ngIf="!isViewOnly && !isTopologyTemplateSelected && !selectedComponent.archived" name="edit-file-o"
+ clickable="true" size="small" class="rename-instance" data-tests-id="renameInstance"
+ (click)="renameInstance()"></svg-icon-label>
+ <svg-icon-label *ngIf="!isViewOnly && !isTopologyTemplateSelected && !selectedComponent.archived" name="trash-o"
+ clickable="true" size="small" class="delete-instance" data-tests-id="deleteInstance"
+ (click)="deleteInstance()"></svg-icon-label>
+
</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less
index 9bbc765..6685f74 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.less
@@ -7,6 +7,7 @@
.icon {
margin: 0 20px;
+ display:flex;
}
.title {
@@ -31,4 +32,17 @@
cursor: pointer;
}
+
+ .non-certified {
+ position: absolute;
+ background-image: url('../../../../../../assets/styles/images/sprites/sprite-global-old.png');
+ background-position: -157px -3386px; width: 15px; height: 15px;
+
+ &.smaller-icon {
+ left: 35px;
+ bottom: -14px;
+ }
+ }
+
+
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.spec.ts
new file mode 100644
index 0000000..76e84a2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.spec.ts
@@ -0,0 +1,123 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed, async } from '@angular/core/testing';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { EventListenerService } from '../../../../../services/event-listener-service';
+import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { GroupsService } from 'app/services-ng2';
+import { PoliciesService } from 'app/services-ng2';
+import { CompositionPanelHeaderComponent } from './panel-header.component';
+import {SdcUiServices} from 'onap-ui-angular';
+import { Capability, Requirement, RequirementsGroup, CapabilitiesGroup, ComponentInstance, Component, FullComponentInstance, PolicyInstance, GroupInstance } from "app/models";
+import { of, Observable } from "rxjs";
+
+describe('CompositionPanelHeaderComponent', () => {
+ let component: CompositionPanelHeaderComponent;
+ let fixture: ComponentFixture<CompositionPanelHeaderComponent>;
+ const componentInstanceServiceNg2Stub = {
+ updateComponentInstance: jest.fn()
+ };
+ const valueEditModalInstance = {
+ innerModalContent : {
+ instance: { name : "VF Test" }
+ },
+ buttons: [{id: 'saveButton', text: 'OK', size: 'xsm', callback: jest.fn(), closeModal: false}],
+ closeModal : jest.fn()
+ };
+
+ beforeEach(
+ () => {
+ const compositionServiceStub = {};
+ const eventListenerServiceStub = {};
+
+ const workspaceServiceStub = {
+ metadata: {
+ componentType: "SERVICE",
+ uniqueId: "123"
+ }
+ };
+ const groupsServiceStub = {
+ updateName: jest.fn()
+ };
+ const policiesServiceStub = {
+ updateName: jest.fn()
+ };
+
+ TestBed.configureTestingModule({
+ schemas: [NO_ERRORS_SCHEMA],
+ declarations: [CompositionPanelHeaderComponent],
+ providers: [
+ { provide: CompositionService, useValue: compositionServiceStub },
+ { provide: EventListenerService, useValue: eventListenerServiceStub },
+ {
+ provide: ComponentInstanceServiceNg2,
+ useValue: componentInstanceServiceNg2Stub
+ },
+ { provide: WorkspaceService, useValue: workspaceServiceStub },
+ { provide: GroupsService, useValue: groupsServiceStub },
+ { provide: PoliciesService, useValue: policiesServiceStub },
+ { provide: SdcUiServices.ModalService, useValue: {}}
+ ]
+ });
+ fixture = TestBed.createComponent(CompositionPanelHeaderComponent);
+ component = fixture.componentInstance;
+ }
+ );
+
+ it('can load instance', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close the modal without saving if the name has not changed', () => {
+ component.selectedComponent = <FullComponentInstance>{name: "VF Test"};
+ component.valueEditModalInstance = valueEditModalInstance;
+
+ component.saveInstanceName();
+ expect(component.componentInstanceService.updateComponentInstance).not.toHaveBeenCalled();
+ expect(component.valueEditModalInstance.closeModal).toHaveBeenCalled();
+ });
+
+ it('after editing instance name, capabilities/requirements should be updated with new name', () => {
+ const newName = "New VF NAME";
+ component.selectedComponent = new FullComponentInstance(<ComponentInstance>{
+ name: "VF Test",
+ requirements: <RequirementsGroup>{"key": [<Requirement>{ownerName: "VF Test"}, <Requirement>{ownerName: "VF Test"}]},
+ capabilities: new CapabilitiesGroup()
+ }, <Component>{});
+ component.selectedComponent.capabilities['key'] = [<Capability>{ownerName: "VF Test"}];
+ component.valueEditModalInstance = valueEditModalInstance;
+ component.valueEditModalInstance.innerModalContent.instance.name = newName;
+ jest.spyOn(component.componentInstanceService, 'updateComponentInstance').mockReturnValue(of(<ComponentInstance>{name: newName}));
+ component.saveInstanceName();
+
+ expect(component.selectedComponent.name).toBe(newName);
+ expect(component.selectedComponent.requirements['key'][0].ownerName).toEqual(newName);
+ expect(component.selectedComponent.requirements['key'][1].ownerName).toEqual(newName);
+ expect(component.selectedComponent.capabilities['key'][0].ownerName).toEqual(newName);
+ });
+
+ it('if update fails, name is reverted to old value', () => {
+ component.selectedComponent = new GroupInstance(<GroupInstance>{name: "GROUP NAME"});
+ component.valueEditModalInstance = valueEditModalInstance;
+ jest.spyOn(component.groupService, 'updateName').mockReturnValue(Observable.throw(new Error('Error')));
+ component.saveInstanceName();
+ expect(component.selectedComponent.name).toEqual("GROUP NAME");
+ });
+
+ it('policy instance uses policies service for update name', () => {
+ component.selectedComponent = new PolicyInstance(<PolicyInstance>{name: "Policy OLD NAME"});
+ component.valueEditModalInstance = valueEditModalInstance;
+ jest.spyOn(component.policiesService, 'updateName').mockReturnValue(of(true));
+ component.saveInstanceName();
+ expect(component.policiesService.updateName).toHaveBeenCalledTimes(1);
+ });
+
+ it('group instance uses groups service for update name', () => {
+ component.selectedComponent = new GroupInstance(<GroupInstance>{name: "GROUP NAME"});
+ component.valueEditModalInstance = valueEditModalInstance;
+ jest.spyOn(component.groupService, 'updateName').mockReturnValue(of(true));
+ component.saveInstanceName();
+ expect(component.groupService.updateName).toHaveBeenCalledTimes(1);
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts
index ab659a3..90a9814 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.component.ts
@@ -18,64 +18,70 @@
* ============LICENSE_END=========================================================
*/
-import { Component, Input, AfterViewInit, SimpleChanges, OnInit, OnChanges } from "@angular/core";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-import { IModalConfig } from 'sdc-ui/lib/angular/modals/models/modal-config';
-import { ZoneInstanceType } from 'app/models/graph/zones/zone-instance';
-import { ValueEditComponent } from './../../../../components/ui/forms/value-edit/value-edit.component';
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { PoliciesService } from '../../../../services/policies.service';
-import { GroupsService } from '../../../../services/groups.service';
-import {IZoneService} from "../../../../../models/graph/zones/zone";
-import { EventListenerService, LoaderService } from "../../../../../services";
-import { GRAPH_EVENTS, EVENTS } from "../../../../../utils";
+import { Component, Input, OnInit } from "@angular/core";
+import { SdcUiComponents, SdcUiCommon, SdcUiServices } from "onap-ui-angular";
+import { EditNameModalComponent } from "app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component";
+import {Component as TopologyTemplate, FullComponentInstance, GroupInstance, PolicyInstance, Requirement, Capability, ComponentInstance} from "app/models";
+import { Select } from "@ngxs/store";
+import { Observable } from "rxjs/Observable";
+import { Subscription } from "rxjs";
+import {GRAPH_EVENTS} from "../../../../../utils/constants";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import {EventListenerService} from "../../../../../services/event-listener-service";
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { GroupsService, PoliciesService } from "app/services-ng2";
import { UIZoneInstanceObject } from "../../../../../models/ui-models/ui-zone-instance-object";
-import { ModalButtonComponent } from "sdc-ui/lib/angular/components";
+import {SelectedComponentType} from "../../common/store/graph.actions";
+import * as _ from 'lodash';
+import {GraphState} from "../../common/store/graph.state";
+
@Component({
selector: 'ng2-composition-panel-header',
templateUrl: './panel-header.component.html',
styleUrls: ['./panel-header.component.less']
})
-export class CompositionPanelHeaderComponent implements OnInit, OnChanges {
-
- @Input() topologyTemplate: TopologyTemplate;
- @Input() selectedZoneInstanceType: ZoneInstanceType;
- @Input() selectedZoneInstanceId: string;
- @Input() name: string;
- @Input() nonCertified: boolean;
+export class CompositionPanelHeaderComponent implements OnInit {
@Input() isViewOnly: boolean;
- @Input() isLoading: boolean;
+ @Input() selectedComponent: FullComponentInstance | TopologyTemplate | GroupInstance | PolicyInstance;
+ @Select(GraphState.getSelectedComponentType) selectedComponentType$:Observable<SelectedComponentType>;
- constructor(private groupsService:GroupsService, private policiesService: PoliciesService,
- private modalService:SdcUiComponents.ModalService, private eventListenerService:EventListenerService) { }
- private service:IZoneService;
+ constructor(private modalService: SdcUiServices.ModalService,
+ private groupService: GroupsService,
+ private policiesService: PoliciesService,
+ private eventListenerService: EventListenerService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private componentInstanceService: ComponentInstanceServiceNg2) { }
+
private iconClassName: string;
+ private valueEditModalInstance: SdcUiComponents.ModalComponent;
+ private isTopologyTemplateSelected: boolean;
+ private componentTypeSubscription: Subscription;
ngOnInit(): void {
- this.init();
- }
+ this.componentTypeSubscription = this.selectedComponentType$.subscribe((newComponentType) => {
- ngOnChanges (changes:SimpleChanges):void {
- if(changes.selectedZoneInstanceId){
- this.init();
- }
+ this.initClasses(newComponentType);
+ this.isTopologyTemplateSelected = (newComponentType === SelectedComponentType.TOPOLOGY_TEMPLATE) ? true : false;
+ });
}
ngOnDestroy() {
-
-
+ if(this.componentTypeSubscription) {
+ this.componentTypeSubscription.unsubscribe();
+ }
}
- private init = (): void => {
- if (this.selectedZoneInstanceType === ZoneInstanceType.POLICY) {
+
+ private initClasses = (componentType:SelectedComponentType): void => {
+ if (componentType === SelectedComponentType.POLICY) {
this.iconClassName = "sprite-policy-icons policy";
- this.service = this.policiesService;
- } else if (this.selectedZoneInstanceType === ZoneInstanceType.GROUP) {
+ } else if (componentType === SelectedComponentType.GROUP) {
this.iconClassName = "sprite-group-icons group";
- this.service = this.groupsService;
} else {
- this.iconClassName = "sprite-resource-icons defaulticon";
+ this.iconClassName = undefined;
}
}
@@ -83,53 +89,95 @@
const modalConfig = {
title: "Edit Name",
size: "sm",
- type: "custom",
+ type: SdcUiCommon.ModalType.custom,
testId: "renameInstanceModal",
buttons: [
{id: 'saveButton', text: 'OK', size: 'xsm', callback: this.saveInstanceName, closeModal: false},
- {id: 'cancelButton', text: 'Cancel', size: 'sm', closeModal: true}
- ] as ModalButtonComponent[]
- } as IModalConfig;
- this.modalService.openCustomModal(modalConfig, ValueEditComponent, {name: this.name, validityChangedCallback: this.enableOrDisableSaveButton});
+ {id: 'cancelButton', text: 'Cancel', size: 'sm', closeModal: true}
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig;
+ this.valueEditModalInstance = this.modalService.openCustomModal(modalConfig, EditNameModalComponent, {name: this.selectedComponent.name, validityChangedCallback: this.enableOrDisableSaveButton});
};
private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
- let saveButton: ModalButtonComponent = this.modalService.getCurrentInstance().getButtonById('saveButton');
+ let saveButton: SdcUiComponents.ModalButtonComponent = this.valueEditModalInstance.getButtonById('saveButton');
saveButton.disabled = !shouldEnable;
}
private saveInstanceName = ():void => {
- let currentModal = this.modalService.getCurrentInstance();
- let nameFromModal:string = currentModal.innerModalContent.instance.name;
+ let nameFromModal:string = this.valueEditModalInstance.innerModalContent.instance.name;
- if(nameFromModal != this.name){
- currentModal.buttons[0].disabled = true;
- this.service.updateName(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId, nameFromModal).subscribe((success)=>{
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_INSTANCE_NAME_CHANGED, nameFromModal);
- this.modalService.closeModal();
- }, (error)=> {
- currentModal.buttons[0].disabled = false;
- });
- } else {
- this.modalService.closeModal();
+ if(nameFromModal != this.selectedComponent.name){
+ let oldName = this.selectedComponent.name;
+ this.selectedComponent.name = nameFromModal;
+ this.valueEditModalInstance.buttons[0].disabled = true;
+
+ let onFailed = (error) => {
+ this.selectedComponent.name = oldName;
+ this.valueEditModalInstance.buttons[0].disabled = false;
+ };
+
+ if(this.selectedComponent instanceof FullComponentInstance){
+ let onSuccess = (componentInstance:ComponentInstance) => {
+ //update requirements and capabilities owner name
+ _.forEach((<FullComponentInstance>this.selectedComponent).requirements, (requirementsArray:Array<Requirement>) => {
+ _.forEach(requirementsArray, (requirement:Requirement):void => {
+ requirement.ownerName = componentInstance.name;
+ });
+ });
+
+ _.forEach((<FullComponentInstance>this.selectedComponent).capabilities, (capabilitiesArray:Array<Capability>) => {
+ _.forEach(capabilitiesArray, (capability:Capability):void => {
+ capability.ownerName = componentInstance.name;
+ });
+ });
+ this.valueEditModalInstance.closeModal();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, this.selectedComponent);
+ };
+
+ this.componentInstanceService.updateComponentInstance(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, new ComponentInstance(this.selectedComponent))
+ .subscribe(onSuccess, onFailed);
+ } else if (this.selectedComponent instanceof PolicyInstance) {
+ this.policiesService.updateName(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.selectedComponent.uniqueId, nameFromModal).subscribe((success)=>{
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, this.selectedComponent);
+ this.valueEditModalInstance.closeModal();
+ }, onFailed);
+ } else if (this.selectedComponent instanceof GroupInstance){
+ this.groupService.updateName(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.selectedComponent.uniqueId, nameFromModal).subscribe((success)=>{
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.selectedComponent);
+ this.valueEditModalInstance.closeModal();
+ }, onFailed);
+ }
+ } else {
+ this.valueEditModalInstance.closeModal();
}
};
-
+
private deleteInstance = (): void => {
let title:string = "Delete Confirmation";
- let message:string = "Are you sure you would like to delete "+ this.name + "?";
- this.modalService.openAlertModal(title, message, "OK", this.deleteInstanceConfirmed, "deleteInstanceModal");
+ let message:string = "Are you sure you would like to delete "+ this.selectedComponent.name + "?";
+ const okButton = {testId: "OK", text: "OK", type: SdcUiCommon.ButtonType.warning, callback: this.deleteInstanceConfirmed, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openWarningModal(title, message, "delete-modal", [okButton]);
};
- private deleteInstanceConfirmed = () => {
- this.eventListenerService.notifyObservers(EVENTS.SHOW_LOADER_EVENT + 'composition-graph');
- this.service.deleteZoneInstance(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).finally(()=> {
- this.eventListenerService.notifyObservers(EVENTS.HIDE_LOADER_EVENT + 'composition-graph');
- }).subscribe(()=> {
- let deletedItem:UIZoneInstanceObject = new UIZoneInstanceObject(this.selectedZoneInstanceId, this.selectedZoneInstanceType, this.name);
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE, deletedItem);
- });
- };
+ private deleteInstanceConfirmed: Function = () => {
+ if(this.selectedComponent instanceof FullComponentInstance){
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE , this.selectedComponent.uniqueId);
+ }
+ else if(this.selectedComponent instanceof PolicyInstance){
+ this.policiesService.deletePolicy(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.selectedComponent.uniqueId).subscribe((success)=>{
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE ,
+ new UIZoneInstanceObject(this.selectedComponent.uniqueId, 1));
+ }, (err) => {});
+ }
+ else if(this.selectedComponent instanceof GroupInstance){
+ this.groupService.deleteGroup(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.selectedComponent.uniqueId).subscribe((success)=>{
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE ,
+ new UIZoneInstanceObject(this.selectedComponent.uniqueId, 0));
+ }, (err) => {});
+
+ }
+ };
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts
index bde0a14..a11bc99 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-header/panel-header.module.ts
@@ -18,29 +18,26 @@
* ============LICENSE_END=========================================================
*/
import { NgModule } from "@angular/core";
-import { HttpModule } from "@angular/http";
import { FormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { CompositionPanelHeaderComponent } from "./panel-header.component";
import { UiElementsModule } from './../../../../components/ui/ui-elements.module';
-import { ValueEditComponent } from './../../../../components/ui/forms/value-edit/value-edit.component';
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { ModalFormsModule } from "app/ng2/components/ui/forms/modal-forms.module";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+import { EditNameModalComponent } from "app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component";
@NgModule({
declarations: [
- CompositionPanelHeaderComponent
+ CompositionPanelHeaderComponent,
+ EditNameModalComponent
],
imports: [
BrowserModule,
FormsModule,
- HttpModule,
UiElementsModule,
- SdcUiComponentsModule,
- ModalFormsModule
+ SdcUiComponentsModule
],
entryComponents: [
- CompositionPanelHeaderComponent, ValueEditComponent
+ CompositionPanelHeaderComponent, EditNameModalComponent
],
exports: [
CompositionPanelHeaderComponent
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap
new file mode 100644
index 0000000..c143e81
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/__snapshots__/artifact-tab.component.spec.ts.snap
@@ -0,0 +1,50 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact-tab component should match current snapshot of artifact-tab component 1`] = `
+<artifacts-tab
+ addOrUpdate={[Function Function]}
+ allowDeleteAndUpdateArtifact={[Function Function]}
+ artifactService={[Function Object]}
+ componentInstanceService="undefined"
+ compositionService={[Function Object]}
+ delete={[Function Function]}
+ getEnvArtifact={[Function Function]}
+ getTitle={[Function Function]}
+ heatToEnv={[Function Map]}
+ isLicenseArtifact={[Function Function]}
+ loadArtifacts={[Function Function]}
+ store={[Function Store]}
+ topologyTemplateService="undefined"
+ updateEnvParams={[Function Function]}
+ viewEnvParams={[Function Function]}
+ workspaceService="undefined"
+>
+ <div
+ class="w-sdc-designer-sidebar-tab-content artifacts"
+ >
+ <div
+ class="w-sdc-designer-sidebar-section"
+ >
+ <ng2-expand-collapse
+ state="0"
+ >
+ <header
+ sdc-tooltip=""
+ >
+
+ </header>
+ <content
+ class="artifacts-container"
+ >
+ <div
+ class="w-sdc-designer-sidebar-section-content"
+ >
+
+ </div>
+
+ </content>
+ </ng2-expand-collapse>
+ </div>
+ </div>
+</artifacts-tab>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts
new file mode 100644
index 0000000..258f229
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifact-tab.component.spec.ts
@@ -0,0 +1,303 @@
+import { async, ComponentFixture } from '@angular/core/testing';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { NgxsModule, Store } from '@ngxs/store';
+import { WorkspaceState } from '../../../../../store/states/workspace.state';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ArtifactsTabComponent } from './artifacts-tab.component';
+import { CompositionService } from '../../../composition.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { ComponentInstanceServiceNg2 } from '../../../../../services/component-instance-services/component-instance.service';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ArtifactsService } from '../../../../../components/forms/artifacts-form/artifacts.service';
+import { ArtifactModel } from '../../../../../../models/artifacts';
+import { ArtifactType } from '../../../../../../utils/constants';
+import { FullComponentInstance } from '../../../../../../models/componentsInstances/fullComponentInstance';
+import { ComponentInstance } from '../../../../../../models/componentsInstances/componentInstance';
+import { Component } from '../../../../../../models/components/component';
+import { GetInstanceArtifactsByTypeAction } from '../../../../../store/actions/instance-artifacts.actions';
+import { Observable } from 'rxjs';
+
+
+describe('artifact-tab component', () => {
+
+ let fixture: ComponentFixture<ArtifactsTabComponent>;
+ let compositionMockService: Partial<CompositionService>;
+ const workspaceMockService: Partial<WorkspaceService>;
+ const componentInstanceMockService: Partial<ComponentInstanceServiceNg2>;
+ const topologyTemplateMockService: Partial<TopologyTemplateService>;
+ let artifactsServiceMockService: Partial<ArtifactsService>;
+ let store: Store;
+
+ beforeEach(
+ async(() => {
+ compositionMockService = {
+ updateInstance: jest.fn()
+ }
+
+ artifactsServiceMockService = {
+ deleteArtifact: jest.fn(),
+ openUpdateEnvParams: jest.fn(),
+ openArtifactModal: jest.fn()
+ }
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [ArtifactsTabComponent],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: CompositionService, useValue: compositionMockService},
+ {provide: WorkspaceService, useValue: workspaceMockService},
+ {provide: ComponentInstanceServiceNg2, useValue: componentInstanceMockService},
+ {provide: TopologyTemplateService, useValue: topologyTemplateMockService},
+ {provide: ArtifactsService, useValue: artifactsServiceMockService}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(ArtifactsTabComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it ('on delete -> deleteArtifact is being called from artifactService', () => {
+ const artifact = new ArtifactModel();
+ const topologyTemplateType: string = undefined;
+ const topologyTemplateId: string = undefined;
+
+ fixture.componentInstance.delete(artifact);
+ expect(artifactsServiceMockService.deleteArtifact).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, artifact);
+ });
+
+ it('should match current snapshot of artifact-tab component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+
+ it ('should get API Artifacts as Title', () => {
+ const artifactType = ArtifactType.SERVICE_API;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('API Artifacts');
+ });
+
+
+ it ('should get Deployment Artifacts as Title', () => {
+ const artifactType = ArtifactType.DEPLOYMENT;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('Deployment Artifacts');
+ });
+
+ it ('should get Informational Artifacts as Title', () => {
+ const artifactType = ArtifactType.INFORMATION;
+
+ const res = fixture.componentInstance.getTitle(artifactType);
+ expect(res).toBe('Informational Artifacts');
+ });
+
+ it ('should get SomeString as Title - This is the default case (return the last val)', () => {
+ // So the last value will be "SomeString"
+ fixture.componentInstance.getTitle('SomeString');
+
+ const res = fixture.componentInstance.getTitle('SomeString');
+ expect(res).toBe('SomeString Artifacts');
+ });
+
+
+ it ('should return isLicenseArtifact false', () => {
+ const artifact = new ArtifactModel();
+ const componentInstance = new ComponentInstance();
+ const component = new Component();
+ fixture.componentInstance.component = new FullComponentInstance(componentInstance, component);
+
+ let res = fixture.componentInstance.isLicenseArtifact(artifact);
+ expect(res).toBe(false);
+ });
+
+ it ('should return isLicenseArtifact true', () => {
+ const artifact = new ArtifactModel();
+ const componentInstance = new ComponentInstance();
+ const component = new Component();
+ fixture.componentInstance.component = new FullComponentInstance(componentInstance, component);
+ fixture.componentInstance.component.isResource = jest.fn(() => true);
+ fixture.componentInstance.component.isCsarComponent = true;
+
+ artifact.artifactType = ArtifactType.VENDOR_LICENSE;
+ const res = fixture.componentInstance.isLicenseArtifact(artifact);
+ expect(res).toBe(true);
+ });
+
+ it ('should verify getEnvArtifact with match', () => {
+ const artifact = new ArtifactModel();
+ artifact.uniqueId = 'matchUniqueID';
+
+ const testItem1 = new ArtifactModel();
+ testItem1.generatedFromId = 'matchUniqueID';
+
+ const testItem2 = new ArtifactModel();
+ testItem2.generatedFromId = '123456';
+
+ const artifacts: ArtifactModel[] = [testItem1, testItem2];
+
+ const res = fixture.componentInstance.getEnvArtifact(artifact, artifacts);
+ expect(res.generatedFromId).toBe('matchUniqueID');
+ });
+
+ it ('should verify getEnvArtifact with no match', () => {
+ const artifact = new ArtifactModel();
+ artifact.uniqueId = 'matchUniqueID';
+
+ const testItem1 = new ArtifactModel();
+ testItem1.generatedFromId = '654321';
+
+ const testItem2 = new ArtifactModel();
+ testItem2.generatedFromId = '123456';
+
+ const artifacts: ArtifactModel[] = [testItem1, testItem2];
+
+ const res = fixture.componentInstance.getEnvArtifact(artifact, artifacts);
+ expect(res).toBe(undefined);
+ });
+
+ it ('on updateEnvParams -> openUpdateEnvParams is being called from artifactService when isComponentInstanceSelected = true', () => {
+ const artifact = new ArtifactModel();
+ artifact.envArtifact = new ArtifactModel();
+
+ const topologyTemplateType: string = undefined;
+ const topologyTemplateId: string = undefined;
+
+ const component = new Component();
+ component.uniqueId = 'id';
+
+ const isComponentInstanceSelected = true;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.updateEnvParams(artifact);
+
+ expect(artifactsServiceMockService.openUpdateEnvParams).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, undefined, component.uniqueId);
+ });
+
+ it ('on updateEnvParams -> openUpdateEnvParams is being called from artifactService when isComponentInstanceSelected = false', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = undefined
+ const topologyTemplateId: string = undefined;
+
+ const component = new Component();
+
+ const isComponentInstanceSelected = false;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.updateEnvParams(artifact);
+
+ expect(artifactsServiceMockService.openUpdateEnvParams).toHaveBeenCalledWith(topologyTemplateType, topologyTemplateId, artifact);
+ });
+
+ it ('on addOrUpdate -> openArtifactModal is being called from artifactService when isComponentInstanceSelected = true', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = 'testType';
+ const topologyTemplateId: string = 'testID';
+ const type: string = 'testType';
+ const isViewOnly: boolean = false;
+
+ const component = new Component();
+ component.uniqueId = 'id';
+
+ const isComponentInstanceSelected = true;
+
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.type = type;
+ fixture.componentInstance.topologyTemplateId = topologyTemplateId;
+ fixture.componentInstance.topologyTemplateType = topologyTemplateType;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.isViewOnly = isViewOnly;
+ fixture.componentInstance.addOrUpdate(artifact);
+
+
+ expect(artifactsServiceMockService.openArtifactModal).toHaveBeenCalledWith(topologyTemplateId, topologyTemplateType, artifact, type, isViewOnly, component.uniqueId);
+ });
+
+ it ('on addOrUpdate -> openArtifactModal is being called from artifactService when isComponentInstanceSelected = false', () => {
+ const artifact = new ArtifactModel();
+
+ const topologyTemplateType: string = 'testType';
+ const topologyTemplateId: string = 'testID';
+ const type: string = 'testType';
+ const isViewOnly: boolean = false;
+
+ const isComponentInstanceSelected = false;
+
+ fixture.componentInstance.type = type;
+ fixture.componentInstance.isComponentInstanceSelected = isComponentInstanceSelected;
+ fixture.componentInstance.topologyTemplateId = topologyTemplateId;
+ fixture.componentInstance.topologyTemplateType = topologyTemplateType;
+ fixture.componentInstance.isViewOnly = isViewOnly;
+ fixture.componentInstance.addOrUpdate(artifact);
+
+ expect(artifactsServiceMockService.openArtifactModal).toHaveBeenCalledWith(topologyTemplateId, topologyTemplateType, artifact, type, isViewOnly);
+ });
+
+
+ it ('verify allowDeleteAndUpdateArtifact return false since isViewOnly=true', () => {
+ const artifact = new ArtifactModel();
+ fixture.componentInstance.isViewOnly = true;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(false)
+ });
+
+ it ('verify allowDeleteAndUpdateArtifact return artifact.isFromCsar since isViewOnly=false && artifactGroupType = DEPLOYMENT', () => {
+ const artifact = new ArtifactModel();
+ artifact.artifactGroupType = ArtifactType.DEPLOYMENT;
+ artifact.isFromCsar = false;
+
+ fixture.componentInstance.isViewOnly = false;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(!artifact.isFromCsar);
+ });
+
+ it ('verify allowDeleteAndUpdateArtifact return !artifact.isHEAT() && !artifact.isThirdParty() &&' +
+ ' !this.isLicenseArtifact(artifact) since isViewOnly=false && artifactGroupType != DEPLOYMENT', () => {
+ const artifact = new ArtifactModel();
+ artifact.artifactGroupType = 'NOT_DEPLOYMENT';
+ artifact.isHEAT = () => false;
+ artifact.isThirdParty = () => false;
+
+ fixture.componentInstance.isLicenseArtifact = jest.fn(() => false);
+
+ fixture.componentInstance.isViewOnly = false;
+
+ const res = fixture.componentInstance.allowDeleteAndUpdateArtifact(artifact);
+ expect(res).toBe(true )
+ });
+
+ it('verify action on loadArtifacts in case isComponentInstanceSelected = true', () => {
+ fixture.componentInstance.isComponentInstanceSelected = true;
+ fixture.componentInstance.topologyTemplateType = 'topologyTemplateType';
+ fixture.componentInstance.topologyTemplateId = 'topologyTemplateId';
+ const component = new Component();
+ component.uniqueId = 'uniqueId';
+ fixture.componentInstance.component = component;
+ fixture.componentInstance.type = 'type';
+
+ const action = new GetInstanceArtifactsByTypeAction(({
+ componentType: 'topologyTemplateType',
+ componentId: 'topologyTemplateId',
+ instanceId: 'uniqueId',
+ artifactType: 'type'
+ }))
+
+ fixture.componentInstance.store.dispatch = jest.fn(() => Observable.of(true));
+ fixture.componentInstance.loadArtifacts();
+
+ expect(store.dispatch).toBeCalledWith(action);
+
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html
new file mode 100644
index 0000000..264444b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.html
@@ -0,0 +1,119 @@
+<div class="w-sdc-designer-sidebar-tab-content artifacts">
+ <div class="w-sdc-designer-sidebar-section">
+ <ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{title}}">{{title}}</header>
+ <content class="artifacts-container">
+ <div class="w-sdc-designer-sidebar-section-content">
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngFor="let artifact of artifacts$ | async">
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact"
+ *ngIf="(!isComponentInstanceSelected || artifact.esId) && 'HEAT_ENV' !== artifact.artifactType"
+ attr.data-tests-id="'artifact-item-' + artifact.artifactDisplayName">
+ <span *ngIf="artifact.heatParameters?.length"
+ class="i-sdc-designer-sidebar-section-content-item-file-link"></span>
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-details"
+ [class.heat]="artifact.isHEAT() && artifact.heatParameters?.length">
+ <div *ngIf="artifact.artifactName"
+ class="i-sdc-designer-sidebar-section-content-item-artifact-filename"
+ attr.data-tests-id="artifactName-{{artifact.artifactDisplayName}}"
+ sdc-tooltip tooltip-text="{{artifact.artifactName}}">{{artifact.artifactName}}
+ </div>
+ <div class="artifact-buttons-container upper-buttons">
+
+
+ <svg-icon
+ *ngIf="!isViewOnly && !artifact.isFromCsar && artifact.artifactName"
+ name="trash-o" clickable="true" size="medium" mode="info"
+ class="artifact-button" testId="delete_{{artifact.artifactDisplayName}}"
+ (click)="delete(artifact)"></svg-icon>
+
+ <!--Display env parameters edit button for Instance -->
+ <svg-icon
+ *ngIf="!isViewOnly && artifact.isHEAT() && isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="indesign_status" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="edit-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="updateEnvParams(artifact)"
+ tooltip="Edit ENV Params"
+ ></svg-icon>
+
+ <!--Display env parameters VIEW button for Instance -->
+ <svg-icon
+ *ngIf="isViewOnly && artifact.isHEAT() && isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="inputs-o" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="view-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="viewEnvParams(artifact)"
+ tooltip="View ENV Params"
+ ></svg-icon>
+
+ <!--Display env parameters edit button for VF -->
+ <svg-icon
+ *ngIf = "!isViewOnly && !isComponentInstanceSelected && artifact.heatParameters?.length"
+ name="indesign_status" clickable="true" size="medium" mode="info"
+ class="artifact-button"
+ testId="edit-parameters-of-{{artifact.artifactDisplayName}}"
+ (click)="updateEnvParams(artifact)"></svg-icon>
+
+
+ <download-artifact *ngIf="artifact.esId && 'deployment' != type"
+ class="artifact-button"
+ [artifact]="artifact" [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ testId="download_{{artifact.artifactDisplayName}}"
+ [isInstance]="isComponentInstanceSelected"></download-artifact>
+ <download-artifact *ngIf="artifact.esId && 'deployment' == type"
+ class="artifact-button"
+ [artifact]="artifact" [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ [isInstance]="isComponentInstanceSelected"
+ testId="download_{{artifact.artifactDisplayName}}"
+ [showLoader]="artifact.isHEAT()"></download-artifact>
+
+ <button *ngIf="!isViewOnly && !artifact.esId && type==='deployment' && !isComponentInstanceSelected && !artifact.isThirdParty()"
+ class="artifact-button attach sprite e-sdc-small-icon-upload"
+ (click)="addOrUpdate(artifact)" type="button"
+ attr.data-tests-id="add_Artifact"></button>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-name"
+ attr.data-tests-id="artifact_Display_Name-{{artifact.artifactDisplayName}}"
+ [ngClass]="{'hand enabled': artifact.allowDeleteAndUpdate}"
+ (click)="artifact.allowDeleteAndUpdate && addOrUpdate(artifact)"
+ sdc-tooltip tooltip-text="{{artifact.artifactDisplayName}}">{{artifact.artifactDisplayName}}</span>
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-heat-env"
+ *ngIf="artifact.heatParameters?.length">
+ <span attr.data-tests-id="heat_env_{{artifact.artifactDisplayName}}">{{artifact.artifactDisplayName}} (ENV)</span>
+ <div class="artifact-buttons-container">
+ <svg-icon *ngIf="!isViewOnly && envArtifactOf(artifact)"
+ name="edit-o" clickable="true" size="medium"
+ mode="info" class="artifact-button edit-pencil"
+ testId="edit_{{artifact.artifactDisplayName}}"
+ (click)="addOrUpdate(envArtifactOf(artifact))"></svg-icon>
+
+ <download-artifact [artifact]="envArtifactOf(artifact)"
+ class="artifact-button"
+ [componentType]="component.componentType"
+ [componentId]="component.uniqueId"
+ [isInstance]="isComponentInstanceSelected"
+ testId="download_env_{{artifact.artifactDisplayName}}"></download-artifact>
+ </div>
+ </div>
+ </div>
+
+ <div class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc">
+ <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label"
+ *ngIf="artifact.description">Description:</span>{{artifact.description}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="w-sdc-designer-sidebar-section-footer"
+ *ngIf="!isViewOnly && type!=='api' && (!isComponentInstanceSelected || isVfOrPnf() && (type !== 'deployment') || isComplex)">
+ <sdc-button testId="add_Artifact_Button" size="large" type="primary" text="Add Artifact"
+ (click)="addOrUpdate({})"></sdc-button>
+ </div>
+ </content>
+ </ng2-expand-collapse>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less
new file mode 100644
index 0000000..fef199d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.less
@@ -0,0 +1,169 @@
+@import '../../../../../../../assets/styles/override';
+
+
+.artifacts /deep/ .expand-collapse-content {
+ padding: 10px 0px;
+
+ &.collapsed {
+ padding: 0 0;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-artifact {
+
+ &:not(:hover) .artifact-button {
+ display:none;
+ }
+ .artifact-buttons-container {
+ display: inline-flex;
+ flex-direction: row-reverse;
+ position: absolute;
+ right:0;
+
+ &.upper-buttons {
+ margin-top: 8px;
+ }
+
+ .artifact-button {
+ cursor:pointer;
+ padding-right:5px;
+
+ &.edit-pencil {
+ margin-top: 10px;
+ }
+ }
+ }
+}
+
+.w-sdc-designer-sidebar-section-footer {
+ padding: 20px;
+ display: flex;
+ justify-content: center;
+
+}
+
+
+.w-sdc-designer-sidebar-tab-content.artifacts {
+
+ .i-sdc-designer-sidebar-section-content-item-artifact.hand {
+ cursor: pointer;
+ }
+
+ .w-sdc-designer-sidebar-section-content {
+ padding: 0;
+ }
+ .w-sdc-designer-sidebar-section-title {
+ &.expanded {
+ margin-bottom: 0;
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details {
+ display: inline-block;
+ margin-left: 5px;
+ vertical-align: middle;
+ width: 180px;
+ &.heat {
+ line-height: 18px;
+ width: 250px;
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-name {
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width:220px;
+ display: inline-block;
+ //text-transform: capitalize;
+ &.enabled {
+ &:hover {
+ color: @sdcui_color_dark-blue;
+ }
+ }
+
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-heat-env {
+ color: @sdcui_color_dark-gray;
+ margin-top: 6px;
+ line-height: 42px;
+ padding-top: 10px;
+ border-top:1px solid #c8cdd1;
+ .enabled {
+ &:hover {
+ cursor: pointer;
+ color: @sdcui_color_dark-blue;
+ }
+ }
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-filename {
+ color: @sdcui_color_dark-gray;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width: 225px;
+ display: inline-block;
+ font-weight: bold;
+ &.enabled {
+ &:hover {
+ color: @sdcui_color_dark-blue;
+ }
+ }
+ }
+
+
+ .i-sdc-designer-sidebar-section-content-item-file-link{
+ border-left: 1px #848586 solid;
+ height: 58px;
+ margin-left: -11px;
+ margin-top: 11px;
+ border-top: 1px #848586 solid;
+ border-bottom: 1px #848586 solid;
+ width: 12px;
+ float: left;
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-desc {
+ display: none;
+ line-height: 16px;
+ word-wrap: break-word;
+ white-space: normal;
+ }
+
+ .i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label {
+ color: @sdcui_color_dark-gray;
+ }
+
+
+ .i-sdc-designer-sidebar-section-content-item-artifact {
+ border-bottom: 1px solid #c8cdd1;
+ padding: 5px 10px 5px 18px;
+ position: relative;
+ // line-height: 36px;
+ min-height: 61px;
+ //cursor: default;
+ display: flex;
+ align-items: center;
+
+
+ .i-sdc-designer-sidebar-section-content-item-button {
+ top: 20px;
+ line-height: 10px;
+ }
+
+ &:hover {
+ //background-color: @color_c;
+ background-color: white;
+ transition: all .3s;
+
+ .i-sdc-designer-sidebar-section-content-item-button {
+ display: block;
+
+ }
+
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts
new file mode 100644
index 0000000..53a6c26
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/artifacts-tab/artifacts-tab.component.ts
@@ -0,0 +1,204 @@
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import { ArtifactModel, Component as TopologyTemplate, FullComponentInstance, Resource } from 'app/models';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
+import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ArtifactType } from 'app/utils';
+import * as _ from 'lodash';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Observable';
+import { map } from 'rxjs/operators';
+import { ArtifactsService } from '../../../../../components/forms/artifacts-form/artifacts.service';
+import { GetArtifactsByTypeAction } from '../../../../../store/actions/artifacts.action';
+import { GetInstanceArtifactsByTypeAction } from '../../../../../store/actions/instance-artifacts.actions';
+import { ArtifactsState } from '../../../../../store/states/artifacts.state';
+import { InstanceArtifactsState } from '../../../../../store/states/instance-artifacts.state';
+import { SelectedComponentType, TogglePanelLoadingAction } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'artifacts-tab',
+ styleUrls: ['./artifacts-tab.component.less'],
+ templateUrl: './artifacts-tab.component.html',
+ providers: [SdcUiServices.ModalService]
+})
+
+export class ArtifactsTabComponent {
+
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() isViewOnly: boolean;
+ @Input() input: any;
+ @Input() componentType: SelectedComponentType;
+
+ public title: string;
+ public type: string;
+ public isComponentInstanceSelected: boolean;
+ public artifacts$: Observable<ArtifactModel[]>;
+ private topologyTemplateType: string;
+ private topologyTemplateId: string;
+ private heatToEnv: Map<string, ArtifactModel>;
+ private resourceType: string;
+ private isComplex: boolean;
+
+ constructor(private store: Store,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
+ private topologyTemplateService: TopologyTemplateService,
+ private artifactService: ArtifactsService) {
+ this.heatToEnv = new Map();
+ }
+
+ ngOnInit() {
+ this.topologyTemplateType = this.workspaceService.metadata.componentType;
+ this.topologyTemplateId = this.workspaceService.metadata.uniqueId;
+ this.type = this.input.type;
+ this.title = this.getTitle(this.type);
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.resourceType = this.component['resourceType'];
+ this.isComplex = this.component.isComplex();
+ this.loadArtifacts();
+ }
+
+ public addOrUpdate = (artifact: ArtifactModel): void => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openArtifactModal(this.topologyTemplateId, this.topologyTemplateType, artifact, this.type, this.isViewOnly, this.component.uniqueId);
+ } else {
+ this.artifactService.openArtifactModal(this.topologyTemplateId, this.topologyTemplateType, artifact, this.type, this.isViewOnly);
+ }
+ }
+
+ public updateEnvParams = (artifact: ArtifactModel) => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openUpdateEnvParams(this.topologyTemplateType, this.topologyTemplateId, this.heatToEnv.get(artifact.uniqueId), this.component.uniqueId);
+ } else {
+ this.artifactService.openUpdateEnvParams(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public viewEnvParams = (artifact: ArtifactModel) => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.openViewEnvParams(this.topologyTemplateType, this.topologyTemplateId, this.heatToEnv.get(artifact.uniqueId), this.component.uniqueId);
+ } else {
+ this.artifactService.openViewEnvParams(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public getEnvArtifact = (heatArtifact: ArtifactModel, artifacts: ArtifactModel[]): ArtifactModel => {
+ const envArtifact = _.find(artifacts, (item: ArtifactModel) => {
+ return item.generatedFromId === heatArtifact.uniqueId;
+ });
+ if (envArtifact && heatArtifact) {
+ envArtifact.artifactDisplayName = heatArtifact.artifactDisplayName;
+ envArtifact.timeout = heatArtifact.timeout;
+ }
+ return envArtifact;
+ }
+
+ public delete = (artifact: ArtifactModel): void => {
+ if (this.isComponentInstanceSelected) {
+ this.artifactService.deleteArtifact(this.topologyTemplateType, this.topologyTemplateId, artifact, this.component.uniqueId);
+ } else {
+ this.artifactService.deleteArtifact(this.topologyTemplateType, this.topologyTemplateId, artifact);
+ }
+ }
+
+ public isVfOrPnf(): boolean {
+ if (this.component.isResource()){
+ if (this.resourceType) {
+ return this.resourceType === 'VF' || this.resourceType == 'PNF';
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ private envArtifactOf(artifact: ArtifactModel): ArtifactModel {
+ return this.heatToEnv.get(artifact.uniqueId);
+ }
+
+ private isLicenseArtifact = (artifact: ArtifactModel): boolean => {
+ let isLicense: boolean = false;
+ if (this.component.isResource && (this.component as Resource).isCsarComponent) {
+ if (ArtifactType.VENDOR_LICENSE === artifact.artifactType || ArtifactType.VF_LICENSE === artifact.artifactType) {
+ isLicense = true;
+ }
+ }
+
+ return isLicense;
+ }
+
+ private getTitle = (artifactType: string): string => {
+ switch (artifactType) {
+ case ArtifactType.SERVICE_API:
+ return 'API Artifacts';
+ case ArtifactType.DEPLOYMENT:
+ return 'Deployment Artifacts';
+ case ArtifactType.INFORMATION:
+ return 'Informational Artifacts';
+ default:
+ return ResourceNamePipe.getDisplayName(artifactType) + ' Artifacts';
+ }
+ }
+
+ private loadArtifacts = (forceLoad?: boolean): void => {
+
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ let action;
+ if (this.isComponentInstanceSelected) {
+ action = new GetInstanceArtifactsByTypeAction(({
+ componentType: this.topologyTemplateType,
+ componentId: this.topologyTemplateId,
+ instanceId: this.component.uniqueId,
+ artifactType: this.type
+ }));
+ } else {
+ action = new GetArtifactsByTypeAction({
+ componentType: this.topologyTemplateType,
+ componentId: this.topologyTemplateId,
+ artifactType: this.type
+ });
+ }
+ this.store.dispatch(action).subscribe(() => {
+ const stateSelector = this.isComponentInstanceSelected ? InstanceArtifactsState.getArtifactsByType : ArtifactsState.getArtifactsByType;
+ this.artifacts$ = this.store.select(stateSelector).pipe(map((filterFn) => filterFn(this.type))).pipe(map((artifacts) => {
+ _.forEach(artifacts, (artifact: ArtifactModel): void => {
+ const envArtifact = this.getEnvArtifact(artifact, artifacts); // Extract the env artifact (if exist) of the HEAT artifact
+ if (envArtifact) {
+ // Set a mapping between HEAT to HEAT_ENV
+ this.heatToEnv.set(artifact.uniqueId, envArtifact);
+ }
+ });
+ return _.orderBy(artifacts, ['mandatory', 'artifactDisplayName'], ['desc', 'asc']);
+ }));
+
+ this.artifacts$.subscribe((artifacts) => {
+ _.forEach(artifacts, (artifact: ArtifactModel) => {
+ artifact.allowDeleteAndUpdate = this.allowDeleteAndUpdateArtifact(artifact);
+ });
+ if (this.component instanceof FullComponentInstance) {
+ this.compositionService.updateInstance(this.component);
+ }
+ });
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ }, () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ });
+ }
+
+ private allowDeleteAndUpdateArtifact = (artifact: ArtifactModel): boolean => {
+ if (!this.isViewOnly) {
+ if (artifact.artifactGroupType === ArtifactType.DEPLOYMENT) {
+ return !artifact.isFromCsar;
+ } else {
+
+ return (!artifact.isHEAT() && !artifact.isThirdParty() && !this.isLicenseArtifact(artifact));
+ }
+ }
+ return false;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html
similarity index 91%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html
index 6585ad2..8c5c9c7 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<div class="w-sdc-designer-sidebar-section-title" tooltip="Members">Members
+<h1 class="w-sdc-designer-sidebar-section-title" tooltip="Members">Members
<svg-icon-label *ngIf="!isViewOnly"
class="add-members-btn"
name="plus-circle-o"
@@ -24,7 +24,7 @@
labelPlacement="right"
(click)="openAddMembersModal()">
</svg-icon-label>
-</div>
+</h1>
<div class="expand-collapse-content">
<ul>
<li *ngFor="let member of members; let i = index" class="component-details-panel-large-item"
@@ -40,7 +40,7 @@
</li>
</ul>
- <div *ngIf="members.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!members || members.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No data to display yet</div>
<div class="component-details-panel-tab-no-data-content">Add members to group to see members</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts
new file mode 100644
index 0000000..43f6aac
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.spec.ts
@@ -0,0 +1,127 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Rx';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { GroupInstance } from '../../../../../../models/graph/zones/group-instance';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { GroupsService } from '../../../../../services/groups.service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { CompositionService } from '../../../composition.service';
+import { GroupMembersTabComponent } from './group-members-tab.component';
+
+describe('group members tab component', () => {
+
+ let fixture: ComponentFixture<GroupMembersTabComponent>;
+
+ // Mocks
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let eventsListenerServiceMock: Partial<EventListenerService>;
+ let groupServiceMock: Partial<GroupsService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let compositionServiceMock: Partial<CompositionService>;
+ let modalServiceMock: Partial<SdcUiServices.ModalService>;
+
+ const membersToAdd = [
+ {uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ ];
+
+ beforeEach(
+ async(() => {
+
+ eventsListenerServiceMock = {};
+
+ groupServiceMock = Mock.of<GroupsService>(
+ {
+ updateMembers: jest.fn().mockImplementation((compType, uid, groupUniqueId, updatedMembers) => {
+ if (updatedMembers === undefined) {
+ return Observable.throwError('error');
+ } else {
+ return Observable.of(updatedMembers);
+ }
+ }
+ )});
+
+ compositionServiceMock = {
+ getComponentInstances: jest.fn().mockImplementation( () => {
+ return [{uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ {uniqueId: '3', name: 'inst3'},
+ {uniqueId: '4', name: 'inst4'},
+ {uniqueId: '5', name: 'inst5'}
+ ];
+ }
+ )
+ };
+
+ workspaceServiceMock = {
+ metadata: Mock.of<ComponentMetadata>()
+ };
+
+ const addMemberModalInstance = {
+ innerModalContent: { instance: { existingElements: membersToAdd }},
+ closeModal: jest.fn()
+ };
+
+ modalServiceMock = {
+ openInfoModal: jest.fn(),
+ openCustomModal: jest.fn().mockImplementation(() => addMemberModalInstance)
+ };
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const groupInstanceMock = Mock.of<GroupInstance>();
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [GroupMembersTabComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: { translate: jest.fn() }},
+ {provide: GroupsService, useValue: groupServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock },
+ {provide: EventListenerService, useValue: eventsListenerServiceMock },
+ {provide: CompositionService, useValue: compositionServiceMock },
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(GroupMembersTabComponent);
+ fixture.componentInstance.group = groupInstanceMock;
+ });
+ })
+ );
+
+ it('test that initially all members are available for adding', () => {
+ const testedComponent = fixture.componentInstance;
+
+ // No members are currently in the group, all 5 members should be returned
+ const optionalMembersToAdd = testedComponent.getOptionalsMembersToAdd();
+ expect(optionalMembersToAdd).toHaveLength(5);
+ });
+
+ it('test list of available instances to add does not include existing members', () => {
+ const testedComponent = fixture.componentInstance;
+
+ // Mock the group instance to return the members that we are about to add
+ testedComponent.group.getMembersAsUiObject = jest.fn().mockImplementation( () => membersToAdd);
+
+ // The opened modal shall return 2 members to be added
+ testedComponent.openAddMembersModal();
+ testedComponent.addMembers(); // Shall add 2 members (1,2)
+
+ // Now the getOptionalsMembersToAdd shall return 3 which are the members that were no added yet
+ const optionalMembersToAdd = testedComponent.getOptionalsMembersToAdd();
+ expect(optionalMembersToAdd).toHaveLength(3);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts
new file mode 100644
index 0000000..7f12223
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-members-tab/group-members-tab.component.ts
@@ -0,0 +1,158 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
+import { Select } from '@ngxs/store';
+import { GroupInstance } from 'app/models/graph/zones/group-instance';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { EventListenerService } from 'app/services/event-listener-service';
+import { GRAPH_EVENTS } from 'app/utils';
+import * as _ from 'lodash';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable, Subscription } from 'rxjs';
+import { tap } from 'rxjs/operators';
+import { ComponentInstance } from '../../../../../../models/componentsInstances/componentInstance';
+import { MemberUiObject } from '../../../../../../models/ui-models/ui-member-object';
+import { AddElementsComponent } from '../../../../../components/ui/modal/add-elements/add-elements.component';
+import {GraphState} from "../../../common/store/graph.state";
+import { GroupsService } from '../../../../../services/groups.service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+
+@Component({
+ selector: 'group-members-tab',
+ templateUrl: './group-members-tab.component.html',
+ styleUrls: ['./../policy-targets-tab/policy-targets-tab.component.less']
+})
+
+export class GroupMembersTabComponent implements OnInit, OnDestroy {
+
+ @Input() group: GroupInstance;
+ @Input() isViewOnly: boolean;
+ @Select(GraphState.getSelectedComponent) group$: Observable<GroupInstance>;
+ @HostBinding('class') classes = 'component-details-panel-tab-group-members';
+
+ private members: MemberUiObject[];
+ private addMemberModalInstance: SdcUiComponents.ModalComponent;
+ private subscription: Subscription;
+
+ constructor(
+ private translateService: TranslateService,
+ private groupsService: GroupsService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService
+ ) {
+ }
+
+ ngOnInit() {
+ this.subscription = this.group$.pipe(
+ tap((group) => {
+ this.group = group;
+ this.members = this.group.getMembersAsUiObject(this.compositionService.componentInstances);
+ })).subscribe();
+ }
+
+ ngOnDestroy() {
+ if (this.subscription) {
+ this.subscription.unsubscribe();
+ }
+ }
+
+ deleteMember = (member: MemberUiObject): void => {
+ this.loaderService.activate();
+ this.groupsService.deleteGroupMember(
+ this.workspaceService.metadata.componentType,
+ this.workspaceService.metadata.uniqueId,
+ this.group,
+ member.uniqueId).subscribe(
+ (updatedMembers: string[]) => {
+ this.group.members = updatedMembers;
+ this.initMembers();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
+ },
+ () => console.log('Error deleting member!'),
+ () => this.loaderService.deactivate()
+ );
+ }
+
+ addMembers = (): void => {
+ // TODO refactor sdc-ui modal in order to return the data
+ const membersToAdd: MemberUiObject[] = this.addMemberModalInstance.innerModalContent.instance.existingElements;
+ if (membersToAdd.length > 0) {
+ this.addMemberModalInstance.closeModal();
+ this.loaderService.activate();
+ const locallyUpdatedMembers: MemberUiObject[] = _.union(this.members, membersToAdd);
+ this.groupsService.updateMembers(
+ this.workspaceService.metadata.componentType,
+ this.workspaceService.metadata.uniqueId,
+ this.group.uniqueId,
+ locallyUpdatedMembers).subscribe(
+ (updatedMembers: string[]) => {
+ this.group.members = updatedMembers;
+ this.initMembers();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
+ },
+ () => {
+ console.log('Error updating members!');
+ }, () =>
+ this.loaderService.deactivate()
+ );
+ }
+ }
+
+ getOptionalsMembersToAdd(): MemberUiObject[] {
+ const optionalsMembersToAdd: MemberUiObject[] = [];
+ // adding all instances as optional members to add if not already exist
+ _.forEach(this.compositionService.getComponentInstances(), (instance: ComponentInstance) => {
+ if (!_.some(this.members, (member: MemberUiObject) => {
+ return member.uniqueId === instance.uniqueId;
+ })) {
+ optionalsMembersToAdd.push(new MemberUiObject(instance.uniqueId, instance.name));
+ }
+ });
+ return optionalsMembersToAdd;
+ }
+
+ openAddMembersModal(): void {
+ const addMembersModalConfig = {
+ title: this.group.name + ' ADD MEMBERS',
+ size: 'md',
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'addMembersModal',
+ buttons: [
+ {text: 'ADD MEMBERS', size: 'medium', callback: this.addMembers, closeModal: false},
+ {text: 'CANCEL', size: 'sm', type: 'secondary', closeModal: true}
+ ]
+ } as SdcUiCommon.IModalConfig;
+ const optionalsMembersToAdd = this.getOptionalsMembersToAdd();
+ this.addMemberModalInstance = this.modalService.openCustomModal(addMembersModalConfig, AddElementsComponent, {
+ elementsToAdd: optionalsMembersToAdd,
+ elementName: 'member'
+ });
+ }
+
+ private initMembers = (groupInstance?: GroupInstance) => {
+ this.group = groupInstance ? groupInstance : this.group;
+ this.members = this.group.getMembersAsUiObject(this.compositionService.getComponentInstances());
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html
similarity index 89%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html
index fe1f6b4..c57f997 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.html
@@ -18,7 +18,7 @@
<header tooltip="Properties">Properties</header>
<content>
<ul>
- <li *ngFor="let property of properties; let i = index"
+ <li *ngFor="let property of component.properties; let i = index"
class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow">
<div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label hand"
[attr.data-tests-id]="'propertyName_'+property.name"
@@ -32,7 +32,7 @@
</li>
</ul>
- <div *ngIf="properties.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!component.properties || component.properties.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No properties to display</div>
</div>
</content>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts
new file mode 100644
index 0000000..24ae8b2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/group-or-policy-properties-tab/group-or-policy-properties-tab.component.ts
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import { Component, Inject, Input} from "@angular/core";
+import { TranslateService } from './../../../../../shared/translator/translate.service';
+import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
+import { PropertyModel } from './../../../../../../models/properties';
+import { ModalsHandler } from "app/utils";
+import { Component as TopologyTemplate, GroupInstance } from "app/models";
+
+@Component({
+ selector: 'group-or-policy-properties-tab',
+ templateUrl: './group-or-policy-properties-tab.component.html',
+ styleUrls: ['./../properties-tab/properties-tab.component.less'],
+})
+export class GroupOrPolicyPropertiesTab {
+
+ @Input() component: GroupInstance | PolicyInstance;
+ @Input() topologyTemplate:TopologyTemplate;
+ @Input() isViewOnly: boolean;
+ @Input() input: {type: string};
+
+
+ constructor(private translateService:TranslateService, private ModalsHandler:ModalsHandler) {
+ }
+
+
+ editProperty = (property?:PropertyModel):void => {
+ this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.component.properties, false, this.input.type, this.component.uniqueId).then((updatedProperty:PropertyModel) => {
+ console.log("ok");
+ });
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html
deleted file mode 100644
index 953b57b..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-
-<ng2-expand-collapse state="0">
-
- <header tooltip="General Information">General Info</header>
-
- <content>
- <!-- CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_category" tooltip="Group">Group</span>
- </div>
-
- <!-- SUB CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_subCategory" tooltip="Group">Group</span>
- </div>
-
- <!-- VERSION -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
- <span class="value" data-tests-id="rightTab_version" tooltip="{{group.version}}">{{group.version}}</span>
- </div>
-
- <!-- DESCRIPTION -->
- <div class="component-details-panel-item description">
- <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
- <span class="value" ellipsis="group.description" max-chars="55" data-tests-id="rightTab_description">{{group.description}}</span>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less
deleted file mode 100644
index 1006e86..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.less
+++ /dev/null
@@ -1,13 +0,0 @@
-/deep/
-.component-details-panel-tab-group-members {
- .component-details-panel-large-item {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
-
- .w-sdc-designer-sidebar-section-title {
- display: flex;
- justify-content: space-between;
- }
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts
deleted file mode 100644
index 148f213..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-members-tab.component.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Input, Output, EventEmitter, OnChanges, HostBinding } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate } from "app/models";
-import { GroupInstance } from "app/models/graph/zones/group-instance";
-import { GroupsService } from "../../../../../services/groups.service";
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-import { MemberUiObject } from "../../../../../../models/ui-models/ui-member-object";
-import { IModalConfig } from "sdc-ui/lib/angular/modals/models/modal-config";
-import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component";
-import { GRAPH_EVENTS } from 'app/utils';
-import { EventListenerService } from 'app/services/event-listener-service';
-import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-
-@Component({
- selector: 'group-members-tab',
- templateUrl: './group-members-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'group-members-tab.component.less']
-})
-
-export class GroupMembersTabComponent implements OnChanges {
-
-
- private members: Array<MemberUiObject>;
-
- @Input() group: GroupInstance;
- @Input() topologyTemplate: TopologyTemplate;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
- @HostBinding('class') classes = 'component-details-panel-tab-group-members';
-
- constructor(private translateService: TranslateService,
- private groupsService: GroupsService,
- private modalService: SdcUiComponents.ModalService,
- private eventListenerService: EventListenerService
- ) {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.initMembers)
- }
-
- ngOnChanges(changes:SimpleChanges):void {
- this.initMembers();
- }
-
- deleteMember = (member: MemberUiObject):void => {
- this.isLoading.emit(true);
- this.groupsService.deleteGroupMember(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.group, member.uniqueId).subscribe(
- (updatedMembers:Array<string>) => {
- this.group.members = updatedMembers;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
- },
- error => console.log("Error deleting member!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private initMembers = (groupInstance?: GroupInstance) => {
- this.group = groupInstance ? groupInstance : this.group;
- this.members = this.group.getMembersAsUiObject(this.topologyTemplate.componentInstances);
- }
-
- addMembers = ():void => {
- var membersToAdd:Array<MemberUiObject> = this.modalService.getCurrentInstance().innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
- if(membersToAdd.length > 0) {
- this.modalService.closeModal();
- this.isLoading.emit(true);
- var updatedMembers: Array<MemberUiObject> = _.union(this.members, membersToAdd);
- this.groupsService.updateMembers(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.group.uniqueId, updatedMembers).subscribe(
- (updatedMembers:Array<string>) => {
- this.group.members = updatedMembers;
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.group);
- },
- error => {
- console.log("Error updating members!");
- }, () =>
- this.isLoading.emit(false)
- );
- }
- }
-
- getOptionalsMembersToAdd():Array<MemberUiObject> {
-
- let optionalsMembersToAdd:Array<MemberUiObject> = [];
-
- // adding all instances as optional members to add if not already exist
- _.forEach(this.topologyTemplate.componentInstances, (instance:ComponentInstance) => {
- if (!_.some(this.members, (member:MemberUiObject) => {
- return member.uniqueId === instance.uniqueId
- })) {
- optionalsMembersToAdd.push(new MemberUiObject(instance.uniqueId, instance.name));
- }
- });
- return optionalsMembersToAdd;
- }
-
- openAddMembersModal():void {
- let addMembersModalConfig:IModalConfig = {
- title: this.group.name + " ADD MEMBERS",
- size: "md",
- type: "custom",
- testId: "addMembersModal",
- buttons: [
- {text: 'ADD MEMBERS', size: 'xsm', callback: this.addMembers, closeModal: false},
- {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
- ]
- };
- var optionalsMembersToAdd = this.getOptionalsMembersToAdd();
- this.modalService.openCustomModal(addMembersModalConfig, AddElementsComponent, {
- elementsToAdd: optionalsMembersToAdd,
- elementName: "member"
- });
- }
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts
deleted file mode 100644
index 6907934..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, OnChanges, SimpleChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { GroupInstance } from 'app/models/graph/zones/group-instance';
-import { PropertyBEModel } from 'app/models';
-import { PropertyModel } from './../../../../../../models/properties';
-import { ModalsHandler } from "app/utils";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-
-@Component({
- selector: 'group-properties-tab',
- templateUrl: './group-properties-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'group-properties-tab.component.less'],
- host: {'class': 'component-details-panel-tab-group-properties'}
-})
-export class GroupPropertiesTabComponent implements OnChanges {
-
- @Input() group:GroupInstance;
- @Input() topologyTemplate:TopologyTemplate;
- @Input() isViewOnly: boolean;
-
- private properties:Array<PropertyModel>;
-
- constructor(private translateService:TranslateService, private ModalsHandler:ModalsHandler) {
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- console.log("GroupPropertiesTabComponent: ngAfterViewInit: ");
- console.log("group: " + JSON.stringify(this.group));
- this.properties = [];
- this.initProperties();
- }
-
- initProperties = ():void => {
- this.properties= this.group.properties;
- }
-
- editProperty = (property?:PropertyModel):void => {
- this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.properties, false, 'group', this.group.uniqueId).then((updatedProperty:PropertyModel) => {
- console.log("ok");
- });
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html
deleted file mode 100644
index 482de5e..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<sdc-tabs>
- <sdc-tab titleIcon="info-circle">
- <group-information-tab [group]="group" [isViewOnly]="isViewOnly" *ngIf="group"></group-information-tab>
- </sdc-tab>
- <sdc-tab titleIcon="inputs-o">
- <group-members-tab [group]="group" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" (isLoading)="setIsLoading($event)" *ngIf="group"></group-members-tab>
- </sdc-tab>
- <sdc-tab titleIcon="settings-o">
- <group-properties-tab [group]="group" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" *ngIf="group"></group-properties-tab>
- </sdc-tab>
-</sdc-tabs>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts
deleted file mode 100644
index 975d5c6..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.component.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, SimpleChanges, OnChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { GroupsService } from '../../../../../services/groups.service';
-import { GroupInstance } from "app/models/graph/zones/group-instance";
-
-@Component({
- selector: 'group-tabs',
- templateUrl: './group-tabs.component.html'
-})
-export class GroupTabsComponent implements OnChanges {
-
- @Input() topologyTemplate:TopologyTemplate;
- @Input() selectedZoneInstanceType:string;
- @Input() selectedZoneInstanceId:string;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
-
- private group:GroupInstance;
-
- constructor(private translateService:TranslateService,
- private groupsService:GroupsService
- ) {
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- this.initGroup();
- }
-
- private initGroup = ():void => {
- this.isLoading.emit(true);
- this.groupsService.getSpecificGroup(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).subscribe(
- group => {
- this.group = group;
- console.log(JSON.stringify(group));
- },
- error => console.log("Error getting group!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private setIsLoading = (value) :void => {
- this.isLoading.emit(value);
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts
deleted file mode 100644
index 50797f8..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-tabs.module.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-import { NgModule } from "@angular/core";
-import { HttpModule } from "@angular/http";
-import { FormsModule } from "@angular/forms";
-import { BrowserModule } from "@angular/platform-browser";
-import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
-import { ExpandCollapseComponent } from 'app/ng2/components/ui/expand-collapse/expand-collapse.component';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { GroupInformationTabComponent } from './group-information-tab.component';
-import { TooltipModule } from './../../../../../components/ui/tooltip/tooltip.module';
-import { GroupTabsComponent } from "./group-tabs.component";
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { GroupMembersTabComponent } from './group-members-tab.component';
-import { TranslateModule } from './../../../../../shared/translator/translate.module';
-import { GroupPropertiesTabComponent } from "./group-properties-tab.component";
-
-@NgModule({
- declarations: [
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- TooltipModule,
- UiElementsModule,
- SdcUiComponentsModule,
- TranslateModule
- ],
- entryComponents: [
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent,
- ExpandCollapseComponent
- ],
- exports: [
- TooltipModule,
- GroupInformationTabComponent,
- GroupMembersTabComponent,
- GroupTabsComponent,
- GroupPropertiesTabComponent
- ],
- providers: [
- PoliciesService
- ]
-})
-export class GroupTabsModule {
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap
new file mode 100644
index 0000000..fdd0dcf
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/__snapshots__/info-tab.component.spec.ts.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`InfoTabComponent can load instance 1`] = `
+<panel-info-tab
+ componentInstanceService={[Function Object]}
+ compositionPaletteService={[Function Object]}
+ compositionService={[Function Object]}
+ eventListenerService={[Function Object]}
+ flatLeftPaletteElementsFromService={[Function Function]}
+ getPathNamesVersionChangeModal={[Function Function]}
+ initEditResourceVersion={[Function Function]}
+ modalService={[Function Object]}
+ onChangeVersion={[Function Function]}
+ sdcMenu={[Function Object]}
+ serviceService={[Function Object]}
+ store={[Function Object]}
+ versioning={[Function Function]}
+ workspaceService={[Function Object]}
+>
+ <ng2-expand-collapse
+ state="0"
+ >
+ <header
+ tooltip="General Information"
+ >
+ General Info
+ </header>
+ <content
+ class="general-info-container"
+ >
+
+
+ <div
+ class="component-details-panel-item"
+ >
+ <span
+ class="name"
+ />
+
+
+ </div>
+
+
+
+
+
+
+
+
+
+
+
+ <div
+ class="component-details-panel-item description"
+ >
+ <span
+ class="name"
+ />
+ <chars-ellipsis />
+ </div>
+
+
+ </content>
+ </ng2-expand-collapse>
+</panel-info-tab>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html
new file mode 100644
index 0000000..71545f8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.html
@@ -0,0 +1,174 @@
+<!--
+ ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<ng2-expand-collapse state="0">
+ <header tooltip="General Information">General Info</header>
+ <content class="general-info-container">
+ <!-- TYPE -->
+ <div class="component-details-panel-item" *ngIf="component.componentType">
+ <span class="name" [innerHTML]="'Type:'"></span>
+ <span class="value" data-tests-id="rightTab_componentType" tooltip="{{component.componentType}}">{{component.componentType}}</span>
+ </div>
+
+ <!-- RESOURCE TYPE-->
+ <div class="component-details-panel-item" *ngIf="component.resourceType">
+ <span class="name" [innerHTML]="'Resource Type:'"></span>
+ <span class="value" data-tests-id="rightTab_resourceType" tooltip="{{component.resourceType}}">{{component.resourceType}}</span>
+ </div>
+
+ <!-- VERSION -->
+ <div class="component-details-panel-item" >
+ <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
+ <span class="value" *ngIf="!isComponentSelectedFlag" data-tests-id="rightTab_version" tooltip="{{component.version}}">{{component.version}}</span>
+ <ng-container *ngIf="isComponentSelectedFlag">
+ <select #versionDropdown (change)="onChangeVersion(versionDropdown)" [ngModel]="component.getComponentUid()" data-tests-id="changeVersion">
+ <option *ngFor="let version of versions" value="{{version.value}}"
+ [disabled]="isDisabledFlag" [class.minor]="(component.componentVersion)%1"
+ >{{version.label}}</option>
+ </select>
+ </ng-container>
+ </div>
+
+ <!-- CATEGORY -->
+ <ng-container *ngIf="component.categories && component.categories[0]">
+ <div class="component-details-panel-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="{{component.categories[0].name}}">{{component.categories[0].name}}</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item" *ngIf="component.categories[0].subcategories && component.categories[0].subcategories[0]">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="{{component.categories[0].subcategories[0].name}}">{{component.categories[0].subcategories[0].name}}</span>
+ </div>
+ </ng-container>
+
+ <!-- CREATION DATE -->
+ <div class="component-details-panel-item" *ngIf="component.creationDate">
+ <span class="name" [innerHTML]="'Creation Date:'"></span>
+ <span class="value" data-tests-id="rightTab_version" tooltip="{{component.creationDate | date: 'MM/dd/yyyy'}}">{{component.creationDate | date: 'MM/dd/yyyy'}}</span>
+ </div>
+
+ <!-- AUTHOR -->
+ <div class="component-details-panel-item" *ngIf="component.creatorFullName">
+ <span class="name" [innerHTML]="'Author:'"></span>
+ <span class="value" data-tests-id="rightTab_author" tooltip="{{component.creatorFullName}}">{{component.creatorFullName}}</span>
+ </div>
+
+ <!-- Vendor Name data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.vendorName">
+ <span class="name" [innerHTML]="'Vendor Name:'"></span>
+ <span class="value" data-tests-id="rightTab_vendorName" tooltip="{{component.vendorName}}">{{component.vendorName}}</span>
+ </div>
+
+ <!-- Vendor Release data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.vendorRelease">
+ <span class="name" [innerHTML]="'Vendor Release:'"></span>
+ <span class="value" data-tests-id="rightTab_vendorRelease" tooltip="{{component.vendorRelease}}">{{component.vendorRelease}}</span>
+ </div>
+
+ <!-- Vendor Release data-ng-if="selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.resourceVendorModelNumber">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_RESOURCE_MODEL_NUMBER' | translate"></span>
+ <span class="value" data-tests-id="rightTab_resourceVendorModelNumber" tooltip="{{component.resourceVendorModelNumber}}">{{component.resourceVendorModelNumber}}</span>
+ </div>
+
+ <!-- Service Type data-ng-if="selectedComponent.isService()"-->
+ <div class="component-details-panel-item" *ngIf="component.serviceType">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SERVICE_TYPE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_serviceType" tooltip="{{component.serviceType}}">{{component.serviceType}}</span>
+ </div>
+
+ <!-- Service Role data-ng-if="selectedComponent.isService()"-->
+ <div class="component-details-panel-item" *ngIf="component.serviceRole">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SERVICE_ROLE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_serviceRole" tooltip="{{component.serviceRole}}">{{component.serviceRole}}</span>
+ </div>
+
+ <!-- Contact ID -->
+ <div class="component-details-panel-item" *ngIf="component.contactId">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CONTACT_ID' | translate"></span>
+ <span class="value" data-tests-id="rightTab_contactId" tooltip="{{component.contactId}}">{{component.contactId}}</span>
+ </div>
+
+ <!-- Service Name data-ng-if="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()"-->
+ <div class="component-details-panel-item" *ngIf="component.sourceModelName">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SOURCE_SERVICE_NAME' | translate"></span>
+ <span class="value" data-tests-id="rightTab_sourceModelName" tooltip="{{component.sourceModelName}}">{{component.sourceModelName}}</span>
+ </div>
+
+ <!-- Customization UUID data-ng-if="isViewMode() && currentComponent.isService() && selectedComponent.isResource()"-->
+ <div class="component-details-panel-item" *ngIf="component.customizationUUID">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_RESOURCE_CUSTOMIZATION_UUID' | translate"></span>
+ <span class="value" data-tests-id="rightTab_customizationModuleUUID" tooltip="{{component.customizationUUID}}">{{component.customizationUUID}}</span>
+ </div>
+
+ <!-- DESCRIPTION -->
+ <div class="component-details-panel-item description">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
+ <chars-ellipsis [text]="component.description" [maxChars]="55" [testId]="'rightTab_description'"></chars-ellipsis>
+ </div>
+
+
+ <!--TODO: move to separate component!-->
+ <ng-container *ngIf="componentType == 'POLICY'">
+ <!-- TYPE -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_TYPE' | translate"></span>
+ <span class="value" data-tests-id="rightTab_componentType" tooltip="{{component.policyTypeUid}}">{{component.policyTypeUid}}</span>
+ </div>
+
+ <!-- CATEGORY -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="Policy">Policy</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item policy-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="Policy">Policy</span>
+ </div>
+ </ng-container>
+
+ <!--TODO: move to separate component!-->
+ <ng-container *ngIf="componentType == 'GROUP'">
+ <!-- CATEGORY -->
+ <div class="component-details-panel-item group-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_category" tooltip="Group">Group</span>
+ </div>
+
+ <!-- SUB CATEGORY -->
+ <div class="component-details-panel-item group-item">
+ <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
+ <span class="value" data-tests-id="rightTab_subCategory" tooltip="Group">Group</span>
+ </div>
+
+ </ng-container>
+
+ </content>
+</ng2-expand-collapse>
+
+<ng2-expand-collapse *ngIf="component.tags || isComponentInstanceSelected()">
+ <header tooltip="Tags">Tags</header>
+ <content class="tags-container">
+ <span *ngIf="component.tags?.indexOf(component.name)===-1" class="i-sdc-designer-sidebar-section-content-item-tag"
+ data-tests-id="rightTab_tag" tooltip="{{component.name}}">{{component.name}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-tag" *ngFor="let tag of component.tags"
+ data-tests-id="rightTab_tag" tooltip="{{tag}}">{{tag}}</span>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less
new file mode 100644
index 0000000..c8da4e3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.less
@@ -0,0 +1,51 @@
+@import '../../../../../../../assets/styles/variables';
+
+.general-info-container {
+ display: flex;
+ flex-direction: column;
+ padding: 10px 20px;
+}
+
+.component-details-panel-item {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-bottom: 5px;
+ order:1;
+
+ .name { font-family: OpenSans-Semibold, sans-serif; }
+ .value { padding-left: 10px; }
+
+
+ &.description {
+ margin-top: 28px;
+ white-space: normal;
+ word-wrap: break-word;
+ overflow: ellipsis;
+
+ .value {
+ padding-left: 0;
+ max-width: none;
+ font-weight: normal;
+ font-family: @font-opensans-regular;
+ }
+ }
+
+ &.group-item, &.policy-item {
+ order:0;
+ }
+}
+
+.tags-container {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 10px 20px;
+
+ .i-sdc-designer-sidebar-section-content-item-tag {
+ padding: 5px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ user-select: all;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts
new file mode 100644
index 0000000..6915d65
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.spec.ts
@@ -0,0 +1,98 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { Store } from '@ngxs/store';
+import { CompositionPaletteService } from '../../../../../pages/composition/palette/services/palette.service';
+import { IAppMenu, SdcMenuToken } from '../../../../../../../app/ng2/config/sdc-menu.config';
+import { CompositionService } from '../../../../../pages/composition/composition.service';
+import { ServiceServiceNg2 } from '../../../../../../../app/services-ng2';
+import { WorkspaceService } from '../../../../../../../app/ng2/pages/workspace/workspace.service';
+import { ComponentInstanceServiceNg2 } from '../../../../../../../app/ng2/services/component-instance-services/component-instance.service';
+import { EventListenerService } from '../../../../../../../app/services';
+import { InfoTabComponent } from './info-tab.component';
+import { ConfigureFn, configureTests } from "../../../../../../../jest/test-config.helper";
+import { Observable } from "rxjs";
+import { leftPaletteElements } from "../../../../../../../jest/mocks/left-paeltte-elements.mock";
+import { TranslatePipe } from "../../../../../shared/translator/translate.pipe";
+import { HttpClientModule } from "@angular/common/http";
+import { TranslateModule } from "../../../../../../../app/ng2/shared/translator/translate.module";
+import _ from "lodash";
+import { TranslateService } from "../../../../../shared/translator/translate.service";
+import { SdcUiServices } from "onap-ui-angular";
+import { Component as TopologyTemplate, FullComponentInstance, ComponentInstance } from '../../../../../../../app/models';
+
+
+describe('InfoTabComponent', () => {
+ // let comp: InfoTabComponent;
+ let fixture: ComponentFixture<InfoTabComponent>;
+
+ // let eventServiceMock: Partial<EventListenerService>;
+ let storeStub:Partial<Store>;
+ let compositionPaletteServiceStub:Partial<CompositionPaletteService>;
+ let iAppMenuStub:Partial<IAppMenu>;
+ let compositionServiceStub:Partial<CompositionService>;
+ let serviceServiceNg2Stub:Partial<ServiceServiceNg2>;
+ let workspaceServiceStub:Partial<WorkspaceService>;
+ let componentInstanceServiceNg2Stub:Partial<ComponentInstanceServiceNg2>;
+ let eventListenerServiceStub:Partial<EventListenerService>;
+
+ beforeEach(
+ async(() => {
+ storeStub = {};
+ iAppMenuStub = {};
+ eventListenerServiceStub = {
+ notifyObservers: jest.fn()
+ }
+ compositionPaletteServiceStub = {
+ getLeftPaletteElements: jest.fn().mockImplementation(()=> Observable.of(leftPaletteElements))
+ }
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ imports: [ ],
+ declarations: [ InfoTabComponent, TranslatePipe ],
+ schemas: [ NO_ERRORS_SCHEMA ],
+ providers: [
+ { provide: Store, useValue: {} },
+ { provide: CompositionPaletteService, useValue: compositionPaletteServiceStub },
+ { provide: SdcMenuToken, useValue: {} },
+ { provide: CompositionService, useValue: {} },
+ { provide: SdcUiServices.ModalService, useValue: {}},
+ { provide: ServiceServiceNg2, useValue: {} },
+ { provide: WorkspaceService, useValue: {} },
+ { provide: ComponentInstanceServiceNg2, useValue: {} },
+ { provide: EventListenerService, useValue: eventListenerServiceStub },
+ { provide: TranslateService, useValue: {}}
+ ]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(InfoTabComponent);
+ let comp = fixture.componentInstance;
+
+ });
+ })
+ );
+
+
+ it('can load instance', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ describe('Version dropdown', () => {
+ it('is undefined for topologyTemplate', () => {
+ fixture.componentInstance.component = <TopologyTemplate>{};
+ fixture.componentInstance.initEditResourceVersion(fixture.componentInstance.component, fixture.componentInstance.flatLeftPaletteElementsFromService(leftPaletteElements));
+ expect(fixture.componentInstance.versions).toBe(undefined);
+ });
+ it('does not contain the highest minor version if it is checked out', () => {
+ fixture.componentInstance.component = new ComponentInstance();
+ fixture.componentInstance.component.allVersions =
+ {'1.0': "9c829122-af05-4bc9-b537-5d84f4c8ae25", '1.1': "930d56cb-868d-4e35-bd0f-e737d2fdb171"};
+ fixture.componentInstance.component.version = "1.0";
+ fixture.componentInstance.component.uuid = "a8cf015e-e4e5-4d4b-a01e-8624e8d36095";
+ fixture.componentInstance.initEditResourceVersion(fixture.componentInstance.component, fixture.componentInstance.flatLeftPaletteElementsFromService(leftPaletteElements));
+ expect(fixture.componentInstance.versions).toHaveLength(1);
+ });
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts
new file mode 100644
index 0000000..45f31e7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/info-tab/info-tab.component.ts
@@ -0,0 +1,189 @@
+import { Component, OnInit, Input, Inject, OnDestroy } from '@angular/core';
+import {
+ PolicyInstance,
+ GroupInstance,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ LeftPaletteComponent,
+ FullComponentInstance
+} from "app/models";
+import {Store} from "@ngxs/store";
+import { EVENTS, GRAPH_EVENTS } from 'app/utils';
+import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
+import { CompositionPaletteService } from "app/ng2/pages/composition/palette/services/palette.service";
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from "onap-ui-angular";
+import { SdcMenuToken, IAppMenu } from "app/ng2/config/sdc-menu.config";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { ServiceServiceNg2 } from "app/services-ng2";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+import { EventListenerService } from "app/services";
+import * as _ from 'lodash';
+import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
+import Dictionary = _.Dictionary;
+
+
+@Component({
+ selector: 'panel-info-tab',
+ templateUrl: './info-tab.component.html',
+ styleUrls: ['./info-tab.component.less'],
+ // providers: [SdcUiServices.ModalService]
+})
+export class InfoTabComponent implements OnInit, OnDestroy {
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | PolicyInstance | GroupInstance | ComponentInstance;
+ public versions: IDropDownOption[];
+ private leftPalletElements: LeftPaletteComponent[];
+ private isDisabledFlag: boolean;
+ private isComponentSelectedFlag: boolean;
+
+ constructor(private store: Store,
+ private compositionPaletteService: CompositionPaletteService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private modalService: SdcUiServices.ModalService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
+ private serviceService: ServiceServiceNg2,
+ private eventListenerService: EventListenerService,
+ @Inject(SdcMenuToken) public sdcMenu:IAppMenu) {
+ }
+
+ ngOnInit() {
+ this.leftPalletElements = this.flatLeftPaletteElementsFromService(this.compositionPaletteService.getLeftPaletteElements());
+ this.initEditResourceVersion(this.component, this.leftPalletElements);
+ this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, (comp) => {
+ this.component = comp;
+ });
+ this.isComponentSelectedFlag = this.isComponentInstanceSelected();
+ this.isDisabledFlag = this.isDisabled();
+
+ }
+
+ ngOnDestroy() {
+ this.eventListenerService.unRegisterObserver(EVENTS.ON_CHECKOUT);
+ }
+
+ flatLeftPaletteElementsFromService = (leftPalleteElementsFromService: Dictionary<Dictionary<LeftPaletteComponent[]>>): LeftPaletteComponent[] => {
+ let retValArr = [];
+ for (const category in leftPalleteElementsFromService) {
+ for (const subCategory in leftPalleteElementsFromService[category]) {
+ retValArr = retValArr.concat(leftPalleteElementsFromService[category][subCategory].slice(0));
+ }
+ }
+ return retValArr;
+ }
+
+ private isComponentInstanceSelected () {
+ return this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ }
+
+ private versioning: Function = (versionNumber: string): string => {
+ let version: Array<string> = versionNumber && versionNumber.split('.');
+ return '00000000'.slice(version[0].length) + version[0] + '.' + '00000000'.slice(version[1].length) + version[1];
+ };
+
+
+ private onChangeVersion = (versionDropdown) => {
+ let newVersionValue = versionDropdown.value;
+ versionDropdown.value = (<FullComponentInstance>this.component).getComponentUid();
+
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ // let service = <Service>this.$scope.currentComponent;
+ if(this.component instanceof FullComponentInstance) {
+
+ let onCancel = (error:any) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ if (error) {
+ console.log(error);
+ }
+ };
+
+ let onUpdate = () => {
+ //this function will update the instance version than the function call getComponent to update the current component and return the new instance version
+ this.componentInstanceService.changeResourceInstanceVersion(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.component.uniqueId, newVersionValue)
+ .subscribe((component) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_VERSION_CHANGED, component);
+ }, onCancel);
+ };
+
+ if (this.component.isService() || this.component.isServiceProxy()) {
+ this.serviceService.checkComponentInstanceVersionChange(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId,
+ this.component.uniqueId, newVersionValue).subscribe((pathsToDelete:string[]) => {
+ if (pathsToDelete && pathsToDelete.length) {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+
+
+ const {title, message} = this.sdcMenu.alertMessages['upgradeInstance'];
+ let pathNames:string = this.getPathNamesVersionChangeModal(pathsToDelete);
+ let onOk: Function = () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ onUpdate();
+ };
+ const okButton = {testId: "OK", text: "OK", type: SdcUiCommon.ButtonType.info, callback: onOk, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ const cancelButton = {testId: "Cancel", text: "Cancel", type: SdcUiCommon.ButtonType.secondary, callback: <Function>onCancel, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ const modal = this.modalService.openInfoModal(title, message.format([pathNames]), 'confirm-modal', [okButton, cancelButton]);
+ modal.getCloseButton().onClick(onCancel);
+ } else {
+ onUpdate();
+ }
+ }, onCancel);
+ } else {
+ onUpdate();
+ }
+ }
+ };
+
+
+ private getPathNamesVersionChangeModal = (pathsToDelete:string[]):string => {
+ const relatedPaths = _.filter(this.compositionService.forwardingPaths, path =>
+ _.find(pathsToDelete, id =>
+ path.uniqueId === id
+ )
+ ).map(path => path.name);
+ const pathNames = _.join(relatedPaths, ', ') || 'none';
+ return pathNames;
+ };
+
+
+ private initEditResourceVersion = (component, leftPaletteComponents): void => {
+ if(this.component instanceof ComponentInstance) {
+
+ this.versions = [];
+ let sorted:any = _.sortBy(_.toPairs(component.allVersions), (item) => {
+ return item[0] !== "undefined" && this.versioning(item[0]);
+ });
+ _.forEach(sorted, (item) => {
+ this.versions.push({label: item[0], value: item[1]});
+ });
+
+ let highestVersion = _.last(sorted)[0];
+
+ if (parseFloat(highestVersion) % 1) { //if highest is minor, make sure it is the latest checked in -
+ let latestVersionComponent: LeftPaletteComponent = _.maxBy(
+ _.filter(leftPaletteComponents, (leftPaletteComponent: LeftPaletteComponent) => { //latest checked in
+ return (leftPaletteComponent.systemName === component.systemName || leftPaletteComponent.uuid === component.uuid);
+ })
+ , (component) => {
+ return component.version
+ });
+
+ let latestVersion: string = latestVersionComponent ? latestVersionComponent.version : highestVersion;
+
+ if (latestVersion && highestVersion != latestVersion) { //highest is checked out - remove from options
+ this.versions = this.versions.filter(version => version.label != highestVersion);
+ }
+ }
+ }
+ }
+
+ private isDisabled() {
+ return this.isViewOnly || this.component['archived'] || this.component['resourceType'] === 'CVFC'
+ }
+
+};
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts
new file mode 100644
index 0000000..c148a4e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tab.component.ts
@@ -0,0 +1,55 @@
+import { NgModule, Component, Compiler, ViewContainerRef, ViewChild, Input, ComponentRef, ComponentFactoryResolver, ChangeDetectorRef } from '@angular/core';
+import {Component as TopologyTemplate} from "app/models";
+import { SdcUiServices } from "onap-ui-angular";
+
+// Helper component to add dynamic tabs
+@Component({
+ selector: 'panel-tab',
+ template: `<div #content></div>`
+})
+export class PanelTabComponent {
+ @ViewChild('content', { read: ViewContainerRef }) content;
+ @Input() isActive:boolean;
+ @Input() panelTabType;
+ @Input() input;
+ @Input() isViewOnly:boolean;
+ @Input() component:TopologyTemplate;
+ @Input() componentType;
+ cmpRef: ComponentRef<any>;
+ private isViewInitialized: boolean = false;
+
+ constructor(private componentFactoryResolver: ComponentFactoryResolver,
+ private cdRef: ChangeDetectorRef) { }
+
+ updateComponent() {
+ if (!this.isViewInitialized || !this.isActive) {
+ return;
+ }
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+
+ let factory = this.componentFactoryResolver.resolveComponentFactory(this.panelTabType);
+ this.cmpRef = this.content.createComponent(factory);
+ this.cmpRef.instance.input = this.input;
+ this.cmpRef.instance.isViewOnly = this.isViewOnly;
+ this.cmpRef.instance.component = this.component;
+ this.cmpRef.instance.componentType = this.componentType;
+ this.cdRef.detectChanges();
+ }
+
+ ngOnChanges() {
+ this.updateComponent();
+ }
+
+ ngAfterViewInit() {
+ this.isViewInitialized = true;
+ this.updateComponent();
+ }
+
+ ngOnDestroy() {
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less
new file mode 100644
index 0000000..b3c03f8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/panel-tabs.less
@@ -0,0 +1,65 @@
+@import '../../../../../../assets/styles/variables';
+@import '../../../../../../assets/styles/override';
+
+
+// ---------------------------------------------------------------------------------------------------
+///* override sdc-ui library tabs */
+// ---------------------------------------------------------------------------------------------------
+
+
+:host ::ng-deep .sdc-tabs {
+
+ .sdc-tabs-list {
+ display: flex;
+ border-bottom: 1px solid @sdcui_color_silver;
+ min-height: min-content;
+ }
+ .sdc-tab {
+ background-color: @sdcui_color_white;
+ border: 1px solid @sdcui_color_silver;
+ border-left: none;
+ border-bottom: none;
+ height: 36px;
+ width: 60px;
+ display: flex;
+ align-content: center;
+ justify-content: center;
+ cursor: pointer;
+ padding: 0;
+ margin: 0;
+
+
+ &.sdc-tab-active {
+ background-color: @sdcui_color_silver;
+ border-bottom: none;
+ }
+ &[disabled] {
+ opacity: 0.3;
+ cursor: default;
+ }
+ }
+ &.sdc-tabs-header {
+ .sdc-tab {
+ font-size: 24px;
+ }
+ }
+ &.sdc-tabs-menu {
+ .sdc-tab {
+ font-size: 14px;
+ padding: 0px 10px 4px 10px;
+ }
+ }
+ .sdc-tab-content {
+ margin-top: 0;
+ flex:1;
+ overflow-y:auto;
+ }
+}
+
+
+:host ::ng-deep .expand-collapse-title {
+ margin-top: 1px;
+ background-color: #eaeaea;
+ color: #5a5a5a;
+ font-family: OpenSans-Semibold, sans-serif;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
deleted file mode 100644
index 2a1c58c..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<ng2-expand-collapse state="0">
- <header tooltip="General Information">General Info</header>
- <content>
- <!-- TYPE -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_TYPE' | translate"></span>
- <span class="value" data-tests-id="rightTab_componentType" tooltip="{{policy.policyTypeUid}}">{{policy.policyTypeUid}}</span>
- </div>
-
- <!-- CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_category" tooltip="Policy">Policy</span>
- </div>
-
- <!-- SUB CATEGORY -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_SUB_CATEGORY' | translate"></span>
- <span class="value" data-tests-id="rightTab_subCategory" tooltip="Policy">Policy</span>
- </div>
-
- <!-- VERSION -->
- <div class="component-details-panel-item">
- <span class="name" [innerHTML]="'GENERAL_LABEL_VERSION' | translate"></span>
- <span class="value" data-tests-id="rightTab_version" tooltip="{{policy.version}}">{{policy.version}}</span>
- </div>
-
- <!-- DESCRIPTION -->
- <div class="component-details-panel-item description">
- <span class="name" [innerHTML]="'GENERAL_LABEL_DESCRIPTION' | translate"></span>
- <span class="value" ellipsis="policy.description" max-chars="55" data-tests-id="rightTab_description">{{policy.description}}</span>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts
deleted file mode 100644
index 3639639..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-information-tab.component.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-
-@Component({
- selector: 'policy-information-tab',
- templateUrl: './policy-information-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less']
-})
-export class PolicyInformationTabComponent {
-
- @Input() policy:PolicyInstance;
- @Input() isViewOnly: boolean;
-
- constructor(private translateService:TranslateService) {
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html
deleted file mode 100644
index fe1f6b4..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<ng2-expand-collapse state="0">
- <header tooltip="Properties">Properties</header>
- <content>
- <ul>
- <li *ngFor="let property of properties; let i = index"
- class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow">
- <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label hand"
- [attr.data-tests-id]="'propertyName_'+property.name"
- tooltip="{{property.name}}"
- (click)="!isViewOnly && editProperty(property)">{{property.name}}
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item-property-value"
- [attr.data-tests-id]="'value_'+property.name"
- tooltip="{{property.value || property.defaultValue}}">{{property.value || property.defaultValue}}
- </div>
- </li>
- </ul>
-
- <div *ngIf="properties.length===0" class="component-details-panel-tab-no-data">
- <div class="component-details-panel-tab-no-data-title">No properties to display</div>
- </div>
- </content>
-</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
deleted file mode 100644
index e69de29..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.less
+++ /dev/null
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts
deleted file mode 100644
index 5862135..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-properties-tab.component.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, OnChanges, SimpleChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-import { PropertyBEModel } from 'app/models';
-import { PropertyModel } from './../../../../../../models/properties';
-import { ModalsHandler } from "app/utils";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-
-@Component({
- selector: 'policy-properties-tab',
- templateUrl: './policy-properties-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'policy-properties-tab.component.less'],
- host: {'class': 'component-details-panel-tab-policy-properties'}
-})
-export class PolicyPropertiesTabComponent implements OnChanges {
-
- @Input() policy:PolicyInstance;
- @Input() topologyTemplate:TopologyTemplate;
- @Input() isViewOnly: boolean;
-
- private properties:Array<PropertyModel>;
-
- constructor(private translateService:TranslateService, private ModalsHandler:ModalsHandler) {
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- console.log("PolicyPropertiesTabComponent: ngAfterViewInit: ");
- console.log("policy: " + this.policy);
- this.properties = [];
- this.initProperties();
- }
-
- initProperties = ():void => {
- this.properties= this.policy.properties;
- }
-
- editProperty = (property?:PropertyModel):void => {
- this.ModalsHandler.openEditPropertyModal((property ? property : new PropertyModel()), this.topologyTemplate, this.properties, false, 'policy', this.policy.uniqueId).then((updatedProperty:PropertyModel) => {
- console.log("ok");
- });
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html
deleted file mode 100644
index 8d1730f..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<sdc-tabs>
- <sdc-tab titleIcon="info-circle">
- <policy-information-tab [policy]="policy" [isViewOnly]="isViewOnly" *ngIf="policy"></policy-information-tab>
- </sdc-tab>
- <sdc-tab titleIcon="inputs-o">
- <policy-targets-tab [policy]="policy" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" (isLoading)="setIsLoading($event)" *ngIf="policy"></policy-targets-tab>
- </sdc-tab>
- <sdc-tab titleIcon="settings-o">
- <policy-properties-tab [policy]="policy" [topologyTemplate]="topologyTemplate" [isViewOnly]="isViewOnly" *ngIf="policy"></policy-properties-tab>
- </sdc-tab>
-</sdc-tabs>
-
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts
deleted file mode 100644
index 1e27399..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.component.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, AfterViewInit, OnChanges } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-import { GRAPH_EVENTS } from './../../../../../../utils/constants';
-import { EventListenerService } from 'app/services/event-listener-service';
-import { ZoneInstance } from 'app/models/graph/zones/zone-instance';
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-
-@Component({
- selector: 'policy-tabs',
- templateUrl: './policy-tabs.component.html'
-})
-export class PolicyTabsComponent implements OnChanges {
-
- @Input() topologyTemplate:TopologyTemplate;
- @Input() selectedZoneInstanceType:string;
- @Input() selectedZoneInstanceId:string;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
-
- private policy:PolicyInstance;
-
- constructor(private translateService:TranslateService,
- private policiesService:PoliciesService
- ) {
-
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- this.initPolicy();
- }
-
- private initPolicy = ():void => {
- this.isLoading.emit(true);
- this.policiesService.getSpecificPolicy(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.selectedZoneInstanceId).subscribe(
- policy => {
- this.policy = policy;
- console.log(JSON.stringify(policy));
- },
- error => console.log("Error getting policy!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private setIsLoading = (value) :void => {
- this.isLoading.emit(value);
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts
deleted file mode 100644
index 38dc19e..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-tabs.module.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-import { NgModule } from "@angular/core";
-import { HttpModule } from "@angular/http";
-import { FormsModule } from "@angular/forms";
-import { BrowserModule } from "@angular/platform-browser";
-import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
-import { ExpandCollapseComponent } from 'app/ng2/components/ui/expand-collapse/expand-collapse.component';
-import { PoliciesService } from "../../../../../services/policies.service";
-import { PolicyInformationTabComponent } from "./policy-information-tab.component";
-import { PolicyTargetsTabComponent } from "./policy-targets-tab.component";
-import { PolicyTabsComponent } from "./policy-tabs.component";
-import { PolicyPropertiesTabComponent } from "./policy-properties-tab.component";
-import { SdcUiComponentsModule } from "sdc-ui/lib/angular";
-import { TranslateModule } from './../../../../../shared/translator/translate.module';
-
-@NgModule({
- declarations: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- SdcUiComponentsModule,
- TranslateModule,
- UiElementsModule
- ],
- entryComponents: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent,
- ExpandCollapseComponent
- ],
- exports: [
- PolicyInformationTabComponent,
- PolicyTargetsTabComponent,
- PolicyPropertiesTabComponent,
- PolicyTabsComponent
- ],
- providers: [
- PoliciesService
- ]
-})
-export class PolicyTabsModule {
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less
deleted file mode 100644
index cd7ace2..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.less
+++ /dev/null
@@ -1,12 +0,0 @@
-/deep/
-.component-details-panel-tab-policy-targets {
- .component-details-panel-large-item {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
- .w-sdc-designer-sidebar-section-title {
- display: flex;
- justify-content: space-between;
- }
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts
deleted file mode 100644
index b79f4d9..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Input, Output, EventEmitter, OnChanges, HostBinding, OnDestroy } from "@angular/core";
-import { TranslateService } from './../../../../../shared/translator/translate.service';
-import { Component as TopologyTemplate } from "app/models";
-import { PoliciesService } from "../../../../../services/policies.service";
-import { PolicyInstance, PolicyTargetsMap } from './../../../../../../models/graph/zones/policy-instance';
-import { SimpleChanges } from "@angular/core/src/metadata/lifecycle_hooks";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-import { IModalConfig } from "sdc-ui/lib/angular/modals/models/modal-config";
-import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component";
-import { TargetUiObject } from "../../../../../../models/ui-models/ui-target-object";
-import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance";
-import { TargetOrMemberType } from "../../../../../../utils/constants";
-import { GRAPH_EVENTS } from 'app/utils';
-import { EventListenerService } from 'app/services/event-listener-service';
-
-@Component({
- selector: 'policy-targets-tab',
- templateUrl: './policy-targets-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less', 'policy-targets-tab.component.less']
-})
-
-export class PolicyTargetsTabComponent implements OnChanges, OnDestroy {
-
- private targets: Array<TargetUiObject>; // UI object to hold all targets with names.
-
- @Input() policy: PolicyInstance;
- @Input() topologyTemplate: TopologyTemplate;
- @Input() isViewOnly: boolean;
- @Output() isLoading: EventEmitter<boolean> = new EventEmitter<boolean>();
- @HostBinding('class') classes = 'component-details-panel-tab-policy-targets';
-
- constructor(private translateService: TranslateService,
- private policiesService: PoliciesService,
- private modalService: SdcUiComponents.ModalService,
- private eventListenerService: EventListenerService
- ) {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, this.initTargets)
- }
-
- ngOnChanges(changes:SimpleChanges):void {
- this.initTargets();
- }
-
- ngOnDestroy() {
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE);
- }
-
- deleteTarget(target: TargetUiObject): void {
- this.isLoading.emit(true);
- this.policiesService.deletePolicyTarget(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.policy, target.uniqueId, target.type).subscribe(
- (policyInstance:PolicyInstance) => {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, policyInstance);
- },
- error => console.log("Error deleting target!"),
- () => this.isLoading.emit(false)
- );
- }
-
- private initTargets = (policyInstance?: PolicyInstance) => {
- this.policy = policyInstance ? policyInstance : this.policy;
- this.targets = this.policy.getTargetsAsUiObject(this.topologyTemplate.componentInstances, this.topologyTemplate.groupInstances);
- }
-
- addTargets = ():void => {
-
- var targetsToAdd:Array<TargetUiObject> = this.modalService.getCurrentInstance().innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
- if(targetsToAdd.length > 0) {
- this.modalService.closeModal();
- this.isLoading.emit(true);
- var updatedTarget: Array<TargetUiObject> = _.union(this.targets, targetsToAdd);
- this.policiesService.updateTargets(this.topologyTemplate.componentType, this.topologyTemplate.uniqueId, this.policy.uniqueId, updatedTarget).subscribe(
- (updatedPolicyInstance:PolicyInstance) => {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, updatedPolicyInstance);
- },
- error => {
- console.log("Error updating targets!");
- },
- () => this.isLoading.emit(false)
- );
- }
- }
-
- getOptionalsTargetsToAdd():Array<TargetUiObject> {
- let optionalsTargetsToAdd:Array<TargetUiObject> = [];
- // adding all instances as optional targets to add if not already exist
- _.forEach(this.topologyTemplate.componentInstances, (instance:ComponentInstance) => {
- if (!_.some(this.targets, (target:TargetUiObject) => {
- return target.uniqueId === instance.uniqueId
- })) {
- optionalsTargetsToAdd.push(new TargetUiObject(instance.uniqueId, TargetOrMemberType.COMPONENT_INSTANCES, instance.name));
- }
- });
-
- // adding all groups as optional targets to add if not already exist
- _.forEach(this.topologyTemplate.groupInstances, (groupInstance:ComponentInstance) => { // adding all instances as optional targets to add if not already exist
- if (!_.some(this.targets, (target:TargetUiObject) => {
- return target.uniqueId === groupInstance.uniqueId
- })) {
- optionalsTargetsToAdd.push(new TargetUiObject(groupInstance.uniqueId, TargetOrMemberType.GROUPS, groupInstance.name));
- }
- });
-
- return optionalsTargetsToAdd;
- }
-
- openAddTargetModal(): void {
- let addTargetModalConfig: IModalConfig = {
- title: this.policy.name + " ADD TARGETS",
- size: "md",
- type: "custom",
- testId: "addTargetsModal",
- buttons: [
- {text: "ADD TARGETS", size: 'xsm', callback: this.addTargets, closeModal: false},
- {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
- ]
- };
- var optionalTargetsToAdd = this.getOptionalsTargetsToAdd();
- this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, {
- elementsToAdd: optionalTargetsToAdd,
- elementName: "target"
- });
-
- }
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html
similarity index 91%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html
index e263836..838fd8b 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policies/policy-targets-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<div class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets
+<h1 class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets
<svg-icon-label *ngIf="!isViewOnly"
class="add-policy-button"
name="plus-circle-o"
@@ -24,7 +24,7 @@
labelPlacement="right"
(click)="openAddTargetModal()">
</svg-icon-label>
-</div>
+</h1>
<div class="expand-collapse-content">
<ul>
<li *ngFor="let target of targets; let i = index" class="component-details-panel-large-item"
@@ -40,7 +40,7 @@
</li>
</ul>
- <div *ngIf="targets.length===0" class="component-details-panel-tab-no-data">
+ <div *ngIf="!targets || targets.length===0" class="component-details-panel-tab-no-data">
<div class="component-details-panel-tab-no-data-title">No data to display yet</div>
<div class="component-details-panel-tab-no-data-content">Add targets to policy to see targets</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less
similarity index 61%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less
index aa8e751..d16a159 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/base/base-tab.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less
@@ -1,8 +1,6 @@
@import './../../../../../../../assets/styles/mixins';
-@import "./../../../../../../../assets/styles/variables-old";
-@import './../../../../../../../assets/styles/mixins_old';
-/deep/
+
.expand-collapse-content {
padding: 20px;
}
@@ -25,7 +23,9 @@
white-space: nowrap;
height: 32px;
line-height: 32px;
- vertical-align: middle;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
&:hover {
background-color: #f8f8f8;
@@ -37,30 +37,25 @@
}
}
-.component-details-panel-item {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- height: 22px;
- line-height: 22px;
- vertical-align: middle;
-
- &.description {
- margin-top: 28px;
- white-space: normal;
- word-wrap: break-word;
- .value {
- max-width: none;
- font-weight: normal;
- font-family: @font-opensans-regular;
- }
- }
-
- .name { font-family: OpenSans-Semibold, sans-serif; }
- .value { }
-}
-
.component-details-panel-item-delete {
cursor: pointer;
visibility: hidden;
}
+
+/deep/ .w-sdc-designer-sidebar-section-title {
+ color: #5a5a5a;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ background-color: #eaeaea;
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ text-transform: uppercase;
+ line-height: 32px;
+ padding: 0 10px 0 20px;
+ margin-top: 1px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts
new file mode 100644
index 0000000..7774138
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts
@@ -0,0 +1,113 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Rx';
+import { Mock } from 'ts-mockery';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { TranslateService } from '../../../../../shared/translator/translate.service';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { CompositionService } from '../../../composition.service';
+import { PolicyTargetsTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component";
+import { PoliciesService } from "app/services-ng2";
+import { PolicyInstance, GroupInstance } from "app/models";
+import { NgxsModule } from "@ngxs/store";
+import { GraphState } from "app/ng2/pages/composition/common/store/graph.state";
+import { WorkspaceState } from "app/ng2/store/states/workspace.state";
+import { TargetUiObject } from "app/models/ui-models/ui-target-object";
+import { TargetOrMemberType } from "app/utils";
+
+
+
+
+describe('policy targets tab component', () => {
+
+ let fixture: ComponentFixture<PolicyTargetsTabComponent>;
+ let component: PolicyTargetsTabComponent;
+
+ let policiesServiceMock = Mock.of<PoliciesService>(
+ {
+ updateTargets: jest.fn().mockImplementation((compType, uid, policyUniqueId, updatedTargets) => {
+ if (updatedTargets === undefined) {
+ return Observable.throwError('error');
+ } else {
+ return Observable.of(updatedTargets);
+ }
+ }
+ )});
+
+ let compositionServiceMock = {
+ componentInstances: [{uniqueId: '1', name: 'inst1'},
+ {uniqueId: '2', name: 'inst2'},
+ {uniqueId: '3', name: 'inst3'},
+ {uniqueId: '4', name: 'inst4'},
+ {uniqueId: '5', name: 'inst5'}
+ ],
+ groupInstances : [
+ Mock.of<GroupInstance>({uniqueId: "group1", name: "group1"}),
+ Mock.of<GroupInstance>({uniqueId: "group2", name: "group2"}),
+ Mock.of<GroupInstance>({uniqueId: "group3", name: "group3"})
+ ]
+ };
+
+ let workspaceServiceMock = {
+ metadata: Mock.of<ComponentMetadata>()
+ };
+
+ let modalServiceMock = {
+ openInfoModal: jest.fn(),
+ openCustomModal: jest.fn().mockImplementation(() => { return {
+ innerModalContent: { instance: { existingElements: targetsToAdd }},
+ closeModal: jest.fn()
+ }})
+ };
+
+ let loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const targetsToAdd = [
+ <TargetUiObject>{uniqueId: '1', name: 'inst1', type: TargetOrMemberType.COMPONENT_INSTANCES},
+ <TargetUiObject>{uniqueId: "group1", name: "group1", type: TargetOrMemberType.GROUPS}
+ ];
+
+ const policyInstanceMock = Mock.of<PolicyInstance>(
+ { getTargetsAsUiObject: jest.fn().mockImplementation( () => targetsToAdd)
+ });
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [PolicyTargetsTabComponent],
+ imports: [NgxsModule.forRoot([WorkspaceState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: { translate: jest.fn() }},
+ {provide: PoliciesService, useValue: policiesServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock },
+ {provide: EventListenerService, useValue: {} },
+ {provide: CompositionService, useValue: compositionServiceMock },
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+
+ fixture = TestBed.createComponent(PolicyTargetsTabComponent);
+ component = fixture.componentInstance;
+ component.policy = policyInstanceMock;
+ });
+
+
+ it('if there are no existing targets, all component instances AND all groups are available for adding', () => {
+ component.targets = [];
+ const optionalTargetsToAdd = component.getOptionalsTargetsToAdd();
+ expect(optionalTargetsToAdd).toHaveLength(8);
+ });
+
+ it('list of available instances to add does not include existing targets', () => {
+ component.targets = targetsToAdd;
+ const optionalMembersToAdd = component.getOptionalsTargetsToAdd();
+ expect(optionalMembersToAdd).toHaveLength(6);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts
new file mode 100644
index 0000000..f117290
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import { Component, Input, Output, EventEmitter, OnChanges, HostBinding, OnDestroy, OnInit } from "@angular/core";
+import { TranslateService } from './../../../../../shared/translator/translate.service';
+import { PoliciesService } from "../../../../../services/policies.service";
+import { PolicyInstance } from './../../../../../../models/graph/zones/policy-instance';
+import { SdcUiComponents, SdcUiCommon, SdcUiServices } from "onap-ui-angular";
+import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component";
+import { TargetUiObject } from "../../../../../../models/ui-models/ui-target-object";
+import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance";
+import { TargetOrMemberType } from "../../../../../../utils/constants";
+import { GRAPH_EVENTS } from 'app/utils';
+import { EventListenerService } from 'app/services/event-listener-service';
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { Store } from "@ngxs/store";
+import { Select } from "@ngxs/store";
+import { Observable } from "rxjs";
+import { tap } from "rxjs/operators";
+import {GraphState} from "../../../common/store/graph.state";
+
+@Component({
+ selector: 'policy-targets-tab',
+ templateUrl: './policy-targets-tab.component.html',
+ styleUrls: ['policy-targets-tab.component.less']
+})
+
+export class PolicyTargetsTabComponent implements OnInit {
+
+ @Input() input:any;
+
+
+ @Input() isViewOnly: boolean;
+ @HostBinding('class') classes = 'component-details-panel-tab-policy-targets';
+ @Select(GraphState.getSelectedComponent) policy$: Observable<PolicyInstance>;
+ public policy: PolicyInstance;
+ private subscription;
+
+ private addModalInstance: SdcUiComponents.ModalComponent;
+ public targets: Array<TargetUiObject>; // UI object to hold all targets with names.
+
+
+ constructor(private translateService: TranslateService,
+ private policiesService: PoliciesService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService,
+ private store: Store
+ ) { }
+
+ ngOnInit() {
+ this.subscription = this.policy$.pipe(
+ tap((policy) => {
+ if(policy instanceof PolicyInstance){
+ this.policy = policy;
+ this.targets = this.policy.getTargetsAsUiObject(<ComponentInstance[]>this.compositionService.componentInstances, this.compositionService.groupInstances);
+ }
+ })).subscribe();
+ }
+
+ ngOnDestroy () {
+ if(this.subscription)
+ this.subscription.unsubscribe();
+ }
+
+ deleteTarget(target: TargetUiObject): void {
+ this.loaderService.activate();
+ this.policiesService.deletePolicyTarget(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy, target.uniqueId, target.type).subscribe(
+ (policyInstance:PolicyInstance) => {
+ this.targets = this.targets.filter(item => item.uniqueId !== target.uniqueId);
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, policyInstance);
+ // this.store.dispatch(new UpdateSelectedComponentAction({uniqueId: policyInstance.uniqueId, type:ComponentType.}));
+ },
+ error => {
+ console.log("Error deleting target!");
+ this.loaderService.deactivate();
+ },
+ () => this.loaderService.deactivate()
+ );
+ }
+
+
+ addTargets = ():void => {
+
+ var targetsToAdd:Array<TargetUiObject> = this.addModalInstance.innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data
+ if(targetsToAdd.length > 0) {
+ this.addModalInstance.closeModal();
+ this.loaderService.activate();
+ var updatedTargets: Array<TargetUiObject> = _.union(this.targets, targetsToAdd);
+ this.policiesService.updateTargets(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy.uniqueId, updatedTargets).subscribe(
+ (updatedPolicyInstance:PolicyInstance) => {
+ this.targets = updatedTargets;
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, updatedPolicyInstance);
+ // this.store.dispatch(new UpdateSelectedComponentAction({component: updatedPolicyInstance}));
+ },
+ error => {
+ console.log("Error updating targets!");
+ this.loaderService.deactivate();
+ },
+ () => this.loaderService.deactivate()
+ );
+ }
+ }
+
+ getOptionalsTargetsToAdd():Array<TargetUiObject> {
+ let optionalsTargetsToAdd:Array<TargetUiObject> = [];
+ // adding all instances as optional targets to add if not already exist
+ _.forEach(this.compositionService.componentInstances, (instance:ComponentInstance) => {
+ if (!_.some(this.targets, (target:TargetUiObject) => {
+ return target.uniqueId === instance.uniqueId
+ })) {
+ optionalsTargetsToAdd.push(new TargetUiObject(instance.uniqueId, TargetOrMemberType.COMPONENT_INSTANCES, instance.name));
+ }
+ });
+
+ // adding all groups as optional targets to add if not already exist
+ _.forEach(this.compositionService.groupInstances, (groupInstance:ComponentInstance) => { // adding all instances as optional targets to add if not already exist
+ if (!_.some(this.targets, (target:TargetUiObject) => {
+ return target.uniqueId === groupInstance.uniqueId
+ })) {
+ optionalsTargetsToAdd.push(new TargetUiObject(groupInstance.uniqueId, TargetOrMemberType.GROUPS, groupInstance.name));
+ }
+ });
+
+ return optionalsTargetsToAdd;
+ }
+
+ openAddTargetModal(): void {
+ let addTargetModalConfig = {
+ title: this.policy.name + " ADD TARGETS",
+ size: "md",
+ type: SdcUiCommon.ModalType.custom,
+ testId: "addTargetsModal",
+ buttons: [
+ {text: "ADD TARGETS", size: 'xsm', callback: this.addTargets, closeModal: false},
+ {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true}
+ ]
+ } as SdcUiCommon.IModalConfig;
+ var optionalTargetsToAdd = this.getOptionalsTargetsToAdd();
+ this.addModalInstance = this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, {
+ elementsToAdd: optionalTargetsToAdd,
+ elementName: "target"
+ });
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
new file mode 100644
index 0000000..86c6fea
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
@@ -0,0 +1,97 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <div class="w-sdc-designer-sidebar-section">
+ <div *ngIf="properties">
+ <ng-container *ngFor="let key of objectKeys(properties); let idx = index">
+ <sdc-accordion [title]="groupNameByKey(key) + ' Properties'" [css-class]="'properties-accordion'" [arrow-direction]="'right'" [testId]="groupNameByKey(key) + 'properties'" [open]="true">
+
+ <!--ng-show="isShowDetailsSection" -->
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngIf="!groupPropertiesByInstance">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" attr.data-tests-id="propertyRow"
+ *ngFor="let property of properties[key]">
+
+ <div class="property-details">
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{property.name}}"
+ (click)="!isViewOnly && updateProperty(property)"
+ attr.data-tests-id="{{property.name}}">{{property.name}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{property.defaultValue}}">{{property.defaultValue}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="!isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{property.value}}"
+ attr.data-tests-id="value_{{property.name}}">{{property.value}}</span>
+ </div>
+ <div class="property-buttons">
+ <svg-icon *ngIf="!isViewOnly && (isPropertyOwner() && !property.readonly)" name="trash-o" clickable="true" size="medium" mode="info" testId="delete_{{property.name}}" (click)="deleteProperty(property)"></svg-icon>
+ </div>
+ </div>
+ </div>
+ <div class="i-sdc-designer-sidebar-section-content-item" *ngIf="groupPropertiesByInstance">
+ <ng-container *ngFor="let InstanceProperties of properties[key]; let propIndex = index">
+ <div class="vfci-properties-group">
+ <div class="second-level">
+ <div class="expand-collapse-title-icon"></div>
+ <span class="w-sdc-designer-sidebar-section-title-text" sdc-tooltip tooltip-text="{{getComponentInstanceNameFromInstanceByKey(InstanceProperties.key)}} Properties"
+ attr.data-tests-id="vfci-properties">{{getComponentInstanceNameFromInstanceByKey(InstanceProperties.key) + ' Properties'}}</span>
+ </div>
+ </div>
+ <div class="w-sdc-designer-sidebar-section-content instance-properties {{propIndex}}">
+ <div class="i-sdc-designer-sidebar-section-content-item">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" attr.data-tests-id="propertyRow"
+ *ngFor="let instanceProperty of InstanceProperties.value">
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{instanceProperty.name}}"
+ attr.data-tests-id="vfci-property">{{instanceProperty.name}}</span>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value"
+ sdc-tooltip tooltip-text="{{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}">
+ {{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-container>
+ </div>
+ <!--<div class="w-sdc-designer-sidebar-section-footer" *ngIf="(!isViewOnly && isPropertyOwner()) || showAddPropertyButton">-->
+ <!--<button class="w-sdc-designer-sidebar-section-footer-action tlv-btn blue" attr.data-tests-id="addGrey" (click)="addProperty()" type="button">-->
+ <!--Add Property-->
+ <!--</button>-->
+ <!--</div>-->
+ </sdc-accordion>
+ </ng-container>
+ </div>
+
+ <!--attributes-->
+ <div *ngIf="attributes">
+ <ng-container *ngFor="let key of objectKeys(attributes); let attrIndex = index">
+ <sdc-accordion [title]="groupNameByKey(key) + ' Attributes'" [arrow-direction]="'right'" [testId]="groupNameByKey(key) + 'attributes'" [css-class]="'attributes-accordion'">
+ <!--ng-show="isShowDetailsSection" -->
+ <div class="i-sdc-designer-sidebar-section-content-item">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute"
+ *ngFor="let attribute of attributes[key]">
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}"
+ sdc-tooltip tooltip-text="{{attribute.name}}"
+ (click)="!isViewOnly && viewAttribute(attribute)"
+ attr.data-tests-id="{{attribute.name}}-attr">{{attribute.name}}</span>
+ </div>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{attribute.defaultValue}}">{{attribute.defaultValue}}</span>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-value" *ngIf="!isPropertyOwner()"
+ sdc-tooltip tooltip-text="{{attribute.value}}" attr.data-tests-id="value-of-{{attribute.name}}">{{attribute.value}}</span>
+ </div>
+ </div>
+ </div>
+ </sdc-accordion>
+ </ng-container>
+ </div>
+ </div>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
new file mode 100644
index 0000000..5cb0697
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
@@ -0,0 +1,66 @@
+.scroll-container {
+ display: flex;
+ overflow-y: auto;
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute {
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ border-bottom: 1px solid #cdcdcd;
+ min-height: 72px;
+ padding: 15px 10px 10px 18px;
+ // position: relative;
+ display:flex;
+
+ .property-details {
+ flex:1;
+ }
+
+ .property-buttons {
+ flex: 0 0 auto;
+ align-self: center;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute-label {
+ display: block;
+ font-weight: bold;
+ &:hover {
+ color: #3b7b9b;
+ }
+}
+
+.i-sdc-designer-sidebar-section-content-item-property-and-attribute-label, .i-sdc-designer-sidebar-section-content-item-property-value {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 245px;
+ white-space: nowrap;
+ display: block;
+}
+
+
+
+/deep/ .expand-collapse-content {
+ max-height: max-content;
+ padding: 10px 0;
+
+ .sdc-accordion .sdc-accordion-header {
+
+ background-color: #e6f6fb;
+ border-left: solid #009fdb 4px;
+ box-shadow: 0 0px 3px -1px rgba(0, 0, 0, 0.3);
+ margin-bottom: 2px;
+ width: auto;
+ height: auto;
+ padding: 10px;
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+
+ }
+
+ /deep/.sdc-accordion .sdc-accordion-body {
+ padding-left: 0;
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
new file mode 100644
index 0000000..b4b8248
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
@@ -0,0 +1,212 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ AttributeModel,
+ AttributesGroup,
+ Component as TopologyTemplate,
+ ComponentMetadata,
+ FullComponentInstance,
+ PropertiesGroup,
+ PropertyModel
+} from 'app/models';
+import { CompositionService } from 'app/ng2/pages/composition/composition.service';
+import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
+import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe';
+import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
+import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
+import { TranslateService } from 'app/ng2/shared/translator/translate.service';
+import { ModalsHandler } from 'app/utils';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
+
+@Component({
+ selector: 'properties-tab',
+ templateUrl: './properties-tab.component.html',
+ styleUrls: ['./properties-tab.component.less']
+})
+export class PropertiesTabComponent implements OnInit {
+ attributes: AttributesGroup;
+ isComponentInstanceSelected: boolean;
+ properties: PropertiesGroup;
+ groupPropertiesByInstance: boolean;
+ propertiesMessage: string;
+ metadata: ComponentMetadata;
+ objectKeys = Object.keys;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() input: {title: string};
+
+ constructor(private store: Store,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private modalsHandler: ModalsHandler,
+ private topologyTemplateService: TopologyTemplateService,
+ private modalService: SdcUiServices.ModalService,
+ private translateService: TranslateService,
+ private groupByPipe: GroupByPipe) {
+ }
+
+ ngOnInit() {
+ this.metadata = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.getComponentInstancesPropertiesAndAttributes();
+ }
+
+ public isPropertyOwner = (): boolean => {
+ return this.component instanceof TopologyTemplate && this.component.isResource();
+ }
+
+ public updateProperty = (property: PropertyModel): void => {
+ this.openEditPropertyModal(property);
+ }
+
+ public deleteProperty = (property: PropertyModel): void => {
+
+ const onOk: Function = (): void => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+ this.topologyTemplateService.deleteProperty(this.component.componentType, this.component.uniqueId, property.uniqueId)
+ .subscribe((response) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.component.properties = this.component.properties.filter((prop) => prop.uniqueId !== property.uniqueId);
+ this.initComponentProperties();
+ }, () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ });
+ };
+
+ const title: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TITLE');
+ const message: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TEXT', {name: property.name});
+ const okButton = {
+ testId: 'OK',
+ text: 'OK',
+ type: SdcUiCommon.ButtonType.info,
+ callback: onOk,
+ closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
+ }
+
+ public groupNameByKey = (key: string): string => {
+ switch (key) {
+ case 'derived':
+ return 'Derived';
+
+ case this.metadata.uniqueId:
+ return ResourceNamePipe.getDisplayName(this.metadata.name);
+
+ default:
+ return this.getComponentInstanceNameFromInstanceByKey(key);
+ }
+ }
+
+ public getComponentInstanceNameFromInstanceByKey = (key: string): string => {
+ let instanceName: string = '';
+ const componentInstance = this.compositionService.getComponentInstances().find((item) => item.uniqueId === key);
+ if (key !== undefined && componentInstance) {
+
+ instanceName = ResourceNamePipe.getDisplayName(componentInstance.name);
+ }
+ return instanceName;
+ }
+
+ private getComponentInstancesPropertiesAndAttributes = () => {
+ this.topologyTemplateService.getComponentInstanceAttributesAndProperties(
+ this.workspaceService.metadata.uniqueId,
+ this.workspaceService.metadata.componentType)
+ .subscribe((genericResponse: ComponentGenericResponse) => {
+ this.compositionService.componentInstancesAttributes = genericResponse.componentInstancesAttributes || new AttributesGroup();
+ this.compositionService.componentInstancesProperties = genericResponse.componentInstancesProperties;
+ this.initPropertiesAndAttributes();
+ });
+ }
+
+ private initComponentProperties = (): void => {
+ let result: PropertiesGroup = {};
+
+ this.propertiesMessage = undefined;
+ this.groupPropertiesByInstance = false;
+ if (this.component instanceof FullComponentInstance) {
+ result[this.component.uniqueId] = _.orderBy(this.compositionService.componentInstancesProperties[this.component.uniqueId], ['name']);
+ if (this.component.originType === 'VF') {
+ this.groupPropertiesByInstance = true;
+ result[this.component.uniqueId] = Array.from(this.groupByPipe.transform(result[this.component.uniqueId], 'path'));
+ }
+ } else if (this.metadata.isService()) {
+ // Temporally fix to hide properties for service (UI stack when there are many properties)
+ result = this.compositionService.componentInstancesProperties;
+ this.propertiesMessage = 'Note: properties for service are disabled';
+ } else {
+ const componentUid = this.component.uniqueId;
+ result[componentUid] = Array<PropertyModel>();
+ const derived = Array<PropertyModel>();
+ _.forEach(this.component.properties, (property: PropertyModel) => {
+ if (componentUid === property.parentUniqueId) {
+ result[componentUid].push(property);
+ } else {
+ property.readonly = true;
+ derived.push(property);
+ }
+ });
+ if (derived.length) {
+ result['derived'] = derived;
+ }
+ this.objectKeys(result).forEach((key) => { result[key] = _.orderBy(result[key], ['name']); });
+ }
+ this.properties = result;
+ }
+
+ private initComponentAttributes = (): void => {
+ let result: AttributesGroup = {};
+
+ if (this.component) {
+ if (this.component instanceof FullComponentInstance) {
+ result[this.component.uniqueId] = this.compositionService.componentInstancesAttributes[this.component.uniqueId] || [];
+ } else if (this.metadata.isService()) {
+ result = this.compositionService.componentInstancesAttributes;
+ } else {
+ result[this.component.uniqueId] = (this.component as TopologyTemplate).attributes;
+ }
+ this.attributes = result;
+ this.objectKeys(this.attributes).forEach((key) => {
+ this.attributes[key] = _.orderBy(this.attributes[key], ['name']);
+ });
+
+ }
+ }
+
+ /**
+ * This function is checking if the component is the value owner of the current property
+ * in order to notify the edit property modal which fields to disable
+ */
+ private isPropertyValueOwner = (): boolean => {
+ return this.metadata.isService() || !!this.component;
+ }
+
+ /**
+ * The function opens the edit property modal.
+ * It checks if the property is from the VF or from one of it's resource instances and sends the needed property list.
+ * For create property reasons an empty array is transferd
+ *
+ * @param property the wanted property to edit/create
+ */
+ private openEditPropertyModal = (property: PropertyModel): void => {
+ this.modalsHandler.newOpenEditPropertyModal(property,
+ (this.isPropertyOwner() ?
+ this.properties[property.parentUniqueId] :
+ this.properties[property.resourceInstanceUniqueId]) || [],
+ this.isPropertyValueOwner(), 'component', property.resourceInstanceUniqueId).then((updatedProperty: PropertyModel) => {
+ if (updatedProperty) {
+ const oldProp = _.find(this.properties[updatedProperty.resourceInstanceUniqueId],
+ (prop: PropertyModel) => prop.uniqueId === updatedProperty.uniqueId);
+ oldProp.value = updatedProperty.value;
+ }
+ });
+ }
+
+ private initPropertiesAndAttributes = (): void => {
+ this.initComponentProperties();
+ this.initComponentAttributes();
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html
new file mode 100644
index 0000000..27e05ec
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html
@@ -0,0 +1,36 @@
+<div class="w-sdc-designer-sidebar-tab-content sdc-general-tab relations">
+ <div *ngIf="!isCurrentDisplayComponentIsComplex(); else complexComponentTemplate">
+ <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
+ <sdc-accordion [title]="'Capabilities'" [arrow-direction]="'right'" [testId]="'Capabilities-accordion'">
+ <div *ngFor="let capability of capabilities" class="relations-details-container">
+ <div class="relations-name">{{capability.name}} </div>
+ <div class="relations-desc"> {{capability.type}} </div>
+ </div>
+ </sdc-accordion>
+ </div>
+ <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
+ <sdc-accordion [title]="'Requirements'" [arrow-direction]="'right'" [testId]="'Requirements-accordion'">
+ <requirement-list [component]='component' [requirements]="requirements" [isInstanceSelected]="isComponentInstanceSelected"></requirement-list>
+ </sdc-accordion>
+
+ </div>
+ </div>
+
+ <ng-template #complexComponentTemplate>
+ <sdc-accordion *ngIf="capabilitiesInstancesMap" [title]="'Capabilities'" [arrow-direction]="'right'" [testId]="'Capabilities-accordion'">
+ <sdc-accordion *ngFor="let key of objectKeys(capabilitiesInstancesMap); let i = index" [title]="key">
+ <div *ngFor="let capability of capabilitiesInstancesMap[key]" class="relations-details-container">
+ <div class="relations-name">{{capability.name}} </div>
+ <div class="relations-desc"> {{capability.type}} </div>
+ </div>
+ </sdc-accordion>
+ </sdc-accordion>
+
+ <sdc-accordion *ngIf="requirementsInstancesMap" [title]="'Requirements'" [arrow-direction]="'right'" [testId]="'Requirements-accordion'">
+ <sdc-accordion *ngFor="let key of objectKeys(requirementsInstancesMap); let i = index" [title]="key">
+ <requirement-list [component]='component' [requirements]="requirementsInstancesMap[key]" [isInstanceSelected]="isComponentInstanceSelected"></requirement-list>
+ </sdc-accordion>
+ </sdc-accordion>
+
+ </ng-template>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less
new file mode 100644
index 0000000..fe4573a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.less
@@ -0,0 +1,57 @@
+
+/deep/.sdc-accordion {
+ margin-bottom: 0;
+ display: grid;
+
+ .sdc-accordion-header {
+ background-color: #e6f6fb;
+ border-left: solid #009fdb 4px;
+ box-shadow: 0 0px 3px -1px rgba(0, 0, 0, 0.3);
+ margin-bottom: 2px;
+ width: auto;
+ height: auto;
+ padding: 10px;
+ color: #666666;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ }
+
+ .sdc-accordion-body.open {
+ padding-left: 0;
+ padding-top: 0;
+ .sdc-accordion-header { /*Second level - nested accordion */
+ background-color: #f8f8f8;
+ padding: 4px 20px 4px 37px;
+ border-bottom: 1px solid #d2d2d2;
+ border-left:none;
+ height: 30px;
+ }
+ }
+}
+
+
+.relations-details-container {
+ border-bottom: 1px solid #cdcdcd;
+ padding: 10px 10px 10px 18px;
+
+ font-size: 14px;
+ font-family: OpenSans-Regular, sans-serif;
+
+ .relations-name {
+ color: #666666;
+ font-weight: bold;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ text-transform: capitalize;
+ max-width: 240px;
+ display: inline-block;
+ }
+
+ .relations-desc {
+ color: #8c8c8c;
+ word-wrap: break-word;
+ white-space: normal;
+ max-width: 265px;
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts
new file mode 100644
index 0000000..03697b3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts
@@ -0,0 +1,165 @@
+import { Component, OnInit, Input, OnDestroy } from '@angular/core';
+import { Component as TopologyTemplate, Capability, Requirement, CapabilitiesGroup, RequirementsGroup, ComponentInstance, FullComponentInstance } from "app/models";
+import { Store } from "@ngxs/store";
+import { GRAPH_EVENTS } from "app/utils";
+import { ComponentGenericResponse } from "app/ng2/services/responses/component-generic-response";
+import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service";
+import { EventListenerService } from "app/services";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
+
+
+export class InstanceCapabilitiesMap {
+ [key:string]:Array<Capability>;
+}
+
+export class InstanceRequirementsMap {
+ [key:string]:Array<Requirement>;
+}
+
+@Component({
+ selector: 'req-capabilities-tab',
+ templateUrl: './req-capabilities-tab.component.html',
+ styleUrls: ['./req-capabilities-tab.component.less']
+})
+export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy {
+
+ isComponentInstanceSelected: boolean;
+ capabilities:Array<Capability>;
+ requirements:Array<Requirement>;
+ capabilitiesInstancesMap:InstanceCapabilitiesMap;
+ requirementsInstancesMap:InstanceRequirementsMap;
+ objectKeys = Object.keys;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | FullComponentInstance;
+ @Input() input: any;
+
+
+ constructor(private store: Store,
+ private topologyTemplateService:TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService:EventListenerService) { }
+
+ ngOnInit(): void {
+
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+
+ this.requirements = [];
+ this.capabilities = [];
+ this.initEvents();
+ this.initRequirementsAndCapabilities();
+
+ }
+
+ private initEvents = ():void => {
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ }
+
+ ngOnDestroy(): void {
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
+ }
+
+ public isCurrentDisplayComponentIsComplex = ():boolean => {
+
+ if (this.component instanceof FullComponentInstance) {
+ if (this.component.originType === 'VF') {
+ return true;
+ }
+ return false;
+ } else {
+ return this.component.isComplex();
+ }
+ }
+
+ private loadComplexComponentData = () => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ this.topologyTemplateService.getCapabilitiesAndRequirements(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId).subscribe((response:ComponentGenericResponse) => {
+ this.workspaceService.metadata.capabilities = response.capabilities;
+ this.workspaceService.metadata.requirements = response.requirements;
+ this.setScopeCapabilitiesRequirements(response.capabilities, response.requirements);
+ this.initInstancesMap();
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ }, (error) => { this.store.dispatch(new TogglePanelLoadingAction({isLoading: false})); });
+ }
+
+
+ private extractValuesFromMap = (map:CapabilitiesGroup | RequirementsGroup):Array<any> => {
+ let values = [];
+ _.forEach(map, (capabilitiesOrRequirements:Array<Capability> | Array<Requirement>, key) => {
+ values = values.concat(capabilitiesOrRequirements)
+ }
+ );
+ return values;
+ }
+
+ private setScopeCapabilitiesRequirements = (capabilities:CapabilitiesGroup, requirements:RequirementsGroup) => {
+ this.capabilities = this.extractValuesFromMap(capabilities);
+ this.requirements = this.extractValuesFromMap(requirements);
+ }
+
+
+ private initInstancesMap = ():void => {
+
+ this.capabilitiesInstancesMap = new InstanceCapabilitiesMap();
+ _.forEach(this.capabilities, (capability:Capability) => {
+ if (this.capabilitiesInstancesMap[capability.ownerName]) {
+ this.capabilitiesInstancesMap[capability.ownerName] = this.capabilitiesInstancesMap[capability.ownerName].concat(capability);
+ } else {
+ this.capabilitiesInstancesMap[capability.ownerName] = new Array<Capability>(capability);
+ }
+ });
+
+ this.requirementsInstancesMap = new InstanceRequirementsMap();
+ _.forEach(this.requirements, (requirement:Requirement) => {
+ if (this.requirementsInstancesMap[requirement.ownerName]) {
+ this.requirementsInstancesMap[requirement.ownerName] = this.requirementsInstancesMap[requirement.ownerName].concat(requirement);
+ } else {
+ this.requirementsInstancesMap[requirement.ownerName] = new Array<Requirement>(requirement);
+ }
+ });
+ }
+
+ private initRequirementsAndCapabilities = (needUpdate?: boolean) => {
+
+ // if instance selected, we take the requirement and capabilities of the instance - always exist because we load them with the graph
+ if (this.component instanceof FullComponentInstance) {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.setScopeCapabilitiesRequirements(this.component.capabilities, this.component.requirements);
+ if (this.component.originType === 'VF') {
+ this.initInstancesMap();
+ }
+ } else {
+ // if instance not selected, we take the requirement and capabilities of the VF/SERVICE, if not exist we call api
+ if (needUpdate || !this.component.capabilities || !this.component.requirements) {
+ this.loadComplexComponentData();
+
+ } else {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ this.setScopeCapabilitiesRequirements(this.component.capabilities, this.component.requirements);
+ this.initInstancesMap();
+ }
+ }
+ }
+
+ private updateRequirementCapabilities = () => {
+ if (!this.isComponentInstanceSelected) {
+ this.loadComplexComponentData();
+ }
+ }
+
+
+
+
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html
new file mode 100644
index 0000000..8292729
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html
@@ -0,0 +1,20 @@
+<div class="i-sdc-designer-sidebar-capabilities-requirements">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-group">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations"
+ *ngFor="let requirement of requirements">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-name">{{requirement.name}} </div>
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-desc">{{requirement.node}}
+ <div *ngIf="getRelation(requirement) != null">
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-indent-box"></div>
+ <div class="i-sdc-designer-sidebar-section-content-item-relations-details-child">
+ <span class="i-sdc-designer-sidebar-section-content-item-relations-details-desc">{{getRelation(requirement).type}} <br/></span>
+ <span class="i-sdc-designer-sidebar-section-content-item-relations-details-name">{{getRelation(requirement).requirementName}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts
new file mode 100644
index 0000000..e167c47
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts
@@ -0,0 +1,40 @@
+import { Component, Input } from '@angular/core';
+import { Component as TopologyTemplate, RelationshipModel, Relationship, Requirement } from "app/models";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { ResourceNamePipe } from "app/ng2/pipes/resource-name.pipe";
+
+@Component({
+ selector: 'requirement-list',
+ templateUrl: './requirement-list.component.html'
+})
+export class RequirementListComponent {
+ @Input() component: TopologyTemplate;
+ @Input() requirements: Array<Requirement>;
+ @Input() isInstanceSelected:boolean;
+
+
+ constructor(private compositionService: CompositionService) { }
+
+
+ public getRelation = (requirement:any):any => {
+ if (this.isInstanceSelected && this.component.componentInstancesRelations) {
+ let relationItem:Array<RelationshipModel> = _.filter(this.component.componentInstancesRelations, (relation:RelationshipModel) => {
+ return relation.fromNode === this.component.uniqueId &&
+ _.filter(relation.relationships, (relationship:Relationship) => {
+ return relationship.relation.requirement == requirement.name && relationship.relation.requirementOwnerId == requirement.ownerId;
+ }).length;
+ });
+
+ if (relationItem && relationItem.length) {
+ return {
+ type: requirement.relationship.split('.').pop(),
+ requirementName: ResourceNamePipe.getDisplayName(this.compositionService.componentInstances[_.map
+ (this.compositionService.componentInstances, "uniqueId").indexOf(relationItem[0].toNode)].name)
+ };
+ }
+ }
+ return null;
+ };
+
+};
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html
new file mode 100644
index 0000000..a52c841
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.html
@@ -0,0 +1,15 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <service-consumption
+ [parentService]="metadata"
+ [selectedService]="component"
+ [selectedServiceInstanceId]="component.uniqueId"
+ [instancesMappedList]="instancesMappedList"
+ [parentServiceInputs]="componentInputs"
+ [instancesCapabilitiesMap]="instancesCapabilitiesMap"
+ [readonly]="isViewOnly">
+ </service-consumption>
+ </content>
+</ng2-expand-collapse>
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.less
similarity index 100%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-properties-tab.component.less
rename to catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.less
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts
new file mode 100644
index 0000000..8715afd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-consumption-tab/service-consumption-tab.component.ts
@@ -0,0 +1,89 @@
+
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ CapabilitiesGroup,
+ Capability,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ FullComponentInstance,
+ InputBEModel,
+ InputsGroup,
+ InterfaceModel,
+ PropertiesGroup
+} from 'app/models';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { ServiceInstanceObject } from '../../../../../../models/service-instance-properties-and-interfaces';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../../../services/responses/component-generic-response';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { SelectedComponentType } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'service-consumption-tab',
+ templateUrl: './service-consumption-tab.component.html',
+ styleUrls: ['./service-consumption-tab.component.less'],
+})
+export class ServiceConsumptionTabComponent {
+ isComponentInstanceSelected: boolean;
+
+ instancesMappedList: ServiceInstanceObject[];
+ componentInstancesProperties: PropertiesGroup;
+ componentInstancesInputs: InputsGroup;
+ componentInstancesInterfaces: Map<string, InterfaceModel[]>;
+ componentInputs: InputBEModel[];
+ componentCapabilities: Capability[];
+ instancesCapabilitiesMap: Map<string, Capability[]>;
+ metadata: ComponentMetadata;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: TopologyTemplate | FullComponentInstance;
+ @Input() input: any;
+
+ constructor(private store: Store,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService: EventListenerService ) {}
+ ngOnInit() {
+ this.metadata = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.initInstances();
+ }
+
+ private initInstances = (): void => {
+ this.topologyTemplateService.getServiceConsumptionData(this.metadata.componentType, this.metadata.uniqueId).subscribe((genericResponse: ComponentGenericResponse) => {
+ this.componentInstancesProperties = genericResponse.componentInstancesProperties;
+ this.componentInstancesInputs = genericResponse.componentInstancesInputs;
+ this.componentInstancesInterfaces = genericResponse.componentInstancesInterfaces;
+ this.componentInputs = genericResponse.inputs;
+ this.buildInstancesCapabilitiesMap(genericResponse.componentInstances);
+ this.updateInstanceAttributes();
+ });
+ }
+
+ private buildInstancesCapabilitiesMap = (componentInstances: Array<ComponentInstance>): void => {
+ this.instancesCapabilitiesMap = new Map();
+ let flattenCapabilities = [];
+ _.forEach(componentInstances, (componentInstance) => {
+ flattenCapabilities = CapabilitiesGroup.getFlattenedCapabilities(componentInstance.capabilities);
+ this.instancesCapabilitiesMap[componentInstance.uniqueId] = _.filter(flattenCapabilities, cap => cap.properties && cap.ownerId === componentInstance.uniqueId);
+ });
+ }
+
+ private updateInstanceAttributes = (): void => {
+ if (this.isComponentInstanceSelected && this.componentInstancesProperties) {
+ this.instancesMappedList = this.compositionService.componentInstances.map((coInstance) => new ServiceInstanceObject({
+ id: coInstance.uniqueId,
+ name: coInstance.name,
+ properties: this.componentInstancesProperties[coInstance.uniqueId] || [],
+ inputs: this.componentInstancesInputs[coInstance.uniqueId] || [],
+ interfaces: this.componentInstancesInterfaces[coInstance.uniqueId] || []
+ }));
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html
new file mode 100644
index 0000000..47351a4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.html
@@ -0,0 +1,18 @@
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="{{input.title}}">{{input.title}}</header>
+ <content>
+ <div *ngIf="isComponentInstanceSelected">
+ <service-dependencies
+ [compositeService]="metaData"
+ [currentServiceInstance]="component"
+ [selectedInstanceProperties]="selectedInstanceProperties"
+ [selectedInstanceSiblings]="selectedInstanceSiblings"
+ [selectedInstanceConstraints]="selectedInstanceConstraints"
+ [readonly]="isViewOnly"
+ (dependencyStatus)="notifyDependencyEventsObserver($event)"
+ (updateRulesListEvent)="updateSelectedInstanceConstraints($event)"
+ (loadRulesListEvent)="loadConstraints()">
+ </service-dependencies>
+ </div>
+ </content>
+</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less
new file mode 100644
index 0000000..47e26e2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.less
@@ -0,0 +1,3 @@
+:host /deep/ .expand-collapse-content {
+ padding: 0 0 10px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts
new file mode 100644
index 0000000..5171e3b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts
@@ -0,0 +1,95 @@
+
+import { Component, Input } from '@angular/core';
+import { Store } from '@ngxs/store';
+import {
+ CapabilitiesGroup,
+ Capability,
+ Component as TopologyTemplate,
+ ComponentInstance,
+ FullComponentInstance,
+ InputBEModel,
+ InputsGroup,
+ InterfaceModel,
+ PropertiesGroup,
+ PropertyBEModel,
+} from 'app/models';
+import { DEPENDENCY_EVENTS } from 'app/utils/constants';
+import { ComponentMetadata } from '../../../../../../models/component-metadata';
+import { ServiceInstanceObject } from '../../../../../../models/service-instance-properties-and-interfaces';
+import { EventListenerService } from '../../../../../../services/event-listener-service';
+import { ConstraintObject } from '../../../../../components/logic/service-dependencies/service-dependencies.component';
+import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../../../services/responses/component-generic-response';
+import { WorkspaceService } from '../../../../workspace/workspace.service';
+import { SelectedComponentType } from '../../../common/store/graph.actions';
+import { CompositionService } from '../../../composition.service';
+
+@Component({
+ selector: 'service-dependencies-tab',
+ templateUrl: 'service-dependencies-tab.component.html',
+ styleUrls: ['service-dependencies-tab.component.less']
+})
+export class ServiceDependenciesTabComponent {
+ isComponentInstanceSelected: boolean;
+
+ selectedInstanceSiblings: ServiceInstanceObject[];
+ componentInstancesConstraints: any[];
+ selectedInstanceConstraints: ConstraintObject[];
+ selectedInstanceProperties: PropertyBEModel[];
+ componentInstanceProperties: PropertiesGroup;
+ metaData: ComponentMetadata;
+
+ @Input() isViewOnly: boolean;
+ @Input() componentType: SelectedComponentType;
+ @Input() component: FullComponentInstance | TopologyTemplate;
+ @Input() input: any;
+
+ constructor(private store: Store,
+ private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private compositionService: CompositionService,
+ private eventListenerService: EventListenerService) {
+ }
+
+ ngOnInit() {
+ this.metaData = this.workspaceService.metadata;
+ this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
+ this.initInstancesWithProperties();
+ this.loadConstraints();
+ this.initInstancesWithProperties();
+ }
+
+ public loadConstraints = (): void => {
+ this.topologyTemplateService.getServiceFilterConstraints(this.metaData.componentType, this.metaData.uniqueId).subscribe((response) => {
+ this.componentInstancesConstraints = response.nodeFilterData;
+ });
+ }
+
+ public notifyDependencyEventsObserver = (isChecked: boolean): void => {
+ this.eventListenerService.notifyObservers(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, isChecked);
+ }
+
+ public updateSelectedInstanceConstraints = (constraintsList:Array<ConstraintObject>):void => {
+ this.componentInstancesConstraints[this.component.uniqueId].properties = constraintsList;
+ this.selectedInstanceConstraints = this.componentInstancesConstraints[this.component.uniqueId].properties;
+ }
+
+ private initInstancesWithProperties = (): void => {
+ this.topologyTemplateService.getComponentInstanceProperties(this.metaData.componentType, this.metaData.uniqueId).subscribe((genericResponse: ComponentGenericResponse) => {
+ this.componentInstanceProperties = genericResponse.componentInstancesProperties;
+ this.updateInstanceAttributes();
+ });
+ }
+
+ private updateInstanceAttributes = (): void => {
+ if (this.isComponentInstanceSelected && this.componentInstanceProperties) {
+ const instancesMappedList = this.compositionService.componentInstances.map((coInstance) => new ServiceInstanceObject({
+ id: coInstance.uniqueId,
+ name: coInstance.name,
+ properties: this.componentInstanceProperties[coInstance.uniqueId] || []
+ }));
+ this.selectedInstanceProperties = this.componentInstanceProperties[this.component.uniqueId];
+ this.selectedInstanceSiblings = instancesMappedList.filter((coInstance) => coInstance.id !== this.component.uniqueId);
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html
deleted file mode 100644
index 9bb8092..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<ng2-composition-panel-header
- [name]="selectedZoneInstanceName"
- [topologyTemplate]="topologyTemplate"
- [selectedZoneInstanceType]="selectedZoneInstanceType"
- [selectedZoneInstanceId]="selectedZoneInstanceId"
- [nonCertified]="nonCertified"
- [isViewOnly]="isViewOnly"
- [isLoading]="isLoading"
-></ng2-composition-panel-header>
-
-<div class="component-details-panel-tabs">
- <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader>
-
- <div *ngIf="selectedZoneInstanceType === zoneInstanceType.POLICY">
- <policy-tabs
- [topologyTemplate]="topologyTemplate"
- [selectedZoneInstanceType]="selectedZoneInstanceType"
- [selectedZoneInstanceId]="selectedZoneInstanceId"
- [isViewOnly]="isViewOnly"
- (isLoading)="setIsLoading($event)"
- ></policy-tabs>
- </div>
-
- <div *ngIf="selectedZoneInstanceType === zoneInstanceType.GROUP">
- <group-tabs
- [topologyTemplate]="topologyTemplate"
- [selectedZoneInstanceType]="selectedZoneInstanceType"
- [selectedZoneInstanceId]="selectedZoneInstanceId"
- [isViewOnly]="isViewOnly"
- (isLoading)="setIsLoading($event)"
- ></group-tabs>
- </div>
-
-</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less
deleted file mode 100644
index 1777d54..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.less
+++ /dev/null
@@ -1,11 +0,0 @@
-/deep/
-.component-details-panel {
-
- color: #666666;
- font-family: OpenSans-Regular, sans-serif;
- font-size: 14px;
-
- .component-details-panel-tabs {
-
- }
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts
deleted file mode 100644
index 53599d6..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel.component.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter, AfterViewInit, SimpleChanges, HostBinding } from "@angular/core";
-import { Component as TopologyTemplate, ComponentInstance, IAppMenu } from "app/models";
-import { PolicyInstance } from 'app/models/graph/zones/policy-instance';
-import { TranslateService } from 'app/ng2/shared/translator/translate.service';
-import { ZoneInstanceType } from "app/models/graph/zones/zone-instance";
-import { GroupsService } from "../../../services/groups.service";
-import { PoliciesService } from "../../../services/policies.service";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-import { IZoneService } from "../../../../models/graph/zones/zone";
-
-@Component({
- selector: 'ng2-composition-panel',
- templateUrl: './panel.component.html',
- styleUrls: ['./panel.component.less'],
- providers: [TranslateService]
-})
-export class CompositionPanelComponent {
-
- @Input() topologyTemplate: TopologyTemplate;
- @Input() selectedZoneInstanceType: ZoneInstanceType;
- @Input() selectedZoneInstanceId: string;
- @Input() selectedZoneInstanceName: string;
- @Input() nonCertified: boolean;
- @Input() isViewOnly: boolean;
- @Input() isLoading: boolean;
-
-
- @HostBinding('class') classes = 'component-details-panel';
-
- private zoneInstanceType = ZoneInstanceType; // Expose ZoneInstanceType to use in template.
-
- constructor(){
- }
-
- private setIsLoading = (value):void => {
- this.isLoading = value;
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts
deleted file mode 100644
index 57f6be8..0000000
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel.module.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-import {NgModule} from "@angular/core";
-import {HttpModule} from "@angular/http";
-import {FormsModule} from "@angular/forms";
-import {BrowserModule} from "@angular/platform-browser";
-import {CompositionPanelComponent} from "./panel.component";
-import {CompositionPanelHeaderModule} from "app/ng2/pages/composition/panel/panel-header/panel-header.module";
-import {GroupTabsModule} from "./panel-tabs/groups/group-tabs.module";
-import {PolicyTabsModule} from "./panel-tabs/policies/policy-tabs.module";
-import {SdcUiComponents} from "sdc-ui/lib/angular";
-import {UiElementsModule} from 'app/ng2/components/ui/ui-elements.module';
-import {AddElementsModule} from "../../../components/ui/modal/add-elements/add-elements.module";
-
-@NgModule({
- declarations: [
- CompositionPanelComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- CompositionPanelHeaderModule,
- PolicyTabsModule,
- GroupTabsModule,
- UiElementsModule,
- AddElementsModule
- ],
- entryComponents: [
- CompositionPanelComponent
- ],
- exports: [],
- providers: [SdcUiComponents.ModalService]
-})
-export class CompositionPanelModule {
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts
deleted file mode 100644
index 054d38b..0000000
--- a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import {Component, OnInit, Inject, forwardRef} from "@angular/core";
-import {IStepComponent} from "../../../../models/wizard-step";
-import {Dictionary} from "lodash";
-import { Match} from "app/models";
-import {ConnectionWizardService} from "../connection-wizard.service";
-import {Requirement} from "../../../../models/requirement";
-import {Capability} from "../../../../models/capability";
-import {PropertyModel} from "../../../../models/properties";
-
-@Component({
- selector: 'from-node-step',
- templateUrl: './from-node-step.component.html'
-})
-
-export class FromNodeStepComponent implements IStepComponent, OnInit{
-
- constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) {}
-
- optionalRequirementsMap: Dictionary<Requirement[]>;
- optionalCapabilitiesMap: Dictionary<Capability[]>;
-
- ngOnInit(){
- this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(true);
- this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(false);
- }
-
- preventNext = ():boolean => {
- return !this.connectWizardService.selectedMatch || (!this.connectWizardService.selectedMatch.capability && !this.connectWizardService.selectedMatch.requirement);
- }
-
- preventBack = ():boolean => {
- return true;
- }
-
- private updateSelectedReqOrCap = (selected:Requirement|Capability):void => {
- if(!selected){
- this.connectWizardService.selectedMatch = null;
- } else if(selected instanceof Requirement){
- this.connectWizardService.selectedMatch = new Match(<Requirement>selected, null, true, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId, null);
- } else{
- this.connectWizardService.selectedMatch = new Match(null,<Capability>selected , false, null, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId);
- }
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap
new file mode 100644
index 0000000..ae5445e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/__snapshots__/home.component.spec.ts.snap
@@ -0,0 +1,28 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`home component should match current snapshot 1`] = `
+<home-page
+ $state={[Function Object]}
+ authService={[Function Object]}
+ cacheService={[Function Object]}
+ componentShouldReload={[Function Function]}
+ homeService={[Function Object]}
+ importVSPService={[Function Object]}
+ initFolders={[Function Function]}
+ isDefaultFilter={[Function Function]}
+ loaderService={[Function Object]}
+ modalService={[Function Object]}
+ modalsHandler={[Function Object]}
+ sdcConfig={[Function Object]}
+ sdcMenu={[Function Object]}
+ translateService={[Function Object]}
+ updateFilter={[Function Function]}
+>
+ <div
+ class="sdc-catalog-container"
+ >
+
+ <top-nav />
+ </div>
+</home-page>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/home/folders.ts b/catalog-ui/src/app/ng2/pages/home/folders.ts
new file mode 100644
index 0000000..036ae32
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/folders.ts
@@ -0,0 +1,93 @@
+
+export interface IItemMenu {
+
+}
+
+export interface IMenuItemProperties {
+ text:string;
+ group:string;
+ state:string;
+ dist:string;
+ groupname:string;
+ states:Array<any>;
+}
+
+export class FoldersMenu {
+ private _folders:Array<FoldersItemsMenu> = [];
+
+ constructor(folders:Array<IMenuItemProperties>) {
+ let self = this;
+ folders.forEach(function (folder:IMenuItemProperties) {
+ if (folder.groupname) {
+ self._folders.push(new FoldersItemsMenuGroup(folder));
+ } else {
+ self._folders.push(new FoldersItemsMenu(folder));
+ }
+ });
+ self._folders[0].setSelected(true);
+ }
+
+ public getFolders():Array<FoldersItemsMenu> {
+ return this._folders;
+ }
+
+ public getCurrentFolder():FoldersItemsMenu {
+ let menuItem:FoldersItemsMenu = undefined;
+ this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
+ if (tmpFolder.isSelected()) {
+ menuItem = tmpFolder;
+ }
+ });
+ return menuItem;
+ }
+
+ public setSelected(folder:FoldersItemsMenu):void {
+ this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
+ tmpFolder.setSelected(false);
+ });
+ folder.setSelected(true);
+ }
+}
+
+export class FoldersItemsMenu implements IItemMenu {
+ public text:string;
+ public group:string;
+ public state:string;
+ public dist:string;
+ public states:Array<any>;
+
+ private selected:boolean = false;
+
+ constructor(menuProperties:IMenuItemProperties) {
+ this.text = menuProperties.text;
+ this.group = menuProperties.group;
+ this.state = menuProperties.state;
+ this.states = menuProperties.states;
+ this.dist = menuProperties.dist;
+ }
+
+ public isSelected():boolean {
+ return this.selected;
+ }
+
+ public setSelected(value:boolean):void {
+ this.selected = value;
+ }
+
+ public isGroup():boolean {
+ return false;
+ }
+}
+
+export class FoldersItemsMenuGroup extends FoldersItemsMenu {
+ public groupname:string;
+
+ constructor(menuProperties:IMenuItemProperties) {
+ super(menuProperties);
+ this.groupname = menuProperties.groupname;
+ }
+
+ public isGroup():boolean {
+ return true;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.html b/catalog-ui/src/app/ng2/pages/home/home.component.html
new file mode 100644
index 0000000..1c8c2b4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.html
@@ -0,0 +1,88 @@
+<div class="sdc-catalog-container">
+ <div class="w-sdc-main-container" *ngIf="user">
+
+ <div id="dashboard-main-scroll" infiniteScroll class="w-sdc-main-right-container" (infiniteScroll)="raiseNumberOfElementToDisplay()" [infiniteScrollDistance]="100">
+
+ <div class='w-sdc-row-flex-items'>
+
+ <!-- ADD Component -->
+ <div *ngIf="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new"
+ (mouseleave)="setDisplayActions(false)"
+ (mouseover)="setDisplayActions(true)">
+ <div class="w-sdc-dashboard-card-new-content" data-tests-id="AddButtonsArea">
+ <div class="w-sdc-dashboard-card-new-content-plus" [hidden]="displayActions"></div>
+ <div class="sdc-dashboard-create-element-container" [hidden]="!displayActions">
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" testId="createResourceButton" size="medium" type="secondary" text="Add VF" (click)="openCreateModal('RESOURCE')"></sdc-button>
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" testId="createCRButton" size="medium" type="secondary" text="Add CR" (click)="createCR()"></sdc-button>
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" testId="createPNFButton" size="medium" type="secondary" text="Add PNF" (click)="createPNF()"></sdc-button>
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" testId="createServiceButton" size="medium" type="secondary" text="Add Service" (click)="openCreateModal('SERVICE')"></sdc-button>
+ </div>
+ </div>
+ </div>
+
+ <!-- Import Component -->
+ <div *ngIf="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new"
+ (mouseleave)="setDisplayActions(false)"
+ (mouseover)="setDisplayActions(true)">
+ <div class="w-sdc-dashboard-card-new-content" data-tests-id="importButtonsArea" >
+ <div class="w-sdc-dashboard-card-import-content-plus" [hidden]="displayActions"></div>
+ <div class="sdc-dashboard-import-element-container" [hidden]="!displayActions">
+ <sdc-button-file-opener
+ *ngIf="roles[user.role].dashboard.showCreateNew"
+ size="medium"
+ type="secondary"
+ text="Import VFC"
+ testId="importVFCbutton"
+ [extensions]="sdcConfig.toscaFileExtension"
+ (fileUpload)="onImportVfc($event)"
+ [convertToBase64]="true"
+ ></sdc-button-file-opener>
+ <sdc-button *ngIf="roles[user.role].dashboard.showCreateNew" data-tests-id="importButtonsVSP" size="medium" type="secondary" text="Import VSP" (click)="notificationIconCallback()"></sdc-button>
+ <sdc-button-file-opener
+ *ngIf="roles[user.role].dashboard.showCreateNew"
+ size="medium"
+ type="secondary"
+ text="Import DCAE"
+ testId="importDCAE"
+ [extensions]="sdcConfig.csarFileExtension"
+ (fileUpload)="onImportVf($event)"
+ [convertToBase64]="true"
+ ></sdc-button-file-opener>
+ </div>
+ </div>
+ </div>
+
+ <!-- Tile new -->
+ <ui-tile *ngFor="let item of homeFilteredSlicedItems"
+ [component]="item" (onTileClick)="goToComponent(item)"></ui-tile>
+ <!-- Tile new -->
+
+ </div>
+
+ </div>
+
+ <div class="w-sdc-left-sidebar">
+ <div class="i-sdc-left-sidebar-item "
+ *ngFor="let folder of folders.getFolders()"
+ [ngClass]="{'category-title': folder.isGroup(), 'selectedLink': folder.isSelected()}">
+
+ <span *ngIf="folder.isGroup()" class="title-text">{{folder.text}}</span>
+ <sdc-checkbox *ngIf="!folder.isGroup() && !folder.dist"
+ [label]="folder.text"
+ [attr.data-tests-id]="'filter-' + folder.state"
+ [checked]="homeFilter.selectedStatuses.indexOf(folder.state) !== -1"
+ (checkedChange)="changeCheckboxesFilter(homeFilter.selectedStatuses, folder.state, $event)"></sdc-checkbox>
+
+ <sdc-checkbox *ngIf="!folder.isGroup() && folder.dist"
+ [label]="folder.text"
+ [checked]="homeFilter.distributed.indexOf(folder.dist) !== -1"
+ (checkedChange)="changeCheckboxesFilter(homeFilter.distributed, folder.dist, $event)"></sdc-checkbox>
+ <span class="i-sdc-left-sidebar-item-state-count" [attr.data-tests-id]="'count-' + folder.state">{{entitiesCount(folder)}}</span>
+ </div>
+ </div>
+
+ </div>
+
+ <top-nav [topLvlSelectedIndex]="0" [version]="version" [searchTerm]="homeFilter.search.filterTerm" (searchTermChange)="changeFilterTerm($event)" [notificationIconCallback]="notificationIconCallback"></top-nav>
+
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.less b/catalog-ui/src/app/ng2/pages/home/home.component.less
new file mode 100644
index 0000000..c5b7374
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.less
@@ -0,0 +1,126 @@
+@import '../../../../assets/styles/mixins_old';
+@import '../../../../assets/styles/sprite';
+.w-sdc-left-sidebar-nav {
+ margin-top: 46px;
+}
+
+.w-sdc-main-right-container {
+ height: 100%;
+ overflow-y: scroll;
+}
+
+.w-sdc-main-right-container-element {
+ float: left;
+ height: 217px;
+ width: 217px;
+ margin: 10px;
+ position: relative;
+}
+
+.w-sdc-main-right-container-element-details-container {
+ position: absolute;
+ top: 165px;
+ left: 50px;
+}
+
+.w-sdc-main-right-container-element-name {
+ font-weight: bold;
+}
+
+.i-sdc-left-sidebar-item{
+ display: flex;
+ &.category-title .title-text, sdc-checkbox{
+ flex-grow: 1;
+ }
+ &:not(.category-title).i-sdc-left-sidebar-item-state-count {
+ line-height: 14px;
+ }
+}
+
+
+//////////////////////////////Cards////////////////////
+.w-sdc-dashboard-card-new {
+ border: 2px dashed @color_m;
+ .border-radius(2px);
+ cursor: pointer;
+ display: inline-block;
+ height: 198px;
+ margin: 11px;
+ position: relative;
+ vertical-align: middle;
+ width: 202px;
+}
+
+.w-sdc-dashboard-card-new-content {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ height: 100%;
+}
+
+.w-sdc-dashboard-card-new-content-plus {
+ .sprite-new;
+ .add-icon;
+ position: relative;
+ margin-bottom: 20px;
+
+ &:after {
+ .n_14_m;
+ content: 'ADD';
+ position: absolute;
+ top: 25px;
+ left: -3px;
+ vertical-align: -50%;
+ }
+}
+
+.w-sdc-dashboard-card-import-content-plus {
+ .sprite-new;
+ .import-icon;
+ position: relative;
+ margin-bottom: 20px;
+
+ &:after {
+ .n_14_m;
+ content: 'IMPORT';
+ position: absolute;
+ top: 25px;
+ left: -16px;
+ vertical-align: -50%;
+ }
+}
+
+.sdc-dashboard-create-element-container,
+.sdc-dashboard-import-element-container {
+
+ width: 140px;
+
+ sdc-button,
+ sdc-button-file-opener {
+ padding-bottom: 5px;
+ &:last-child{
+ padding-bottom: 0;
+ }
+ }
+
+ .import-file{
+ position: relative;
+ file-opener{
+ position: absolute;
+ top: 0;
+ /deep/ input[type="file"] {
+ .hand;
+ filter: alpha(opacity=0);
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 140px;
+ height: 36px;
+ }
+ }
+ }
+}
+
+
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts b/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts
new file mode 100644
index 0000000..df85402
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.spec.ts
@@ -0,0 +1,270 @@
+
+import { SdcConfigToken, ISdcConfig } from "../../config/sdc-config.config";
+import { SdcMenuToken, IAppMenu } from "../../config/sdc-menu.config";
+
+
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { HomeComponent } from "./home.component";
+import {ConfigureFn, configureTests} from "../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import { TranslateService } from "../../shared/translator/translate.service";
+import { HomeService, CacheService, AuthenticationService, ImportVSPService } from '../../../../app/services-ng2';
+import { ModalsHandler } from "../../../../app/utils";
+import { SdcUiServices } from "onap-ui-angular";
+import {ComponentType, ResourceType} from "../../../utils/constants";
+import { FoldersMenu, FoldersItemsMenu, FoldersItemsMenuGroup } from './folders';
+import { HomeFilter } from "../../../../app/models/home-filter";
+import {Component} from "../../../models/components/component";
+
+
+
+
+describe('home component', () => {
+
+ // const mockedEvent = <MouseEvent>{ target: {} }
+ let fixture: ComponentFixture<HomeComponent>;
+ // let eventServiceMock: Partial<EventListenerService>;
+
+ let importVspService: Partial<ImportVSPService>;
+ let mockStateService;
+ let modalServiceMock :Partial<SdcUiServices.ModalService>;
+ let translateServiceMock : Partial<TranslateService>;
+ let foldersItemsMenuMock;
+ let homeFilterMock :Partial<HomeFilter>;
+ let foldersMock;
+ let loaderServiceMock;
+
+
+ beforeEach(
+ async(() => {
+ modalServiceMock = {
+ openWarningModal: jest.fn()
+ }
+
+ mockStateService = {
+ // go: jest.fn().mockReturnValue( new Promise.resolve((resolve, reject )=> resolve()))
+ go: jest.fn()
+ }
+
+ translateServiceMock = {
+ translate: jest.fn()
+ }
+
+ homeFilterMock = {
+ search: jest.fn,
+ toUrlParam: jest.fn()
+ }
+
+ foldersMock = {
+ setSelected: jest.fn()
+ }
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [HomeComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: SdcConfigToken, useValue: {"csarFileExtension":"csar", "toscaFileExtension":"yaml,yml"}},
+ {provide: SdcMenuToken, useValue: {}},
+ {provide: "$state", useValue: mockStateService},
+ {provide: HomeService, useValue: {}},
+ {provide: AuthenticationService, useValue: {}},
+ {provide: CacheService, useValue: {}},
+ {provide: TranslateService, useValue: translateServiceMock},
+ {provide: ModalsHandler, useValue: {}},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock},
+ {provide: ImportVSPService, useValue: {}}
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(HomeComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should call on home component openCreateModal with null imported file', () => {
+ const component = TestBed.createComponent(HomeComponent);
+ let componentType:string = 'test';
+ let importedFile:any = null;
+ component.componentInstance.openCreateModal(componentType, importedFile);
+ expect(mockStateService.go).toBeCalledWith('workspace.general', {type: componentType.toLowerCase()});
+ });
+
+
+ it('should call on home component openCreateModal with imported file', () => {
+ const component = TestBed.createComponent(HomeComponent);
+ component.componentInstance.initEntities = jest.fn();
+ let componentType:string = 'test';
+ let importedFile:any = 'importedFile';
+ component.componentInstance.openCreateModal(componentType, importedFile);
+ expect(component.componentInstance.initEntities).toBeCalledWith(true);
+ });
+
+
+ it ('should call on home component onImportVf without file without extension', () => {
+ const component = TestBed.createComponent(HomeComponent);
+ let file:any = {filename : 'test'};
+ let expectedTitle:string = translateServiceMock.translate("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE");
+ let expectedMessage:string = translateServiceMock.translate("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS", {"csarFileExtension":"csar"});
+ component.componentInstance.onImportVf(file);
+ expect(modalServiceMock.openWarningModal).toBeCalledWith(expectedTitle, expectedMessage , 'error-invalid-csar-ext');
+ });
+
+
+ it ('should call on home component onImportVf with file without extension' , () => {
+ const component = TestBed.createComponent(HomeComponent);
+ let file:any = {filename : 'test.csar'};
+ component.componentInstance.onImportVf(file);
+ expect(mockStateService.go).toBeCalledWith('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ importedFile: file,
+ resourceType: ResourceType.VF
+ });
+ });
+
+
+ it ('should call on home component onImportVfc without file without extension', () => {
+ const component = TestBed.createComponent(HomeComponent);
+ let file:any = {filename : 'test'};
+ let expectedTitle:string = translateServiceMock.translate("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE");
+ let expectedMessage:string = translateServiceMock.translate("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS", {"toscaFileExtension":"yaml,yml"});
+ component.componentInstance.onImportVfc(file);
+ expect(modalServiceMock.openWarningModal).toBeCalledWith(expectedTitle, expectedMessage , 'error-invalid-tosca-ext');
+ });
+
+ it ('should call on home component onImportVfc with file without extension' , () => {
+ const component = TestBed.createComponent(HomeComponent);
+ let file:any = {filename : 'test.yml'};
+ component.componentInstance.onImportVfc(file);
+ expect(mockStateService.go).toBeCalledWith('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ importedFile: file,
+ resourceType: ResourceType.VFC
+ });
+ });
+
+ it ('should call on home component createPNF' , () => {
+ const component = TestBed.createComponent(HomeComponent);
+ component.componentInstance.createPNF();
+ expect(mockStateService.go).toBeCalledWith('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ resourceType: ResourceType.PNF
+ });
+ });
+
+ it ('should call on home component createCR' , () => {
+ const component = TestBed.createComponent(HomeComponent);
+ component.componentInstance.createCR();
+ expect(mockStateService.go).toBeCalledWith('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ resourceType: ResourceType.CR
+ });
+ });
+
+
+ it ('should call on home component updateFilter' , () => {
+ const component = TestBed.createComponent(HomeComponent);
+ component.componentInstance.homeFilter = homeFilterMock;
+ component.componentInstance.filterHomeItems = jest.fn();
+ component.componentInstance.updateFilter();
+
+ expect(mockStateService.go).toBeCalledWith('.', homeFilterMock.toUrlParam(), {location: 'replace', notify: false});
+ // expect(spy).toHaveBeenCalledTimes(1);
+
+ // let spy = spyOn(homeFilterMock, 'toUrlParam').and.returnValue({
+ // 'filter.term': '',
+ // 'filter.distributed': '',
+ // 'filter.status':''
+ // });
+ });
+
+ // it ('should call on home component setSelectedFolder' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // let folderItem:Partial<FoldersItemsMenu> = { text:'someThing'};
+ // let folderItem1:number;
+ // component.componentInstance.folders = foldersMock;
+ // expect(foldersMock.setSelected).toBeCalledWith(folderItem);
+ // });
+
+ // it ('should call on home component goToComponent' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // let componentParam:Partial<Component> = { uuid:'someThing', uniqueId:'uniqueID', componentType:'componentType'};
+ // component.componentInstance.goToComponent(componentParam);
+ // expect(loaderServiceMock.activate).toHaveBeenCalled();
+ // // expect(mockStateService.go).toBeCalledWith('workspace.general', {id: componentParam.uniqueId, type: componentParam.componentType.toLowerCase()}).then(function(){
+ // // loaderServiceMock.deactivate();
+ // // });
+ // expect(mockStateService.go).toBeCalled();
+ // });
+
+ // it ('should call on home component raiseNumberOfElementToDisplay so numberOfItemToDisplay will be 0' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.raiseNumberOfElementToDisplay();
+ // expect(component.componentInstance.numberOfItemToDisplay).toEqual(0);
+ // });
+ //
+ // it ('should call on home component raiseNumberOfElementToDisplay with min(2,70) so numberOfItemToDisplay will be 2' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.homeItems = ['item1', 'item2'];
+ // component.componentInstance.numberOfItemToDisplay = 70;
+ // component.componentInstance.raiseNumberOfElementToDisplay(true);
+ // expect(component.componentInstance.numberOfItemToDisplay).toEqual(2);
+ // });
+ //
+ // it ('should call on home component raiseNumberOfElementToDisplay with min(3,35) so numberOfItemToDisplay will be 2 after fullPagesAmount is calculated' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.homeItems = ['item1', 'item2', 'item3'];
+ // component.componentInstance.numberOfItemToDisplay = 70;
+ // component.componentInstance.numberOfItemToDisplay = 0;
+ // component.componentInstance.raiseNumberOfElementToDisplay(false);
+ // expect(component.componentInstance.numberOfItemToDisplay).toEqual(3);
+ // });
+ //
+ //
+ // it ('should call on home component changeFilterTerm' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.changeFilterTerm("testStr");
+ // // expect ( "testStr" ).toEqual(homeFilterMock.search.)
+ // });
+
+
+
+
+
+
+ // it ('should call on home component entitiesCount' , () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.entitiesCount("aaa");
+ // expect(mockStateService.go).toBeCalledWith('workspace.general', {
+ // type: ComponentType.RESOURCE.toLowerCase(),
+ // resourceType: ResourceType.CR
+ // });
+ // });
+
+
+ // it('should call on home component notificationIconCallback', () => {
+ // const component = TestBed.createComponent(HomeComponent);
+ // component.componentInstance.initEntities = jest.fn();
+ // component.componentInstance.notificationIconCallback();
+ // expect(mockStateService.go).toBeCalledWith('workspace.general', {});
+ // });
+
+
+
+
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/home/home.component.ts b/catalog-ui/src/app/ng2/pages/home/home.component.ts
new file mode 100644
index 0000000..1b69eba
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/home.component.ts
@@ -0,0 +1,358 @@
+/*-
+ * ============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=========================================================
+ */
+'use strict';
+import { Component as NgComponent, Inject, OnInit } from '@angular/core';
+import { Component, IConfigRoles, IUserProperties, Resource } from 'app/models';
+import { HomeFilter } from 'app/models/home-filter';
+import { AuthenticationService, CacheService, HomeService } from 'app/services-ng2';
+import { ModalsHandler } from 'app/utils';
+import { SdcUiServices } from 'onap-ui-angular';
+import { CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, ResourceType } from '../../../utils/constants';
+import { ImportVSPService } from '../../components/modals/onboarding-modal/import-vsp.service';
+import { ISdcConfig, SdcConfigToken } from '../../config/sdc-config.config';
+import { IAppMenu, SdcMenuToken } from '../../config/sdc-menu.config';
+import { EntityFilterPipe } from '../../pipes/entity-filter.pipe';
+import { TranslateService } from '../../shared/translator/translate.service';
+import { FoldersItemsMenu, FoldersItemsMenuGroup, FoldersMenu } from './folders';
+
+@NgComponent({
+ selector: 'home-page',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.less']
+})
+export class HomeComponent implements OnInit {
+ public numberOfItemToDisplay: number;
+ public homeItems: Component[];
+ public homeFilteredItems: Component[];
+ public homeFilteredSlicedItems: Component[];
+ public folders: FoldersMenu;
+ public roles: IConfigRoles;
+ public user: IUserProperties;
+ public showTutorial: boolean;
+ public isFirstTime: boolean;
+ public version: string;
+ public homeFilter: HomeFilter;
+ public vfcmtType: string;
+ public displayActions: boolean;
+
+ constructor(
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
+ @Inject(SdcMenuToken) public sdcMenu: IAppMenu,
+ @Inject('$state') private $state: ng.ui.IStateService,
+ private homeService: HomeService,
+ private authService: AuthenticationService,
+ private cacheService: CacheService,
+ private translateService: TranslateService,
+ private modalsHandler: ModalsHandler,
+ private modalService: SdcUiServices.ModalService,
+ private loaderService: SdcUiServices.LoaderService,
+ private importVSPService: ImportVSPService
+ ) {}
+
+ ngOnInit(): void {
+ this.initHomeComponentVars();
+ this.initFolders();
+ this.initEntities();
+
+ if (this.$state.params) {
+ if (this.$state.params.folder) {
+ const folderName = this.$state.params.folder.replaceAll('_', ' ');
+
+ const selectedFolder = this.folders.getFolders().find((tmpFolder: FoldersItemsMenu) => tmpFolder.text === folderName);
+ if (selectedFolder) {
+ this.setSelectedFolder(selectedFolder);
+ }
+ // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script>
+ // This is called from the welcome page.
+ } else if (this.$state.params.show === 'tutorial') {
+ this.showTutorial = true;
+ this.isFirstTime = true;
+ }
+ }
+ }
+
+ // Open onboarding modal
+ public notificationIconCallback(): void {
+ this.importVSPService.openOnboardingModal().subscribe((result) => {
+ if (!result.previousComponent || result.previousComponent.csarVersion !== result.componentCsar.csarVersion) {
+ this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, result.componentCsar.csarVersion);
+ }
+ this.$state.go('workspace.general', {
+ id: result.previousComponent && result.previousComponent.uniqueId,
+ componentCsar: result.componentCsar,
+ type: result.type
+ });
+ });
+ }
+
+ public onImportVf(file: any): void {
+ if (file && file.filename) {
+ // Check that the file has valid extension.
+ const fileExtension: string = file.filename.split('.').pop();
+ if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
+ this.$state.go('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ importedFile: file,
+ resourceType: ResourceType.VF
+ });
+ } else {
+ const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE');
+ const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS', {extensions: this.sdcConfig.csarFileExtension});
+ this.modalService.openWarningModal(title, message, 'error-invalid-csar-ext');
+ }
+ }
+ }
+
+ public onImportVfc(file: any): void {
+ if (file && file.filename) {
+ // Check that the file has valid extension.
+ const fileExtension: string = file.filename.split('.').pop();
+ if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
+ this.$state.go('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ importedFile: file,
+ resourceType: ResourceType.VFC
+ });
+ } else {
+ const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE');
+ const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS', {extensions: this.sdcConfig.toscaFileExtension});
+ this.modalService.openWarningModal(title, message, 'error-invalid-tosca-ext');
+ }
+ }
+ }
+
+ public openCreateModal(componentType: string, importedFile: any): void {
+ if (importedFile) {
+ this.initEntities(true); // Return from import
+ } else {
+ this.$state.go('workspace.general', {type: componentType.toLowerCase()});
+ }
+ }
+
+ public createPNF(): void {
+ this.$state.go('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ resourceType: ResourceType.PNF
+ });
+ }
+
+ public createCR(): void {
+ this.$state.go('workspace.general', {
+ type: ComponentType.RESOURCE.toLowerCase(),
+ resourceType: ResourceType.CR
+ });
+ }
+
+ public entitiesCount(folderItem: FoldersItemsMenu): any {
+ let total: number = 0;
+ if (folderItem.isGroup()) {
+ this.folders.getFolders().forEach((tmpFolder: FoldersItemsMenu) => {
+ if (tmpFolder.group && tmpFolder.group === (folderItem as FoldersItemsMenuGroup).groupname) {
+ total = total + this._getTotalCounts(tmpFolder);
+ }
+ });
+ } else {
+ total = total + this._getTotalCounts(folderItem);
+ }
+ return total;
+ }
+
+ public updateFilter = () => {
+ this.$state.go('.', this.homeFilter.toUrlParam(), {location: 'replace', notify: false});
+ this.filterHomeItems();
+ }
+
+ public getCurrentFolderDistributed(): any[] {
+ const states = [];
+ if (this.folders) {
+ const folderItem: FoldersItemsMenu = this.folders.getCurrentFolder();
+ if (folderItem.isGroup()) {
+ this.folders.getFolders().forEach((tmpFolder: FoldersItemsMenu) => {
+ if (tmpFolder.group && tmpFolder.group === (folderItem as FoldersItemsMenuGroup).groupname) {
+ this._setStates(tmpFolder, states);
+ }
+ });
+ } else {
+ this._setStates(folderItem, states);
+ }
+ }
+ return states;
+ }
+
+ public setSelectedFolder(folderItem: FoldersItemsMenu): void {
+ this.folders.setSelected(folderItem);
+ }
+
+ public goToComponent(component: Component): void {
+ const loaderService = this.loaderService;
+ loaderService.activate();
+ this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()}).then(() => {
+ loaderService.deactivate();
+ });
+ }
+
+ public raiseNumberOfElementToDisplay(recalculate: boolean = false) {
+ const scrollPageAmount = 35;
+ if (!this.homeItems) {
+ this.numberOfItemToDisplay = 0;
+ } else if (this.homeItems.length > this.numberOfItemToDisplay || recalculate) {
+ let fullPagesAmount = Math.ceil(this.numberOfItemToDisplay / scrollPageAmount) * scrollPageAmount;
+ if (!recalculate || fullPagesAmount === 0) { // TODO trigger infiniteScroll to check bottom and fire onBottomHit by itself (sdc-ui)
+ fullPagesAmount += scrollPageAmount;
+ }
+ this.numberOfItemToDisplay = Math.min(this.homeItems.length, fullPagesAmount);
+ this.homeFilteredSlicedItems = this.homeFilteredItems.slice(0, this.numberOfItemToDisplay);
+ }
+ }
+
+ public changeCheckboxesFilter(checkboxesFilterArray: string[], checkboxValue: string, checked?: boolean) {
+ const checkboxIdx = checkboxesFilterArray.indexOf(checkboxValue);
+
+ checked = (checked !== undefined) ? checked : checkboxIdx === -1;
+ if (checked && checkboxIdx === -1) {
+ checkboxesFilterArray.push(checkboxValue);
+ } else if (!checked && checkboxIdx !== -1) {
+ checkboxesFilterArray.splice(checkboxIdx, 1);
+ }
+ this.updateFilter();
+ }
+
+ public changeFilterTerm(filterTerm: string): void {
+ this.homeFilter.search = { filterTerm };
+ this.updateFilter();
+ }
+
+ public setDisplayActions(display?: boolean) {
+ this.displayActions = display !== undefined ? display : !this.displayActions;
+ }
+
+ private _getTotalCounts(tmpFolder): number {
+ let total: number = 0;
+ if (tmpFolder.dist !== undefined) {
+ const distributions = tmpFolder.dist.split(',');
+ distributions.forEach((item: any) => {
+ total = total + this.getEntitiesByStateDist(tmpFolder.state, item).length;
+ });
+ } else {
+ total = total + this.getEntitiesByStateDist(tmpFolder.state, tmpFolder.dist).length;
+ }
+ return total;
+ }
+
+ private _setStates(tmpFolder, states) {
+ if (tmpFolder.states !== undefined) {
+ tmpFolder.states.forEach((item: any) => {
+ states.push({state: item.state, dist: item.dist});
+ });
+ } else {
+ states.push({state: tmpFolder.state, dist: tmpFolder.dist});
+ }
+ }
+
+ private initEntities(reload?: boolean) {
+ if (reload || this.componentShouldReload()) {
+ this.loaderService.activate();
+ this.homeService.getAllComponents(true).subscribe(
+ (components: Component[]) => {
+ this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); // dashboard
+ this.cacheService.set('breadcrumbsComponents', components);
+ this.homeItems = components;
+ this.loaderService.deactivate();
+ this.filterHomeItems();
+ }, (error) => { this.loaderService.deactivate(); });
+ } else {
+ this.homeItems = this.cacheService.get('breadcrumbsComponents');
+ this.filterHomeItems();
+ }
+ }
+
+ private isDefaultFilter = (): boolean => {
+ const defaultFilter = new HomeFilter();
+ return angular.equals(defaultFilter, this.homeFilter);
+ }
+
+ private componentShouldReload = (): boolean => {
+ const breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
+ return !breadcrumbsValid || this.isDefaultFilter();
+ }
+
+ private getEntitiesByStateDist(state: string, dist: string): Component[] {
+ let gObj: Component[];
+ if (this.homeItems && (state || dist)) {
+ gObj = this.homeItems.filter((obj: Component) => {
+ if (dist !== undefined && obj.distributionStatus === dist && obj.lifecycleState === state) {
+ return true;
+ } else if (dist === undefined && (obj.lifecycleState === state || obj.distributionStatus === state)) {
+ return true;
+ }
+ return false;
+ });
+ } else {
+ gObj = [];
+ }
+ return gObj;
+ }
+
+ private filterHomeItems() {
+ this.homeFilteredItems = this.makeFilteredItems(this.homeItems, this.homeFilter);
+ this.raiseNumberOfElementToDisplay(true);
+ this.homeFilteredSlicedItems = this.homeFilteredItems.slice(0, this.numberOfItemToDisplay);
+ }
+
+ private makeFilteredItems(homeItems: Component[], filter: HomeFilter) {
+ let filteredComponents: Component[] = homeItems;
+
+ // filter: exclude all resources of type 'vfcmtType':
+ filteredComponents = filteredComponents.filter((c) =>
+ !c.isResource() || (c as Resource).resourceType.indexOf(this.vfcmtType) === -1);
+
+ // common entity filter
+ // --------------------------------------------------------------------------
+ filteredComponents = EntityFilterPipe.transform(filteredComponents, filter);
+
+ return filteredComponents;
+ }
+
+ private initFolders = (): void => {
+ // Note: Do not use SdcUi.ChecklistComponent for folders checkboxes, since from the data structure
+ // it is not determined that all checkboxes under the same group are managed by the same selectedValues array.
+ if (this.user) {
+ this.folders = new FoldersMenu(this.roles[this.user.role].folder);
+ }
+ }
+
+ private initHomeComponentVars(): void {
+ this.version = this.cacheService.get('version');
+ this.numberOfItemToDisplay = 0;
+ this.displayActions = false;
+ this.user = this.authService.getLoggedinUser();
+ this.roles = this.sdcMenu.roles;
+ this.showTutorial = false;
+ this.isFirstTime = false;
+ this.vfcmtType = ResourceType.VFCMT;
+
+ // Checkboxes filter init
+ this.homeFilter = new HomeFilter(this.$state.params);
+
+ // bind callbacks that are transferred as inputs
+ this.notificationIconCallback = this.notificationIconCallback.bind(this);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/home/home.module.ts b/catalog-ui/src/app/ng2/pages/home/home.module.ts
new file mode 100644
index 0000000..3e7c0cd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/home/home.module.ts
@@ -0,0 +1,31 @@
+import { NgModule } from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { HomeComponent } from "./home.component";
+import { LayoutModule } from "../../components/layout/layout.module";
+import { UiElementsModule } from "../../components/ui/ui-elements.module";
+import { GlobalPipesModule } from "../../pipes/global-pipes.module";
+import { TranslateModule } from "../../shared/translator/translate.module";
+import { SdcUiComponentsModule } from "onap-ui-angular";
+
+@NgModule({
+ declarations: [
+ HomeComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ LayoutModule,
+ UiElementsModule,
+ GlobalPipesModule,
+ TranslateModule
+ ],
+ exports: [
+ HomeComponent
+ ],
+ entryComponents: [
+ HomeComponent
+ ],
+ providers: []
+})
+export class HomeModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts
index 6292d85..941b10f 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts
@@ -1,9 +1,9 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {InterfaceOperationComponent} from "./interface-operation.page.component";
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
import {TranslateModule} from "app/ng2/shared/translator/translate.module";
+import { SdcUiComponentsModule } from 'onap-ui-angular';
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
index e32a0b6..cd06e18 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
@@ -1,5 +1,5 @@
<!--
- ~ Copyright © 2016-2018 European Support Limited
+ ~ 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.
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
index c2a9582..9d41c37 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
@@ -1,14 +1,14 @@
import * as _ from "lodash";
-import {Component, Input, Output, ComponentRef, Inject} from '@angular/core';
-import {Component as IComponent} from 'app/models/components/component';
+import { Component, Input, Output, ComponentRef, Inject } from '@angular/core';
+import {Component as IComponent } from 'app/models/components/component';
-import {SdcConfigToken, ISdcConfig} from "app/ng2/config/sdc-config.config";
-import {TranslateService} from "app/ng2/shared/translator/translate.service";
+import { SdcConfigToken, ISdcConfig } from "app/ng2/config/sdc-config.config";
+import {TranslateService } from "app/ng2/shared/translator/translate.service";
-import {Observable} from "rxjs/Observable";
+import {Observable } from "rxjs/Observable";
-import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
-import {ModalService} from 'app/ng2/services/modal.service';
+import {ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
+import {ModalService } from 'app/ng2/services/modal.service';
import {
InputBEModel,
OperationModel,
@@ -18,15 +18,19 @@
Capability
} from 'app/models';
-import {IModalConfig, IModalButtonComponent} from "sdc-ui/lib/angular/modals/models/modal-config";
-import {SdcUiComponents} from "sdc-ui/lib/angular";
-import {ModalButtonComponent} from "sdc-ui/lib/angular/components";
+// import {SdcUiComponents } from 'sdc-ui/lib/angular';
+// import {ModalButtonComponent } from 'sdc-ui/lib/angular/components';
+// import { IModalButtonComponent, IModalConfig } from 'sdc-ui/lib/angular/modals/models/modal-config';
-import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
-import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
-import {PluginsService} from "app/ng2/services/plugins.service";
+import {ComponentServiceNg2 } from 'app/ng2/services/component-services/component.service';
+import {PluginsService } from 'app/ng2/services/plugins.service';
+import {WorkflowServiceNg2 } from 'app/ng2/services/workflow.service';
-import {OperationCreatorComponent, OperationCreatorInput} from 'app/ng2/pages/interface-operation/operation-creator/operation-creator.component';
+import { OperationCreatorComponent, OperationCreatorInput } from 'app/ng2/pages/interface-operation/operation-creator/operation-creator.component';
+import { IModalButtonComponent } from 'onap-ui-angular';
+import { ModalButtonComponent } from 'onap-ui-angular';
+import { IModalConfig } from 'onap-ui-angular';
+import { SdcUiServices } from 'onap-ui-angular';
export class UIOperationModel extends OperationModel {
isCollapsed: boolean = true;
@@ -61,6 +65,7 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
class ModalTranslation {
CREATE_TITLE: string;
EDIT_TITLE: string;
@@ -74,7 +79,7 @@
constructor(private TranslateService: TranslateService) {
this.TranslateService.languageChangedObservable.subscribe(lang => {
this.CREATE_TITLE = this.TranslateService.translate("INTERFACE_CREATE_TITLE");
- this.EDIT_TITLE = this.TranslateService.translate("INTERFACE_EDIT_TITLE");
+ this.EDIT_TITLE = this.TranslateService.translate('INTERFACE_EDIT_TITLE');
this.DELETE_TITLE = this.TranslateService.translate("INTERFACE_DELETE_TITLE");
this.CANCEL_BUTTON = this.TranslateService.translate("INTERFACE_CANCEL_BUTTON");
this.SAVE_BUTTON = this.TranslateService.translate("INTERFACE_SAVE_BUTTON");
@@ -85,6 +90,7 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
export class UIInterfaceModel extends InterfaceModel {
isCollapsed: boolean = false;
@@ -92,7 +98,7 @@
super(interf);
this.operations = _.map(
this.operations,
- operation => new UIOperationModel(operation)
+ (operation) => new UIOperationModel(operation)
);
}
@@ -101,6 +107,7 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
@Component({
selector: 'interface-operation',
templateUrl: './interface-operation.page.component.html',
@@ -110,16 +117,16 @@
export class InterfaceOperationComponent {
- interfaces: Array<UIInterfaceModel>;
+ interfaces: UIInterfaceModel[];
modalInstance: ComponentRef<ModalComponent>;
openOperation: OperationModel;
enableWorkflowAssociation: boolean;
- inputs: Array<InputBEModel>;
+ inputs: InputBEModel[];
isLoading: boolean;
- interfaceTypes:{ [interfaceType: string]: Array<string> };
+ interfaceTypes: { [interfaceType: string]: string[] };
modalTranslation: ModalTranslation;
workflowIsOnline: boolean;
- workflows: Array<any>;
+ workflows: any[];
capabilities: CapabilitiesGroup;
@Input() component: IComponent;
@@ -135,7 +142,8 @@
private ComponentServiceNg2: ComponentServiceNg2,
private WorkflowServiceNg2: WorkflowServiceNg2,
private ModalServiceNg2: ModalService,
- private ModalServiceSdcUI: SdcUiComponents.ModalService
+ private ModalServiceSdcUI: SdcUiServices.ModalService
+
) {
this.enableWorkflowAssociation = sdcConfig.enableWorkflowAssociation;
this.modalTranslation = new ModalTranslation(TranslateService);
@@ -146,11 +154,11 @@
this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner'));
Observable.forkJoin(
- this.ComponentServiceNg2.getInterfaces(this.component),
+ this.ComponentServiceNg2.getInterfaceOperations(this.component),
this.ComponentServiceNg2.getComponentInputs(this.component),
this.ComponentServiceNg2.getInterfaceTypes(this.component),
this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId)
- ).subscribe((response: Array<any>) => {
+ ).subscribe((response: any[]) => {
const callback = (workflows) => {
this.isLoading = false;
this.initInterfaces(response[0].interfaces);
@@ -174,36 +182,36 @@
});
}
- initInterfaces(interfaces: Array<InterfaceModel>): void {
- this.interfaces = _.map(interfaces, interf => new UIInterfaceModel(interf));
+ initInterfaces(interfaces: InterfaceModel[]): void {
+ this.interfaces = _.map(interfaces, (interf) => new UIInterfaceModel(interf));
}
sortInterfaces(): void {
- this.interfaces = _.filter(this.interfaces, interf => interf.operations && interf.operations.length > 0); // remove empty interfaces
+ this.interfaces = _.filter(this.interfaces, (interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces
this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically
- _.forEach(this.interfaces, interf => {
+ _.forEach(this.interfaces, (interf) => {
interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically
});
}
collapseAll(value: boolean = true): void {
- _.forEach(this.interfaces, interf => {
+ _.forEach(this.interfaces, (interf) => {
interf.isCollapsed = value;
});
}
isAllCollapsed(): boolean {
- return _.every(this.interfaces, interf => interf.isCollapsed);
+ return _.every(this.interfaces, (interf) => interf.isCollapsed);
}
isAllExpanded(): boolean {
- return _.every(this.interfaces, interf => !interf.isCollapsed);
+ return _.every(this.interfaces, (interf) => !interf.isCollapsed);
}
isListEmpty(): boolean {
return _.filter(
this.interfaces,
- interf => interf.operations && interf.operations.length > 0
+ (interf) => interf.operations && interf.operations.length > 0
).length === 0;
}
@@ -291,11 +299,6 @@
}
- private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
- let saveButton: ModalButtonComponent = this.ModalServiceSdcUI.getCurrentInstance().getButtonById('saveButton');
- saveButton.disabled = !shouldEnable;
- }
-
onRemoveOperation = (event: Event, operation: OperationModel): void => {
event.stopPropagation();
@@ -303,11 +306,11 @@
this.ComponentServiceNg2
.deleteInterfaceOperation(this.component, operation)
.subscribe(() => {
- const curInterf = _.find(this.interfaces, interf => interf.type === operation.interfaceType);
- const index = _.findIndex(curInterf.operations, el => el.uniqueId === operation.uniqueId);
+ const curInterf = _.find(this.interfaces, (interf) => interf.type === operation.interfaceType);
+ const index = _.findIndex(curInterf.operations, (el) => el.uniqueId === operation.uniqueId);
curInterf.operations.splice(index, 1);
if (!curInterf.operations.length) {
- const interfIndex = _.findIndex(this.interfaces, interf => interf.type === operation.interfaceType);
+ const interfIndex = _.findIndex(this.interfaces, (interf) => interf.type === operation.interfaceType);
this.interfaces.splice(interfIndex, 1);
}
});
@@ -322,13 +325,18 @@
);
}
+ private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
+ const saveButton: ModalButtonComponent = this.ModalServiceSdcUI.getCurrentInstance().getButtonById('saveButton');
+ saveButton.disabled = !shouldEnable;
+ }
+
private createOperation = (operation: OperationModel): void => {
this.ComponentServiceNg2.createInterfaceOperation(this.component, operation).subscribe((response: OperationModel) => {
this.openOperation = null;
let curInterf = _.find(
this.interfaces,
- interf => interf.type === operation.interfaceType
+ (interf) => interf.type === operation.interfaceType
);
if (!curInterf) {
@@ -358,18 +366,19 @@
this.ComponentServiceNg2.updateInterfaceOperation(this.component, operation).subscribe((newOperation: OperationModel) => {
this.openOperation = null;
- let oldOpIndex, oldInterf;
- _.forEach(this.interfaces, interf => {
- _.forEach(interf.operations, op => {
+ let oldOpIndex;
+ let oldInterf;
+ _.forEach(this.interfaces, (interf) => {
+ _.forEach(interf.operations, (op) => {
if (op.uniqueId === newOperation.uniqueId) {
oldInterf = interf;
- oldOpIndex = _.findIndex(interf.operations, el => el.uniqueId === op.uniqueId);
+ oldOpIndex = _.findIndex(interf.operations, (el) => el.uniqueId === op.uniqueId);
}
})
});
oldInterf.operations.splice(oldOpIndex, 1);
- const newInterf = _.find(this.interfaces, interf => interf.type === operation.interfaceType);
+ const newInterf = _.find(this.interfaces, (interf) => interf.type === operation.interfaceType);
const newOpModel = new UIOperationModel(newOperation);
newInterf.operations.push(newOpModel);
this.sortInterfaces();
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
index ec056ad..df2a505 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
@@ -180,6 +180,9 @@
<span class="bold-message">{{ 'EMPTY_PARAM_TABLE_NO_SELECTED_WORKFLOW_1' | translate }}</span>
<span>{{ 'EMPTY_PARAM_TABLE_NO_SELECTED_WORKFLOW_2' | translate }}</span>
</div>
+ <div *ngIf="!workflows.length">
+ Only <span class="bold-message">certified</span> workflow versions can be assigned to an operation
+ </div>
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
index f2bd0f8..2721d30 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
@@ -11,7 +11,7 @@
font-size: 12px;
}
- .w-sdc-form .form-item {
+ .w-sdc-form .i-sdc-form-item {
margin-bottom: 15px;
}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
index e129056..12fba24 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
@@ -15,9 +15,9 @@
Capability
} from 'app/models';
-import {IDropDownOption} from "sdc-ui/lib/angular/form-elements/dropdown/dropdown-models";
import {Tabs, Tab} from "app/ng2/components/ui/tabs/tabs.component";
import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import { IDropDownOption } from 'onap-ui-angular';
export class DropDownOption implements IDropDownOption {
value: string;
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts
index 0b6f833..b91f3aa 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts
@@ -3,10 +3,10 @@
import {FormsModule} from "@angular/forms";
import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
import {TranslateModule} from "app/ng2/shared/translator/translate.module";
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+import { UiElementsModule } from '../../../components/ui/ui-elements.module';
import {OperationCreatorComponent} from "./operation-creator.component";
import {ParamRowComponent} from './param-row/param-row.component';
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
index 4a4782e..b8173ea 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
@@ -1,5 +1,5 @@
<!--
- ~ Copyright © 2016-2018 European Support Limited
+ ~ 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.
@@ -13,7 +13,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
+
<div class="cell field-name">
<ui-element-input
*ngIf="!isAssociateWorkflow"
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
index f6cda17..5447fe5 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
@@ -32,6 +32,7 @@
input {
height: 30px;
+ border: none;
padding-left: 10px;
}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
index d32edc7..de6e703 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
@@ -1,4 +1,5 @@
import {Component, Input} from '@angular/core';
+import {PROPERTY_DATA} from "app/utils";
import {DataTypeService} from "app/ng2/services/data-type.service";
import {OperationModel, OperationParameter, InputBEModel, DataTypeModel, Capability} from 'app/models';
import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
@@ -36,7 +37,7 @@
filteredInputProps: Array<DropdownValue> = [];
filteredCapabilitiesProps: Array<{capabilityName: string, properties: Array<DropdownValueType>}> = [];
- constructor(private dataTypeService: DataTypeService) {}
+ constructor(private dataTypeService:DataTypeService) {}
ngOnInit() {
if (this.isInputParam) {
diff --git a/catalog-ui/src/app/ng2/pages/page404/page404.component.html b/catalog-ui/src/app/ng2/pages/page404/page404.component.html
index 278ab4d..a9335a5 100644
--- a/catalog-ui/src/app/ng2/pages/page404/page404.component.html
+++ b/catalog-ui/src/app/ng2/pages/page404/page404.component.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="page404">
Page404
</div>
diff --git a/catalog-ui/src/app/ng2/pages/plugin-not-connected/plugin-not-connected.component.html b/catalog-ui/src/app/ng2/pages/plugin-not-connected/plugin-not-connected.component.html
index 98e896f..0f8aeb3 100644
--- a/catalog-ui/src/app/ng2/pages/plugin-not-connected/plugin-not-connected.component.html
+++ b/catalog-ui/src/app/ng2/pages/plugin-not-connected/plugin-not-connected.component.html
@@ -13,8 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-
<div class="plugin-not-connected">
<div class="plugin-error-message">
<div class="icon-wrapper">
diff --git a/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.html b/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.html
new file mode 100644
index 0000000..85e83c4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.html
@@ -0,0 +1,4 @@
+<div class="workspace-plugins">
+ <plugin-frame (onLoadingDone)="onLoadingDone(plugin)" [plugin]="plugin" [queryParams]="queryParams"></plugin-frame>
+ <loader [display]="isLoading && plugin.isOnline" ></loader>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context.less b/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.less
similarity index 100%
rename from catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context.less
rename to catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.less
diff --git a/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.ts b/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.ts
new file mode 100644
index 0000000..21aa858
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/plugins/plugin-context-view/plugin-context-view.page.component.ts
@@ -0,0 +1,58 @@
+import {Component, Inject} from "@angular/core";
+import {Component as ComponentData, IUserProperties, Plugin} from "app/models";
+import {CacheService, PluginsService} from "app/services-ng2";
+
+
+@Component({
+ selector: 'plugin-context-view',
+ templateUrl: './plugin-context-view.page.component.html',
+ styleUrls: ['./plugin-context-view.page.component.less']
+})
+
+export class PluginContextViewPageComponent {
+ plugin: Plugin;
+ user: IUserProperties;
+ queryParams: Object;
+ isLoading: boolean;
+ show: boolean;
+ component: ComponentData;
+
+ constructor(@Inject("$stateParams") private _stateParams,
+ private cacheService: CacheService,
+ private pluginsService: PluginsService) {
+
+ this.show = false;
+ this.component = this._stateParams.component;
+ this.plugin = this.pluginsService.getPluginByStateUrl(_stateParams.path);
+ this.user = this.cacheService.get('user');
+ }
+
+ ngOnInit() {
+ this.isLoading = true;
+
+ this.queryParams = {
+ userId: this.user.userId,
+ userRole: this.user.role,
+ displayType: "context",
+ contextType: this.component.getComponentSubType(),
+ uuid: this.component.uuid,
+ lifecycleState: this.component.lifecycleState,
+ isOwner: this.component.lastUpdaterUserId === this.user.userId,
+ version: this.component.version,
+ parentUrl: window.location.origin,
+ eventsClientId: this.plugin.pluginId
+ };
+
+ if (this._stateParams.queryParams) {
+ _.assign(this.queryParams, this._stateParams.queryParams);
+ }
+ }
+
+ onLoadingDone(plugin: Plugin) {
+ if (plugin.pluginId == this.plugin.pluginId) {
+ this.isLoading = false;
+ }
+ }
+
+
+}
diff --git a/catalog-ui/src/app/view-models/plugins/plugins-tab-view.html b/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.html
similarity index 75%
rename from catalog-ui/src/app/view-models/plugins/plugins-tab-view.html
rename to catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.html
index 50c5766..5ce95d1 100644
--- a/catalog-ui/src/app/view-models/plugins/plugins-tab-view.html
+++ b/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.html
@@ -13,9 +13,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="sdc-catalog-container plugins-tab-container">
- <loader display="isLoading"></loader>
- <top-nav [version]="version" [hide-search]="true"></top-nav>
- <plugin-frame (on-loading-done)="onLoadingDone(plugin)" [plugin]="plugin" [query-params]="queryParams"></plugin-frame>
+ <top-nav [version]="version" [hideSearch]="true"></top-nav>
+ <plugin-frame (onLoadingDone)="onLoadingDone(plugin)" [plugin]="plugin" [queryParams]="queryParams"></plugin-frame>
+ <loader [display]="isLoading"></loader>
</div>
diff --git a/catalog-ui/src/app/view-models/plugins/plugins-tab.less b/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.less
similarity index 100%
rename from catalog-ui/src/app/view-models/plugins/plugins-tab.less
rename to catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.less
diff --git a/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.ts b/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.ts
new file mode 100644
index 0000000..7ba8474
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/plugins/plugin-tab-view/plugin-tab-view.page.component.ts
@@ -0,0 +1,45 @@
+import {Component, Inject} from "@angular/core";
+import {IUserProperties, Plugin} from "app/models";
+import {CacheService, PluginsService} from "app/services-ng2";
+
+@Component({
+ selector: 'plugin-tab-view',
+ templateUrl: './plugin-tab-view.page.component.html',
+ styleUrls: ['./plugin-tab-view.page.component.less']
+})
+
+export class PluginTabViewPageComponent {
+ plugin: Plugin;
+ user: IUserProperties;
+ version: string;
+ queryParams: Object;
+ isLoading: boolean;
+
+ constructor(@Inject("$stateParams") private _stateParams,
+ private cacheService: CacheService,
+ private pluginsService: PluginsService) {
+
+ this.plugin = this.pluginsService.getPluginByStateUrl(_stateParams.path);
+ this.version = this.cacheService.get('version');
+ this.user = this.cacheService.get('user');
+ }
+
+ ngOnInit() {
+ this.isLoading = true;
+
+ this.queryParams = {
+ userId: this.user.userId,
+ userRole: this.user.role,
+ displayType: "tab",
+ parentUrl: window.location.origin,
+ eventsClientId: this.plugin.pluginId
+ };
+
+ }
+
+ onLoadingDone(plugin: Plugin) {
+ if (plugin.pluginId == this.plugin.pluginId) {
+ this.isLoading = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/plugins/plugins-module.ts b/catalog-ui/src/app/ng2/pages/plugins/plugins-module.ts
new file mode 100644
index 0000000..763e329
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/plugins/plugins-module.ts
@@ -0,0 +1,34 @@
+import {NgModule} from "@angular/core";
+import {PluginContextViewPageComponent} from "./plugin-context-view/plugin-context-view.page.component";
+import {PluginFrameModule} from "../../components/ui/plugin/plugin-frame.module";
+import {CommonModule} from "@angular/common";
+import {UiElementsModule} from "../../components/ui/ui-elements.module";
+import {PluginTabViewPageComponent} from "./plugin-tab-view/plugin-tab-view.page.component";
+import {LayoutModule} from "../../components/layout/layout.module";
+import {HttpModule} from "@angular/http";
+
+@NgModule({
+ declarations: [
+ PluginContextViewPageComponent,
+ PluginTabViewPageComponent
+ ],
+ imports: [
+ CommonModule,
+ PluginFrameModule,
+ UiElementsModule,
+ LayoutModule,
+ HttpModule
+ ],
+ exports: [
+ PluginContextViewPageComponent,
+ PluginTabViewPageComponent
+ ],
+ entryComponents: [
+ PluginContextViewPageComponent,
+ PluginTabViewPageComponent
+ ]
+})
+export class PluginsModule {
+
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts
index 20e04f8..fe31066 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts
@@ -18,97 +18,95 @@
* ============LICENSE_END=========================================================
*/
-import * as _ from "lodash";
-import {Component} from '@angular/core';
-import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
-import { DataTypeService } from "app/ng2/services/data-type.service";
-import {PropertyBEModel, DataTypesMap} from "app/models";
-import {PROPERTY_DATA} from "app/utils";
-import {PROPERTY_TYPES} from "../../../../utils";
-import { ModalService } from "app/ng2/services/modal.service";
-import { InstancePropertiesAPIMap } from "app/models/properties-inputs/property-fe-map";
-import { ModalModel } from "app/models/modal";
-import { DataTypeModel } from "app/models/data-types";
-
-
+import { Component } from '@angular/core';
+import { DataTypesMap, PropertyBEModel } from 'app/models';
+import { DataTypeModel } from 'app/models/data-types';
+import { ModalModel } from 'app/models/modal';
+import { InstancePropertiesAPIMap } from 'app/models/properties-inputs/property-fe-map';
+import { DropdownValue } from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
+import { DataTypeService } from 'app/ng2/services/data-type.service';
+import { ModalService } from 'app/ng2/services/modal.service';
+import { PROPERTY_DATA } from 'app/utils';
+import * as _ from 'lodash';
+import { PROPERTY_TYPES } from '../../../../utils';
@Component({
selector: 'declare-list',
templateUrl: './declare-list.component.html',
- styleUrls:['./declare-list.component.less'],
+ styleUrls: ['./declare-list.component.less'],
})
export class DeclareListComponent {
- typesProperties: Array<DropdownValue>;
- typesSchemaProperties: Array<DropdownValue>;
+ typesProperties: DropdownValue[];
+ typesSchemaProperties: DropdownValue[];
propertyModel: PropertyBEModel;
- //propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/;
- //commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/;
- //types:Array<string>;
- dataTypes:DataTypesMap;
- isLoading:boolean;
- inputsToCreate:InstancePropertiesAPIMap;
- propertiesListString:string;
+ // propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/;
+ // commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/;
+ // types:Array<string>;
+ dataTypes: DataTypesMap;
+ isLoading: boolean;
+ inputsToCreate: InstancePropertiesAPIMap;
+ propertiesListString: string;
privateDataType: DataTypeModel;
- constructor(protected dataTypeService:DataTypeService, private modalService:ModalService) {}
+ constructor(protected dataTypeService: DataTypeService, private modalService: ModalService) {}
ngOnInit() {
console.log('DeclareListComponent.ngOnInit() - enter');
this.propertyModel = new PropertyBEModel();
this.propertyModel.type = '';
this.propertyModel.schema.property.type = '';
- const types: Array<string> = PROPERTY_DATA.TYPES; //All types - simple type + map + list
- this.dataTypes = this.dataTypeService.getAllDataTypes(); //Get all data types in service
- const nonPrimitiveTypes :Array<string> = _.filter(Object.keys(this.dataTypes), (type:string)=> {
- return types.indexOf(type) == -1;
+ const types: string[] = PROPERTY_DATA.TYPES; // All types - simple type + map + list
+ this.dataTypes = this.dataTypeService.getAllDataTypes(); // Get all data types in service
+ const nonPrimitiveTypes: string[] = _.filter(Object.keys(this.dataTypes), (type: string) => {
+ return types.indexOf(type) === -1;
});
this.typesProperties = _.map(PROPERTY_DATA.TYPES,
(type: string) => new DropdownValue(type, type)
);
- let typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES,
+ const typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES,
(type: string) => new DropdownValue(type, type)
);
- let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes,
+ const nonPrimitiveTypesValues = _.map(nonPrimitiveTypes,
(type: string) => new DropdownValue(type,
- type.replace("org.openecomp.datatypes.heat.",""))
+ type.replace('org.openecomp.datatypes.heat.',""))
);
- this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues);
- this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues);
- this.typesProperties.unshift(new DropdownValue('','Select Type...'));
- this.typesSchemaProperties.unshift(new DropdownValue('','Select Schema Type...'));
+ this.typesProperties = _.concat(this.typesProperties, nonPrimitiveTypesValues);
+ this.typesSchemaProperties = _.concat(typesSimpleProperties, nonPrimitiveTypesValues);
+ this.typesProperties.unshift(new DropdownValue('', 'Select Type...'));
+ this.typesSchemaProperties.unshift(new DropdownValue('', 'Select Schema Type...'));
this.inputsToCreate = this.modalService.currentModal.instance.dynamicContent.instance.input.properties;
this.propertiesListString = this.modalService.currentModal.instance.dynamicContent.instance.input.propertyNameList.join(", ");
this.privateDataType = new DataTypeModel(null);
- this.privateDataType.name = "datatype";
+ this.privateDataType.name = 'datatype';
console.log('DeclareListComponent.ngOnInit() - leave');
}
- checkFormValidForSubmit(){
- const showSchema:boolean = this.showSchema();
- let isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type)? false : true;
- if (!showSchema){
+ checkFormValidForSubmit() {
+ const showSchema: boolean = this.showSchema();
+ const isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type) ? false : true;
+ if (!showSchema) {
this.propertyModel.schema.property.type = '';
}
return this.propertyModel.name && this.propertyModel.type && isSchemaValid;
}
- showSchema():boolean {
+ showSchema(): boolean {
return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.propertyModel.type) > -1;
- };
+ }
- onSchemaTypeChange():void {
- if (this.propertyModel.type == PROPERTY_TYPES.MAP) {
+ onSchemaTypeChange(): void {
+ if (this.propertyModel.type === PROPERTY_TYPES.MAP) {
this.propertyModel.value = JSON.stringify({'': null});
- } else if (this.propertyModel.type == PROPERTY_TYPES.LIST) {
+ } else if (this.propertyModel.type === PROPERTY_TYPES.LIST) {
this.propertyModel.value = JSON.stringify([]);
}
- };
+ }
}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts
index 54af76a..97667f9 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts
@@ -18,13 +18,13 @@
* ============LICENSE_END=========================================================
*/
-import {NgModule} from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {DeclareListComponent} from "./declare-list.component";
-import {FormsModule} from "@angular/forms";
-import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {TranslateModule} from "../../../shared/translator/translate.module";
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-elements.module';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from '../../../shared/translator/translate.module';
+import { DeclareListComponent } from './declare-list.component';
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts
index c46d617..f5500d4 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts
@@ -19,7 +19,6 @@
*/
import { NgModule } from "@angular/core";
import {HierarchyNavigationComponent} from "../../components/logic/hierarchy-navigtion/hierarchy-navigation.component";
-import {HttpModule} from "@angular/http";
import {FormsModule} from "@angular/forms";
import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module";
import {UiElementsModule} from "../../components/ui/ui-elements.module";
@@ -46,12 +45,11 @@
imports: [
BrowserModule,
FormsModule,
- HttpModule,
GlobalPipesModule,
PropertyTableModule,
PoliciesTableModule,
UiElementsModule],
-
+
entryComponents: [PropertiesAssignmentComponent],
exports: [
PropertiesAssignmentComponent
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
index 580c362..8d4215a 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
@@ -18,7 +18,7 @@
<div class="main-content">
<div class="left-column">
<div class="main-tabs-section">
- <tabs #propertyInputTabs tabStyle="round-tabs" (tabChanged)="tabChanged($event)" [hideIndicationOnTabChange]="true">
+ <tabs #propertyInputTabs tabStyle="round-tabs" (tabChanged)="tabChanged($event)" [hideIndicationOnTabChange]="true" >
<tab tabTitle="Properties">
<properties-table class="properties-table"
[fePropertiesMap]="instanceFePropertiesMap"
@@ -42,12 +42,13 @@
</tab>
<tab tabTitle="Inputs">
<inputs-table class="properties-table"
- [readonly]="isReadonly"
- [inputs]="inputs | searchFilter:'name':searchQuery"
- [instanceNamesMap]="componentInstanceNamesMap"
- [isLoading]="loadingInputs"
- (deleteInput)="deleteInput($event)"
- (inputChanged)="dataChanged($event)">
+ [fePropertiesMap]="instanceFePropertiesMap"
+ [readonly]="isReadonly"
+ [inputs]="inputs | searchFilter:'name':searchQuery"
+ [instanceNamesMap]="componentInstanceNamesMap"
+ [isLoading]="loadingInputs"
+ (deleteInput)="deleteInput($event)"
+ (inputChanged)="dataChanged($event)">
</inputs-table>
</tab>
<tab tabTitle="Policies">
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less
index 855bdc5..a1309ab 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less
@@ -133,13 +133,12 @@
flex-direction:column;
margin: 0px 0 0 1em;
overflow-x:auto;
- .add-btn{
+ .add-btn{
align-self: flex-end;
margin-top: 10px;
margin-bottom: 19px;
}
-
/deep/ .tabs {
border-bottom: solid 1px #d0d0d0;
}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
index 0614398..4b84f0e 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
@@ -19,58 +19,34 @@
*/
import * as _ from "lodash";
-import {Component, ViewChild, Inject, TemplateRef} from "@angular/core";
+import { Component, ViewChild, Inject, TemplateRef } from "@angular/core";
import { PropertiesService } from "../../services/properties.service";
-import {
- PropertyFEModel,
- InstanceFePropertiesMap,
- InstanceBePropertiesMap,
- InstancePropertiesAPIMap,
- Component as ComponentData,
- FilterPropertiesAssignmentData,
- ModalModel,
- ButtonModel,
- Capability,
- ToscaPresentationData
-} from "app/models";
+import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData, ModalModel, ButtonModel } from "app/models";
import { ResourceType } from "app/utils";
-import {ComponentServiceNg2} from "../../services/component-services/component.service";
-import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
-import {
- InputBEModel,
- InputFEModel,
- ComponentInstance,
- GroupInstance,
- PolicyInstance,
- PropertyBEModel,
- DerivedFEProperty,
- SimpleFlatProperty,
- CapabilitiesGroup
-} from "app/models";
+import { ComponentServiceNg2 } from "../../services/component-services/component.service";
+import { TopologyTemplateService } from "../../services/component-services/topology-template.service";
+import { ComponentInstanceServiceNg2 } from "../../services/component-instance-services/component-instance.service"
+import { InputBEModel, InputFEModel, ComponentInstance, GroupInstance, PolicyInstance, PropertyBEModel, DerivedFEProperty, SimpleFlatProperty } from "app/models";
import { KeysPipe } from 'app/ng2/pipes/keys.pipe';
-import {WorkspaceMode, EVENTS} from "../../../utils/constants";
-import {EventListenerService} from "app/services/event-listener-service"
-import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
-import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
-import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
-import {HierarchyNavService} from "./services/hierarchy-nav.service";
-import {PropertiesUtils} from "./services/properties.utils";
-import {ComponentModeService} from "../../services/component-services/component-mode.service";
-import {ModalService} from "../../services/modal.service";
-import {Tabs, Tab} from "../../components/ui/tabs/tabs.component";
-import {InputsUtils} from "./services/inputs.utils";
-import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
-import {DeclareListComponent} from "./declare-list/declare-list.component";
+import { WorkspaceMode, EVENTS, PROPERTY_TYPES } from "../../../utils/constants";
+import { EventListenerService } from "app/services/event-listener-service"
+import { HierarchyDisplayOptions } from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
+import { FilterPropertiesAssignmentComponent } from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
+import { PropertyRowSelectedEvent } from "../../components/logic/properties-table/properties-table.component";
+import { HierarchyNavService } from "./services/hierarchy-nav.service";
+import { PropertiesUtils } from "./services/properties.utils";
+import { ComponentModeService } from "../../services/component-services/component-mode.service";
+import { Tabs, Tab } from "../../components/ui/tabs/tabs.component";
+import { InputsUtils } from "./services/inputs.utils";
import { InstanceFeDetails } from "../../../models/instance-fe-details";
-import { SdcUiComponents } from "sdc-ui/lib/angular";
-//import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service";
-import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config";
+import { SdcUiServices, SdcUiCommon } from "onap-ui-angular";
import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
-import {Observable} from "rxjs";
-import { DataTypeService } from "app/ng2/services/data-type.service";
-import { DataTypeModel } from "app/models";
-import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils";
-import { PropertyDeclareAPIModel} from "app/models";
+import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
+import {ModalService} from "../../services/modal.service";
+import { DeclareListComponent } from "./declare-list/declare-list.component";
+import { CapabilitiesGroup, Capability } from "../../../models/capability";
+import { ToscaPresentationData } from "../../../models/tosca-presentation";
+import { Observable } from "rxjs";
const SERVICE_SELF_TITLE = "SELF";
@Component({
@@ -119,7 +95,7 @@
stateChangeStartUnregister:Function;
serviceBePropertiesMap: InstanceBePropertiesMap;
serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
- selectedInstance_FlattenCapabilitiesList: Array<Capability>;
+ selectedInstance_FlattenCapabilitiesList: Capability[];
@ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
@ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
@@ -136,12 +112,13 @@
@Inject("$state") private $state:ng.ui.IStateService,
@Inject("Notification") private Notification:any,
private componentModeService:ComponentModeService,
- private ModalService:ModalService,
private EventListenerService:EventListenerService,
- private ModalServiceSdcUI: SdcUiComponents.ModalService) {
+ private ModalServiceSdcUI: SdcUiServices.ModalService,
+ private ModalService: ModalService,
+ private keysPipe:KeysPipe,
+ private topologyTemplateService: TopologyTemplateService) {
this.instanceFePropertiesMap = new InstanceFePropertiesMap();
-
/* This is the way you can access the component data, please do not use any data except metadata, all other data should be received from the new api calls on the first time
than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
this.component = _stateParams.component;
@@ -159,8 +136,8 @@
this.loadingPolicies = true;
this.loadingInstances = true;
this.loadingProperties = true;
- this.componentServiceNg2
- .getComponentInputsWithProperties(this.component)
+ this.topologyTemplateService
+ .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
.subscribe(response => {
_.forEach(response.inputs, (input: InputBEModel) => {
const newInput: InputFEModel = new InputFEModel(input);
@@ -169,7 +146,7 @@
});
this.loadingInputs = false;
- });
+ }, error => {}); //ignore error
this.componentServiceNg2
.getComponentResourcePropertiesData(this.component)
.subscribe(response => {
@@ -177,6 +154,7 @@
this.instances = [];
this.instances.push(...response.componentInstances);
this.instances.push(...response.groupInstances);
+ this.instances.push(...response.policies);
_.forEach(response.policies, (policy: any) => {
const newPolicy: InputFEModel = new InputFEModel(policy);
@@ -199,7 +177,7 @@
this.loadingProperties = false;
}
this.selectFirstInstanceByDefault();
- });
+ }, error => { this.loadingInstances = false; }); //ignore error
this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
// stop if has changed properties
@@ -238,14 +216,14 @@
getServiceProperties(){
this.loadingProperties = false;
- this.componentServiceNg2
- .getServiceProperties(this.component)
- .subscribe(response => {
+ this.topologyTemplateService
+ .getServiceProperties(this.component.uniqueId)
+ .subscribe((response) => {
this.serviceBePropertiesMap = new InstanceBePropertiesMap();
this.serviceBePropertiesMap[this.component.uniqueId] = response;
this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
this.loadingProperties = false;
- }, error => {
+ }, (error) => {
this.loadingProperties = false;
});
}
@@ -267,14 +245,12 @@
this.loadingProperties = true;
if (instance instanceof ComponentInstance) {
let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
- this.selectedInstance_FlattenCapabilitiesList = instance.capabilities ? CapabilitiesGroup.getFlattenedCapabilities(instance.capabilities) : [];
if (this.isInput(instance.originType)) {
this.componentInstanceServiceNg2
.getComponentInstanceInputs(this.component, instance)
.subscribe(response => {
instanceBePropertiesMap[instance.uniqueId] = response;
this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
- this.processInstanceCapabilitiesPropertiesResponse(false);
this.loadingProperties = false;
}, error => {
}); //ignore error
@@ -286,7 +262,6 @@
.subscribe(response => {
instanceBePropertiesMap[instance.uniqueId] = response;
this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
- this.processInstanceCapabilitiesPropertiesResponse(false);
this.loadingProperties = false;
}, error => {
}); //ignore error
@@ -305,7 +280,7 @@
} else if (instance instanceof PolicyInstance) {
let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
this.componentInstanceServiceNg2
- .getComponentPolicyInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
+ .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
.subscribe((response) => {
instanceBePropertiesMap[instance.uniqueId] = response;
this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
@@ -480,7 +455,7 @@
let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
- let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
+ let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
angular.forEach(instancesIds, (instanceId: string): void => {
let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
@@ -500,7 +475,7 @@
let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
- //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
+ //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
(inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
_.filter(
@@ -526,15 +501,14 @@
}
}
);
-
- this.componentServiceNg2
+ this.topologyTemplateService
.createInput(this.component, inputsToCreate, this.isSelf())
- .subscribe(response => {
+ .subscribe((response) => {
this.setInputTabIndication(response.length);
this.checkedPropertiesCount = 0;
this.checkedChildPropertiesCount = 0;
_.forEach(response, (input: InputBEModel) => {
- let newInput: InputFEModel = new InputFEModel(input);
+ const newInput: InputFEModel = new InputFEModel(input);
this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
this.inputs.push(newInput);
this.updatePropertyValueAfterDeclare(newInput);
@@ -628,8 +602,8 @@
};
console.log("save button clicked. input=", input);
- this.componentServiceNg2
- .createListInput(this.component, input, this.isSelf())
+ this.topologyTemplateService
+ .createListInput(this.component.uniqueId, input, this.isSelf())
.subscribe(response => {
this.setInputTabIndication(response.length);
this.checkedPropertiesCount = 0;
@@ -662,8 +636,8 @@
console.log('declareListProperties() - leave');
};
- /*** DECLARE PROPERTIES/POLICIES ***/
- declarePropertiesToPolicies = (): void => {
+ /*** DECLARE PROPERTIES/POLICIES ***/
+ declarePropertiesToPolicies = (): void => {
let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
@@ -679,7 +653,7 @@
let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
this.loadingPolicies = true;
- this.componentServiceNg2
+ this.topologyTemplateService
.createPolicy(this.component, policiesToCreate, this.isSelf())
.subscribe(response => {
this.setPolicyTabIndication(response.length);
@@ -688,7 +662,7 @@
this.loadingPolicies = false;
}); //ignore error
- };
+ }
displayPoliciesAsDeclared = (policies) => {
_.forEach(policies, (policy: any) => {
@@ -699,8 +673,7 @@
this.updatePropertyValueAfterDeclare(newPolicy);
this.policies.push(policy);
});
- };
-
+ }
saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
return new Promise((resolve, reject) => {
@@ -736,7 +709,8 @@
if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
request = Observable.forkJoin(
this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
- this.componentInstanceServiceNg2.updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
+ this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
+ this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
);
}
else if (changedInputsProperties.length) {
@@ -745,7 +719,7 @@
}
else if (changedCapabilitiesProperties.length) {
request = this.componentInstanceServiceNg2
- .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
+ .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
}
handleSuccess = (response) => {
// reset each changed property with new value and remove it from changed properties list
@@ -757,19 +731,18 @@
};
} else {
if (this.isSelf()) {
- request = this.componentServiceNg2.updateServiceProperties(this.component, _.map(changedProperties, cp => {
+ request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
delete cp.constraints;
return cp;
}));
} else {
request = this.componentInstanceServiceNg2
- .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties);
+ .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
}
handleSuccess = (response) => {
// reset each changed property with new value and remove it from changed properties list
response.forEach((resProp) => {
- const changedProp = <PropertyFEModel>_.find(this.changedData, changedDataObject => changedDataObject.uniqueId === resProp.uniqueId);
- this.changedData = _.filter(this.changedData, changedDataObject => changedDataObject.uniqueId !== resProp.uniqueId);
+ const changedProp = <PropertyFEModel>this.changedData.shift();
this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
});
resolve(response);
@@ -778,7 +751,7 @@
}
} else if (this.selectedInstanceData instanceof GroupInstance) {
request = this.componentInstanceServiceNg2
- .updateComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties);
+ .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
handleSuccess = (response) => {
// reset each changed property with new value and remove it from changed properties list
response.forEach((resProp) => {
@@ -790,7 +763,7 @@
};
} else if (this.selectedInstanceData instanceof PolicyInstance) {
request = this.componentInstanceServiceNg2
- .updateComponentPolicyInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties);
+ .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
handleSuccess = (response) => {
// reset each changed property with new value and remove it from changed properties list
response.forEach((resProp) => {
@@ -802,6 +775,7 @@
};
}
} else if (this.isInputsTabSelected) {
+
const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
changedInput = <InputFEModel>changedInput;
const inputBE = new InputBEModel(changedInput);
@@ -925,27 +899,27 @@
{
title: modalTitle,
size: 'sm',
- type: 'custom',
- testId: "id",
-
+ type: SdcUiCommon.ModalType.custom,
+ testId: "navigate-modal",
+
buttons: [
- {id: 'cancelButton', text: 'Cancel', type: 'secondary', size: 'xsm', closeModal: true, callback: () => reject()},
- {id: 'discardButton', text: 'Discard', type: 'secondary', size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
- {id: 'saveButton', text: 'Save', type: 'primary', size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
- ] as IModalButtonComponent[]
- }, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
+ {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
+ {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
+ {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
});
}
updatePropertyValueAfterDeclare = (input: InputFEModel) => {
if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
- let instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
- let propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
- return feProperty.uniqueId === input.propertyId &&
+ const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
+ const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
+ return feProperty.name == input.relatedPropertyName &&
(feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
});
- let inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
+ const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
@@ -968,7 +942,7 @@
setPolicyTabIndication = (numPolicies: number): void => {
this.propertyInputTabs.setTabIndication('Policies', numPolicies);
- };
+ }
resetUnsavedChangesForInput = (input:InputFEModel) => {
this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
@@ -1009,9 +983,9 @@
deletePolicy = (policy: PolicyInstance) => {
this.loadingPolicies = true;
- this.componentServiceNg2
+ this.topologyTemplateService
.deletePolicy(this.component, policy)
- .subscribe(response => {
+ .subscribe((response) => {
this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
//Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
this.changeSelectedInstance(this.selectedInstanceData);
@@ -1020,25 +994,25 @@
};
deleteProperty = (property: PropertyFEModel) => {
- let propertyToDelete = new PropertyFEModel(property);
+ const propertyToDelete = new PropertyFEModel(property);
this.loadingProperties = true;
- let feMap = this.instanceFePropertiesMap;
- this.componentServiceNg2
- .deleteServiceProperty(this.component, propertyToDelete)
- .subscribe(response => {
+ const feMap = this.instanceFePropertiesMap;
+ this.topologyTemplateService
+ .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
+ .subscribe((response) => {
const props = feMap[this.component.uniqueId];
props.splice(props.findIndex(p => p.uniqueId === response),1);
this.loadingProperties = false;
- }, error => {
+ }, (error) => {
this.loadingProperties = false;
console.error(error);
});
- };
+ }
/*** addProperty ***/
addProperty = () => {
let modalTitle = 'Add Property';
- const modal = this.ModalService.createCustomModal(new ModalModel(
+ let modal = this.ModalService.createCustomModal(new ModalModel(
'sm',
modalTitle,
null,
@@ -1046,10 +1020,10 @@
new ButtonModel('Save', 'blue', () => {
modal.instance.dynamicContent.instance.isLoading = true;
const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
- this.componentServiceNg2.createServiceProperty(this.component, newProperty)
- .subscribe(response => {
+ this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
+ .subscribe((response) => {
modal.instance.dynamicContent.instance.isLoading = false;
- let newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
+ const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
modal.instance.close();
}, (error) => {
@@ -1059,7 +1033,6 @@
title: 'Failure'
});
});
-
}, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
new ButtonModel('Cancel', 'outline grey', () => {
modal.instance.close();
@@ -1069,24 +1042,23 @@
));
this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
modal.instance.open();
- };
+ }
/*** SEARCH RELATED FUNCTIONS ***/
searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
let instanceBePropertiesMap:InstanceBePropertiesMap;
this.componentServiceNg2
.filterComponentInstanceProperties(this.component, filterData)
- .subscribe(response => {
-
+ .subscribe((response) => {
this.processInstancePropertiesResponse(response, false);
this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
this.searchPropertyName = filterData.propertyName;//mark in table
this.hierarchyNavTabs.triggerTabChange('Composition');
this.propertiesNavigationData = [];
this.displayClearSearch = true;
- }, error => {}); //ignore error
+ }, (error) => {}); //ignore error
- };
+ }
clearSearch = () => {
this.instancesNavigationData = this.instances;
@@ -1106,5 +1078,6 @@
private isInput = (instanceType:string):boolean =>{
return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
}
+
}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts
index 7d76904..5053d52 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts
@@ -1,79 +1,78 @@
-import * as _ from "lodash";
-import {Component} from '@angular/core';
-import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
-import { DataTypeService } from "app/ng2/services/data-type.service";
-import {PropertyBEModel, DataTypesMap} from "app/models";
-import {PROPERTY_DATA} from "app/utils";
-import {PROPERTY_TYPES} from "../../../../utils";
-
+import { Component } from '@angular/core';
+import { DataTypesMap, PropertyBEModel } from 'app/models';
+import { DropdownValue } from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
+import { DataTypeService } from 'app/ng2/services/data-type.service';
+import { PROPERTY_DATA } from 'app/utils';
+import * as _ from 'lodash';
+import { PROPERTY_TYPES } from '../../../../utils';
@Component({
selector: 'property-creator',
templateUrl: './property-creator.component.html',
- styleUrls:['./property-creator.component.less'],
+ styleUrls: ['./property-creator.component.less'],
})
export class PropertyCreatorComponent {
- typesProperties: Array<DropdownValue>;
- typesSchemaProperties: Array<DropdownValue>;
+ typesProperties: DropdownValue[];
+ typesSchemaProperties: DropdownValue[];
propertyModel: PropertyBEModel;
- //propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/;
- //commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/;
- //types:Array<string>;
- dataTypes:DataTypesMap;
- isLoading:boolean;
+ // propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/;
+ // commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/;
+ // types:Array<string>;
+ dataTypes: DataTypesMap;
+ isLoading: boolean;
- constructor(protected dataTypeService:DataTypeService) {}
+ constructor(protected dataTypeService: DataTypeService) {}
ngOnInit() {
this.propertyModel = new PropertyBEModel();
this.propertyModel.type = '';
this.propertyModel.schema.property.type = '';
- const types: Array<string> = PROPERTY_DATA.TYPES; //All types - simple type + map + list
- this.dataTypes = this.dataTypeService.getAllDataTypes(); //Get all data types in service
- const nonPrimitiveTypes :Array<string> = _.filter(Object.keys(this.dataTypes), (type:string)=> {
- return types.indexOf(type) == -1;
+ const types: string[] = PROPERTY_DATA.TYPES; // All types - simple type + map + list
+ this.dataTypes = this.dataTypeService.getAllDataTypes(); // Get all data types in service
+ const nonPrimitiveTypes: string[] = _.filter(Object.keys(this.dataTypes), (type: string) => {
+ return types.indexOf(type) === -1;
});
this.typesProperties = _.map(PROPERTY_DATA.TYPES,
(type: string) => new DropdownValue(type, type)
);
- let typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES,
+ const typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES,
(type: string) => new DropdownValue(type, type)
);
- let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes,
+ const nonPrimitiveTypesValues = _.map(nonPrimitiveTypes,
(type: string) => new DropdownValue(type,
- type.replace("org.openecomp.datatypes.heat.",""))
+ type.replace('org.openecomp.datatypes.heat.', ''))
)
.sort((a, b) => a.label.localeCompare(b.label));
- this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues);
- this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues);
- this.typesProperties.unshift(new DropdownValue('','Select Type...'));
- this.typesSchemaProperties.unshift(new DropdownValue('','Select Schema Type...'));
+ this.typesProperties = _.concat(this.typesProperties, nonPrimitiveTypesValues);
+ this.typesSchemaProperties = _.concat(typesSimpleProperties, nonPrimitiveTypesValues);
+ this.typesProperties.unshift(new DropdownValue('', 'Select Type...'));
+ this.typesSchemaProperties.unshift(new DropdownValue('', 'Select Schema Type...'));
}
- checkFormValidForSubmit(){
- const showSchema:boolean = this.showSchema();
- let isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type)? false : true;
- if (!showSchema){
+ checkFormValidForSubmit() {
+ const showSchema: boolean = this.showSchema();
+ const isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type) ? false : true;
+ if (!showSchema) {
this.propertyModel.schema.property.type = '';
}
return this.propertyModel.name && this.propertyModel.type && isSchemaValid;
}
- showSchema():boolean {
+ showSchema(): boolean {
return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.propertyModel.type) > -1;
- };
+ }
- onSchemaTypeChange():void {
- if (this.propertyModel.type == PROPERTY_TYPES.MAP) {
+ onSchemaTypeChange(): void {
+ if (this.propertyModel.type === PROPERTY_TYPES.MAP) {
this.propertyModel.value = JSON.stringify({'': null});
- } else if (this.propertyModel.type == PROPERTY_TYPES.LIST) {
+ } else if (this.propertyModel.type === PROPERTY_TYPES.LIST) {
this.propertyModel.value = JSON.stringify([]);
}
- };
+ }
}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts
index 92accb2..1cbb4e1 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts
@@ -1,10 +1,10 @@
-import {NgModule} from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {PropertyCreatorComponent} from "./property-creator.component";
-import {FormsModule} from "@angular/forms";
-import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {TranslateModule} from "../../../shared/translator/translate.module";
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-elements.module';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from '../../../shared/translator/translate.module';
+import { PropertyCreatorComponent } from './property-creator.component';
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts
index 011be41..bd7ccd1 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts
@@ -48,7 +48,7 @@
let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE
- this.initValueObjectRef(newFEProp); //initialize valueObj.
+ this.initValueObjectRef(newFEProp); //initialize valueObj AND creates flattened children
propertyFeArray.push(newFEProp);
newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children
this.dataTypeService.checkForCustomBehavior(newFEProp);
@@ -79,8 +79,8 @@
return instanceFePropertiesMap;
}
- public convertAddPropertyBAToPropertyFE = (property: PropertyBEModel):PropertyFEModel => {
- let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE
+ public convertAddPropertyBAToPropertyFE = (property: PropertyBEModel): PropertyFEModel => {
+ const newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE
this.initValueObjectRef(newFEProp);
newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children
this.dataTypeService.checkForCustomBehavior(newFEProp);
@@ -108,7 +108,7 @@
let tempProps: Array<DerivedFEProperty> = [];
let dataTypeObj: DataTypeModel = this.dataTypeService.getDataTypeByTypeName(type);
this.dataTypeService.getDerivedDataTypeProperties(dataTypeObj, tempProps, parentName);
- return tempProps;
+ return _.sortBy(tempProps, ['propertiesName']);
}
/* Sets the valueObj of parent property and its children.
diff --git a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module.ts b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module.ts
index 1e767a5..104a6d0 100644
--- a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module.ts
+++ b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module.ts
@@ -5,7 +5,8 @@
import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/requirements-editor/requirements-editor.module.ts b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/requirements-editor/requirements-editor.module.ts
index 1be8be5..d38790a 100644
--- a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/requirements-editor/requirements-editor.module.ts
+++ b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/requirements-editor/requirements-editor.module.ts
@@ -4,7 +4,7 @@
import {FormsModule} from "@angular/forms";
import {FormElementsModule} from "../../../components/ui/form-components/form-elements.module";
import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
-import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
+import { SdcUiComponentsModule } from "onap-ui-angular";
@NgModule({
declarations: [
diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts
index 2c86cc5..8444c62 100644
--- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts
+++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts
@@ -14,29 +14,29 @@
* permissions and limitations under the License.
*/
-import * as _ from "lodash";
import { Component } from '@angular/core';
-import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
import {
- Service,
- ServiceInstanceObject,
- InstanceFePropertiesMap,
- InstanceBePropertiesMap,
- PropertyBEModel,
+ Capability,
InputBEModel,
- OperationModel,
+ InstanceBePropertiesMap,
+ InstanceFePropertiesMap,
InterfaceModel,
- Capability
+ OperationModel,
+ PropertyBEModel,
+ Service
} from 'app/models';
-import {ConsumptionInput, ConsumptionInputDetails, ServiceOperation} from 'app/ng2/components/logic/service-consumption/service-consumption.component';
-import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils";
+import { ConsumptionInput, ConsumptionInputDetails, ServiceOperation } from 'app/ng2/components/logic/service-consumption/service-consumption.component';
+import { PropertiesUtils } from 'app/ng2/pages/properties-assignment/services/properties.utils';
+import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
import { PROPERTY_DATA } from 'app/utils';
-
+import * as _ from 'lodash';
+import { ServiceInstanceObject } from '../../../models/service-instance-properties-and-interfaces';
+import { TopologyTemplateService } from '../../services/component-services/topology-template.service';
@Component({
selector: 'service-consumption-editor',
templateUrl: './service-consumption-editor.component.html',
- styleUrls:['./service-consumption-editor.component.less'],
+ styleUrls: ['./service-consumption-editor.component.less'],
providers: []
})
@@ -45,27 +45,27 @@
input: {
interfaceId: string,
serviceOperationIndex: number,
- serviceOperations: Array<ServiceOperation>,
+ serviceOperations: ServiceOperation[],
parentService: Service,
selectedService: Service,
- parentServiceInputs: Array<InputBEModel>,
- selectedServiceProperties: Array<PropertyBEModel>,
- selectedServiceInstanceId: String,
- selectedInstanceSiblings: Array<ServiceInstanceObject>,
- selectedInstanceCapabilitisList: Array<Capability>,
- siblingsCapabilitiesList: Map<string, Array<Capability>>
+ parentServiceInputs: InputBEModel[],
+ selectedServiceProperties: PropertyBEModel[],
+ selectedServiceInstanceId: string,
+ selectedInstanceSiblings: ServiceInstanceObject[],
+ selectedInstanceCapabilitisList: Capability[],
+ siblingsCapabilitiesList: Map<string, Capability[]>
};
- sourceTypes: Array<any> = [];
- serviceOperationsList: Array<ServiceOperation>;
+ sourceTypes: any[] = [];
+ serviceOperationsList: ServiceOperation[];
serviceOperation: ServiceOperation;
currentIndex: number;
isLoading: boolean = false;
parentService: Service;
selectedService: Service;
- selectedServiceInstanceId: String;
- parentServiceInputs: Array<InputBEModel>;
- selectedServiceProperties: Array<PropertyBEModel>;
- changedData: Array<ConsumptionInputDetails> = [];
+ selectedServiceInstanceId: string;
+ parentServiceInputs: InputBEModel[];
+ selectedServiceProperties: PropertyBEModel[];
+ changedData: ConsumptionInputDetails[] = [];
inputFePropertiesMap: any = [];
SOURCE_TYPES = {
@@ -75,7 +75,7 @@
SERVICE_INPUT_LABEL: 'Service Input'
};
- constructor(private serviceServiceNg2: ServiceServiceNg2, private propertiesUtils:PropertiesUtils) {}
+ constructor(private topologyTemplateService: TopologyTemplateService, private propertiesUtils: PropertiesUtils) {}
ngOnInit() {
this.serviceOperationsList = this.input.serviceOperations;
@@ -112,7 +112,7 @@
capabilities: []
}
];
- _.forEach(this.input.selectedInstanceSiblings, sib =>
+ _.forEach(this.input.selectedInstanceSiblings, (sib) =>
this.sourceTypes.push({
label: sib.name,
value: sib.id,
@@ -128,163 +128,34 @@
}
onExpandAll() {
- _.forEach(this.serviceOperation.consumptionInputs, coInput => {
+ _.forEach(this.serviceOperation.consumptionInputs, (coInput) => {
coInput.expanded = true;
- })
+ });
}
onCollapseAll() {
- _.forEach(this.serviceOperation.consumptionInputs, coInput => {
+ _.forEach(this.serviceOperation.consumptionInputs, (coInput) => {
coInput.expanded = false;
- })
+ });
}
isAllInputExpanded() {
- return _.every(this.serviceOperation.consumptionInputs, coInput => coInput.expanded === true);
+ return _.every(this.serviceOperation.consumptionInputs, (coInput) => coInput.expanded === true);
}
isAllInputCollapsed() {
- return _.every(this.serviceOperation.consumptionInputs, coInput => coInput.expanded === false);
+ return _.every(this.serviceOperation.consumptionInputs, (coInput) => coInput.expanded === false);
}
onChangePage(newIndex) {
if (newIndex >= 0 && newIndex < this.serviceOperationsList.length) {
this.currentIndex = newIndex;
this.serviceOperation = this.serviceOperationsList[newIndex];
- if(!this.serviceOperation.consumptionInputs || this.serviceOperation.consumptionInputs.length === 0) {
+ if (!this.serviceOperation.consumptionInputs || this.serviceOperation.consumptionInputs.length === 0) {
this.initConsumptionInputs();
}
this.getComplexPropertiesForCurrentInputsOfOperation(this.serviceOperation.consumptionInputs);
}
}
- private initConsumptionInputs() {
- this.isLoading = true;
- this.serviceServiceNg2.getServiceConsumptionInputs(this.parentService, this.selectedServiceInstanceId, this.input.interfaceId, this.serviceOperation.operation).subscribe((result: Array<ConsumptionInput>) => {
- this.isLoading = false;
- this.serviceOperation.consumptionInputs = this.analyzeCurrentConsumptionInputs(result);
- this.getComplexPropertiesForCurrentInputsOfOperation(this.serviceOperation.consumptionInputs);
- }, err=> {
- this.isLoading = false;
- });
- }
-
- private analyzeCurrentConsumptionInputs(result: Array<any>): Array<ConsumptionInputDetails> {
- let inputsResult: Array<ConsumptionInputDetails> = [];
- let currentOp = this.serviceOperation.operation;
- if(currentOp) {
- inputsResult = _.map(result, input => {
- let sourceVal = input.source || this.SOURCE_TYPES.STATIC;
- let consumptionInputDetails: ConsumptionInputDetails = _.cloneDeep(input);
- consumptionInputDetails.source = sourceVal;
- consumptionInputDetails.isValid = true;
- consumptionInputDetails.expanded = false;
- let filteredListsObj = this.getFilteredProps(sourceVal, input.type);
- consumptionInputDetails.assignValueLabel = this.getAssignValueLabel(sourceVal);
- consumptionInputDetails.associatedProps = filteredListsObj.associatedPropsList;
- consumptionInputDetails.associatedInterfaces = filteredListsObj.associatedInterfacesList;
- consumptionInputDetails.associatedCapabilities = filteredListsObj.associatedCapabilitiesList;
- return new ConsumptionInputDetails(consumptionInputDetails);
- });
- }
- return inputsResult;
- }
-
- private onSourceChanged(consumptionInput: ConsumptionInputDetails): void {
- consumptionInput.assignValueLabel = this.getAssignValueLabel(consumptionInput.source);
- let filteredListsObj = this.getFilteredProps(consumptionInput.source, consumptionInput.type);
- consumptionInput.associatedProps = filteredListsObj.associatedPropsList;
- consumptionInput.associatedInterfaces = filteredListsObj.associatedInterfacesList;
- consumptionInput.associatedCapabilities = filteredListsObj.associatedCapabilitiesList;
- if(consumptionInput.source === this.SOURCE_TYPES.STATIC) {
- if(PROPERTY_DATA.SIMPLE_TYPES.indexOf(consumptionInput.type) !== -1) {
- consumptionInput.value = consumptionInput.defaultValue || "";
- }
- else {
- consumptionInput.value = null;
- Object.assign(this.inputFePropertiesMap, this.processPropertiesOfComplexTypeInput(consumptionInput));
- }
- }
- }
-
- private getFilteredProps(sourceVal, inputType) {
- let currentSourceObj = this.sourceTypes.find(s => s.value === sourceVal);
- let associatedInterfacesList = [], associatedPropsList = [], associatedCapabilitiesPropsList: Array<Capability> = [];
- if(currentSourceObj) {
- if (currentSourceObj.interfaces) {
- associatedInterfacesList = this.getFilteredInterfaceOutputs(currentSourceObj, inputType);
- }
- associatedPropsList = currentSourceObj.options.reduce((result, prop) => {
- if (prop.type === inputType) {
- result.push(prop.name);
- }
- return result;
- }, []);
- associatedCapabilitiesPropsList =
- _.reduce(currentSourceObj.capabilities,
- (filteredCapsList, capability: Capability) => {
- let filteredProps = _.filter(capability.properties, prop => prop.type === inputType);
- if (filteredProps.length) {
- let cap = new Capability(capability);
- cap.properties = filteredProps;
- filteredCapsList.push(cap);
- }
- return filteredCapsList
- }, []);
- }
- return {
- associatedPropsList: associatedPropsList,
- associatedInterfacesList: associatedInterfacesList,
- associatedCapabilitiesList: associatedCapabilitiesPropsList
- }
- }
-
- private getFilteredInterfaceOutputs(currentSourceObj, inputType) {
- let currentServiceOperationId = this.serviceOperation.operation.uniqueId;
- let filteredInterfacesList = [];
- Object.keys(currentSourceObj.interfaces).map(interfId => {
- let interfaceObj: InterfaceModel = new InterfaceModel(currentSourceObj.interfaces[interfId]);
- Object.keys(interfaceObj.operations).map(opId => {
- if(currentServiceOperationId !== opId) {
- let operationObj: OperationModel = interfaceObj.operations[opId];
- let filteredOutputsList = _.filter(operationObj.outputs.listToscaDataDefinition, output => output.type === inputType);
- if (filteredOutputsList.length) {
- filteredInterfacesList.push({
- name: `${interfaceObj.type}.${operationObj.name}`,
- label: `${interfaceObj.displayType()}.${operationObj.name}`,
- outputs: filteredOutputsList
- });
- }
- }
- });
- });
- return filteredInterfacesList;
- }
-
- getAssignValueLabel(selectedSource: string): string {
- if(selectedSource === this.SOURCE_TYPES.STATIC || selectedSource === "") {
- return this.SOURCE_TYPES.STATIC;
- }
- else {
- if(selectedSource === this.parentService.uniqueId) { //parent is the source
- return this.SOURCE_TYPES.SERVICE_INPUT_LABEL;
- }
- return this.SOURCE_TYPES.SERVICE_PROPERTY_LABEL;
- }
- }
-
-
- private isValidInputsValues(): boolean {
- return this.changedData.length > 0 && this.changedData.every((changedItem) => changedItem.isValid);
- }
-
- private isMandatoryFieldsValid(): boolean {
- const invalid: Array<ConsumptionInputDetails> = this.serviceOperation.consumptionInputs.filter(item =>
- item.required && (item.value === null || typeof item.value === 'undefined' || item.value === ''));
- if (invalid.length > 0) {
- return false;
- }
- return true;
- }
-
checkFormValidForSubmit(): boolean {
return this.isValidInputsValues() && this.isMandatoryFieldsValid();
}
@@ -307,23 +178,153 @@
}
}
- private getComplexPropertiesForCurrentInputsOfOperation(opInputs: Array<ConsumptionInput>) {
- _.forEach(opInputs, input => {
- if(PROPERTY_DATA.SIMPLE_TYPES.indexOf(input.type) === -1 && input.source === this.SOURCE_TYPES.STATIC) {
+ onComplexPropertyChanged(property, consumptionInput) {
+ consumptionInput.value = JSON.stringify(property.valueObj);
+ this.onChange(property.valueObj, property.valueObjIsValid , consumptionInput);
+ }
+
+ private initConsumptionInputs() {
+ this.isLoading = true;
+ this.topologyTemplateService.getServiceConsumptionInputs(this.parentService.uniqueId, this.selectedServiceInstanceId,
+ this.input.interfaceId, this.serviceOperation.operation).subscribe((result: ConsumptionInput[]) => {
+ this.isLoading = false;
+ this.serviceOperation.consumptionInputs = this.analyzeCurrentConsumptionInputs(result);
+ this.getComplexPropertiesForCurrentInputsOfOperation(this.serviceOperation.consumptionInputs);
+ }, (err) => {
+ this.isLoading = false;
+ });
+ }
+
+ private analyzeCurrentConsumptionInputs(result: any[]): ConsumptionInputDetails[] {
+ let inputsResult: ConsumptionInputDetails[] = [];
+ const currentOp = this.serviceOperation.operation;
+ if (currentOp) {
+ inputsResult = _.map(result, (input) => {
+ const sourceVal = input.source || this.SOURCE_TYPES.STATIC;
+ const consumptionInputDetails: ConsumptionInputDetails = _.cloneDeep(input);
+ consumptionInputDetails.source = sourceVal;
+ consumptionInputDetails.isValid = true;
+ consumptionInputDetails.expanded = false;
+ const filteredListsObj = this.getFilteredProps(sourceVal, input.type);
+ consumptionInputDetails.assignValueLabel = this.getAssignValueLabel(sourceVal);
+ consumptionInputDetails.associatedProps = filteredListsObj.associatedPropsList;
+ consumptionInputDetails.associatedInterfaces = filteredListsObj.associatedInterfacesList;
+ consumptionInputDetails.associatedCapabilities = filteredListsObj.associatedCapabilitiesList;
+ return new ConsumptionInputDetails(consumptionInputDetails);
+ });
+ }
+ return inputsResult;
+ }
+
+ private onSourceChanged(consumptionInput: ConsumptionInputDetails): void {
+ consumptionInput.assignValueLabel = this.getAssignValueLabel(consumptionInput.source);
+ const filteredListsObj = this.getFilteredProps(consumptionInput.source, consumptionInput.type);
+ consumptionInput.associatedProps = filteredListsObj.associatedPropsList;
+ consumptionInput.associatedInterfaces = filteredListsObj.associatedInterfacesList;
+ consumptionInput.associatedCapabilities = filteredListsObj.associatedCapabilitiesList;
+ if (consumptionInput.source === this.SOURCE_TYPES.STATIC) {
+ if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(consumptionInput.type) !== -1) {
+ consumptionInput.value = consumptionInput.defaultValue || '';
+ } else {
+ consumptionInput.value = null;
+ Object.assign(this.inputFePropertiesMap, this.processPropertiesOfComplexTypeInput(consumptionInput));
+ }
+ }
+ }
+
+ private getFilteredProps(sourceVal, inputType) {
+ const currentSourceObj = this.sourceTypes.find((s) => s.value === sourceVal);
+ let associatedInterfacesList = [];
+ let associatedPropsList = [];
+ let associatedCapabilitiesPropsList: Capability[] = [];
+ if (currentSourceObj) {
+ if (currentSourceObj.interfaces) {
+ associatedInterfacesList = this.getFilteredInterfaceOutputs(currentSourceObj, inputType);
+ }
+ associatedPropsList = currentSourceObj.options.reduce((result, prop) => {
+ if (prop.type === inputType) {
+ result.push(prop.name);
+ }
+ return result;
+ }, []);
+ associatedCapabilitiesPropsList =
+ _.reduce(currentSourceObj.capabilities,
+ (filteredCapsList, capability: Capability) => {
+ const filteredProps = _.filter(capability.properties, (prop) => prop.type === inputType);
+ if (filteredProps.length) {
+ const cap = new Capability(capability);
+ cap.properties = filteredProps;
+ filteredCapsList.push(cap);
+ }
+ return filteredCapsList;
+ }, []);
+ }
+ return {
+ associatedPropsList,
+ associatedInterfacesList,
+ associatedCapabilitiesList: associatedCapabilitiesPropsList
+ };
+ }
+
+ private getFilteredInterfaceOutputs(currentSourceObj, inputType) {
+ const currentServiceOperationId = this.serviceOperation.operation.uniqueId;
+ const filteredInterfacesList = [];
+ Object.keys(currentSourceObj.interfaces).map((interfId) => {
+ const interfaceObj: InterfaceModel = new InterfaceModel(currentSourceObj.interfaces[interfId]);
+ Object.keys(interfaceObj.operations).map((opId) => {
+ if (currentServiceOperationId !== opId) {
+ const operationObj: OperationModel = interfaceObj.operations[opId];
+ const filteredOutputsList = _.filter(operationObj.outputs.listToscaDataDefinition, (output) => output.type === inputType);
+ if (filteredOutputsList.length) {
+ filteredInterfacesList.push({
+ name: `${interfaceObj.type}.${operationObj.name}`,
+ label: `${interfaceObj.displayType()}.${operationObj.name}`,
+ outputs: filteredOutputsList
+ });
+ }
+ }
+ });
+ });
+ return filteredInterfacesList;
+ }
+
+ private getAssignValueLabel(selectedSource: string): string {
+ if (selectedSource === this.SOURCE_TYPES.STATIC || selectedSource === '') {
+ return this.SOURCE_TYPES.STATIC;
+ } else {
+ if (selectedSource === this.parentService.uniqueId) { // parent is the source
+ return this.SOURCE_TYPES.SERVICE_INPUT_LABEL;
+ }
+ return this.SOURCE_TYPES.SERVICE_PROPERTY_LABEL;
+ }
+ }
+
+ private isValidInputsValues(): boolean {
+ return this.changedData.length > 0 && this.changedData.every((changedItem) => changedItem.isValid);
+ }
+
+ private isMandatoryFieldsValid(): boolean {
+ const invalid: ConsumptionInputDetails[] = this.serviceOperation.consumptionInputs.filter((item) =>
+ item.required && (item.value === null || typeof item.value === 'undefined' || item.value === ''));
+ if (invalid.length > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ private getComplexPropertiesForCurrentInputsOfOperation(opInputs: ConsumptionInput[]) {
+ _.forEach(opInputs, (input) => {
+ if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(input.type) === -1 && input.source === this.SOURCE_TYPES.STATIC) {
Object.assign(this.inputFePropertiesMap, this.processPropertiesOfComplexTypeInput(input));
}
});
}
private processPropertiesOfComplexTypeInput(input: ConsumptionInput): InstanceFePropertiesMap {
- let inputBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+ const inputBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
inputBePropertiesMap[input.name] = [input];
- let originTypeIsVF = false;
- return this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(inputBePropertiesMap, originTypeIsVF); //create flattened children and init values
+ const originTypeIsVF = false;
+ return this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(inputBePropertiesMap, originTypeIsVF); // create flattened children and init values
}
- onComplexPropertyChanged(property, consumptionInput) {
- consumptionInput.value = JSON.stringify(property.valueObj);
- this.onChange(property.valueObj, property.valueObjIsValid , consumptionInput);
- }
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.module.ts b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.module.ts
index e37cd76..43e88eb 100644
--- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.module.ts
+++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.module.ts
@@ -1,11 +1,11 @@
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {ServiceConsumptionCreatorComponent} from "./service-consumption-editor.component";
-import {FormsModule} from "@angular/forms";
-import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
-import {PropertyTableModule} from 'app/ng2/components/logic/properties-table/property-table.module';
-import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { PropertyTableModule } from 'app/ng2/components/logic/properties-table/property-table.module';
+import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-elements.module';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { TranslateModule } from 'app/ng2/shared/translator/translate.module';
+import { ServiceConsumptionCreatorComponent } from './service-consumption-editor.component';
@NgModule({
declarations: [
@@ -25,4 +25,4 @@
providers: []
})
export class ServiceConsumptionCreatorModule {
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts
index 271dd4a..708742a 100644
--- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts
+++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts
@@ -14,20 +14,23 @@
* permissions and limitations under the License.
*/
import { Component } from '@angular/core';
-import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
-import {ConstraintObjectUI, OPERATOR_TYPES} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component';
-import {ServiceInstanceObject, PropertyBEModel, InputBEModel} from 'app/models';
+import { InputBEModel, PropertyBEModel } from 'app/models';
+import { ConstraintObjectUI, OPERATOR_TYPES } from 'app/ng2/components/logic/service-dependencies/service-dependencies.component';
+import { DropdownValue } from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
+import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
import { PROPERTY_DATA } from 'app/utils';
-import {DropdownValue} from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
+import { ServiceInstanceObject } from '../../../models/service-instance-properties-and-interfaces';
-export class UIDropDownSourceTypesElement extends DropdownValue{
- options: Array<any>;
+export class UIDropDownSourceTypesElement extends DropdownValue {
+ options: any[];
assignedLabel: string;
type: string;
- constructor(input?: any){
- if(input) {
- let value = input.value || '';
- let label = input.label || '';
+ constructor(input?: any) {
+ if (input) {
+ const value = input.value || '';
+ const label = input.label || '';
+ // const hidden = input.hidden || '';
+ // const selected = input.selected || '';
super(value, label);
this.options = input.options;
this.assignedLabel = input.assignedLabel;
@@ -36,10 +39,11 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
@Component({
selector: 'service-dependencies-editor',
templateUrl: './service-dependencies-editor.component.html',
- styleUrls:['./service-dependencies-editor.component.less'],
+ styleUrls: ['./service-dependencies-editor.component.less'],
providers: [ServiceServiceNg2]
})
@@ -47,44 +51,42 @@
input: {
serviceRuleIndex: number,
- serviceRules: Array<ConstraintObjectUI>,
+ serviceRules: ConstraintObjectUI[],
compositeServiceName: string,
currentServiceName: string,
- parentServiceInputs: Array<InputBEModel>,
- selectedInstanceProperties: Array<PropertyBEModel>,
- operatorTypes: Array<DropdownValue>,
- selectedInstanceSiblings: Array<ServiceInstanceObject>
+ parentServiceInputs: InputBEModel[],
+ selectedInstanceProperties: PropertyBEModel[],
+ operatorTypes: DropdownValue[],
+ selectedInstanceSiblings: ServiceInstanceObject[]
};
currentServiceName: string;
- selectedServiceProperties: Array<PropertyBEModel>;
+ selectedServiceProperties: PropertyBEModel[];
selectedPropertyObj: PropertyBEModel;
- ddValueSelectedServicePropertiesNames: Array<DropdownValue>;
- operatorTypes: Array<DropdownValue>;
- sourceTypes: Array<UIDropDownSourceTypesElement> = [];
+ ddValueSelectedServicePropertiesNames: DropdownValue[];
+ operatorTypes: DropdownValue[];
+ sourceTypes: UIDropDownSourceTypesElement[] = [];
currentRule: ConstraintObjectUI;
currentIndex: number;
- listOfValuesToAssign: Array<DropdownValue>;
- listOfSourceOptions: Array<PropertyBEModel>;
+ listOfValuesToAssign: DropdownValue[];
+ listOfSourceOptions: PropertyBEModel[];
assignedValueLabel: string;
- serviceRulesList: Array<ConstraintObjectUI>;
-
+ serviceRulesList: ConstraintObjectUI[];
SOURCE_TYPES = {
STATIC: {label: 'Static', value: 'static'},
SERVICE_PROPERTY: {label: 'Service Property', value: 'property'}
};
-
ngOnInit() {
this.currentIndex = this.input.serviceRuleIndex;
this.serviceRulesList = this.input.serviceRules;
this.currentRule = this.serviceRulesList && this.input.serviceRuleIndex >= 0 ?
- this.serviceRulesList[this.input.serviceRuleIndex]:
- new ConstraintObjectUI({sourceName: this.SOURCE_TYPES.STATIC.value, sourceType: this.SOURCE_TYPES.STATIC.value, value: "", constraintOperator: OPERATOR_TYPES.EQUAL});
+ this.serviceRulesList[this.input.serviceRuleIndex] :
+ new ConstraintObjectUI({sourceName: this.SOURCE_TYPES.STATIC.value, sourceType: this.SOURCE_TYPES.STATIC.value, value: '', constraintOperator: OPERATOR_TYPES.EQUAL});
this.currentServiceName = this.input.currentServiceName;
this.operatorTypes = this.input.operatorTypes;
this.selectedServiceProperties = this.input.selectedInstanceProperties;
- this.ddValueSelectedServicePropertiesNames = _.map(this.input.selectedInstanceProperties, prop => new DropdownValue(prop.name, prop.name));
+ this.ddValueSelectedServicePropertiesNames = _.map(this.input.selectedInstanceProperties, (prop) => new DropdownValue(prop.name, prop.name));
this.initSourceTypes();
this.syncRuleData();
this.updateSourceTypesRelatedValues();
@@ -100,7 +102,7 @@
type: this.SOURCE_TYPES.SERVICE_PROPERTY.value,
options: this.input.parentServiceInputs
});
- _.forEach(this.input.selectedInstanceSiblings, sib =>
+ _.forEach(this.input.selectedInstanceSiblings, (sib) =>
this.sourceTypes.push({
label: sib.name,
value: sib.name,
@@ -112,28 +114,27 @@
}
syncRuleData() {
- if(!this.currentRule.sourceName && this.currentRule.sourceType === this.SOURCE_TYPES.STATIC.value) {
+ if (!this.currentRule.sourceName && this.currentRule.sourceType === this.SOURCE_TYPES.STATIC.value) {
this.currentRule.sourceName = this.SOURCE_TYPES.STATIC.value;
}
- this.selectedPropertyObj = _.find(this.selectedServiceProperties, prop => prop.name === this.currentRule.servicePropertyName);
+ this.selectedPropertyObj = _.find(this.selectedServiceProperties, (prop) => prop.name === this.currentRule.servicePropertyName);
this.updateOperatorTypesList();
this.updateSourceTypesRelatedValues();
}
updateOperatorTypesList() {
if (this.selectedPropertyObj && PROPERTY_DATA.SIMPLE_TYPES_COMPARABLE.indexOf(this.selectedPropertyObj.type) === -1) {
- this.operatorTypes = [{label: "=", value: OPERATOR_TYPES.EQUAL}];
+ this.operatorTypes = [{label: '=', value: OPERATOR_TYPES.EQUAL}];
this.currentRule.constraintOperator = OPERATOR_TYPES.EQUAL;
- }
- else {
+ } else {
this.operatorTypes = this.input.operatorTypes;
}
}
updateSourceTypesRelatedValues() {
- if(this.currentRule.sourceName) {
- let selectedSourceType: UIDropDownSourceTypesElement = this.sourceTypes.find(
- t => t.value === this.currentRule.sourceName && t.type === this.currentRule.sourceType
+ if (this.currentRule.sourceName) {
+ const selectedSourceType: UIDropDownSourceTypesElement = this.sourceTypes.find(
+ (t) => t.value === this.currentRule.sourceName && t.type === this.currentRule.sourceType
);
this.listOfSourceOptions = selectedSourceType.options || [];
this.assignedValueLabel = selectedSourceType.assignedLabel || this.SOURCE_TYPES.STATIC.label;
@@ -150,7 +151,7 @@
}
onServicePropertyChanged() {
- this.selectedPropertyObj = _.find(this.selectedServiceProperties, prop => prop.name === this.currentRule.servicePropertyName);
+ this.selectedPropertyObj = _.find(this.selectedServiceProperties, (prop) => prop.name === this.currentRule.servicePropertyName);
this.updateOperatorTypesList();
this.filterOptionsByType();
this.currentRule.value = '';
@@ -165,11 +166,11 @@
}
filterOptionsByType() {
- if(!this.selectedPropertyObj) {
+ if (!this.selectedPropertyObj) {
this.listOfValuesToAssign = [];
return;
}
- this.listOfValuesToAssign = this.listOfSourceOptions.reduce((result, op:PropertyBEModel) => {
+ this.listOfValuesToAssign = this.listOfSourceOptions.reduce((result, op: PropertyBEModel) => {
if (op.type === this.selectedPropertyObj.type && (!op.schemaType || op.schemaType === this.selectedPropertyObj.schemaType)) {
result.push(new DropdownValue(op.name, op.name));
}
@@ -182,11 +183,11 @@
}
checkFormValidForSubmit() {
- if(!this.serviceRulesList) { //for create modal
- let isStatic = this.currentRule.sourceName === this.SOURCE_TYPES.STATIC.value;
+ if (!this.serviceRulesList) { // for create modal
+ const isStatic = this.currentRule.sourceName === this.SOURCE_TYPES.STATIC.value;
return this.currentRule.isValidRule(isStatic);
}
- //for update all rules
- return this.serviceRulesList.every(rule => rule.isValidRule(rule.sourceName === this.SOURCE_TYPES.STATIC.value));
+ // for update all rules
+ return this.serviceRulesList.every((rule) => rule.isValidRule(rule.sourceName === this.SOURCE_TYPES.STATIC.value));
}
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts
index 98ac997..7b128f4 100644
--- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts
+++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts
@@ -1,9 +1,9 @@
-import { NgModule } from "@angular/core";
-import {CommonModule} from "@angular/common";
-import {ServiceDependenciesEditorComponent} from "./service-dependencies-editor.component";
-import {FormsModule} from "@angular/forms";
-import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
-import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-elements.module';
+import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
+import { ServiceDependenciesEditorComponent } from './service-dependencies-editor.component';
@NgModule({
declarations: [
@@ -22,4 +22,4 @@
providers: []
})
export class ServiceDependenciesEditorModule {
-}
\ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.html b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.html
new file mode 100644
index 0000000..d7cf2f9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.html
@@ -0,0 +1,68 @@
+<!--
+ ~ 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="activity-log">
+ <div class="sdc-filter-bar-wrapper">
+ <sdc-filter-bar
+ [placeHolder]="'Search...'"
+ [testId]="activityLogSearchBar"
+ (keyup)="updateFilter($event)">
+ </sdc-filter-bar>
+ </div>
+ <ngx-datatable
+ columnMode="flex"
+ [footerHeight]="0"
+ [limit]="50"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ #activityLogTable
+ [rows]="activities">
+
+ <ngx-datatable-column name="Time" [flexGrow]="2" [prop]="'TIMESTAMP'">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.TIMESTAMP | date }} | {{row.TIMESTAMP | date:"HH:mm O"}}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Action" [flexGrow]="3" [prop]="'ACTION'">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.ACTION}}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Comment" [flexGrow]="5" [prop]="'COMMENT'">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span sdc-tooltip [tooltip-text]="row.COMMENT">{{ row.COMMENT }}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Modifier" [flexGrow]="3" [prop]="'MODIFIER'">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{ row.MODIFIER }}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Status" [flexGrow]="1" [prop]="'STATUS'">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <svg-icon-label
+ [name]="row.STATUS <= 399 ? 'success' : 'icons_close'"
+ [mode]="row.STATUS <= 399 ? 'success' : 'error'"
+ [size]="'medium'"
+ [label]="row.STATUS"
+ [labelPlacement]="'left'"
+ [labelClassName]="'label'"
+ >
+ </svg-icon-label>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.less b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.less
new file mode 100644
index 0000000..4845f4f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.less
@@ -0,0 +1,8 @@
+.sdc-filter-bar-wrapper {
+ sdc-filter-bar {
+ flex: 0 0 30%;
+ }
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.spec.ts
new file mode 100644
index 0000000..25651e0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.spec.ts
@@ -0,0 +1,84 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiServices } from 'onap-ui-angular';
+import 'rxjs/add/observable/of';
+import { Observable } from 'rxjs/Observable';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { ActivityLogService } from '../../../services/activity-log.service';
+import { WorkspaceService } from '../workspace.service';
+import { ActivityLogComponent } from './activity-log.component';
+
+describe('activity log component', () => {
+
+ let fixture: ComponentFixture<ActivityLogComponent>;
+ let activityLogServiceMock: Partial<ActivityLogService>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let componentMetadataMock: ComponentMetadata;
+
+ const mockLogs = '[' +
+ '{"MODIFIER":"Carlos Santana(m08740)","COMMENT":"comment","STATUS":"200","ACTION":"Checkout","TIMESTAMP":"2018-11-19 13:00:02.388 UTC"},' +
+ '{"MODIFIER":"John Doe(m08741)","COMMENT":"comment","STATUS":"200","ACTION":"Checkin","TIMESTAMP":"2018-11-20 13:00:02.388 UTC"},' +
+ '{"MODIFIER":"Jane Doe(m08742)","COMMENT":"comment","STATUS":"200","ACTION":"Checkout","TIMESTAMP":"2018-11-21 13:00:02.388 UTC"}' +
+ ']';
+
+ beforeEach(
+ async(() => {
+
+ componentMetadataMock = new ComponentMetadata();
+ componentMetadataMock.uniqueId = 'fake';
+ componentMetadataMock.componentType = 'SERVICE';
+
+ activityLogServiceMock = {
+ getActivityLog : jest.fn().mockImplementation((type, id) => Observable.of(JSON.parse(mockLogs)) )
+ };
+
+ workspaceServiceMock = {
+ metadata : componentMetadataMock
+ };
+
+ loaderServiceMock = {
+ activate : jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [ActivityLogComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: WorkspaceService, useValue: workspaceServiceMock },
+ { provide: ActivityLogService, useValue: activityLogServiceMock },
+ { provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(ActivityLogComponent);
+ });
+ })
+ );
+
+ it('should see exactly 3 activity logs', () => {
+ fixture.componentInstance.ngOnInit();
+ expect(fixture.componentInstance.activities.length).toBe(3);
+ });
+
+ it('should filter out 1 element when searching', () => {
+ fixture.componentInstance.ngOnInit();
+
+ const event = {
+ target : {
+ value : 'Checkin'
+ }
+ };
+
+ expect(fixture.componentInstance.activities.length).toBe(3);
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.activities.length).toBe(1);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.ts b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.ts
new file mode 100644
index 0000000..84fb81a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Activity } from '../../../../models/activity';
+import { ActivityLogService } from '../../../services/activity-log.service';
+import { WorkspaceService } from '../workspace.service';
+
+@Component({
+ selector: 'activity-log',
+ templateUrl: './activity-log.component.html',
+ styleUrls: ['./activity-log.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class ActivityLogComponent implements OnInit {
+
+ activities: Activity[] = [];
+ temp: Activity[] = [];
+
+ constructor(private workspaceService: WorkspaceService,
+ private activityLogService: ActivityLogService,
+ private loaderService: SdcUiServices.LoaderService) {
+ }
+
+ ngOnInit(): void {
+ this.loaderService.activate();
+ const componentId: string = this.workspaceService.metadata.uniqueId;
+ const componentType: string = this.workspaceService.metadata.componentType;
+ this.activityLogService.getActivityLog(componentType, componentId).subscribe((logs) => {
+ this.activities = logs;
+ this.temp = [...logs];
+ this.loaderService.deactivate();
+ }, (error) => { this.loaderService.deactivate(); });
+ }
+
+ updateFilter(event) {
+ const val = event.target.value.toLowerCase();
+
+ // filter our data
+ const temp = this.temp.filter((activity: Activity) => {
+ return !val ||
+ activity.COMMENT.toLowerCase().indexOf(val) !== -1 ||
+ activity.STATUS.toLowerCase().indexOf(val) !== -1 ||
+ activity.ACTION.toLowerCase().indexOf(val) !== -1 ||
+ activity.MODIFIER.toLowerCase().indexOf(val) !== -1;
+ });
+
+ // update the rows
+ this.activities = temp;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.module.ts b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.module.ts
new file mode 100644
index 0000000..39334d8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/activity-log/activity-log.module.ts
@@ -0,0 +1,28 @@
+import {CommonModule} from "@angular/common";
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {GlobalPipesModule} from "../../../pipes/global-pipes.module";
+import {ActivityLogComponent} from "./activity-log.component";
+import {ActivityLogService} from "../../../services/activity-log.service";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+
+@NgModule({
+ declarations: [
+ ActivityLogComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ GlobalPipesModule,
+ NgxDatatableModule
+ ],
+ exports: [
+ ActivityLogComponent
+ ],
+ entryComponents: [
+ ActivityLogComponent
+ ],
+ providers: [ ActivityLogService ]
+})
+export class ActivityLogModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html
new file mode 100644
index 0000000..bd30a46
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html
@@ -0,0 +1,104 @@
+<form>
+ <div class="attr-container">
+
+ <div class="attr-col">
+ <!-- ATTRIBUTE NAME - MANDATORY -->
+ <div>
+ <sdc-input
+ #attributeName
+ label="Name"
+ [required]="true"
+ [(value)]="attributeToEdit.name"
+ [disabled]="isEdit"
+ name="attributeName"
+ testId="attributeName"
+ [maxLength]="255">
+ </sdc-input>
+ <sdc-validation [validateElement]="attributeName" (validityChanged)="onValidityChange($event, 'name')">
+ <sdc-required-validator message="{{'VALIDATION_ERROR_REQUIRED' | translate : { 'field' : 'Name' } }}"></sdc-required-validator>
+ <sdc-regex-validator message="{{'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate }}" [pattern]="validationPatterns.propertyName"></sdc-regex-validator>
+ </sdc-validation>
+ </div>
+
+ <!-- ATTRIBUTE DESCRIPTION - OPTIONAL -->
+ <div>
+ <sdc-textarea #attributeDescription
+ [(value)]="attributeToEdit.description"
+ [required]="false"
+ testId="description"
+ [maxLength]="256"
+ label="Description">
+ </sdc-textarea>
+ </div>
+ </div>
+
+ <div class="attr-col">
+
+ <div class="attributeType">
+ <!-- ATTRIBUTE TYPE - MANDATORY -->
+ <sdc-dropdown #attributeType [disabled]="false" label="Type" [required]="true"
+ [selectedOption]="toDropDownOption(this.attributeToEdit.type)" placeHolder="Choose Type"
+ [options]="types" (changed)="onTypeSelected($event)">
+ <sdc-validation [validateElement]="attributeType" (validityChanged)="onValidityChange($event, 'type')">
+ <sdc-required-validator message="'required field'"></sdc-required-validator>
+ </sdc-validation>
+ </sdc-dropdown>
+ </div>
+
+ <!-- ATTRIBUTE DEFAULT VALUE TEXT - OPTIONAL -->
+ <div *ngIf="attributeToEdit.type != 'boolean'">
+ <sdc-input
+ #defaultValue
+ [required]="false"
+ label="Default Value"
+ [(value)]="attributeToEdit.defaultValue"
+ [disabled]="false"
+ name="defaultValue"
+ testId="defaultValue"
+ [maxLength]="255"
+ (valueChange)="defaultValueChanged()">
+ </sdc-input>
+
+ <sdc-validation [validateElement]="defaultValue" (validityChanged)="onValidityChange($event, 'defaultValue')">
+ <sdc-regex-validator *ngIf="this.attributeToEdit.defaultValue && this.attributeToEdit.defaultValue.length > 0" message="{{ this.defaultValueErrorMessage }}"
+ [pattern]="defaultValuePattern"></sdc-regex-validator>
+ <sdc-custom-validator *ngIf="this.attributeToEdit.type == 'map' && this.attributeToEdit.schema.property.type" message="{{ 'PROPERTY_EDIT_MAP_UNIQUE_KEYS' | translate }}"
+ [callback]="isMapUnique" [disabled]="false"></sdc-custom-validator>
+ </sdc-validation>
+ </div>
+
+ <!-- ATTRIBUTE DEFAULT VALUE BOOLEAN- OPTIONAL -->
+ <div *ngIf="attributeToEdit.type == 'boolean'">
+ <sdc-dropdown [disabled]="false" label="Default Value"
+ [required]="false"
+ [selectedOption]="toDropDownOption(this.attributeToEdit.defaultValue)" placeHolder="Choose Default Value"
+ [options]="booleanValues" (changed)="onBooleanDefaultValueSelected($event)">
+
+ </sdc-dropdown>
+ </div>
+
+ <div *ngIf="attributeToEdit.type == 'list' || attributeToEdit.type == 'map'">
+ <!-- ATTRIBUTE ENTRY SCHEMA - MANDATORY -->
+ <sdc-dropdown #entrySchema
+ [disabled]="false" label="Entry Schema" [required]="true"
+ [selectedOption]="toDropDownOption(this.attributeToEdit.schema.property.type)" placeHolder="Choose Schema Type"
+ [options]="entrySchemaValues" (changed)="onEntrySchemaTypeSelected($event)">
+ <sdc-validation [validateElement]="entrySchema" (validityChanged)="onValidityChange($event, 'entrySchema')">
+ <sdc-required-validator message="'required !TODO - CHANGE MESSAGE'"></sdc-required-validator>
+ </sdc-validation>
+ </sdc-dropdown>
+ </div>
+
+ <!-- ATTRIBUTE HIDDEN - OPTIONAL -->
+ <sdc-checkbox
+ label="Hidden"
+ [checked]="attributeToEdit.hidden"
+ [disabled]="false"
+ testId="hidden"
+ (checkedChange)="this.onHiddenCheckboxClicked($event)"
+ >
+ </sdc-checkbox>
+ </div>
+ </div>
+
+</form>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.ts
new file mode 100644
index 0000000..c703869
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.ts
@@ -0,0 +1,138 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { IDropDownOption } from 'onap-ui-angular/dist/form-elements/dropdown/dropdown-models';
+import { InputComponent } from 'onap-ui-angular/dist/form-elements/text-elements/input/input.component';
+import { Subject } from 'rxjs/Subject';
+import { AttributeModel } from '../../../../models/attributes';
+import { ValidationUtils } from '../../../../utils/validation-utils';
+import { CacheService } from '../../../services/cache.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { AttributeOptions } from './attributes-options';
+
+@Component({
+ selector: 'attribute-modal',
+ templateUrl: './attribute-modal.component.html',
+ styleUrls: ['./attributes.component.less']
+})
+export class AttributeModalComponent implements OnInit {
+
+ @ViewChild('defaultValue') validatedInput: InputComponent;
+
+ public readonly types = AttributeOptions.types; // integer, string, boolean etc.
+
+ public readonly booleanValues = AttributeOptions.booleanValues; // true / false
+
+ public readonly entrySchemaValues = AttributeOptions.entrySchemaValues; // integer, string, boolean, float
+
+ public onValidationChange: Subject<boolean> = new Subject();
+
+ public validationPatterns: any;
+ public readonly listPattern = ValidationUtils.getPropertyListPatterns();
+ public readonly mapPattern = ValidationUtils.getPropertyMapPatterns();
+
+ // The current effective default value pattern
+ public defaultValuePattern: string;
+ public defaultValueErrorMessage: string;
+
+ // Attribute being Edited
+ public attributeToEdit: AttributeModel;
+
+ constructor(private translateService: TranslateService, private cacheService: CacheService) {
+ this.validationPatterns = this.cacheService.get('validation').validationPatterns;
+ }
+
+ ngOnInit() {
+ this.revalidateDefaultValue();
+ }
+
+ onHiddenCheckboxClicked(event: boolean) {
+ this.attributeToEdit.hidden = event;
+ }
+
+ onTypeSelected(selectedElement: IDropDownOption) {
+ if (this.attributeToEdit.type !== selectedElement.value && selectedElement.value === 'boolean') {
+ this.attributeToEdit.defaultValue = ''; // Clean old value in case we choose change type to boolean
+ }
+ this.attributeToEdit.type = selectedElement.value;
+ this.revalidateDefaultValue();
+ }
+
+ onBooleanDefaultValueSelected(selectedElement: IDropDownOption) {
+ if (this.attributeToEdit.type === 'boolean') {
+ this.attributeToEdit.defaultValue = selectedElement.value;
+ }
+ }
+
+ onEntrySchemaTypeSelected(selectedElement: IDropDownOption) {
+ this.attributeToEdit.schema.property.type = selectedElement.value;
+ this.revalidateDefaultValue();
+ }
+
+ onValidityChange(isValid: boolean, field: string) {
+ const typeIsValid = this.attributeToEdit.type && this.attributeToEdit.type.length > 0; // Make sure type is defined
+
+ // Make sure name is defined when other fields are changed
+ let nameIsValid = true;
+ if (field !== 'name') {
+ nameIsValid = this.attributeToEdit.name && this.attributeToEdit.name.length > 0;
+ }
+ this.onValidationChange.next(isValid && nameIsValid && typeIsValid);
+ }
+
+ defaultValueChanged() {
+ this.revalidateDefaultValue();
+ }
+
+ /**
+ * Utility function for UI that converts a simple value to IDropDownOption
+ * @param val
+ * @returns {{value: any; label: any}}
+ */
+ toDropDownOption(val: string) {
+ return { value : val, label: val };
+ }
+
+ public isMapUnique = () => {
+ if (this.attributeToEdit && this.attributeToEdit.type === 'map' && this.attributeToEdit.defaultValue) {
+ return ValidationUtils.validateUniqueKeys(this.attributeToEdit.defaultValue);
+ }
+ return true;
+ }
+
+ private revalidateDefaultValue() {
+ this.setDefaultValuePattern(this.attributeToEdit.type);
+ setTimeout(() => {
+ if (this.validatedInput) {
+ this.validatedInput.onKeyPress(this.attributeToEdit.defaultValue);
+ } }, 250);
+ }
+
+ private setDefaultValuePattern(valueType: string) {
+ const selectedSchemaType = this.attributeToEdit.schema.property.type;
+ this.defaultValuePattern = '.*';
+ switch (valueType) {
+ case 'float':
+ this.defaultValuePattern = this.validationPatterns.number;
+ this.defaultValueErrorMessage = this.translateService.translate('VALIDATION_ERROR_TYPE', { type : 'float' });
+ break;
+ case 'integer':
+ this.defaultValuePattern = this.validationPatterns.integerNoLeadingZero;
+ this.defaultValueErrorMessage = this.translateService.translate('VALIDATION_ERROR_TYPE', { type : 'integer' });
+ break;
+ case 'list':
+ if (selectedSchemaType != undefined) {
+ this.defaultValuePattern = this.listPattern[selectedSchemaType];
+ const listTypeStr = `list of ${selectedSchemaType}s (v1, v2, ...) `;
+ this.defaultValueErrorMessage = this.translateService.translate('VALIDATION_ERROR_TYPE', { type : listTypeStr });
+ }
+ break;
+ case 'map':
+ if (selectedSchemaType != undefined) {
+ this.defaultValuePattern = this.mapPattern[selectedSchemaType];
+ const mapTypeStr = `map of ${selectedSchemaType}s (k1:v1, k2:v2, ...)`;
+ this.defaultValueErrorMessage = this.translateService.translate('VALIDATION_ERROR_TYPE', { type : mapTypeStr });
+ }
+ break;
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-modal.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-modal.component.spec.ts
new file mode 100644
index 0000000..99aa140
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-modal.component.spec.ts
@@ -0,0 +1,128 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { AttributeModel } from '../../../../models/attributes';
+import { ValidationUtils } from '../../../../utils/validation-utils';
+import { CacheService } from '../../../services/cache.service';
+import { TranslatePipe } from '../../../shared/translator/translate.pipe';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { AttributeModalComponent } from './attribute-modal.component';
+
+describe('attributes modal component', () => {
+
+ let fixture: ComponentFixture<AttributeModalComponent>;
+
+ // Mocks
+ let translateServiceMock: Partial<TranslateService>;
+ let cacheServiceMock: Partial<CacheService>;
+
+ const validationPatterns = {
+ integerNoLeadingZero : 'int_regx',
+ number : 'number_regx'
+ };
+
+ const newAttribute = {
+ uniqueId: '1', name: 'attr1', description: 'description1', type: 'string', hidden: false, defaultValue: 'val1', schema: null
+ };
+
+ beforeEach(
+ async(() => {
+
+ translateServiceMock = {
+ translate: jest.fn()
+ };
+
+ cacheServiceMock = {
+ get: jest.fn().mockImplementation((k) => {
+ return { validationPatterns};
+ } )
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [AttributeModalComponent, TranslatePipe],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: TranslateService, useValue: translateServiceMock},
+ {provide: CacheService, useValue: cacheServiceMock},
+ ]
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(AttributeModalComponent);
+ });
+ })
+ );
+
+ it('test that when hidden is clicked, hidden attribute is set', async () => {
+ fixture.componentInstance.attributeToEdit = new AttributeModel();
+ const hidden = fixture.componentInstance.attributeToEdit.hidden;
+ fixture.componentInstance.ngOnInit();
+
+ expect(hidden).toBe(false);
+ fixture.componentInstance.onHiddenCheckboxClicked(true);
+ expect(fixture.componentInstance.attributeToEdit.hidden).toBe(true);
+ });
+
+ it('test that when type is set to boolean default value is cleared', async () => {
+ const component = fixture.componentInstance;
+ component.attributeToEdit = new AttributeModel();
+ component.ngOnInit();
+
+ component.onTypeSelected({ value : 'string', label : 'string'});
+ component.attributeToEdit.defaultValue = 'some_value';
+ component.onTypeSelected({ value : 'boolean', label : 'boolean'});
+ expect(component.attributeToEdit.defaultValue).toBe('');
+
+ component.onBooleanDefaultValueSelected({ value : 'true', label : 'true'});
+ expect(component.attributeToEdit.defaultValue).toBe('true');
+ });
+
+ it('test that when certain type is selected, the correct regex pattern is chosen', async () => {
+ const component = fixture.componentInstance;
+ component.attributeToEdit = new AttributeModel();
+ component.ngOnInit();
+
+ // integer
+ component.onTypeSelected({ value : 'integer', label : 'integer'});
+ expect(component.defaultValuePattern).toBe(validationPatterns.integerNoLeadingZero);
+
+ // float
+ component.onTypeSelected({ value : 'float', label : 'float'});
+ expect(component.defaultValuePattern).toBe(validationPatterns.number);
+
+ // list is chosen with no schema, regex pattern is set to default
+ component.onTypeSelected({ value : 'list', label : 'list'});
+ expect(component.defaultValuePattern).toEqual('.*');
+
+ // schema is set to list of int
+ component.onEntrySchemaTypeSelected({ value : 'integer', label : 'integer' });
+ expect(component.defaultValuePattern).toEqual(ValidationUtils.getPropertyListPatterns().integer);
+
+ // schema is set to list of float
+ component.onEntrySchemaTypeSelected({ value : 'float', label : 'float' });
+ expect(component.defaultValuePattern).toEqual(ValidationUtils.getPropertyListPatterns().float);
+
+ // map is selected (float schema is still selected from previous line)
+ component.onTypeSelected({ value : 'map', label : 'map'});
+ expect(component.defaultValuePattern).toEqual(ValidationUtils.getPropertyMapPatterns().float);
+
+ // change schema type to boolean
+ component.onEntrySchemaTypeSelected({ value : 'boolean', label : 'boolean' });
+ });
+
+ it('should detect map with non-unique keys', async () => {
+ const component = fixture.componentInstance;
+ component.attributeToEdit = new AttributeModel();
+ component.ngOnInit();
+ expect(component.isMapUnique()).toBe(true); // map is not selected so return true by default
+ component.onTypeSelected({ value : 'map', label : 'map'});
+ component.onEntrySchemaTypeSelected({ value : 'boolean', label : 'boolean' });
+ component.attributeToEdit.defaultValue = '"1":true,"2":false';
+ expect(component.isMapUnique()).toBe(true);
+ component.attributeToEdit.defaultValue = '"1":true,"1":false';
+ expect(component.isMapUnique()).toBe(false);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-options.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-options.ts
new file mode 100644
index 0000000..2a6924b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes-options.ts
@@ -0,0 +1,60 @@
+import { IDropDownOption } from 'onap-ui-angular/dist/form-elements/dropdown/dropdown-models';
+
+export class AttributeOptions {
+ public static readonly types: IDropDownOption[] = [
+ {
+ label: 'integer',
+ value: 'integer',
+ },
+ {
+ label: 'string',
+ value: 'string',
+ },
+ {
+ label: 'float',
+ value: 'float'
+ },
+ {
+ label: 'boolean',
+ value: 'boolean'
+ },
+ {
+ label: 'list',
+ value: 'list'
+ },
+ {
+ label: 'map',
+ value: 'map'
+ }
+ ];
+
+ public static readonly booleanValues: IDropDownOption[] = [
+ {
+ label: 'true',
+ value: 'true',
+ },
+ {
+ label: 'false',
+ value: 'false',
+ }
+ ];
+
+ public static readonly entrySchemaValues: IDropDownOption[] = [
+ {
+ label: 'integer',
+ value: 'integer',
+ },
+ {
+ label: 'string',
+ value: 'string',
+ },
+ {
+ label: 'float',
+ value: 'float'
+ },
+ {
+ label: 'boolean',
+ value: 'boolean'
+ }
+ ];
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.html b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.html
new file mode 100644
index 0000000..00a7a5c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.html
@@ -0,0 +1,93 @@
+<!--
+ ~ 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-attributes">
+
+ <div class="action-bar-wrapper">
+ <svg-icon-label
+ *ngIf="!(this.isViewOnly$ | async)"
+ class="add-attr-icon"
+ [name]="'plus'"
+ [mode]="'primary'"
+ [size]="'medium'"
+ [label]="'Add'"
+ [labelPlacement]="'right'"
+ [labelClassName]="'externalActionLabel'"
+ (click)="onAddAttribute()">
+ </svg-icon-label>
+ </div>
+
+ <ngx-datatable
+ columnMode="flex"
+ [footerHeight]="0"
+ [limit]="50"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rows]="attributes"
+ #componentAttributesTable
+ (activate)="onExpandRow($event)">
+
+ <ngx-datatable-row-detail [rowHeight]="80">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
+ <div>{{row.description}}</div>
+ </ng-template>
+ </ngx-datatable-row-detail>
+
+ <ngx-datatable-column [resizeable]="false" name="Name" [flexGrow]="2">
+
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded">
+ <div class="expand-collapse-cell">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ <span>{{ row.name }}</span>
+ </div>
+ </ng-template>
+
+ </ngx-datatable-column>
+
+ <ngx-datatable-column [resizeable]="false" name="Type" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.type}}
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-column [resizeable]="false" name="Default Value" [flexGrow]="3">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.defaultValue}}
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-column *ngIf="!(this.isViewOnly$ | async)" [resizeable]="false" name="Action" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row" let-rowIndex="rowIndex">
+ <div class="actionColumn">
+ <svg-icon [clickable]="true"
+ [mode]="'primary2'"
+ [name]="'edit-o'"
+ [size]="'medium'"
+ (click)="onEditAttribute($event, row)">
+ </svg-icon>
+ <svg-icon [clickable]="true"
+ [mode]="'primary2'"
+ [name]="'trash-o'"
+ (click)="onDeleteAttribute($event, row)"
+ [size]="'medium'">
+ </svg-icon>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.less b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.less
new file mode 100644
index 0000000..3e91ae4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.less
@@ -0,0 +1,36 @@
+.action-bar-wrapper {
+ flex: 0 0 30%;
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+}
+
+.add-attr-icon{
+ cursor: pointer;
+}
+
+.attr-container {
+ display: flex;
+ justify-content: space-between;
+
+ .attr-col {
+ display: flex;
+ flex-direction: column;
+ max-width: 275px;
+ flex-grow: 1;
+ }
+
+}
+
+.attributeType {
+ margin-bottom: 10px;
+}
+
+sdc-checkbox {
+ margin-top: 20px;
+}
+
+.actionColumn {
+ text-align: center;
+ padding: 5px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.spec.ts
new file mode 100644
index 0000000..f676e2b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.spec.ts
@@ -0,0 +1,182 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import 'rxjs/add/observable/of';
+import { Observable } from 'rxjs/Rx';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { ModalsHandler } from '../../../../utils';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { WorkspaceService } from '../workspace.service';
+import { AttributesComponent } from './attributes.component';
+
+describe('attributes component', () => {
+
+ let fixture: ComponentFixture<AttributesComponent>;
+
+ // Mocks
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let componentMetadataMock: ComponentMetadata;
+ let modalServiceMock: Partial<SdcUiServices.ModalService>;
+
+ const mockAttributesList = [
+ { uniqueId: '1', name: 'attr1', description: 'description1', type: 'string', hidden: false, defaultValue: 'val1', schema: null },
+ { uniqueId : '2', name : 'attr2', description: 'description2', type : 'int', hidden : false, defaultValue : 1, schema : null},
+ { uniqueId : '3', name : 'attr3', description: 'description3', type : 'double', hidden : false, defaultValue : 1.0, schema : null},
+ { uniqueId : '4', name : 'attr4', description: 'description4', type : 'boolean', hidden : false, defaultValue : true, schema : null},
+ ];
+
+ const newAttribute = {
+ uniqueId : '5', name : 'attr5', description: 'description5', type : 'string', hidden : false, defaultValue : 'val5', schema : null
+ };
+ const updatedAttribute = {
+ uniqueId : '2', name : 'attr2', description: 'description_new', type : 'string', hidden : false, defaultValue : 'new_val2', schema : null
+ };
+ const errorAttribute = {
+ uniqueId : '99', name : 'attr99', description: 'description_error', type : 'string', hidden : false, defaultValue : 'error', schema : null
+ };
+
+ beforeEach(
+ async(() => {
+
+ componentMetadataMock = new ComponentMetadata();
+ componentMetadataMock.uniqueId = 'fake';
+ componentMetadataMock.componentType = 'VL';
+
+ topologyTemplateServiceMock = {
+ getComponentAttributes: jest.fn().mockResolvedValue({ attributes : mockAttributesList }),
+ addAttributeAsync: jest.fn().mockImplementation(
+ (compType, cUid, attr) => {
+ if (attr === errorAttribute) {
+ return Observable.throwError('add_error').toPromise();
+ } else {
+ return Observable.of(newAttribute).toPromise();
+ }
+ }
+ ),
+ updateAttributeAsync: jest.fn().mockImplementation(
+ (compType, cUid, attr) => {
+ if (attr === errorAttribute) {
+ return Observable.throwError('update_error').toPromise();
+ } else {
+ return Observable.of(updatedAttribute).toPromise();
+ }
+ }
+ ),
+ deleteAttributeAsync: jest.fn().mockImplementation((cid, ctype, attr) => Observable.of(attr))
+ };
+
+ workspaceServiceMock = {
+ metadata: componentMetadataMock
+ };
+
+ const customModalInstance = { innerModalContent: { instance: { onValidationChange: { subscribe: jest.fn()}}}};
+
+ modalServiceMock = {
+ openInfoModal: jest.fn(),
+ openCustomModal: jest.fn().mockImplementation(() => customModalInstance)
+ };
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [AttributesComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: TopologyTemplateService, useValue: topologyTemplateServiceMock},
+ {provide: ModalsHandler, useValue: {}},
+ {provide: TranslateService, useValue: { translate: jest.fn() }},
+ {provide: SdcUiServices.ModalService, useValue: modalServiceMock },
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(AttributesComponent);
+ });
+ })
+ );
+
+ it('should see exactly 1 attributes on init', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ expect(fixture.componentInstance.getAttributes().length).toEqual(4);
+ });
+
+ it('should see exactly 5 attributes when adding', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ expect(fixture.componentInstance.getAttributes().length).toEqual(4);
+
+ await fixture.componentInstance.addOrUpdateAttribute(newAttribute, false);
+ expect(fixture.componentInstance.getAttributes().length).toEqual(5);
+ });
+
+ it('should see exactly 3 attributes when deleting', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ expect(fixture.componentInstance.getAttributes().length).toEqual(4);
+ const attrToDelete = mockAttributesList[0];
+ expect(fixture.componentInstance.getAttributes().filter((attr) => attr.uniqueId === attrToDelete.uniqueId).length).toEqual(1);
+ await fixture.componentInstance.deleteAttribute(attrToDelete);
+ expect(fixture.componentInstance.getAttributes().length).toEqual(3);
+ expect(fixture.componentInstance.getAttributes().filter((attr) => attr.uniqueId === attrToDelete.uniqueId).length).toEqual(0);
+ });
+
+ it('should see updated attribute', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+
+ await fixture.componentInstance.addOrUpdateAttribute(updatedAttribute, true);
+ expect(fixture.componentInstance.getAttributes().length).toEqual(4);
+ const attribute = fixture.componentInstance.getAttributes().filter( (attr) => {
+ return attr.uniqueId === updatedAttribute.uniqueId;
+ })[0];
+ expect(attribute.description).toEqual( 'description_new');
+ });
+
+ it('Add fails, make sure loader is deactivated and attribute is not added', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ const numAttributes = fixture.componentInstance.getAttributes().length;
+ await fixture.componentInstance.addOrUpdateAttribute(errorAttribute, false); // Add
+ expect(loaderServiceMock.deactivate).toHaveBeenCalled();
+ expect(fixture.componentInstance.getAttributes().length).toEqual(numAttributes);
+ });
+
+ it('Update fails, make sure loader is deactivated', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ const numAttributes = fixture.componentInstance.getAttributes().length;
+ await fixture.componentInstance.addOrUpdateAttribute(errorAttribute, true); // Add
+ expect(loaderServiceMock.deactivate).toHaveBeenCalled();
+ expect(fixture.componentInstance.getAttributes().length).toEqual(numAttributes);
+ });
+
+ it('on delete modal shell be opened', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ const event = { stopPropagation: jest.fn() };
+ fixture.componentInstance.onDeleteAttribute(event, fixture.componentInstance.getAttributes()[0]);
+ expect(event.stopPropagation).toHaveBeenCalled();
+ expect(modalServiceMock.openInfoModal).toHaveBeenCalled();
+ });
+
+ it('on add modal shell be opened', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ fixture.componentInstance.onAddAttribute();
+ expect(modalServiceMock.openCustomModal).toHaveBeenCalled();
+ });
+
+ it('on edit modal shell be opened', async () => {
+ await fixture.componentInstance.asyncInitComponent();
+ const event = { stopPropagation: jest.fn() };
+ fixture.componentInstance.onEditAttribute(event, fixture.componentInstance.getAttributes()[0]);
+ expect(event.stopPropagation).toHaveBeenCalled();
+ expect(modalServiceMock.openCustomModal).toHaveBeenCalled();
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.ts
new file mode 100644
index 0000000..bc47f14
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.component.ts
@@ -0,0 +1,188 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { Select } from '@ngxs/store';
+import { IAttributeModel } from 'app/models';
+import * as _ from 'lodash';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { ModalComponent } from 'onap-ui-angular/dist/modals/modal.component';
+import { AttributeModel } from '../../../../models';
+import { Resource } from '../../../../models';
+import { ModalsHandler } from '../../../../utils';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { WorkspaceState } from '../../../store/states/workspace.state';
+import { WorkspaceService } from '../workspace.service';
+import { AttributeModalComponent } from './attribute-modal.component';
+
+@Component({
+ selector: 'attributes',
+ templateUrl: './attributes.component.html',
+ styleUrls: ['./attributes.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class AttributesComponent implements OnInit {
+
+ @Select(WorkspaceState.isViewOnly)
+ isViewOnly$: boolean;
+
+ @ViewChild('componentAttributesTable')
+ private table: any;
+
+ private componentType: string;
+ private componentUid: string;
+
+ private attributes: IAttributeModel[] = [];
+ private temp: IAttributeModel[] = [];
+ private customModalInstance: ModalComponent;
+
+ constructor(private workspaceService: WorkspaceService,
+ private topologyTemplateService: TopologyTemplateService,
+ private modalsHandler: ModalsHandler,
+ private modalService: SdcUiServices.ModalService,
+ private loaderService: SdcUiServices.LoaderService,
+ private translateService: TranslateService) {
+
+ this.componentType = this.workspaceService.metadata.componentType;
+ this.componentUid = this.workspaceService.metadata.uniqueId;
+ }
+
+ ngOnInit(): void {
+ this.asyncInitComponent();
+ }
+
+ async asyncInitComponent() {
+ this.loaderService.activate();
+ const response = await this.topologyTemplateService.getComponentAttributes(this.componentType, this.componentUid);
+ this.attributes = response.attributes;
+ this.temp = [...response.attributes];
+ this.loaderService.deactivate();
+ }
+
+ getAttributes(): IAttributeModel[] {
+ return this.attributes;
+ }
+
+ addOrUpdateAttribute = async (attribute: AttributeModel, isEdit: boolean) => {
+ this.loaderService.activate();
+ let attributeFromServer: AttributeModel;
+ this.temp = [...this.attributes];
+
+ const deactivateLoader = () => {
+ this.loaderService.deactivate();
+ return undefined;
+ };
+
+ if (isEdit) {
+ attributeFromServer = await this.topologyTemplateService
+ .updateAttributeAsync(this.componentType, this.componentUid, attribute)
+ .catch(deactivateLoader);
+ if (attributeFromServer) {
+ const indexOfUpdatedAttribute = _.findIndex(this.temp, (e) => e.uniqueId === attributeFromServer.uniqueId);
+ this.temp[indexOfUpdatedAttribute] = attributeFromServer;
+ }
+ } else {
+ attributeFromServer = await this.topologyTemplateService
+ .addAttributeAsync(this.componentType, this.componentUid, attribute)
+ .catch(deactivateLoader);
+ if (attributeFromServer) {
+ this.temp.push(attributeFromServer);
+ }
+ }
+ this.attributes = this.temp;
+ this.loaderService.deactivate();
+ }
+
+ deleteAttribute = async (attributeToDelete: AttributeModel) => {
+ this.loaderService.activate();
+ this.temp = [...this.attributes];
+ const res = await this.topologyTemplateService.deleteAttributeAsync(this.componentType, this.componentUid, attributeToDelete);
+ _.remove(this.temp, (attr) => attr.uniqueId === attributeToDelete.uniqueId);
+ this.attributes = this.temp;
+ this.loaderService.deactivate();
+ };
+
+ openAddEditModal(selectedRow: AttributeModel, isEdit: boolean) {
+ const component = new Resource(undefined, undefined, undefined);
+ component.componentType = this.componentType;
+ component.uniqueId = this.componentUid;
+
+ const title: string = this.translateService.translate('ATTRIBUTE_DETAILS_MODAL_TITLE');
+ const attributeModalConfig = {
+ title,
+ size: 'md',
+ type: SdcUiCommon.ModalType.custom,
+ buttons: [
+ {
+ id: 'save',
+ text: 'Save',
+ // spinner_position: Placement.left,
+ size: 'sm',
+ callback: () => this.modalCallBack(isEdit),
+ closeModal: true,
+ disabled: false,
+ }
+ ] as SdcUiCommon.IModalButtonComponent[]
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(attributeModalConfig, AttributeModalComponent, { attributeToEdit: selectedRow });
+ this.customModalInstance.innerModalContent.instance.
+ onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('save').disabled = !isValid);
+ }
+
+ /***********************
+ * Call Backs from UI *
+ ***********************/
+
+ /**
+ * Called when 'Add' is clicked
+ */
+ onAddAttribute() {
+ this.openAddEditModal(new AttributeModel(), false);
+ }
+
+ /**
+ * Called when 'Edit' button is clicked
+ */
+ onEditAttribute(event, row) {
+ event.stopPropagation();
+
+ const attributeToEdit: AttributeModel = new AttributeModel(row);
+ this.openAddEditModal(attributeToEdit, true);
+ }
+
+ /**
+ * Called when 'Delete' button is clicked
+ */
+ onDeleteAttribute(event, row: AttributeModel) {
+ event.stopPropagation();
+ const onOk = () => {
+ this.deleteAttribute(row);
+ };
+
+ const title: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TITLE');
+ const message: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TEXT');
+ const okButton = new SdcUiComponents.ModalButtonComponent();
+ okButton.testId = 'OK';
+ okButton.text = 'OK';
+ okButton.type = SdcUiCommon.ButtonType.info;
+ okButton.closeModal = true;
+ okButton.callback = onOk;
+
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
+ }
+
+ onExpandRow(event) {
+ if (event.type === 'click') {
+ this.table.rowDetail.toggleExpandRow(event.row);
+ }
+ }
+
+ /**
+ * Callback from Modal after "Save" is clicked
+ *
+ * @param {boolean} isEdit - Whether modal is edit or add attribute
+ */
+ modalCallBack = (isEdit: boolean) => {
+ const attribute: AttributeModel = this.customModalInstance.innerModalContent.instance.attributeToEdit;
+ this.addOrUpdateAttribute(attribute, isEdit);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.module.ts b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.module.ts
new file mode 100644
index 0000000..5abb952
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attributes.module.ts
@@ -0,0 +1,32 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+import { GlobalPipesModule } from '../../../pipes/global-pipes.module';
+import { AttributesComponent } from './attributes.component';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { AttributeModalComponent } from './attribute-modal.component';
+import { TranslateModule } from '../../../shared/translator/translate.module';
+
+@NgModule({
+ declarations: [
+ AttributesComponent,
+ AttributeModalComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ GlobalPipesModule,
+ NgxDatatableModule,
+ TranslateModule
+ ],
+ exports: [
+ AttributesComponent
+ ],
+ entryComponents: [
+ AttributesComponent, AttributeModalComponent
+ ],
+ providers: [TopologyTemplateService]
+})
+export class AttributesModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/__snapshots__/deployment-artifacts-page.spec.ts.snap b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/__snapshots__/deployment-artifacts-page.spec.ts.snap
new file mode 100644
index 0000000..b536744
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/__snapshots__/deployment-artifacts-page.spec.ts.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`deployment artifacts page should match current snapshot of informational artifact pages component 1`] = `
+<deployment-artifact-page
+ addOrUpdateArtifact={[Function Function]}
+ artifactsService={[Function Object]}
+ cacheService={[Function Object]}
+ deleteArtifact={[Function Function]}
+ getEnvArtifact={[Function Function]}
+ modalService={[Function Object]}
+ openGenericArtifactBrowserModal={[Function Function]}
+ openPopOver={[Function Function]}
+ popoverContentComponent="undefined"
+ popoverService={[Function Object]}
+ sortArtifacts={[Function Function]}
+ store={[Function Store]}
+ table="undefined"
+ translateService={[Function Object]}
+ updateEnvParams={[Function Function]}
+ workspaceService={[Function Object]}
+>
+
+</deployment-artifact-page>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.html b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.html
new file mode 100644
index 0000000..35592d8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.html
@@ -0,0 +1,73 @@
+<div class="deployment-artifact-page" *ngIf="(workspaceState$ | async) as state">
+ <svg-icon-label *ngIf="!state.isViewOnly" class="add-artifact-btn" [clickable]="true" [mode]="'primary'" [labelPlacement]="'right'"
+ [label]="'Add'" [name]="'plus'"
+ (click)="addOrUpdateArtifact()"></svg-icon-label>
+ <ngx-datatable
+ columnMode="flex"
+ [headerHeight]="40"
+ [footerHeight]="'undefined'"
+ [reorderable]="false"
+ [swapColumns]="false"
+ [rows]="deploymentArtifacts$ | async"
+ #deploymentArtifactsTable>
+ <ngx-datatable-column [resizeable]="false" name="Name" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div *ngIf="row.generatedFromId" class="env-artifact-container">
+ <div class="env-artifact"></div>
+ </div>
+ <span sdc-tooltip [tooltip-text]="row.artifactDisplayName" [tooltip-placement]="3" [attr.data-tests-id]="'artifactDisplayName_' + row.artifactDisplayName">{{row.artifactDisplayName}}</span>
+ <span *ngIf="row.description.length > 0" class="info">
+ <svg-icon [clickable]="true" [name]="'comment'" [mode]="'primary2'" (click)="openPopOver('Description',row.description,{x:$event.pageX , y:$event.pageY },'bottom')"></svg-icon>
+ </span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="Type" [flexGrow]="0.6">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span sdc-tooltip [tooltip-text]="row.artifactType" [tooltip-placement]="3" [attr.data-tests-id]="'artifactType_' + row.artifactDisplayName">{{row.artifactType}}</span>
+ </ng-template>
+ </ngx-datatable-column> exactly 2 tosca artifacts
+ <ngx-datatable-column [resizeable]="false" name="Version" [flexGrow]="0.3">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span [attr.data-tests-id]="'artifactVersion_' + row.artifactDisplayName">{{ row.artifactVersion }}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="UUID" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span sdc-tooltip [tooltip-text]="row.artifactUUID" [tooltip-placement]="3">{{ row.artifactUUID }}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [flexGrow]="0.6">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class="download-artifact-button">
+ <svg-icon *ngIf="!row.heatParameters?.length && !state.isViewOnly" class="action-icon" [mode]="'primary2'" [name]="'edit-o'"
+ testId="edit_{{row.artifactDisplayName}}" clickable="true" size="medium"
+ (click)="addOrUpdateArtifact(row, state.isViewOnly)"></svg-icon>
+ <svg-icon *ngIf="row.heatParameters?.length && !state.isViewOnly" class="action-icon" [mode]="'primary2'" [name]="'indesign_status'"
+ testId="update_heat_params_{{row.artifactDisplayName}}" clickable="true" size="medium"
+ (click)="updateEnvParams(row, state.isViewOnly)"></svg-icon>
+ <svg-icon *ngIf="!row.isFromCsar && !state.isViewOnly" class="action-icon" [mode]="'primary2'" [name]="'trash-o'"
+ testId="delete_{{row.artifactDisplayName}}" clickable="true" size="medium" (click)="deleteArtifact(row)"></svg-icon>
+ <svg-icon *ngIf="row.isGenericBrowseable()" class="action-icon" [mode]="'primary2'" [name]="'search-o'"
+ testId="gab-{{row.artifactDisplayName}}" clickable="true" size="medium" (click)="openGenericArtifactBrowserModal(row)"></svg-icon>
+
+ <!--Download-->
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-footer>
+ <ng-template ngx-datatable-footer-template>
+ <div class="table-footer-container">
+ <sdc-button *ngIf="!state.isViewOnly" [type]="'secondary'"
+ [testId]="'add_artifact_btn'"
+ [text]="'DEPLOYMENT_ARTIFACT_BUTTON_ADD_OTHER' | translate"
+ [icon_name]="'plus-circle-o'"
+ [icon_mode] = "'secondary'"
+ [icon_position]="'left'"
+ (click)="addOrUpdateArtifact()">
+ </sdc-button>
+ </div>
+ </ng-template>
+ </ngx-datatable-footer>
+ </ngx-datatable>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.less b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.less
new file mode 100644
index 0000000..22ceb96
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.less
@@ -0,0 +1,55 @@
+.deployment-artifact-page {
+
+
+ .env-artifact-container {
+ margin-left: -25px;
+ margin-top: -21px;
+ padding-left: 10px;
+ position: absolute;
+ background-color: white;
+ .env-artifact {
+ border-left: 1px #848586 solid;
+ height: 33px;
+
+ border-top: 1px #848586 solid;
+ border-bottom: 1px #848586 solid;
+ width: 10px;
+ float: left;
+
+ }
+ }
+ .add-artifact-btn {
+ display: flex;
+ cursor: pointer;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+ }
+ .download-artifact-button {
+ display: flex;
+ justify-content: center;
+
+ .action-icon {
+ margin-right: 10px;
+ }
+ }
+
+ .table-footer-container {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ justify-content: center;
+ margin: 20px 0px;
+ }
+}
+
+:host ::ng-deep {
+
+ .ngx-datatable {
+ //border: 1px solid red;
+ .datatable-body-cell {
+ .info {
+ float: right;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.ts
new file mode 100644
index 0000000..53b21b3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.component.ts
@@ -0,0 +1,155 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { Select, Store } from '@ngxs/store';
+import { ArtifactModel } from 'app/models';
+import * as _ from 'lodash';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/index';
+import { map } from 'rxjs/operators';
+import { GabConfig } from '../../../../models/gab-config';
+import { PathsAndNamesDefinition } from '../../../../models/paths-and-names';
+import { GenericArtifactBrowserComponent } from '../../../../ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component';
+import { ArtifactGroupType, ArtifactType } from '../../../../utils/constants';
+import { ArtifactsService } from '../../../components/forms/artifacts-form/artifacts.service';
+import { PopoverContentComponent } from '../../../components/ui/popover/popover-content.component';
+import { CacheService } from '../../../services/cache.service';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { GetArtifactsByTypeAction } from '../../../store/actions/artifacts.action';
+import { ArtifactsState } from '../../../store/states/artifacts.state';
+import { WorkspaceState, WorkspaceStateModel } from '../../../store/states/workspace.state';
+import { WorkspaceService } from '../workspace.service';
+import { ModalService } from 'app/ng2/services/modal.service';
+
+export interface IPoint {
+ x: number;
+ y: number;
+}
+
+@Component({
+ selector: 'deployment-artifact-page',
+ templateUrl: './deployment-artifacts-page.component.html',
+ styleUrls: ['./deployment-artifacts-page.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class DeploymentArtifactsPageComponent implements OnInit {
+
+ public componentId: string;
+ public componentType: string;
+ public deploymentArtifacts$: Observable<ArtifactModel[]>;
+ public isComponentInstanceSelected: boolean;
+
+ @Select(WorkspaceState) workspaceState$: Observable<WorkspaceStateModel>;
+ @ViewChild('informationArtifactsTable') table: any;
+ @ViewChild('popoverForm') popoverContentComponent: PopoverContentComponent;
+
+ constructor(private workspaceService: WorkspaceService,
+ private artifactsService: ArtifactsService,
+ private store: Store,
+ private popoverService: SdcUiServices.PopoverService,
+ private cacheService: CacheService,
+ private modalService: SdcUiServices.ModalService,
+ private translateService: TranslateService) {
+ }
+
+ private getEnvArtifact = (heatArtifact: ArtifactModel, artifacts: ArtifactModel[]): ArtifactModel => {
+ return _.find(artifacts, (item: ArtifactModel) => {
+ return item.generatedFromId === heatArtifact.uniqueId;
+ });
+ };
+
+ // we need to sort the artifact in a way that the env artifact is always under the artifact he is connected to- this is cause of the way the ngx databale work
+ private sortArtifacts = ((artifacts) => {
+ const sortedArtifacts = [];
+ _.forEach(artifacts, (artifact: ArtifactModel): void => {
+ const envArtifact = this.getEnvArtifact(artifact, artifacts);
+ if (!artifact.generatedFromId) {
+ sortedArtifacts.push(artifact);
+ }
+ if (envArtifact) {
+ sortedArtifacts.push(envArtifact);
+ }
+ });
+ return sortedArtifacts;
+ })
+
+ ngOnInit(): void {
+ this.componentId = this.workspaceService.metadata.uniqueId;
+ this.componentType = this.workspaceService.metadata.componentType;
+
+ this.store.dispatch(new GetArtifactsByTypeAction({
+ componentType: this.componentType,
+ componentId: this.componentId,
+ artifactType: ArtifactGroupType.DEPLOYMENT
+ }));
+ this.deploymentArtifacts$ = this.store.select(ArtifactsState.getArtifactsByType).pipe(map((filterFn) => filterFn(ArtifactType.DEPLOYMENT))).pipe(map(artifacts => {
+ return this.sortArtifacts(artifacts);
+ }));
+ }
+
+ onActivate(event) {
+ if (event.type === 'click') {
+ this.table.rowDetail.toggleExpandRow(event.row);
+ }
+ }
+
+ public addOrUpdateArtifact = (artifact: ArtifactModel, isViewOnly: boolean) => {
+ this.artifactsService.openArtifactModal(this.componentId, this.componentType, artifact, ArtifactGroupType.DEPLOYMENT, isViewOnly);
+ }
+
+ public deleteArtifact = (artifactToDelete) => {
+ this.artifactsService.deleteArtifact(this.componentType, this.componentId, artifactToDelete);
+ }
+
+ private openPopOver = (title: string, content: string, positionOnPage: IPoint, location: string) => {
+ this.popoverService.createPopOver(title, content, positionOnPage, location);
+ }
+
+ public updateEnvParams = (artifact: ArtifactModel, isViewOnly: boolean) => {
+ this.artifactsService.openUpdateEnvParams(this.componentType, this.componentId, artifact );
+ }
+
+ private openGenericArtifactBrowserModal = (artifact: ArtifactModel): void => {
+ const titleStr = 'Generic Artifact Browser';
+ const modalConfig = {
+ size: 'sdc-xl',
+ title: titleStr,
+ type: SdcUiCommon.ModalType.custom,
+ buttons: [{
+ id: 'closeGABButton',
+ text: 'Close',
+ size: 'sm',
+ closeModal: true
+ }] as SdcUiCommon.IModalButtonComponent[]
+ };
+
+ const uiConfiguration: any = this.cacheService.get('UIConfiguration');
+ let noConfig: boolean = false;
+ let pathsandnamesArr: PathsAndNamesDefinition[] = [];
+
+ if (typeof uiConfiguration.gab === 'undefined') {
+ noConfig = true;
+ } else {
+ const gabConfig: GabConfig = uiConfiguration.gab
+ .find((config) => config.artifactType === artifact.artifactType);
+ if (typeof gabConfig === 'undefined') {
+ noConfig = true;
+ } else {
+ pathsandnamesArr = gabConfig.pathsAndNamesDefinitions;
+ }
+ }
+
+
+ if (noConfig) {
+ const msg = this.translateService.translate('DEPLOYMENT_ARTIFACT_GAB_NO_CONFIG');
+ this.modalService.openAlertModal(titleStr, msg);
+ }
+
+ const modalInputs = {
+ pathsandnames: pathsandnamesArr,
+ artifactid: artifact.esId,
+ resourceid: this.componentId
+ };
+
+ this.modalService.openCustomModal(modalConfig, GenericArtifactBrowserComponent, modalInputs);
+
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.module.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.module.ts
new file mode 100644
index 0000000..398e9d3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.module.ts
@@ -0,0 +1,35 @@
+import {CommonModule} from "@angular/common";
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {UiElementsModule} from "../../../components/ui/ui-elements.module";
+import {ArtifactFormModule} from "../../../components/forms/artifacts-form/artifact-form.module";
+import {ArtifactsService} from "../../../components/forms/artifacts-form/artifacts.service";
+import {DeploymentArtifactsPageComponent} from "./deployment-artifacts-page.component";
+import {TranslatePipe} from "../../../shared/translator/translate.pipe";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+import {GenericArtifactBrowserModule} from "../../../components/logic/generic-artifact-browser/generic-artifact-browser.module";
+
+@NgModule({
+ declarations: [
+ DeploymentArtifactsPageComponent
+ ],
+ imports: [
+ TranslateModule,
+ CommonModule,
+ SdcUiComponentsModule,
+ NgxDatatableModule,
+ UiElementsModule,
+ ArtifactFormModule,
+ GenericArtifactBrowserModule
+ ],
+ exports: [
+ DeploymentArtifactsPageComponent
+ ],
+ entryComponents: [
+ DeploymentArtifactsPageComponent
+ ],
+ providers:[ArtifactsService]
+})
+export class DeploymentArtifactsPageModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.spec.ts
new file mode 100644
index 0000000..056efdc
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment-artifacts/deployment-artifacts-page.spec.ts
@@ -0,0 +1,86 @@
+// import ' rxjs/add/observable/of';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture } from '@angular/core/testing';
+import { NgxsModule, Store } from '@ngxs/store';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Observable } from 'rxjs/Observable';
+import { deploymentArtifactMock } from '../../../../../jest/mocks/artifacts-mock';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { ArtifactsService } from '../../../components/forms/artifacts-form/artifacts.service';
+import { CacheService } from '../../../services/cache.service';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { TranslateModule } from '../../../shared/translator/translate.module';
+import { TranslateService } from '../../../shared/translator/translate.service';
+import { ArtifactsState } from '../../../store/states/artifacts.state';
+import { WorkspaceService } from '../workspace.service';
+import { DeploymentArtifactsPageComponent } from './deployment-artifacts-page.component';
+import {ModalService} from "../../../services/modal.service";
+
+describe('deployment artifacts page', () => {
+
+ let fixture: ComponentFixture<DeploymentArtifactsPageComponent>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let store: Store;
+
+ beforeEach(
+ async(() => {
+
+ topologyTemplateServiceMock = {
+ getArtifactsByType: jest.fn().mockImplementation((componentType, id, artifactType) => Observable.of(deploymentArtifactMock))
+ };
+ workspaceServiceMock = {
+ metadata: <ComponentMetadata>{
+ uniqueId: 'service_unique_id',
+ componentType: 'SERVICE'
+ }
+ }
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ }
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [DeploymentArtifactsPageComponent],
+ imports: [NgxDatatableModule, TranslateModule, NgxsModule.forRoot([ArtifactsState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: TopologyTemplateService, useValue: topologyTemplateServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock},
+ {provide: ArtifactsService, useValue: {}},
+ {provide: SdcUiServices.PopoverService, useValue: {}},
+ {provide: CacheService, useValue: {}},
+ {provide: SdcUiServices.ModalService, useValue: {}},
+ {provide: ModalService, useValue: {}},
+ {provide: TranslateService, useValue: {}}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(DeploymentArtifactsPageComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it('should match current snapshot of informational artifact pages component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should see exactly 2 tosca artifacts', () => {
+ fixture.componentInstance.ngOnInit();
+ fixture.componentInstance.deploymentArtifacts$.subscribe((artifacts) => {
+ expect(artifacts.length).toEqual(8);
+ })
+ store.selectOnce((state) => state.artifacts.deploymentArtifacts).subscribe((artifacts) => {
+ expect(artifacts.length).toEqual(8);
+ });
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.html b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.html
new file mode 100644
index 0000000..8852772
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.html
@@ -0,0 +1,11 @@
+<div class="deployment-page">
+ <deployment-graph></deployment-graph>
+ <panel-wrapper-component>
+ <sdc-tabs class="deployment-tabs" [iconsSize]="'large'" [isVertical]="true">
+ <sdc-tab *ngFor="let tab of tabs" [titleIcon]="tab.titleIcon" [active]="tab.isActive"
+ [tooltipText]="tab.tooltipText">
+ <hierarchy-tab *ngIf="isDataAvailable" [isViewOnly]="(isViewOnly$ | async)"></hierarchy-tab>
+ </sdc-tab>
+ </sdc-tabs>
+ </panel-wrapper-component>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.less b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.less
new file mode 100644
index 0000000..4b7a1e7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.less
@@ -0,0 +1,24 @@
+@import './../../../../../assets/styles/variables.less';
+@import './../../../../../assets/styles/override.less';
+.deployment-page {
+ width: 100%;
+ height: 100%;
+
+ /deep/ .sdc-tabs {
+ height: 100%;
+ }
+ /deep/ .sdc-tabs-list {
+ position: absolute;
+ top: 22px;
+ right: 303px;
+ background-color: @sdcui_color_silver;
+
+ svg-icon-label {
+ vertical-align: middle;
+ }
+ }
+ /deep/ .sdc-tab-content {
+ height: 100%;
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.ts
new file mode 100644
index 0000000..12bd536
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.component.ts
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {Component} from "@angular/core";
+import {HierarchyTabComponent} from "./panel/panel-tabs/hierarchy-tab/hierarchy-tab.component";
+import {ComponentGenericResponse} from "../../../services/responses/component-generic-response";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../workspace.service";
+import {Module} from "app/models";
+import {SdcUiServices} from "onap-ui-angular";
+import {Select} from "@ngxs/store";
+import {WorkspaceState} from "../../../store/states/workspace.state";
+import {DeploymentGraphService} from "../../composition/deployment/deployment-graph.service";
+
+const tabs =
+ {
+ hierarchyTab: {
+ titleIcon: 'composition-o',
+ component: HierarchyTabComponent,
+ input: {},
+ isActive: true,
+ tooltipText: 'Hierarchy'
+ }
+ };
+
+@Component({
+ selector: 'deployment-page',
+ templateUrl: './deployment-page.component.html',
+ styleUrls: ['deployment-page.component.less']
+})
+
+export class DeploymentPageComponent {
+ public tabs: Array<any>;
+ public resourceType: string;
+ public modules: Array<Module>;
+ public isDataAvailable: boolean;
+
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+
+ constructor(private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private deploymentService: DeploymentGraphService,
+ private loaderService: SdcUiServices.LoaderService) {
+ this.tabs = [];
+ this.isDataAvailable = false;
+ }
+
+ ngOnInit(): void {
+ this.topologyTemplateService.getDeploymentGraphData(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId).subscribe((response: ComponentGenericResponse) => {
+ this.deploymentService.componentInstances = response.componentInstances;
+ this.deploymentService.componentInstancesRelations = response.componentInstancesRelations;
+ this.deploymentService.modules = response.modules;
+ this.isDataAvailable = true;
+ this.loaderService.deactivate();
+ });
+
+ this.loaderService.activate();
+ this.resourceType = this.workspaceService.getMetadataType();
+ this.tabs.push(tabs.hierarchyTab);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.module.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.module.ts
new file mode 100644
index 0000000..3635e8f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/deployment-page.module.ts
@@ -0,0 +1,30 @@
+/**
+ * Created by ob0695 on 6/4/2018.
+ */
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {DeploymentPageComponent} from "./deployment-page.component";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {UiElementsModule} from "../../../components/ui/ui-elements.module";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+import {GlobalPipesModule} from "../../../pipes/global-pipes.module";
+import {HierarchyTabModule} from "./panel/panel-tabs/hierarchy-tab/hierarchy-tab.module";
+import {DeploymentGraphService} from "../../composition/deployment/deployment-graph.service";
+import {DeploymentGraphModule} from "../../composition/deployment/deployment-graph.module";
+
+@NgModule({
+ declarations: [DeploymentPageComponent],
+ imports: [CommonModule,
+ DeploymentGraphModule,
+ SdcUiComponentsModule,
+ UiElementsModule,
+ TranslateModule,
+ GlobalPipesModule,
+ HierarchyTabModule
+ ],
+ exports: [DeploymentPageComponent],
+ entryComponents: [DeploymentPageComponent],
+ providers: [DeploymentGraphService]
+})
+export class DeploymentPageModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.html b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.html
new file mode 100644
index 0000000..d5b9d9e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.html
@@ -0,0 +1,29 @@
+<div class="edit-module-name">
+ <div class="edit-module-name-label vfInstance-name" data-tests-id="popover-vfinstance-name" sdc-tooltip [tooltip-text]="selectModule.vfInstanceName">{{selectModule.vfInstanceName}}</div>
+ <div class="edit-module-name-heatName">
+ <sdc-input #heatName [maxLength]="50"
+ [(value)]="selectModule.heatName"
+ [testId]="'popover-heat-name'"
+ [placeHolder]="'Enter Name'">
+ </sdc-input>
+ <sdc-validation [validateElement]="heatName">
+ <sdc-regex-validator [message]="'Special characters not allowed.'" [pattern]="pattern"></sdc-regex-validator>
+ </sdc-validation>
+ </div>
+ <div class="edit-module-name-label module-name" data-tests-id="'popover-module-name'" sdc-tooltip [tooltip-text]="selectModule.moduleName">{{selectModule.moduleName}}</div>
+ <sdc-button class="edit-module-name-btn cancel-button"
+ [text]="'Cancel'"
+ [testId]="'popover-close-button'"
+ [type]="'primary'"
+ [size] = "'small'"
+ (click)="clickButton(false)">
+ </sdc-button>
+ <sdc-button class="edit-module-name-btn save-button"
+ [text]="'Save'"
+ [testId]="'popover-save-button'"
+ [type]="'primary'"
+ [size] = "'small'"
+ (click)="clickButton(true)"
+ [disabled]="selectModule.heatName == originalName">
+ </sdc-button>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.less b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.less
new file mode 100644
index 0000000..721ad53
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.less
@@ -0,0 +1,20 @@
+.edit-module-name-btn{
+ float:right;
+ margin-left: 10px;
+ margin-bottom: 20px;
+}
+.save-button {
+ margin-left: 30px;
+}
+.cancel-button {
+ margin-left: 20px;
+}
+.edit-module-name-heatName {
+ margin-bottom: 15px;
+}
+.edit-module-name-label {
+ text-overflow: ellipsis;
+ display: block;
+ white-space: nowrap;
+ margin-bottom: 10px;
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.ts
new file mode 100644
index 0000000..819182c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.ts
@@ -0,0 +1,24 @@
+import { Component, Input, Output, OnInit } from "@angular/core";
+import { EventEmitter } from "@angular/core";
+import { DisplayModule } from "../../../../../../../models/modules/base-module";
+import { ValidationConfiguration } from "../../../../../../../models/validation-config";
+
+@Component({
+ selector: 'edit-module-name',
+ templateUrl: './edit-module-name.component.html',
+ styleUrls: ['edit-module-name.component.less']
+})
+export class EditModuleName implements OnInit{
+ @Input() selectModule:DisplayModule;
+ @Output() clickButtonEvent: EventEmitter<String> = new EventEmitter();
+ private pattern = ValidationConfiguration.validation.validationPatterns.stringOrEmpty;
+ private originalName: string;
+ constructor(){}
+ public ngOnInit(): void {
+ this.originalName = this.selectModule.heatName;
+ }
+
+ private clickButton(saveOrCancel: boolean) : void {
+ this.clickButtonEvent.emit(saveOrCancel ? this.selectModule.heatName : null);
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.html b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.html
new file mode 100644
index 0000000..7c0e60b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.html
@@ -0,0 +1,119 @@
+<div class="sdc-hierarchy-tab" ng-class="">
+ <sdc-loader [global]="false" [testId]="'hierarchy-tab-loader'" [active]="isLoading" [relative]="true" [size]="'medium'"></sdc-loader>
+ <div class="sdc-hierarchy-tab-title"
+ [attr.data-tests-id]="'tab-header'">{{'DEPLOYMENT_TAB_TITLE' | translate }}</div>
+ <div [ngClass]="{'scroll-module-list': selectedModule}">
+ <div *ngIf="topologyTemplateType != 'SERVICE'; else isService" class="modules-list">
+ <div>
+ <div class="sdc-hierarchy-tab-sub-title" data-tests-id="tab-sub-header">{{topologyTemplateName}}</div>
+ <div *ngFor="let module of modules; index as i">
+ <sdc-accordion [title]="module.name" [arrow-direction]="'left'"
+ [css-class]="'expand-collapse-container'"
+ [ngClass]="{'selected': selectedModule !== undefined && selectedModule.uniqueId === module.uniqueId}"
+ [testId]="'hierarchy-module-' + i + '-title'" tooltip="{{module.name}}"
+ (click)="onModuleSelected(module)">
+ <div *ngFor="let memberId of getKeys(module.members)">
+ <div class="expand-collapse-sub-title" tooltip="{{memberId}}">{{memberId}}</div>
+ </div>
+ </sdc-accordion>
+ </div>
+ </div>
+ </div>
+
+ <ng-template #isService>
+ <div class="module-list">
+ <div *ngFor="let instance of componentInstances; index as instanceIndex">
+ <sdc-accordion [title]="instance.name" [arrow-direction]="'left'"
+ [css-class]="'expand-collapse-container outer-container'"
+ [testId]="'hierarchy-instance-' + instanceIndex + '-title'"
+ tooltip="{{instance.name}}">
+ <div *ngFor="let module of instance.groupInstances; index as moduleIndex">
+ <sdc-accordion [title]="module.name" [arrow-direction]="'left'"
+ [css-class]="'expand-collapse-container inner-container'"
+ [ngClass]="{'selected': selectedModule && selectedModule.groupInstanceUniqueId === module.uniqueId}"
+ [testId]="'hierarchy-module-' + moduleIndex + '-title'"
+ tooltip="{{module.uniqueId}}"
+ (click)="onModuleSelected(module, instance.uniqueId)">
+ <div *ngFor="let memberId of getKeys(module.members)">
+ <div class="expand-collapse-sub-title" tooltip="{{memberId}}">{{memberId}}</div>
+ </div>
+ </sdc-accordion>
+ </div>
+ </sdc-accordion>
+ </div>
+ </div>
+ </ng-template>
+
+ <!--TODO: Add Resizable-->
+ <div *ngIf="selectedModule"class="module-data-container" [attr.data-tests-id]="'selected-module-data'">
+ <div class="module-data">
+ <div class="module-name-container">
+ <div class="module-name module-text-overflow" [attr.data-tests-id]="'selected-module-name'"
+ tooltip="{{selectedModule.name}}">{{selectedModule.name}}</div>
+ <div class="edit-name-container" *ngIf="topologyTemplateType != 'SERVICE'">
+ <svg-icon name="edit-o" [size]="'medium'" [ngClass]="{'hand-pointer': !isViewOnly}" (click)="openEditModuleNamePopup($event)"></svg-icon>
+ </div>
+ </div>
+ <div [attr.data-tests-id]="'selected-module-group-uuid'" tooltip="{{selectedModule.groupUUID}}">
+ <div class="selected-module-property-header">Module ID:</div>
+ <div class="selected-module-property-value small-font">{{selectedModule.groupUUID}}</div>
+ </div>
+ <div [attr.data-tests-id]="'selected-module-group-customization-uuid'"
+ *ngIf="topologyTemplateType == 'SERVICE' && isViewOnly"
+ tooltip="{{selectedModule.customizationUUID}}">
+ <div class="selected-module-property-header">Customization ID:</div>
+ <div class="selected-module-property-value small-font">{{selectedModule.customizationUUID}}</div>
+ </div>
+ <div [attr.data-tests-id]="'selected-module-group-invariant-uuid'"
+ tooltip="{{selectedModule.invariantUUID}}">
+ <div class="selected-module-property-header">Invariant UUID:</div>
+ <div class="selected-module-property-value small-font">{{selectedModule.invariantUUID}}</div>
+ </div>
+ <div [attr.data-tests-id]="'selected-module-version'" class="selected-module-property-container">
+ <div class="selected-module-property-header">Version:</div>
+ <div class="selected-module-property-value same-row">{{selectedModule.version}}</div>
+ </div>
+ <div data-tests-id="selected-module-is-base" class="selected-module-property-container">
+ <div class="selected-module-property-header">IsBase:</div>
+ <div class="selected-module-property-value same-row">{{selectedModule.isBase}}</div>
+ </div>
+
+ </div>
+ <sdc-accordion [title]="'Properties'" [arrow-direction]="'right'"
+ [css-class]="'expand-collapse-module-data-container'">
+ <div *ngFor="let property of selectedModule.properties | orderBy:['name']:['asc']">
+ <div class="module-data-list-item">
+ <div class="module-data-list-item-value property-name"
+ [attr.data-tests-id]="'selected-module-property-name'">
+ <span tooltip="{{property.name}}" [ngClass]="{'hand-pointer': !isViewOnly}"
+ (click)="!isViewOnly && openEditPropertyModal(property)">{{property.name}}</span>
+ </div>
+ <div class="module-data-list-item-value property-info"
+ [attr.data-tests-id]="'selected-module-property-type'"> Type: {{property.type}}</div>
+ <div class="module-data-list-item-value property-info"
+ [attr.data-tests-id]="'selected-module-property-schema-type'">
+ Value: {{property.value}}</div>
+ </div>
+ </div>
+ </sdc-accordion>
+ <sdc-accordion [title]="'Artifacts'" [arrow-direction]="'right'"
+ [css-class]="'expand-collapse-module-data-container'">
+ <div *ngFor="let artifact of selectedModule.artifacts | orderBy:['artifactName']:['asc']">
+ <div class="module-data-list-item">
+ <div class="artifact-list-item">
+ <div class="module-data-list-item-value"
+ [attr.data-tests-id]="'selected-module-artifact-name'"
+ tooltip="{{artifact.artifactName}}">{{artifact.artifactName}}</div>
+ <div class="module-data-list-item-value artifact-info"
+ [attr.data-tests-id]="'selected-module-artifact-uuid'"
+ tooltip="{{artifact.artifactUUID}}">UUID: {{artifact.artifactUUID}}</div>
+ <div class="module-data-list-item-value artifact-info"
+ [attr.data-tests-id]="'selected-module-artifact-version'">
+ Version: {{artifact.artifactVersion}}</div>
+ </div>
+ </div>
+ </div>
+ </sdc-accordion>
+ </div>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.less b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.less
new file mode 100644
index 0000000..269ca0a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.less
@@ -0,0 +1,222 @@
+@import './../../../../../../../../assets/styles/variables.less';
+.sdc-hierarchy-tab {
+ padding: 15px 0 0 0;
+ background-color: #f8f8f8;
+ height: 100%;
+ box-shadow: 0.3px 1px 3px rgba(24, 24, 25, 0.42);
+ display: flex;
+ flex-flow: column;
+
+ .sdc-hierarchy-tab-title {
+ color: @main_color_a;
+ padding: 0 0 15px 20px;
+ border-bottom: 1px solid #d2d2d2;
+ }
+
+ .sdc-hierarchy-tab-sub-title {
+ color: @main_color_a;
+ padding: 15px 20px 15px 20px;
+ }
+
+ .scroll-module-list {
+ overflow-y: auto;
+ display: flex;
+ height: 100%;
+ flex-direction: column;
+ }
+
+ /deep/ .expand-collapse-container {
+ margin-bottom: 0;
+
+ .sdc-accordion-header {
+ white-space: nowrap;
+ line-height: 22px;
+ background-color: @tlv_color_u;
+ padding: 8px 20px 8px 8px;
+ box-shadow: inset 0px -1px 0px 0px rgba(255, 255, 255, 0.7);
+ height: 40px;
+
+ .title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 215px;
+ }
+ }
+
+ .sdc-accordion-body.open {
+ padding: 0 0 5px 0;
+ }
+
+ .sdc-accordion-header:hover {
+ background-color: @main_color_o;
+ }
+
+ &.outer-container {
+ .sdc-accordion-body {
+ padding-left: 0;
+ }
+ }
+
+ &.inner-container {
+ margin-bottom: 0;
+
+ .sdc-accordion-header {
+ padding: 8px 20px 8px 30px;
+ background-color: @tlv_color_t
+ }
+ }
+ }
+
+ sdc-accordion.selected {
+ /deep/ .expand-collapse-container {
+ .sdc-accordion-header {
+ background-color: @main_color_a;
+ color: @main_color_p;
+
+ .svg-icon {
+ fill: @main_color_p;
+ }
+ }
+ }
+ }
+
+ .expand-collapse-sub-title {
+ max-width: 225px;
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 10px 0 0 33px;
+ }
+
+ .expand-collapse-content {
+ .expand-collapse-title {
+ padding: 0 10px 0 30px;
+ }
+ }
+
+ .module-data-container {
+ width: 100%;
+ overflow-y: overlay;
+ background-color: @tlv_color_v;
+ border: 1px solid @main_color_a;
+ border-top: 4px solid @main_color_a;
+ box-shadow: 0.3px 1px 2px rgba(24, 24, 25, 0.32);
+ .module-data {
+ color: @main_color_a;
+ padding: 10px 0 10px 0;
+ margin: 0 20px 0 20px;
+
+ .selected-module-property-header {
+ font-weight: bold;
+ }
+
+ .selected-module-property-value {
+ font-family: @font-opensans-regular;
+
+ &.small-font {
+ font-size: 12px;
+ }
+ }
+
+ .module-name-container {
+
+ display: flex;
+ flex-direction: row;
+
+ .module-name {
+ font-size: 14px;
+ width: 75%;
+ max-width: 240px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .edit-name-container {
+ float: right;
+ border-left: 1px solid @main_color_a;
+ height: 20px;
+ padding-left: 12px;
+
+ svg-icon {
+ padding-top: 3px;
+ fill: @main_color_s;
+
+ &.hand-pointer {
+ cursor: pointer;
+ }
+
+ }
+ }
+ }
+ }
+
+ .selected-module-property-container {
+ flex-direction: row;
+ display: flex;
+
+ .selected-module-property-value {
+ text-indent: 2px;
+ }
+ }
+
+ /deep/ .expand-collapse-module-data-container {
+ margin-bottom: 0;
+
+ .sdc-accordion-header {
+ white-space: nowrap;
+ line-height: 22px;
+ padding: 8px 20px 8px 16px;
+ height: 40px;
+ background-color: @tlv_color_w;
+ color: @main_color_l;
+ border-top: 1px solid @main_color_a;
+ border-bottom: 1px solid @main_color_a;
+ width: 100%;
+ }
+
+ }
+
+ .module-data-list-item {
+ padding-bottom: 10px;
+ margin: 0 20px 0 20px;
+
+ .artifact-list-item {
+ color: @main_color_m;
+ }
+
+ .module-data-list-item-value {
+ width: 100%;
+ max-width: 240px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ &.artifact-info {
+ font-family: @font-opensans-regular;
+ font-size: 12px;
+ }
+
+ &.property-name {
+ font-weight: 400;
+ color: @main_color_a;
+
+ .hand-pointer {
+ cursor: pointer;
+ }
+ }
+
+ &.property-info {
+ color: @func_color_s;
+ font-family: @font-opensans-regular;
+ }
+ }
+ }
+ }
+}
+
+.modules-list {
+ overflow-y: overlay;
+ flex-grow: 1;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.spec.ts
new file mode 100644
index 0000000..ab88867
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.spec.ts
@@ -0,0 +1,133 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {HierarchyTabComponent} from "./hierarchy-tab.component";
+import {ConfigureFn, configureTests} from "../../../../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {TranslateModule} from "../../../../../../shared/translator/translate.module";
+import {TopologyTemplateService} from "../../../../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../../../../workspace.service";
+import {ModulesService} from "../../../../../../services/modules.service";
+import {GlobalPipesModule} from "../../../../../../pipes/global-pipes.module";
+import {TranslateService} from "../../../../../../shared/translator/translate.service";
+import {ModalsHandler} from "../../../../../../../utils/modals-handler";
+import {ComponentFactory} from "../../../../../../../utils/component-factory";
+import {NgxsModule} from "@ngxs/store";
+import { SdcUiServices } from "onap-ui-angular";
+import {Observable} from "rxjs";
+import {DisplayModule, Module} from "../../../../../../../models/modules/base-module";
+import {DeploymentGraphService} from "../../../../../composition/deployment/deployment-graph.service";
+import {ComponentMetadata} from "../../../../../../../models/component-metadata";
+
+describe('HierarchyTabComponent', () => {
+
+ let fixture: ComponentFixture<HierarchyTabComponent>;
+ let workspaceService: Partial<WorkspaceService>;
+ let popoverServiceMock: Partial<SdcUiServices.PopoverService>;
+ let modulesServiceMock: Partial<ModulesService>;
+
+ let editModuleNameInstanceMock = {innerPopoverContent:{instance: { clickButtonEvent: Observable.of("new heat name")}},
+ closePopover: jest.fn()};
+ let eventMock = {x: 1650, y: 350};
+ let moduleMock: Array<Module> = [{name: "NewVf2..base_vepdg..module-0", uniqueId: '1'}];
+ let selectedModuleMock: DisplayModule = {name: "NewVf2..base_vepdg..module-0", vfInstanceName: "NewVf2", moduleName:"module-0",
+ heatName: "base_vepdg", uniqueId: '1', updateName: jest.fn().mockImplementation(() => {
+ selectedModuleMock.name = selectedModuleMock.vfInstanceName + '..' + selectedModuleMock.heatName + '..' +
+ selectedModuleMock.moduleName;})}
+ let updateSelectedModuleMock = () => {
+ selectedModuleMock.heatName = "base_vepdg";
+ selectedModuleMock.name = "NewVf2..base_vepdg..module-0";
+ fixture.componentInstance.selectedModule = selectedModuleMock;
+ fixture.componentInstance.modules = moduleMock;
+ }
+ beforeEach(
+ async(() => {
+
+ workspaceService ={
+ metadata: <ComponentMetadata> {
+ name: '',
+ componentType: ''
+ }
+ }
+ popoverServiceMock = {
+ createPopOverWithInnerComponent: jest.fn().mockImplementation(() => {return editModuleNameInstanceMock})
+ }
+ modulesServiceMock = {
+ updateModuleMetadata: jest.fn().mockReturnValue(Observable.of({}))
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [HierarchyTabComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ imports: [TranslateModule, NgxsModule.forRoot([]), GlobalPipesModule],
+ providers: [
+ {provide: DeploymentGraphService, useValue: {}},
+ {provide: ComponentFactory, useValue: {}},
+ {provide: TopologyTemplateService, useValue: {}},
+ {provide: WorkspaceService, useValue: workspaceService},
+ {provide: ModulesService, useValue: modulesServiceMock},
+ {provide: TranslateService, useValue: {}},
+ {provide: ModalsHandler, useValue: {}},
+ {provide: SdcUiServices.PopoverService, useValue: popoverServiceMock}
+ ]
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(HierarchyTabComponent);
+ });
+ })
+ );
+
+ it('expected heirarchy component to be defined', () => {
+ expect(fixture).toBeDefined();
+ });
+
+ it('Update heat name and name sucessfully', () => {
+ updateSelectedModuleMock();
+ fixture.componentInstance.openEditModuleNamePopup(eventMock);
+ expect(fixture.componentInstance.selectedModule.updateName).toHaveBeenCalled();
+ expect(modulesServiceMock.updateModuleMetadata).toHaveBeenCalled();
+ expect(fixture.componentInstance.selectedModule.name).toEqual('NewVf2..new heat name..module-0');
+ expect(fixture.componentInstance.modules[0].name).toEqual('NewVf2..new heat name..module-0');
+ expect(fixture.componentInstance.selectedModule.heatName).toEqual('new heat name');
+ })
+ it('Try to update heat name and name and get error from server', () => {
+ updateSelectedModuleMock();
+ modulesServiceMock.updateModuleMetadata.mockImplementation(() => Observable.throwError({}));
+ fixture.componentInstance.openEditModuleNamePopup(eventMock);
+ expect(fixture.componentInstance.selectedModule.updateName).toHaveBeenCalled();
+ expect(modulesServiceMock.updateModuleMetadata).toHaveBeenCalled();
+ expect(fixture.componentInstance.modules[0].name).toEqual('NewVf2..base_vepdg..module-0');
+ expect(fixture.componentInstance.selectedModule.heatName).toEqual('base_vepdg');
+ expect(fixture.componentInstance.selectedModule.name).toEqual('NewVf2..base_vepdg..module-0');
+ })
+ it('Try to update heat name and name but not find the module with the same uniqueId', () => {
+ selectedModuleMock.uniqueId = '2'
+ updateSelectedModuleMock();
+ fixture.componentInstance.openEditModuleNamePopup(eventMock);
+ expect(fixture.componentInstance.selectedModule.updateName).toHaveBeenCalled();
+ expect(modulesServiceMock.updateModuleMetadata).not.toHaveBeenCalled();
+ expect(fixture.componentInstance.modules[0].name).toEqual('NewVf2..base_vepdg..module-0');
+ expect(fixture.componentInstance.selectedModule.heatName).toEqual('base_vepdg');
+ expect(fixture.componentInstance.selectedModule.name).toEqual('NewVf2..base_vepdg..module-0');
+ selectedModuleMock.uniqueId = '1'
+ })
+ it('Open edit module name popover and change the heat name', () => {
+ updateSelectedModuleMock();
+ spyOn(fixture.componentInstance, 'updateHeatName');
+ spyOn(fixture.componentInstance, 'updateOriginalHeatName');
+ fixture.componentInstance.openEditModuleNamePopup(eventMock);
+ expect(popoverServiceMock.createPopOverWithInnerComponent).toHaveBeenCalled();
+ expect(fixture.componentInstance.selectedModule.heatName).toEqual("new heat name");
+ expect(fixture.componentInstance.updateHeatName).toHaveBeenCalled();
+ })
+
+
+ it('Open edit module name popover and not change the heat name', () => {
+ updateSelectedModuleMock();
+ editModuleNameInstanceMock.innerPopoverContent.instance.clickButtonEvent = Observable.of(null);
+ fixture.componentInstance.openEditModuleNamePopup(eventMock);
+ expect(popoverServiceMock.createPopOverWithInnerComponent).toHaveBeenCalled();
+ expect(fixture.componentInstance.selectedModule.heatName).toEqual("base_vepdg");
+ })
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.ts
new file mode 100644
index 0000000..604b194
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.component.ts
@@ -0,0 +1,139 @@
+import {Component, Input} from "@angular/core";
+import {Component as TopologyTemplate, ComponentInstance, DisplayModule, Module, PropertyModel} from "app/models";
+import {TranslateService} from "app/ng2/shared/translator/translate.service";
+import {ComponentType} from "app/utils/constants";
+import {WorkspaceService} from "../../../../workspace.service";
+import {ModulesService} from "../../../../../../services/modules.service";
+import * as _ from "lodash";
+import {ModalsHandler} from "../../../../../../../utils/modals-handler";
+import {ComponentFactory} from "../../../../../../../utils/component-factory";
+import {Select, Store} from "@ngxs/store";
+import { SdcUiServices } from "onap-ui-angular";
+import { EditModuleName } from "../edit-module-name/edit-module-name.component";
+import {GraphState} from "../../../../../composition/common/store/graph.state";
+import {DeploymentGraphService} from "../../../../../composition/deployment/deployment-graph.service";
+import {OnSidebarOpenOrCloseAction} from "../../../../../composition/common/store/graph.actions";
+
+@ Component({
+ selector: 'hierarchy-tab',
+ templateUrl: './hierarchy-tab.component.html',
+ styleUrls: ['./hierarchy-tab.component.less'],
+})
+export class HierarchyTabComponent {
+
+ @Select(GraphState.withSidebar) withSidebar$: boolean;
+ @Input() isViewOnly: boolean;
+ public selectedIndex: number;
+ public selectedModule: DisplayModule;
+ public isLoading: boolean;
+ public topologyTemplateName: string;
+ public topologyTemplateType: string;
+ public modules: Array<Module> = [];
+ public componentInstances: Array<ComponentInstance> = [];
+ private editPropertyModalTopologyTemplate: TopologyTemplate;
+
+ constructor(private translateService: TranslateService,
+ private workspaceService: WorkspaceService,
+ private deploymentService: DeploymentGraphService,
+ private modulesService: ModulesService,
+ private ModalsHandler: ModalsHandler,
+ private componentFactory: ComponentFactory,
+ private store: Store,
+ private popoverService: SdcUiServices.PopoverService) {
+ this.isLoading = false;
+ this.topologyTemplateName = this.workspaceService.metadata.name;
+ this.topologyTemplateType = this.workspaceService.metadata.componentType;
+ }
+
+ ngOnInit() {
+ this.modules = this.deploymentService.modules;
+ this.componentInstances = this.deploymentService.componentInstances;
+ this.editPropertyModalTopologyTemplate = this.componentFactory.createEmptyComponent(this.topologyTemplateType);
+ this.editPropertyModalTopologyTemplate.componentInstances = this.deploymentService.componentInstances;
+ }
+
+ onModuleSelected(module: Module, componentInstanceId?: string): void {
+
+ let onSuccess = (module: DisplayModule) => {
+ console.log("Module Loaded: ", module);
+ this.selectedModule = module;
+ this.isLoading = false;
+ };
+
+ let onFailed = () => {
+ this.isLoading = false;
+ };
+
+ if (!this.selectedModule || (this.selectedModule && this.selectedModule.uniqueId != module.uniqueId)) {
+ this.isLoading = true;
+ if (this.topologyTemplateType == ComponentType.SERVICE) {
+ // this.selectedInstanceId = componentInstanceId;
+ this.modulesService.getComponentInstanceModule(this.topologyTemplateType, this.workspaceService.metadata.uniqueId, componentInstanceId, module.uniqueId).subscribe((resultModule: DisplayModule) => {
+ onSuccess(resultModule);
+ }, () => {
+ onFailed();
+ });
+ } else {
+ this.modulesService.getModuleForDisplay(this.topologyTemplateType, this.workspaceService.metadata.uniqueId, module.uniqueId).subscribe((resultModule: DisplayModule) => {
+ onSuccess(resultModule);
+ }, () => {
+ onFailed();
+ });
+ }
+ }
+ }
+
+ updateHeatName(): void {
+ this.isLoading = true;
+ let originalName: string = this.selectedModule.name;
+
+ this.selectedModule.updateName();
+ let moduleIndex: number = _.indexOf(this.modules, _.find(this.modules, (module: Module) => {
+ return module.uniqueId === this.selectedModule.uniqueId;
+ }));
+
+ if (moduleIndex !== -1) {
+ this.modules[moduleIndex].name = this.selectedModule.name;
+ this.modulesService.updateModuleMetadata(this.topologyTemplateType, this.workspaceService.metadata.uniqueId, this.modules[moduleIndex]).subscribe(() => {
+ this.isLoading = false;
+ }, () => {
+ this.updateOriginalHeatName(originalName, moduleIndex);
+ this.modules[moduleIndex].name = originalName;
+ });
+ } else {
+ this.updateOriginalHeatName(originalName, moduleIndex);
+ }
+ };
+
+ private updateOriginalHeatName(originalName: string, moduleIndex: number){
+ this.isLoading = false;
+ this.selectedModule.name = originalName;
+ this.selectedModule.heatName = this.selectedModule.name.split('..')[1];
+ }
+
+ openEditPropertyModal(property: PropertyModel): void {
+ this.editPropertyModalTopologyTemplate.setComponentMetadata(this.workspaceService.metadata);
+ this.ModalsHandler.openEditModulePropertyModal(property, this.editPropertyModalTopologyTemplate, this.selectedModule, this.selectedModule.properties).then(() => {
+ });
+ }
+
+ private getKeys(map: Map<any, any>) {
+ return _.keys(map);
+ }
+
+ private toggleSidebarDisplay = () => {
+ // this.withSidebar = !this.withSidebar;
+ this.store.dispatch(new OnSidebarOpenOrCloseAction());
+ }
+
+ public openEditModuleNamePopup($event) {
+ const editModuleNameInstance = this.popoverService.createPopOverWithInnerComponent('Edit Module Name', '', {x:$event.x , y:$event.y }, EditModuleName, {selectModule: _.cloneDeep(this.selectedModule)}, 'top');
+ editModuleNameInstance.innerPopoverContent.instance.clickButtonEvent.subscribe((newHeatName) => {
+ if(newHeatName != null){
+ this.selectedModule.heatName = newHeatName;
+ this.updateHeatName();
+ }
+ editModuleNameInstance.closePopover();
+ })
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.module.ts b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.module.ts
new file mode 100644
index 0000000..048ca0c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/hierarchy-tab/hierarchy-tab.module.ts
@@ -0,0 +1,24 @@
+/**
+ * Created by ob0695 on 6/4/2018.
+ */
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {HierarchyTabComponent} from "./hierarchy-tab.component";
+import {UiElementsModule} from "../../../../../../components/ui/ui-elements.module";
+import {TranslateModule} from "../../../../../../shared/translator/translate.module";
+import {CommonModule} from "@angular/common";
+import {GlobalPipesModule} from "../../../../../../pipes/global-pipes.module";
+import { EditModuleName } from "../edit-module-name/edit-module-name.component";
+
+@NgModule({
+ declarations: [HierarchyTabComponent, EditModuleName],
+ imports: [CommonModule,
+ UiElementsModule,
+ SdcUiComponentsModule,
+ TranslateModule,
+ GlobalPipesModule],
+ entryComponents: [HierarchyTabComponent, EditModuleName],
+ exports: [HierarchyTabComponent, EditModuleName],
+})
+export class HierarchyTabModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.html b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.html
new file mode 100644
index 0000000..574f2d1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.html
@@ -0,0 +1,62 @@
+<div class="status-page">
+ <ngx-datatable
+ class="material"
+ [columnMode]="'standard'"
+ [rowHeight]="'auto'"
+ [reorderable]="false"
+ [swapColumns]="false"
+ [rows]="artifacts"
+ [scrollbarH]="true"
+ #statusTable>
+ <ngx-datatable-row-detail [rowHeight]="'auto'">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
+ <div *ngFor="let status of row.statuses">
+ <span class = "status" [attr.data-tests-id]="generateDataTestID('statusTimeStamp_',componentName, row.name, status.status)">{{ status.timeStamp | date:'short':'UTC'}}</span>
+ <span class = "status" [attr.data-tests-id]="generateDataTestID('statusValue_',componentName, row.name, status.status)">{{ status.status }}</span>
+ </div>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column name="Component ID" [resizeable]="false" [width]="250">
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded" >
+ <div>
+ <span class="urlValue">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'" (click)="expandRow(row)" [attr.data-tests-id]="generateDataTestID('expandIcon_compID_', componentName, row.name)"></svg-icon>
+ </span>
+ <span class="urlValue ellipsisCell" [attr.data-tests-id]="generateDataTestID('compID_',componentName, row.name)" sdc-tooltip [tooltip-placement]="3" [tooltip-text]="componentName">
+ {{ componentName }}
+ </span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [width]="280" name="Artifact Name">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class = "distributionRowValue ellipsisCell" [attr.data-tests-id]="generateDataTestID('artName_',componentName, row.name)" sdc-tooltip [tooltip-placement]="3" [tooltip-text]="row.name">{{ row.name }}</div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [width]="380" name="URL">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div>
+ <span class="urlValue ellipsisCell" id="urlCell" [attr.data-tests-id]="generateDataTestID('url_',componentName, row.name)">{{ row.url }}</span>
+ <span class="urlCopyIcon" title="Copy URL">
+ <svg-icon-label [clickable]="true" [mode]="'primary'" [labelPlacement]="'right'"
+ [label]="" [name]="'copy-o'" [testId]="'copyToClipboard'"
+ (click)="copyToClipboard(row.url)">
+ </svg-icon-label>
+ </span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [width]="180" name="Time(UTC)">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class = "distributionRowValue ellipsisCell" [attr.data-tests-id]="generateDataTestID('time_',componentName, row.name)" sdc-tooltip [tooltip-placement]="3" [tooltip-text]="getLatestArtifact(row.name).timeStamp | date:'short':'UTC'">{{ getLatestArtifact(row.name).timeStamp | date:'short':'UTC'}}</div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [width]="280" name="Status">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class = "distributionRowValue ellipsisCell" [attr.data-tests-id]="generateDataTestID('status_',componentName, row.name)" sdc-tooltip [tooltip-placement]="3" [tooltip-text]="getLatestArtifact(row.name).status">{{ getLatestArtifact(row.name).status }}</div>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.less b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.less
new file mode 100644
index 0000000..81b8805
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.less
@@ -0,0 +1,78 @@
+:host ::ng-deep {
+ .ngx-datatable {
+ > div {
+ min-height: 5px;
+ }
+ }
+}
+
+.datatable-header-cell {
+ text-align: left;
+ color: red;
+}
+
+.statusHeaderTable {
+ color: #000000;
+ font-family: OpenSans-Bold, sans-serif;
+ font-size: 12px;
+ font-weight: bold;
+ float: left;
+}
+
+.status {
+ padding-right: 30px;
+ color: #5a5a5a;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 12px;
+}
+
+.distributionIDBlock {
+ display: inline-block;
+}
+
+.distributionRowContainer{
+ background-color: #eaeaea;
+ text-align: center;
+}
+
+.distributionRowLabel {
+ overflow: hidden;
+ padding-top: 10px;
+ color: #000000;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 12px;
+ font-weight: bold;
+}
+
+.distributionRowValue {
+ color: #263d4d;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+}
+
+.urlValue {
+ float: left;
+ color: #263d4d;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+}
+
+.urlCopyIcon {
+ float: right;
+ width: 8%;
+}
+
+.ellipsisCell {
+ width: 92%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+
+
+
+
+
+
+
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.spec.ts
new file mode 100644
index 0000000..72b930b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.spec.ts
@@ -0,0 +1,90 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture } from '@angular/core/testing';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiServices } from 'onap-ui-angular';
+import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper';
+import { DistributionService } from '../../distribution.service';
+import { DistributionComponentArtifactTableComponent } from './distribution-component-artifact-table.component';
+
+describe('DistributionComponentArtifactTableComponent', () => {
+ let fixture: ComponentFixture<DistributionComponentArtifactTableComponent>;
+ let distibutionServiceMock: Partial<DistributionService>;
+
+ const mockArtifactsForDistributionAndComponentName = [
+ {
+ name: 'Artifact1',
+ statuses: [
+ {timeStamp: '7/25/2019 12:48AM', status: 'DEPLOY_OK'},
+ {timeStamp: '7/25/2019 12:48AM', status: 'DOWNLOAD_OK'},
+ {timeStamp: '7/25/2019 12:48AM', status: 'NOTIFIED'}
+ ],
+ url: 'URL1',
+ },
+ {
+ name: 'Artifact2',
+ statuses: [
+ {timeStamp: '7/26/2019 12:48AM', status: 'STATUS_TO_DISPLAY'},
+ {timeStamp: '7/25/2019 12:48AM', status: 'DOWNLOAD_OK'},
+ {timeStamp: '7/25/2019 12:48AM', status: 'NOTIFIED'}
+ ],
+ url: 'URL2',
+ },
+ {
+ name: 'ArtifactWithNoStatuses',
+ url: 'URL2',
+ }
+ ];
+
+ beforeEach(() => {
+
+ distibutionServiceMock = {
+ getArtifactstByDistributionIDAndComponentsName: jest.fn().mockReturnValue(mockArtifactsForDistributionAndComponentName),
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [DistributionComponentArtifactTableComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: DistributionService, useValue: distibutionServiceMock}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(DistributionComponentArtifactTableComponent);
+ });
+
+ });
+
+ it('Get Latest Artifact (status and timeStamp) - So the Component Table will display the last time stamp of the notification', async () => {
+ await fixture.componentInstance.ngOnInit();
+ expect(fixture.componentInstance.getLatestArtifact('Artifact2')).toEqual({status: 'STATUS_TO_DISPLAY', timeStamp: '7/26/2019 12:48AM'});
+ expect(fixture.componentInstance.getLatestArtifact('ArtifactWithNoStatuses')).toEqual(null);
+ });
+
+ it('Once the Distribution Component Artifact Table Component is created - artifacts will keep the relevant artifacts for a specific distributionID and Component Name', async () => {
+ await fixture.componentInstance.ngOnInit();
+ // tslint:disable:no-string-literal
+ expect(fixture.componentInstance.artifacts.length).toBe(3);
+ expect(fixture.componentInstance.artifacts[0].name).toBe('Artifact1');
+ expect(fixture.componentInstance.artifacts[0].url).toBe('URL1');
+ expect(fixture.componentInstance.artifacts[0].statuses.length).toBe(3);
+
+ expect(fixture.componentInstance.artifacts[1].name).toBe('Artifact2');
+ });
+
+ it('Once the Distribution Component Artifact Table Component is created for Modal- artifacts will keep the relevant artifacts for a ' +
+ 'specific distributionID and Component Name filtered by Status', async () => {
+ fixture.componentInstance.statusFilter = 'DOWNLOAD_OK';
+ await fixture.componentInstance.ngOnInit();
+ expect(fixture.componentInstance.artifacts.length).toBe(3);
+ expect(fixture.componentInstance.artifacts[0].name).toBe('Artifact1');
+ expect(fixture.componentInstance.artifacts[0].url).toBe('URL1');
+
+ expect(fixture.componentInstance.artifacts[0].statuses.length).toBe(1);
+ expect(fixture.componentInstance.artifacts[0].statuses[0]).toEqual({status: 'DOWNLOAD_OK', timeStamp: '7/25/2019 12:48AM'});
+
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.ts
new file mode 100644
index 0000000..af9aef5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component.ts
@@ -0,0 +1,68 @@
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+import * as _ from 'lodash';
+import { DistributionService } from '../../distribution.service';
+
+// tslint:disable:no-string-literal
+
+@Component({
+ selector: 'app-distribution-component-artifact-table',
+ templateUrl: './distribution-component-artifact-table.component.html',
+ styleUrls: ['./distribution-component-artifact-table.component.less']
+})
+export class DistributionComponentArtifactTableComponent implements OnInit {
+
+ @ViewChild('statusTable', {}) table: any;
+
+ @Input() componentName: string;
+ @Input() rowDistributionID: string;
+ @Input() statusFilter: string;
+
+ public artifacts = [];
+
+ constructor(private distributionService: DistributionService) {
+ }
+
+ ngOnInit() {
+ this.artifacts = this.distributionService.getArtifactstByDistributionIDAndComponentsName(this.rowDistributionID, this.componentName);
+ if (this.statusFilter) {
+ this.artifacts.forEach(
+ (artifact) => {
+ artifact.statuses = _.filter(artifact.statuses, {status: this.statusFilter});
+ });
+ }
+ }
+
+ public getLatestArtifact(artifactName: string) {
+ const selectedArtifact = this.artifacts.filter((artifact) => artifact.name === artifactName);
+ if (selectedArtifact && selectedArtifact[0] && selectedArtifact[0]['statuses'] && selectedArtifact[0]['statuses'][0]) {
+ return selectedArtifact[0]['statuses'][0];
+ } else {
+ return null;
+ }
+ }
+
+ private copyToClipboard(urlToCopy: any) {
+
+ const inputForCopyToClipboard = document.getElementById('inputForCopyToClipboard') as HTMLInputElement;
+ inputForCopyToClipboard.value = urlToCopy;
+ /* Select the text field */
+ inputForCopyToClipboard.select();
+
+ /* Copy the text inside the text field */
+ document.execCommand('copy');
+
+ }
+
+ private generateDataTestID(preFix: string, componentName: string, artifactName: string, status?: string) {
+ if (!status) {
+ return preFix + componentName + '_' + artifactName;
+ } else {
+ return preFix + status + '_' + componentName + '_' + artifactName;
+ }
+ }
+
+ private expandRow(row: any) {
+ this.table.rowDetail.toggleExpandRow(row);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.html b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.html
new file mode 100644
index 0000000..fa5a9ad
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.html
@@ -0,0 +1,47 @@
+<div >
+ <div class="distributionSummary" *ngIf="!isModal">
+ <span class= "rightVerticalSeperator titleSummaryFontSettings" data-tests-id="totalDistributionArtifactsLabel">Total Artifacts <span class="blue" data-tests-id="totalDistributionArtifactsValue">{{ getTotalArtifactsForDistributionID(rowDistributionID) }} </span></span>
+ <span class="blue rightVerticalSeperator" (click)="openModal(rowDistributionID,'NOTIFIED')" data-tests-id="totalDistributionNotifiedArtifactsLabel">Notified <span data-tests-id="totalDistributionNotifiedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'NOTIFIED') }}</span></span>
+ <span class="blue rightVerticalSeperator" (click)="openModal(rowDistributionID,'DOWNLOAD_OK')" data-tests-id="totalDistributionDownloadedArtifactsLabel">Downloaded <span data-tests-id="totalDistributionDownloadedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DOWNLOAD_OK') }}</span></span>
+ <span class="blue rightVerticalSeperator" (click)="openModal(rowDistributionID,'DEPLOY_OK')" data-tests-id="totalDistributionDeployedArtifactsLabel">Deployed <span data-tests-id="totalDistributionDeployedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DEPLOY_OK') }}</span></span>
+ <span class="blue rightVerticalSeperator" (click)="openModal(rowDistributionID,'NOT_NOTIFIED')" data-tests-id="totalDistributionNotNotifiedArtifactsLabel">Not Notified <span data-tests-id="totalDistributionNotNotifiedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'NOT_NOTIFIED') }}</span></span>
+ <span class="blue rightVerticalSeperator floatRight" (click)="openModal(rowDistributionID,'DEPLOY_ERROR')" data-tests-id="totalDistributionDeployErrorArtifactsLabel">Deploy Errors <span class="red" data-tests-id="totalDistributionDeployErrorArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DEPLOY_ERROR') }}</span></span>
+ <span class="blue rightVerticalSeperator floatRight" (click)="openModal(rowDistributionID,'DOWNLOAD_ERROR ')" data-tests-id="totalDistributionDownloadErrorArtifactsLabel">Download Errors <span class="red" data-tests-id="totalDistributionDownloadErrorArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DOWNLOAD_ERROR') }}</span></span>
+ </div>
+
+ <div class="distributionSummary" *ngIf="isModal">
+ <span data-tests-id="modalStatusLabel"><a>Status {{ statusFilter }} <span class="blue" data-tests-id="statusValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, statusFilter) }}</span></a></span>
+ </div>
+
+
+ <div class="componentShiftLeft" *ngFor="let component of components">
+ <div class="componentSummary" *ngIf="!isModal">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="isExpanded(component) ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'" [attr.data-tests-id]="generateExpandDataTestID(component)" (click)="expandRow(component)"></svg-icon>
+
+
+ <span class="rightVerticalSeperatorComponent titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, '')">{{ component }} <span class="blue" data-tests-id="totalComponentArtifactsValue">{{ getTotalArtifactsForDistributionID(rowDistributionID, component) }}</span></span>
+ <span class="rightVerticalSeperatorComponent titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'Notified')">Notified <span class="blue" data-tests-id="totalComponentNotifiedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'NOTIFIED', component) }}</span></span>
+ <span class="rightVerticalSeperatorComponent titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'Downloaded')">Downloaded <span class="blue" data-tests-id="totalComponentDownloadedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DOWNLOAD_OK', component) }}</span></span>
+ <span class="rightVerticalSeperatorComponent titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'Deployed')">Deployed <span class="blue" data-tests-id="totalComponentDeployedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DEPLOY_OK', component) }}</span></span>
+ <span class="rightVerticalSeperatorComponent titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'NotNotified')">Not Notified <span class="blue" data-tests-id="totalComponentNotNotifiedArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'NOT_NOTIFIED', component) }}</span></span>
+ <span class="msoStatus" [ngClass]="{'red': getMSOStatus (rowDistributionID, component) === 'COMPONENT_DONE_ERROR', 'green': getMSOStatus (rowDistributionID, component) === 'COMPONENT_DONE_OK'}">{{ getMSOStatus (rowDistributionID, component) }}</span>
+ <span class="rightVerticalSeperatorComponent floatRight titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'DeployErrors')">Deploy Errors <span class="red" data-tests-id="totalComponentDeployErrorArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DEPLOY_ERROR', component) }}</span></span>
+ <span class="rightVerticalSeperatorComponent floatRight titleSummaryFontSettings" [attr.data-tests-id]="generateTotalComponentArtifactsLabel(component, 'DownloadErrors')">Download Errors <span class="red" data-tests-id="totalComponentDownloadErrorArtifactsValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, 'DOWNLOAD_ERROR', component) }}</span></span>
+ </div>
+
+ <div class="componentSummary" *ngIf="isModal">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="isExpanded(component) ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'" [attr.data-tests-id]="generateExpandDataTestID(component+'_ForModal')" (click)="expandRow(component)"></svg-icon>
+ <span data-tests-id="modalComponentLabel"><a>{{ component }} <span class="blue" data-tests-id="modalComponentValue">{{ getLengthArtifactsForDistributionIDByStatus(rowDistributionID, statusFilter, component) }} </span></a></span>
+ </div>
+
+ <div *ngIf="isExpanded(component)">
+ <app-distribution-component-artifact-table [rowDistributionID]= rowDistributionID [componentName]=component
+ [statusFilter]="statusFilter"></app-distribution-component-artifact-table>
+ </div>
+ </div>
+</div>
+
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.less b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.less
new file mode 100644
index 0000000..3eab18c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.less
@@ -0,0 +1,66 @@
+.red {
+ color: red;
+}
+
+.green {
+ color: green;
+}
+
+.msoStatus {
+ padding-left: 5px;
+}
+
+.blue {
+ color: #009fdb;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+}
+
+.rightVerticalSeperator {
+ border-right: 1px solid #d2d2d2;
+ padding-left: 5px;
+ padding-right: 5px;
+ cursor: pointer;
+}
+
+.rightVerticalSeperatorComponent {
+ border-right: 1px solid #d2d2d2;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.floatRight{
+ float: right;
+}
+
+.distributionSummary {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ background-color: #eaeaea;
+ padding-left: 25px;
+ padding-right: 25px;
+}
+
+.componentSummary {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ background-color: #eaeaea;
+ padding-left: 25px;
+ padding-right: 25px;
+}
+
+.componentShiftLeft {
+ margin-left: 15px;
+}
+
+.titleSummaryFontSettings {
+ color: #191919;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+}
+
+
+
+
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.spec.ts
new file mode 100644
index 0000000..ff89b92
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.spec.ts
@@ -0,0 +1,47 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture } from '@angular/core/testing';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiServices } from 'onap-ui-angular';
+import { ConfigureFn, configureTests } from '../../../../../../jest/test-config.helper';
+import { DistributionService } from '../distribution.service';
+import { DistributionComponentTableComponent } from './distribution-component-table.component';
+
+describe('DistributionComponentTableComponent', () => {
+ let fixture: ComponentFixture<DistributionComponentTableComponent>;
+ let distibutionServiceMock: Partial<DistributionService>;
+
+ const mockComponentsForDistribution = ['Consumer1', 'Consumer2'];
+
+ beforeEach(() => {
+
+ distibutionServiceMock = {
+ getComponentsByDistributionID: jest.fn().mockReturnValue(mockComponentsForDistribution),
+ getArtifactstByDistributionIDAndComponentsName: jest.fn(),
+ getArtifactsForDistributionIDAndComponentByStatus: jest.fn()
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [DistributionComponentTableComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: DistributionService, useValue: distibutionServiceMock},
+ {provide: SdcUiServices.ModalService, useValue: {}}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(DistributionComponentTableComponent);
+ });
+
+ });
+
+ it('Once the Distribution Component Table Component is created - components will keep the relevant components for a specific distributionID', async () => {
+ await fixture.componentInstance.ngOnInit();
+ expect(fixture.componentInstance.components.length).toBe(2);
+ expect(fixture.componentInstance.components[0]).toBe('Consumer1');
+ expect(fixture.componentInstance.components[1]).toBe('Consumer2');
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.ts
new file mode 100644
index 0000000..e3aaf9d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution-component-table/distribution-component-table.component.ts
@@ -0,0 +1,104 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { ModalComponent } from 'onap-ui-angular/dist/modals/modal.component';
+import { DistributionComponent } from '../distribution.component';
+import { DistributionService } from '../distribution.service';
+
+@Component({
+ selector: 'app-distribution-component-table',
+ templateUrl: './distribution-component-table.component.html',
+ styleUrls: ['./distribution-component-table.component.less']
+})
+export class DistributionComponentTableComponent implements OnInit {
+
+ @Input() rowDistributionID: string;
+ @Input() isModal: boolean = false;
+ @Input() statusFilter: string;
+ public components = [];
+ private customModalInstance: ModalComponent;
+ private expanded = [];
+ constructor(private distributionService: DistributionService,
+ private modalService: SdcUiServices.ModalService) {
+ }
+
+ ngOnInit() {
+ this.initComponents();
+ }
+
+ private generateTotalComponentArtifactsLabel(componentName: any, status: string): string {
+ return 'total' + componentName + status + 'ArtifactsLabel';
+ }
+
+ private generateExpandDataTestID(componentName: string) {
+ return 'expandIcon_' + componentName;
+ }
+
+ private initComponents() {
+ this.components = this.distributionService.getComponentsByDistributionID(this.rowDistributionID);
+ this.components.map((component) => this.expanded.push({componentName: component, expanded: false}));
+ }
+
+ private getTotalArtifactsForDistributionID(distributionID: string, componentName?: string): number {
+ return this.distributionService.getArtifactstByDistributionIDAndComponentsName(distributionID, componentName).length;
+ }
+
+ private getLengthArtifactsForDistributionIDByStatus(distributionID: string, statusToSerach: string, componentName?: string): number {
+ if (componentName) {
+ return this.distributionService.getArtifactsForDistributionIDAndComponentByStatus(distributionID, statusToSerach, componentName).length;
+ } else {
+ return this.distributionService.getArtifactsForDistributionIDAndComponentByStatus(distributionID, statusToSerach).length;
+ }
+ }
+
+ private openModal(rowDistributionID: string, statusFilter: string) {
+
+ const title: string = 'Distribution by Status';
+ const attributeModalConfig = {
+ title,
+ size: 'sdc-xl',
+ type: SdcUiCommon.ModalType.custom,
+ buttons: [
+ {
+ id: 'close',
+ text: 'Close',
+ size: 'sm',
+ closeModal: true,
+ disabled: false,
+ }
+ ] as SdcUiCommon.IModalButtonComponent[]
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(attributeModalConfig, DistributionComponent, {
+ // inputs
+ rowDistributionID,
+ statusFilter,
+ isModal: true,
+ });
+ }
+
+ private expandRow(componentName: string) {
+ console.log('Should expand componentSummary for componentName = ' + componentName);
+ const selectedComponent = this.expanded.find((component) => component.componentName === componentName);
+ // tslint:disable:no-string-literal
+ const selectedComponentExpandedVal = selectedComponent['expanded'];
+ // this.expanded = !this.expanded;
+ for (const i in this.expanded) {
+ if (this.expanded[i].componentName === componentName) {
+ this.expanded[i].expanded = !this.expanded[i].expanded;
+ break; //Stop this loop, we found it!
+ }
+ }
+ const selectedComponentAfter = this.expanded.find((component) => component.componentName === componentName);
+ const selectedComponentExpandedValAfter = selectedComponentAfter['expanded'];
+ }
+
+ private isExpanded(componentName: string) {
+ const selectedComponent = this.expanded.find((component) => component.componentName === componentName);
+ return selectedComponent['expanded'];
+ }
+
+
+ private getMSOStatus(rowDistributionID: string, componentName: string): string {
+ return this.distributionService.getMSOStatus(rowDistributionID, componentName);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.html b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.html
new file mode 100644
index 0000000..d0cacb0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.html
@@ -0,0 +1,80 @@
+<div *ngIf="!isModal">
+ <div *ngIf="serviceHasDistibutions" class="w-sdc-distribution-view-header">
+ <div class="w-sdc-distribution-view-title" data-tests-id="DistributionsLabel">DISTRIBUTION <span class="blue-font" data-tests-id="totalArtifacts">[{{distributions.length}}]</span></div>
+ <div class="header-spacer"></div>
+ <input type="text" value="GeeksForGeeks" id="inputForCopyToClipboard" [ngStyle]="{'z-index': '-2', 'width': '25px'}">
+ <div class="top-search">
+ <input type="text"
+ style="width: auto;"
+ class="search-text"
+ data-tests-id="searchTextbox"
+ placeholder="Search"
+ data-ng-model="searchBind"
+ ng-model-options="{ debounce: 500 }"
+ (keyup)="updateFilter($event)"/>
+ </div>
+ <div class="sprite-new refresh-btn" data-tests-id="refreshButton" (click)="refreshDistributions()" title="Refresh"></div>
+ </div>
+ <div class="w-sdc-distribution-view-header w-sdc-distribution-view-title" data-tests-id="noDistributionsLabel" *ngIf="!serviceHasDistibutions">No Distributions To Present</div>
+</div>
+
+<div *ngIf="serviceHasDistibutions">
+ <ngx-datatable
+ [columnMode]="'flex'"
+ [rowHeight]="'auto'"
+ [reorderable]="false"
+ [swapColumns]="false"
+ [scrollbarV]="false"
+ [rows]="distributions"
+ [sorts]="[{prop: 'timestamp', dir: 'desc'}]"
+
+ #distributionTable>
+ <ngx-datatable-row-detail [rowHeight]="'auto'">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
+ <app-distribution-component-table [rowDistributionID]=row.distributionID [isModal]="isModal"
+ [statusFilter]="statusFilter"></app-distribution-component-table>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column [resizeable]="false" [flexGrow]="2" name="Distribution ID">
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded" >
+ <div class="expand-collapse-cell">
+ <a><svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'" (click)="expandRow(row, expanded)" [attr.data-tests-id]="generateDataTestID('expandIcon_', row.distributionID, isModal)"></svg-icon></a>
+
+ </div>
+ <div class="distributionIDBlock">
+ <div class = "distributionRowValue" [attr.data-tests-id]="generateDataTestID('distID_', row.distributionID, isModal)">{{ row.distributionID }}</div>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [flexGrow]="1" name="User id">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class = "distributionRowValue ellipsisCell" [attr.data-tests-id]="generateDataTestID('userID_', row.distributionID)" sdc-tooltip [tooltip-placement]="3" [tooltip-text]="row.userId">{{ row.userId }}</div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [flexGrow]="1" name="Time[UTC]">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class = "distributionRowValue" [attr.data-tests-id]="generateDataTestID('timeStamp_', row.distributionID)">{{ row.timestamp }} </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false"[flexGrow]="1" name="Status" >
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div>
+ <span class="statusIcon">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]= "getIconName(row.deployementStatus)" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ </span>
+ <span class = "distributionRowValue" [attr.data-tests-id]="generateDataTestID('status_', row.distributionID)">
+ {{ row.deployementStatus }}
+ </span>
+ <span class="btnMarkAsDistributed" (click)="markDeploy(row.distributionID, row.deployementStatus)">
+ <svg-icon [clickable]="true" [name]= "'success'" [mode]="getIconMode(row.deployementStatus)"
+ [size]="'medium'"></svg-icon>
+ </span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.less b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.less
new file mode 100644
index 0000000..b630881
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.less
@@ -0,0 +1,92 @@
+:host ::ng-deep {
+ .ngx-datatable {
+ > div {
+ min-height: 500px;
+ datatable-body {
+ max-height: max-content;
+ }
+ }
+ }
+}
+
+.w-sdc-distribution-view-header {
+ display: flex;
+ -webkit-justify-content: space-between;
+ margin: 0 25px 5px 40px;
+
+ .header-spacer {
+ flex-grow: 5;
+ }
+
+ .w-sdc-distribution-view-title{
+ color: #191919;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+ line-height: 30px;
+
+
+ .blue-font {
+ color: #009fdb;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 14px;
+ }
+ }
+
+}
+
+.distribution-page {
+ max-height: 150px;
+}
+
+ .distributionIDBlock {
+ display: inline-block;
+ }
+
+ .expand-collapse-cell {
+ display: inline-block;
+ }
+
+ .statusIcon {
+ display: inline-block;
+ margin-right: 10px;
+ }
+
+ .btnMarkAsDistributed {
+ float: right;
+ background-color: #E5F3FF;
+ border: 1px solid #8DCCD5;
+ width: 55px;
+ height: 21px;
+ text-align: center;
+ }
+
+ .distributionRowContainer{
+ background-color: #eaeaea;
+ text-align: center;
+ }
+
+ .distributionRowLabel {
+ overflow: hidden;
+ padding-top: 10px;
+ color: #000000;
+ font-family: OpenSans-Semibold, sans-serif;
+ font-size: 12px;
+ font-weight: bold;
+ }
+
+ .distributionRowValue {
+ color: #263d4d;
+ font-family: OpenSans-Regular, sans-serif;
+ font-size: 14px;
+ }
+
+.ellipsisCell {
+ width: 92%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+
+
+
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.spec.ts
new file mode 100644
index 0000000..e6c9c23
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.spec.ts
@@ -0,0 +1,92 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture } from '@angular/core/testing';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiServices } from 'onap-ui-angular';
+import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper';
+import { ComponentMetadata } from '../../../../models/component-metadata';
+import { AuthenticationService } from '../../../services/authentication.service';
+import { WorkspaceService } from '../workspace.service';
+import { DistributionComponent } from './distribution.component';
+import { DistributionService } from './distribution.service';
+import {EventListenerService} from "../../../../services/event-listener-service";
+
+describe('DistributionComponent', () => {
+ let fixture: ComponentFixture<DistributionComponent>;
+ let distibutionServiceMock: Partial<DistributionService>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let authenticationServiceMock: Partial <AuthenticationService>;
+ let eventListenerService: Partial <EventListenerService>;
+
+ const mockDistributionListFromService = [
+ {
+ deployementStatus: 'Distributed',
+ distributionID: '1',
+ timestamp: '2019-07-21 08:37:02.834 UTC',
+ userId: 'Aretha Franklin(op0001)'
+ }, {
+ deployementStatus: 'Distributed',
+ distributionID: '2',
+ timestamp: '2019-07-21 09:37:02.834 UTC',
+ userId: 'Aretha Franklin(op0001)'
+ }];
+
+ beforeEach(() => {
+
+ distibutionServiceMock = {
+ initDistributionsList: jest.fn(),
+ getDistributionList: jest.fn().mockReturnValue(mockDistributionListFromService),
+ initDistributionsStatusForDistributionID: jest.fn()
+ };
+
+ const componentMetadata = new ComponentMetadata();
+ componentMetadata.uuid = '111';
+
+ workspaceServiceMock = {
+ metadata : componentMetadata
+ };
+
+ authenticationServiceMock = {
+ getLoggedinUser: jest.fn().mockReturnValue({role: 'designer'})
+ };
+
+ eventListenerService = {
+ registerObserverCallback: jest.fn(),
+ unRegisterObserver: jest.fn()
+ }
+
+ loaderServiceMock = {
+ activate: jest.fn(),
+ deactivate: jest.fn()
+ };
+
+ const configure: ConfigureFn = (testBed) => {
+ testBed.configureTestingModule({
+ declarations: [DistributionComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: DistributionService, useValue: distibutionServiceMock},
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock},
+ {provide: AuthenticationService, useValue: authenticationServiceMock},
+ {provide: EventListenerService, useValue: eventListenerService}
+ ],
+ });
+ };
+
+ configureTests(configure).then((testBed) => {
+ fixture = testBed.createComponent(DistributionComponent);
+ });
+
+ });
+
+ it('Once the Distribution Component is created - distributionsResponseFromServer save all the distributions from the Service', async () => {
+ fixture.componentInstance.componentUuid = 'componentUid';
+ fixture.componentInstance.rowDistributionID = null;
+ fixture.componentInstance.isModal = false;
+
+ await fixture.componentInstance.ngOnInit();
+ expect(fixture.componentInstance.distributions.length).toBe(2);
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.ts
new file mode 100644
index 0000000..ca1b629
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.component.ts
@@ -0,0 +1,117 @@
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+import { SdcUiCommon, SdcUiServices } from 'onap-ui-angular';
+import { EventListenerService } from '../../../../services/event-listener-service';
+import { AuthenticationService } from '../../../services/authentication.service';
+import { WorkspaceService } from '../workspace.service';
+import { DistributionService } from './distribution.service';
+import { EVENTS } from '../../../../utils/constants';
+
+@Component({
+ selector: 'distribution',
+ templateUrl: './distribution.component.html',
+ styleUrls: ['../../../../../assets/styles/table-style.less', './distribution.component.less']
+})
+export class DistributionComponent implements OnInit {
+
+ @ViewChild('distributionTable', { }) table: any;
+
+ @Input() isModal: boolean = false;
+ @Input() statusFilter: string;
+ @Input() rowDistributionID: string;
+ public componentUuid: string;
+ public distributions = [];
+ private expanded: any = {};
+ private serviceHasDistibutions: boolean = false;
+ private readonly uniqueId: string;
+ private userRole: string;
+
+ constructor(private workspaceService: WorkspaceService,
+ private distributionService: DistributionService,
+ private loaderService: SdcUiServices.LoaderService,
+ private authService: AuthenticationService,
+ private eventListenerService: EventListenerService) {
+ this.componentUuid = this.workspaceService.metadata.uuid;
+ this.uniqueId = this.workspaceService.metadata.uniqueId;
+ }
+
+
+
+ async ngOnInit() {
+ this.userRole = this.authService.getLoggedinUser().role;
+ this.eventListenerService.registerObserverCallback(EVENTS.ON_DISTRIBUTION_SUCCESS, async () => {
+ await this.refreshDistributions();
+ });
+ await this.initDistributions(this.componentUuid, this.rowDistributionID);
+ }
+
+ ngOnDestroy(): void {
+ this.eventListenerService.unRegisterObserver(EVENTS.ON_DISTRIBUTION_SUCCESS);
+ }
+
+ async initDistributions(componentUuid: string, specificDistributionID?: string) {
+ this.loaderService.activate();
+ await this.distributionService.initDistributionsList(componentUuid);
+ this.distributions = this.distributionService.getDistributionList();
+ this.distributions.length > 0 ? this.serviceHasDistibutions = true : this.serviceHasDistibutions = false;
+ if (specificDistributionID) {
+ this.distributions = this.distributionService.getDistributionList(specificDistributionID);
+ }
+ this.loaderService.deactivate();
+ }
+
+ getIconName(rowStatus: string ) {
+ if (rowStatus === 'Distributed') {
+ return 'distributed';
+ }
+ if (rowStatus === 'Deployed') {
+ return 'v-circle';
+ }
+ }
+
+ getIconMode(rowStatus: string) {
+ if (rowStatus === 'Distributed') {
+ return 'primary';
+ }
+ if (rowStatus === 'Deployed') {
+ return 'secondary';
+ }
+ }
+
+ private async markDeploy(distributionID: string, status: string) {
+ if (status === 'Distributed') {
+ console.log('Should send MarkDeploy POST Request ServiceID:' + this.uniqueId + ' DISTID:' + distributionID);
+ await this.distributionService.markDeploy(this.uniqueId, distributionID);
+ this.refreshDistributions();
+ }
+ }
+
+ private async refreshDistributions() {
+ await this.initDistributions(this.componentUuid);
+ }
+
+ private updateFilter(event) {
+ const val = event.target.value.toLowerCase();
+
+ // filter our data
+ this.distributions = this.distributionService.getDistributionList().filter((distribution: any[]) => {
+ return !val ||
+ // tslint:disable:no-string-literal
+ distribution['distributionID'].toLowerCase().indexOf(val) !== -1;
+ });
+ }
+
+ private generateDataTestID(preFix: string, distributionID: string, isModal?: boolean ): string {
+ if (isModal) {
+ return preFix + distributionID.substring(0, 5) + '_Modal';
+ } else {
+ return preFix + distributionID.substring(0, 5);
+ }
+ }
+
+ private async expandRow(row: any, expanded: boolean) {
+ if (!expanded) {
+ await this.distributionService.initDistributionsStatusForDistributionID(row.distributionID);
+ }
+ this.table.rowDetail.toggleExpandRow(row);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.module.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.module.ts
new file mode 100644
index 0000000..723a6d8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.module.ts
@@ -0,0 +1,34 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+import { DistributionComponentArtifactTableComponent } from './distribution-component-table/distribution-component-artifact-table/distribution-component-artifact-table.component';
+import { DistributionComponentTableComponent } from './distribution-component-table/distribution-component-table.component';
+import { DistributionComponent } from './distribution.component';
+import { DistributionService } from './distribution.service';
+
+@NgModule({
+ declarations: [
+ DistributionComponent,
+ DistributionComponentTableComponent,
+ DistributionComponentArtifactTableComponent,
+ ],
+ imports: [
+ // TranslateModule,
+ CommonModule,
+ SdcUiComponentsModule,
+ NgxDatatableModule,
+ ],
+ exports: [
+ DistributionComponent,
+ DistributionComponentTableComponent
+ ],
+ entryComponents: [
+ DistributionComponent,
+ DistributionComponentTableComponent,
+ DistributionComponentArtifactTableComponent
+ ],
+ providers: [DistributionService]
+})
+export class DistributionModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.service.ts b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.service.ts
new file mode 100644
index 0000000..ed6791c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/disribution/distribution.service.ts
@@ -0,0 +1,233 @@
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { tap } from 'rxjs/operators';
+import { Distribution } from '../../../../models/distribution';
+import { ISdcConfig, SdcConfigToken } from '../../../config/sdc-config.config';
+
+@Injectable()
+export class DistributionService {
+ protected baseUrl;
+ private distributionList = [];
+ private distributionStatusesMap = {};
+
+ // tslint:disable:no-string-literal
+
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
+ }
+
+ // Once the distribution page is loaded or when the user wants to refresh the list
+ async initDistributionsList(componentUuid: string): Promise<object> {
+ const distributionsListURL = this.baseUrl + 'services/' + componentUuid + '/distribution';
+ const res = this.http.get<Distribution[]>(distributionsListURL).pipe(tap( (result) => {
+ this.distributionList = result['distributionStatusOfServiceList'];
+ this.insertDistrbutionsToMap();
+ } ));
+ return res.toPromise();
+ }
+
+ // Once the user click on the relevant distribution ID in the distribution table (open and close)
+ async initDistributionsStatusForDistributionID(distributionID: string): Promise<object> {
+ const distributionStatus = this.baseUrl + 'services/distribution/' + distributionID;
+ const res = this.http.get<object>(distributionStatus).pipe(tap( (result) => {
+ this.insertDistributionStatusToDistributionsMap(distributionID, result['distributionStatusList']);
+ } ));
+ return res.toPromise();
+ }
+
+ public getDistributionList(specificDistributionID?: string) {
+ if (specificDistributionID) {
+ return this.distributionList.filter((distribution) => {
+ return distribution['distributionID'] === specificDistributionID;
+ });
+ } else {
+ return this.distributionList;
+ }
+ }
+
+ public getComponentsByDistributionID(distributionID: string) {
+ const components = [];
+ const distributionStatusMap = this.getStatusMapForDistributionID(distributionID);
+ if (distributionStatusMap) {
+ distributionStatusMap.forEach((component) => components.push(component.componentID));
+ }
+ return components;
+ }
+
+ // get array of artifacts per distributionID w/o componentName, sliced by artifact status
+ public getArtifactsForDistributionIDAndComponentByStatus(distributionID: string, statusToSearch: string, componentName?: string) {
+ const filteredArtifactsByStatus = [];
+
+ if (componentName) {
+ this.getArtifactstByDistributionIDAndComponentsName(distributionID, componentName).forEach ( (artifact) => {
+ if (this.artifactStatusHasMatch(artifact, statusToSearch)) {
+ filteredArtifactsByStatus.push(artifact);
+ }
+ } );
+ } else {
+ this.getArtifactstByDistributionIDAndComponentsName(distributionID).forEach ( (artifact) => {
+ if (this.artifactStatusHasMatch(artifact, statusToSearch)) {
+ filteredArtifactsByStatus.push(artifact);
+ }
+ } );
+ }
+ return filteredArtifactsByStatus;
+ }
+
+ public getArtifactstByDistributionIDAndComponentsName(distributionID: string, componentName?: string): any[] {
+ const artifacts = [];
+ if (this.getStatusMapForDistributionID(distributionID)) {
+ if (componentName) {
+ if (this.getStatusMapForDistributionID(distributionID).filter((component) => component.componentID === componentName).length > 0) {
+ const artifactsArr = this.getStatusMapForDistributionID(distributionID).filter((component) => component.componentID === componentName)[0]['artifacts']
+ if (artifactsArr.length > 0) {
+ artifactsArr.forEach((artifact) => {
+ const artifactObj = {
+ url: artifact.artifactUrl,
+ name: artifact.artifactName,
+ statuses: artifact.statuses
+ };
+ artifacts.push(artifactObj);
+ });
+ }
+ }
+ } else {
+ const components = this.getComponentsByDistributionID(distributionID);
+ components.forEach((componentName) => {
+ if (this.getStatusMapForDistributionID(distributionID).filter((component) => component.componentID === componentName).length > 0) {
+ const artifactsArr = this.getStatusMapForDistributionID(distributionID).filter((component) => component.componentID === componentName)[0]['artifacts']
+ if (artifactsArr.length > 0) {
+ artifactsArr.forEach((artifact) => {
+ const artifactObj = {
+ url: artifact.artifactUrl,
+ name: artifact.artifactName,
+ statuses: artifact.statuses
+ };
+ artifacts.push(artifactObj);
+ });
+ }
+ }
+ });
+ }
+ }
+ return artifacts;
+ }
+
+ public getStatusMapForDistributionID(distributionID: string) {
+ return this.distributionStatusesMap[distributionID];
+ }
+
+ public markDeploy(uniqueId: string, distributionID: string): Promise<object> {
+ const distributionStatus = this.baseUrl + 'services/' + uniqueId + '/distribution/' + distributionID + '/markDeployed';
+ const res = this.http.post<object>(distributionStatus, {}).pipe(tap( (result) => {
+ console.log(result);
+ } ));
+ return res.toPromise();
+ }
+
+ public getMSOStatus(distributionID: string, componentName: string): string {
+ const msoStatus = this.distributionStatusesMap[distributionID].filter((component) => component.componentID === componentName)[0].msoStatus;
+ return msoStatus ? msoStatus : '';
+ }
+
+ private artifactStatusHasMatch(artifact: any, statusToSerach: string) {
+ for (let i = 0; i < artifact.statuses.length; i++) {
+ if (artifact.statuses[i].status === statusToSerach) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private insertDistributionStatusToDistributionsMap(distributionID: string, distributionStatusMapResponseFromServer: object[]) {
+
+ // // Clear the Distribution ID array - to avoid statuses duplications
+ const distribution = this.distributionStatusesMap[distributionID];
+ distribution.length = 0;
+
+ // Sort the response of statuses from Server, so it will be easy to pop the latest status when it will be required
+ const sortedResponseByTimeStamp = distributionStatusMapResponseFromServer.sort((a, b) => b['timestamp'] - a['timestamp'])
+
+ sortedResponseByTimeStamp.map((distributionStatus) => {
+ const formattedDate = this.formatDate(distributionStatus['timestamp']);
+
+ // if (distributionStatus['url'] === null) {
+ // distributionStatus['url'] = "";
+ // }
+
+ const detailedArtifactStatus = {
+ componentID: distributionStatus['omfComponentID'],
+ artifactName: distributionStatus['url']? distributionStatus['url'].split('/').pop() : '',
+ url: distributionStatus['url'],
+ time: distributionStatus['timestamp'],
+ status: distributionStatus['status'],
+ };
+
+
+
+ // Add Component to this.distributionStatusesMap in case not exist.
+ let componentPosition = _.findIndex(distribution, {componentID: detailedArtifactStatus.componentID})
+
+ if (componentPosition === -1) {
+ this.addComponentIdToDistributionStatusMap(distributionID, detailedArtifactStatus.componentID);
+ componentPosition = distribution.length - 1;
+ }
+
+ const component = distribution[componentPosition];
+
+
+ // Add Artifact to this.distributionStatusesMap[componentID] in case not exist.
+ let artifactPosition = _.findIndex(component.artifacts, {artifactUrl: detailedArtifactStatus.url})
+
+ if (artifactPosition === -1) {
+ this.addArtifactToComponentId(distributionID, componentPosition, detailedArtifactStatus.artifactName, detailedArtifactStatus.url);
+ artifactPosition = component.artifacts.length - 1;
+ }
+
+
+ // Add status to relevat artifact in relevent componentID.
+ if (detailedArtifactStatus.url) {
+ // Case where there is a url -> should add its status
+ component.artifacts[artifactPosition].statuses.push({
+ timeStamp: detailedArtifactStatus.time,
+ status: detailedArtifactStatus.status
+ });
+ } else {
+ // Should update the Component -> status from MSO
+ this.distributionStatusesMap[distributionID][componentPosition].msoStatus = detailedArtifactStatus.status;
+ }
+
+
+ });
+ }
+
+ private addComponentIdToDistributionStatusMap(distributionID: string, componentIDValue: string) {
+ this.distributionStatusesMap[distributionID].push({
+ componentID: componentIDValue,
+ msoStatus: null,
+ artifacts: []
+ });
+ }
+
+ private addArtifactToComponentId(distributionID: string, componentPosition: number, artifactNameValue: string, artifactURLValue: any) {
+ if (artifactNameValue) {
+ this.distributionStatusesMap[distributionID][componentPosition].artifacts.push({
+ artifactName: artifactNameValue,
+ artifactUrl: artifactURLValue,
+ statuses: []
+ });
+ }
+ }
+
+ private insertDistrbutionsToMap() {
+ this.distributionList.map((distribution) => this.distributionStatusesMap[distribution.distributionID] = []);
+ }
+
+ private formatDate(epochTime: string) {
+ const intEpochTime = new Date(parseInt(epochTime, 10));
+ const amOrPm = (intEpochTime.getHours() + 24) % 24 > 12 ? 'PM' : 'AM';
+ const formattedDate = (intEpochTime.getMonth() + 1) + '/' + intEpochTime.getDate() + '/' + intEpochTime.getFullYear() + ' ' + intEpochTime.getHours() + ':' +
+ intEpochTime.getMinutes() + amOrPm;
+ return formattedDate;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/__snapshots__/informational-artifact-page.spec.ts.snap b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/__snapshots__/informational-artifact-page.spec.ts.snap
new file mode 100644
index 0000000..1a19b36
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/__snapshots__/informational-artifact-page.spec.ts.snap
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`informational artifacts page should match current snapshot of informational artifact pages component 1`] = `
+<information-artifact-page
+ addOrUpdateArtifact={[Function Function]}
+ artifactsService={[Function Object]}
+ deleteArtifact={[Function Function]}
+ store={[Function Store]}
+ table={[Function DatatableComponent]}
+ workspaceService={[Function Object]}
+>
+ <div
+ class="information-artifact-page"
+ >
+ <svg-icon-label
+ class="add-artifact-btn"
+ />
+ <ngx-datatable
+ class="ngx-datatable"
+ columnmode="flex"
+ >
+ <div
+ visibilityobserver=""
+ >
+
+ <datatable-body
+ class="datatable-body"
+ >
+ <datatable-selection>
+
+
+
+ </datatable-selection>
+ </datatable-body>
+
+ </div>
+ </ngx-datatable>
+ </div>
+</information-artifact-page>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.html b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.html
new file mode 100644
index 0000000..cff3325
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.html
@@ -0,0 +1,82 @@
+<div class="information-artifact-page">
+ <svg-icon-label class="add-artifact-btn" [clickable]="true" [mode]="'primary'" [labelPlacement]="'right'"
+ [label]="'Add'" [name]="'plus'" [testId]="'add-information-artifact-button'"
+ (click)="addOrUpdateArtifact()"></svg-icon-label>
+ <ngx-datatable
+ columnMode="flex"
+ [headerHeight]="40"
+ [reorderable]="false"
+ [swapColumns]="false"
+ [rows]="informationArtifacts$ | async"
+ [footerHeight]="'undefined'"
+ [sorts]="[{prop: 'artifactDisplayName', dir: 'desc'}]"
+ #informationArtifactsTable
+ (activate)="onActivate($event)">
+ <ngx-datatable-row-detail [rowHeight]="80">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
+ <div [attr.data-tests-id]="row.artifactDisplayName+'Description'">{{row.description}}</div>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column [resizeable]="false" name="Name" [flexGrow]="3"
+ [prop]="'artifactDisplayName'">
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded">
+ <div class="expand-collapse-cell">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ <span [attr.data-tests-id]="'artifactDisplayName_' + row.artifactDisplayName">{{row.artifactDisplayName }}</span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="Type" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.artifactType}}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="Version" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{ row.artifactVersion }}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="UUID" [flexGrow]="2">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{ row.artifactUUID }}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class="download-artifact-button">
+ <svg-icon class="action-icon" *ngIf="!row.isThirdParty()" [mode]="'primary2'"
+ [disabled]="isViewOnly$ | async" [name]="'edit-o'"
+ testId="edit_{{row.artifactDisplayName}}" clickable="true" size="medium"
+ (click)="addOrUpdateArtifact(row)"></svg-icon>
+ <svg-icon class="action-icon" *ngIf="!row.isThirdParty()" [mode]="'primary2'"
+ [disabled]="isViewOnly$ | async" [name]="'trash-o'"
+ testId="delete_{{row.artifactDisplayName}}" clickable="true" size="medium" (click)="deleteArtifact(row)"></svg-icon>
+ <download-artifact class="action-icon" [disabled]="isViewOnly$ | async" [artifact]="row"
+ [componentId]="componentId"
+ [componentType]="componentType"
+ testId="download_{{row.artifactDisplayName}}"></download-artifact>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+
+ <ngx-datatable-footer>
+ <ng-template ngx-datatable-footer-template>
+ <div class="add-artifacts-dynamic-btn-list">
+ <sdc-button *ngFor="let artifact of informationArtifactsAsButtons$ | async"
+ class="add-artifacts-dynamic-btn"
+ testId="add_artifact_{{artifact.artifactDisplayName}}"
+ [type]="'secondary'"
+ [size]="'xx-large'"
+ [text]="'ADD ' + artifact.artifactDisplayName"
+ [icon_name]="'plus-circle-o'"
+ [icon_mode] = "'secondary'"
+ [icon_position]="'left'"
+ (click)="addOrUpdateArtifact(artifact)">
+ </sdc-button>
+ </div>
+ </ng-template>
+ </ngx-datatable-footer>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.less b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.less
new file mode 100644
index 0000000..b69e511
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.less
@@ -0,0 +1,29 @@
+.information-artifact-page {
+
+ .add-artifact-btn {
+ display: flex;
+ cursor: pointer;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+ }
+ .download-artifact-button {
+ display: flex;
+ justify-content: center;
+
+ .action-icon{
+ margin-right: 10px;
+ }
+ }
+
+ .add-artifacts-dynamic-btn-list {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+ margin: 20px 0px;
+ .add-artifacts-dynamic-btn{
+ width: 350px;
+ margin-top: 15px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.ts b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.ts
new file mode 100644
index 0000000..a6804a4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.component.ts
@@ -0,0 +1,69 @@
+import {Component, OnInit, ViewChild} from "@angular/core";
+import {WorkspaceService} from "../workspace.service";
+import {SdcUiCommon, SdcUiComponents, SdcUiServices} from "onap-ui-angular";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import * as _ from "lodash";
+import {ArtifactGroupType, ArtifactType} from "../../../../utils/constants";
+import {ArtifactsService} from "../../../components/forms/artifacts-form/artifacts.service";
+import {DeleteArtifactAction, GetArtifactsByTypeAction} from "../../../store/actions/artifacts.action";
+import {Select, Store} from "@ngxs/store";
+import {Observable} from "rxjs/index";
+import {ArtifactsState} from "../../../store/states/artifacts.state";
+import {map} from "rxjs/operators";
+import {WorkspaceState} from "../../../store/states/workspace.state";
+import {ArtifactModel} from "../../../../models/artifacts";
+
+@Component({
+ selector: 'information-artifact-page',
+ templateUrl: './information-artifact-page.component.html',
+ styleUrls: ['./information-artifact-page.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class InformationArtifactPageComponent implements OnInit {
+
+ public componentId: string;
+ public componentType: string;
+ public informationArtifacts$: Observable<ArtifactModel[]>;
+ public informationArtifactsAsButtons$: Observable<ArtifactModel[]>;
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+ @ViewChild('informationArtifactsTable') table: any;
+
+ constructor(private workspaceService: WorkspaceService,
+ private artifactsService: ArtifactsService,
+ private store: Store) {
+ }
+
+ ngOnInit(): void {
+ this.componentId = this.workspaceService.metadata.uniqueId;
+ this.componentType = this.workspaceService.metadata.componentType;
+
+ this.store.dispatch(new GetArtifactsByTypeAction({
+ componentType: this.componentType,
+ componentId: this.componentId,
+ artifactType: ArtifactGroupType.INFORMATION
+ }));
+
+ let artifacts = this.store.select(ArtifactsState.getArtifactsByType).pipe(map(filterFn => filterFn(ArtifactType.INFORMATION)));
+ this.informationArtifacts$ = artifacts.pipe(map(artifacts => _.filter(artifacts, (artifact) => {
+ return artifact.esId;
+ })));
+
+ this.informationArtifactsAsButtons$ = artifacts.pipe(map(artifacts => _.filter(artifacts, (artifact) => {
+ return !artifact.esId;
+ })));
+ }
+
+ onActivate(event) {
+ if (event.type === 'click') {
+ this.table.rowDetail.toggleExpandRow(event.row);
+ }
+ }
+
+ public addOrUpdateArtifact = (artifact: ArtifactModel, isViewOnly?: boolean) => {
+ this.artifactsService.openArtifactModal(this.componentId, this.componentType, artifact, ArtifactGroupType.INFORMATION, isViewOnly);
+ }
+
+ public deleteArtifact = (artifactToDelete) => {
+ this.artifactsService.deleteArtifact(this.componentType, this.componentId, artifactToDelete)
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.module.ts b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.module.ts
new file mode 100644
index 0000000..5eb9e58
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/information-artifact-page.module.ts
@@ -0,0 +1,30 @@
+import {CommonModule} from "@angular/common";
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {UiElementsModule} from "../../../components/ui/ui-elements.module";
+import {InformationArtifactPageComponent} from "./information-artifact-page.component";
+import {ArtifactFormModule} from "../../../components/forms/artifacts-form/artifact-form.module";
+import {ArtifactsService} from "../../../components/forms/artifacts-form/artifacts.service";
+
+@NgModule({
+ declarations: [
+ InformationArtifactPageComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ NgxDatatableModule,
+ UiElementsModule,
+ ArtifactFormModule
+ ],
+ exports: [
+ InformationArtifactPageComponent
+ ],
+ entryComponents: [
+ InformationArtifactPageComponent
+ ],
+ providers:[ArtifactsService]
+})
+export class InformationArtifactPageModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/information-artifact/informational-artifact-page.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/informational-artifact-page.spec.ts
new file mode 100644
index 0000000..10fd147
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/information-artifact/informational-artifact-page.spec.ts
@@ -0,0 +1,77 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {WorkspaceService} from "../workspace.service";
+import {SdcUiServices} from "onap-ui-angular";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {Observable} from "rxjs/Observable";
+import {ComponentMetadata} from "../../../../models/component-metadata";
+import 'rxjs/add/observable/of';
+import {NgxsModule, Store} from "@ngxs/store";
+import {ArtifactsState} from "../../../store/states/artifacts.state";
+import {InformationArtifactPageComponent} from "./information-artifact-page.component";
+import { informationalArtifactsMock} from "../../../../../jest/mocks/artifacts-mock";
+import {ArtifactsService} from "../../../components/forms/artifacts-form/artifacts.service";
+
+describe('informational artifacts page', () => {
+
+ let fixture: ComponentFixture<InformationArtifactPageComponent>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let store: Store;
+
+ beforeEach(
+ async(() => {
+
+ topologyTemplateServiceMock = {
+ getArtifactsByType: jest.fn().mockImplementation((componentType, id, artifactType) => Observable.of(informationalArtifactsMock))
+ };
+ workspaceServiceMock = {metadata: <ComponentMetadata>{uniqueId: 'service_unique_id', componentType: 'SERVICE'}}
+
+ loaderServiceMock = {
+ activate : jest.fn(),
+ deactivate: jest.fn()
+ }
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [InformationArtifactPageComponent],
+ imports: [NgxDatatableModule, NgxsModule.forRoot([ArtifactsState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: TopologyTemplateService, useValue: topologyTemplateServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock },
+ {provide: ArtifactsService, useValue: {}},
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(InformationArtifactPageComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it('should match current snapshot of informational artifact pages component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should see exactly 3 informational artifacts and six buttons to add artifact by template', () => {
+ fixture.componentInstance.ngOnInit();
+ fixture.componentInstance.informationArtifacts$.subscribe((artifacts)=> {
+ expect(artifacts.length).toEqual(3);
+ })
+ fixture.componentInstance.informationArtifactsAsButtons$.subscribe((artifacts)=> {
+ expect(artifacts.length).toEqual(6);
+ })
+
+ store.selectOnce(state => state.artifacts.artifacts).subscribe(artifacts => {
+ expect(artifacts.length).toEqual(9);
+ });
+ })
+
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.html
new file mode 100644
index 0000000..f496e64
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.html
@@ -0,0 +1,22 @@
+<div class="capabilities-properties-table">
+ <ngx-datatable #componentsMetadataTable
+ columnMode="flex"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rows]="capabilitiesProperties"
+ [sorts]="[{prop: 'name', dir: 'desc'}]">
+ <ngx-datatable-column *ngFor="let column of capabilityPropertiesColumns" [ngSwitch]="column.prop" [resizeable]="false"
+ [draggable]="false" name={{column.name}} [flexGrow]="column.flexGrow">
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'name'">
+ <a data-tests-id="row[column.prop]" sdc-tooltip [tooltip-text]="row[column.prop]" (click)="updateProperty(row)">{{row[column.prop]}}</a>
+ </ng-template>
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'schema'">
+ <span *ngIf="row[column.prop] && row[column.prop].property" data-tests-id="row[column.prop].property.type"
+ sdc-tooltip [tooltip-text]="row[column.prop].property.type">{{row[column.prop].property.type}}</span>
+ </ng-template>
+ <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchDefault>
+ <span data-tests-id="row[column.prop]" sdc-tooltip [tooltip-text]="row[column.prop]" [tooltip-placement]="3">{{row[column.prop]}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.less
new file mode 100644
index 0000000..007f509
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.less
@@ -0,0 +1,9 @@
+
+:host ::ng-deep {
+ .ngx-datatable {
+ > div {
+ min-height: auto !important;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.ts
new file mode 100644
index 0000000..2a1a16e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities-properties/capabilities-properties.ts
@@ -0,0 +1,33 @@
+
+import { ViewChild, Input, OnInit, Component } from "@angular/core";
+import {SdcUiServices} from "onap-ui-angular";
+import { ModalsHandler } from "../../../../../../utils/modals-handler";
+import { WorkspaceService } from "../../../workspace.service";
+import { PropertyModel } from "../../../../../../models/properties";
+
+
+@Component({
+ selector: 'capabilities-properties',
+ templateUrl: './capabilities-properties.html',
+ styleUrls: ['./capabilities-properties.less', '../../../../../../../assets/styles/table-style.less']
+})
+export class CapabilitiesPropertiesComponent {
+ @Input() public capabilitiesProperties: Array<PropertyModel> = [];
+
+ private capabilityPropertiesColumns = [
+ {name: 'Name', prop: 'name', flexGrow: 1},
+ {name: 'Type', prop: 'type', flexGrow: 1},
+ {name: 'Schema', prop: 'schema', flexGrow: 1},
+ {name: 'Description', prop: 'description', flexGrow: 1},
+ ];
+ constructor(private modalsHandler: ModalsHandler,
+ private workspaceService: WorkspaceService) {}
+
+ private updateProperty(property: PropertyModel): void {
+ _.forEach(this.capabilitiesProperties, (prop: PropertyModel) => {
+ prop.readonly = true;
+ });
+ this.modalsHandler.openEditPropertyModal(property, this.workspaceService.metadata, this.capabilitiesProperties, false, 'component',
+ this.workspaceService.metadata.uniqueId);
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.html
new file mode 100644
index 0000000..819eb84
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.html
@@ -0,0 +1,59 @@
+<div class="capabilities-table">
+ <div class="expand-collapse-all-rows">
+ <svg-icon class="selected-all-capabilities"
+ [mode]="'primary'" [clickable]="true" [name]="'expand-o'"
+ [size]="'medium'" (click)="capabilitiesTable.rowDetail.expandAllRows()">
+ </svg-icon>
+ <svg-icon class="unselected-all-capabilities"
+ [mode]="'primary'" [clickable]="true" [name]="'minimize-o'"
+ [size]="'medium'" (click)="capabilitiesTable.rowDetail.collapseAllRows()">
+ </svg-icon>
+ </div>
+ <ngx-datatable #capabilitiesTable
+ columnMode="flex"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rows]="capabilities"
+ (select)="onSelectCapabilities($event)"
+ [selectionType]="'single'">
+ <ngx-datatable-row-detail [rowHeight]="undefiend">
+ <ng-template let-row="row" ngx-datatable-row-detail-template>
+ <div class="properties-title">Properties</div>
+ <capabilities-properties [capabilitiesProperties]="row.properties"></capabilities-properties>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column name="Name" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded">
+ <div class="expand-collapse-cell">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'" (click)="expendRow(row)"></svg-icon>
+ <span data-tests-id="row.name" sdc-tooltip [tooltip-text]="row.name" [tooltip-placement]="3" (click)="editCapability(row)">{{row.name}}</span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Type" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.type" sdc-tooltip [tooltip-text]="row.type" [tooltip-placement]="3">{{row.type ? row.type.replace("tosca.capabilities.",""): ''}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Description" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.description" sdc-tooltip [tooltip-text]="row.description" [tooltip-placement]="3">{{row.description}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Valid Source" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.validSourceTypes.join(',')" sdc-tooltip [tooltip-text]="row.validSourceTypes ? row.validSourceTypes.join(',') : null" [tooltip-placement]="3">
+ {{row.validSourceTypes ? row.validSourceTypes.join(','): ''}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Occurrences" [flexGrow]="1" [prop]="'minOccurrences'" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.minOccurrences+','+row.maxOccurrences" sdc-tooltip
+ [tooltip-text]="row.minOccurrences+','+row.maxOccurrences" [tooltip-placement]="3">
+ {{row.minOccurrences}},{{row.maxOccurrences}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.less
new file mode 100644
index 0000000..0c520a8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.less
@@ -0,0 +1,16 @@
+:host ::ng-deep {
+ .datatable-row-detail {
+ width: 1260px;
+ }
+ .datatable-body-row {
+ cursor: pointer;
+ }
+}
+.expand-collapse-all-rows {
+ position: absolute;
+ top: 172px;
+ left: 890px;
+}
+.properties-title {
+ padding-bottom: 10px;
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.ts
new file mode 100644
index 0000000..02db5d3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilities.component.ts
@@ -0,0 +1,79 @@
+import {Capability, CapabilityUI} from "../../../../../models/capability";
+import { ViewChild, Input, OnInit, Component } from "@angular/core";
+import {SdcUiServices} from "onap-ui-angular";
+import {CapabilitiesEditorComponent} from "./capabilityEditor/capabilities-editor.component";
+import {WorkspaceService} from "../../workspace.service";
+import {TopologyTemplateService} from "../../../../services/component-services/topology-template.service";
+import {ReqAndCapabilitiesService} from "../req-and-capabilities.service";
+import {ModalComponent} from "onap-ui-angular/dist/modals/modal.component";
+import {EventListenerService} from "../../../../../services/event-listener-service";
+
+
+@Component({
+ selector: 'capabilities',
+ templateUrl: './capabilities.component.html',
+ styleUrls: ['./capabilities.component.less','../../../../../../assets/styles/table-style.less']
+})
+export class CapabilitiesComponent {
+ @Input() public capabilities: Array<Capability>;
+ @ViewChild('capabilitiesTable') capabilitiesTable: any;
+ private customModalInstance: ModalComponent;
+
+ constructor(
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService,
+ private topologyTemplateService: TopologyTemplateService,
+ private reqAndCapabilitiesService : ReqAndCapabilitiesService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService) {
+ }
+
+ private onSelectCapabilities({ selected }) {
+ }
+
+ editCapability(cap: CapabilityUI) {
+ let modalConfig = {
+ size: 'md',
+ title: 'Update Capability',
+ type: 'custom',
+ buttons: [
+ {
+ id: 'saveButton',
+ text: ('Update'),
+ size: "'x-small'",
+ callback: () => this.updateCapability(),
+ closeModal: true
+ },
+ {text: "Cancel", size: "'x-small'", closeModal: true}]
+ };
+ let modalInputs = {
+ capability: cap,
+ capabilityTypesList: this.reqAndCapabilitiesService.getCapabilityTypesList(),
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(modalConfig, CapabilitiesEditorComponent, {input: modalInputs});
+ this.customModalInstance.innerModalContent.instance.
+ onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('saveButton').disabled = !isValid);
+ }
+
+ expendRow(row) {
+ this.capabilitiesTable.rowDetail.toggleExpandRow(row);
+ }
+
+ private updateCapability() {
+ const capability = this.customModalInstance.innerModalContent.instance.capabilityData;
+ this.loaderService.activate();
+ if (capability.uniqueId) {
+ this.topologyTemplateService.updateCapability(this.workspaceService.metadata.getTypeUrl(), this.workspaceService.metadata.uniqueId, capability).subscribe((result) => {
+ let index = this.capabilities.findIndex((cap) => result[0].uniqueId === cap.uniqueId);
+ this.capabilities[index] = new CapabilityUI(result[0], this.workspaceService.metadata.uniqueId);
+ this.loaderService.deactivate();
+ this.eventListenerService.notifyObservers('CAPABILITIES_UPDATED');
+ }, () => {
+ this.loaderService.deactivate();
+ });
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.html
new file mode 100644
index 0000000..bc15d4d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.html
@@ -0,0 +1,93 @@
+<div class="capability-editor">
+ <form class="w-sdc-form">
+ <div class="i-sdc-form-content-capability-content">
+ <div class="content-row">
+ <div class="i-sdc-form-item">
+ <sdc-input
+ label="{{ 'CAP_NAME' | translate }}"
+ required="true"
+ class="i-sdc-form-input"
+ testId="capName"
+ [disabled]="isReadonly"
+ [(value)]="capabilityData.name"
+ (valueChange)="validityChanged()">
+ </sdc-input>
+ </div>
+ </div>
+
+ <div class="group-with-border">
+ <div class="content-row i-sdc-form-item">
+ <sdc-dropdown
+ label="{{ 'CAP_TYPE' | translate }}"
+ required="true"
+ class="i-sdc-form-select"
+ testId="capType"
+ [disabled]="isReadonly"
+ [options]="capabilityTypesMappedList"
+ selectedOption="{{ capabilityData.type }}"
+ [placeHolder] = "capabilityData.type"
+ (changed)="onSelectCapabilityType($event)">
+ </sdc-dropdown>
+ </div>
+ <div class="content-row i-sdc-form-item">
+ <label class="i-sdc-form-label"> {{ 'CAP_DESCRIPTION' | translate }} </label>
+ <textarea
+ rows="3"
+ class="i-sdc-form-input description"
+ data-tests-id="capDesc"
+ disabled
+ value="{{capabilityData.description}}">
+ </textarea>
+ </div>
+ <div class="content-row i-sdc-form-item">
+ <label class="i-sdc-form-label valid-source-label"> {{ 'CAP_VALID_SOURCE' | translate }} </label>
+ <textarea
+ rows="2"
+ class="i-sdc-form-input"
+ data-tests-id="capValidSrc"
+ disabled
+ value="{{capabilityData.validSourceTypes}}">
+ </textarea>
+ </div>
+ </div>
+
+ <label class="i-sdc-form-label occurrences-label"> {{ 'REQ_CAP_OCCURRENCES' | translate }} </label>
+ <div class="content-row occurrences-section">
+ <div class="min-occurrences-value">
+ <sdc-input
+ label="{{ 'REQ_CAP_OCCURRENCES_MIN' | translate }}"
+ class="i-sdc-form-input"
+ testId="capOccurrencesMin"
+ [disabled]="isReadonly"
+ [(value)]="capabilityData.minOccurrences"
+ (valueChange)="validityChanged()"
+ type="number">
+ </sdc-input>
+ </div>
+ <div class="sdc-input">
+ <label class="sdc-input__label"> {{ 'REQ_CAP_OCCURRENCES_MAX' | translate }} </label>
+ <div class="max-occurrences-value">
+ <sdc-checkbox
+ class="checkbox-label unbounded-value"
+ testId="capOccurrencesMaxUnbounded"
+ label="{{translatedUnboundTxt.toLowerCase()}}"
+ (checkedChange)="onUnboundedChanged()"
+ [checked]="isUnboundedChecked"
+ [disabled]="isReadonly">
+ </sdc-checkbox>
+
+ <sdc-input
+ *ngIf="!isUnboundedChecked"
+ class="i-sdc-form-input"
+ testId="capOccurrencesMax"
+ [disabled]="isReadonly"
+ [(value)]="capabilityData.maxOccurrences"
+ (valueChange)="validityChanged()"
+ type="number">
+ </sdc-input>
+ </div>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.less
new file mode 100644
index 0000000..324dc6c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.less
@@ -0,0 +1,38 @@
+@import '../../../../../../../assets/styles/variables.less';
+
+.capability-editor {
+ .i-sdc-form-content-capability-content {
+ padding: 10px 25px;
+ .group-with-border {
+ margin: 25px 0;
+ padding: 15px 0;
+ border-top: 1px solid @tlv_color_u;
+ border-bottom: 1px solid @tlv_color_u;
+ .content-row:not(:last-of-type) {
+ padding-bottom: 13px;
+ }
+ }
+
+ .occurrences-label {
+ font-family: @font-opensans-bold;
+ margin-bottom: 19px;
+ }
+ .occurrences-section, /deep/ .max-occurrences-value {
+ display: flex;
+ .min-occurrences-value {
+ padding-right: 30px;
+ }
+ .unbounded-value {
+ padding-top: 7px;
+ padding-right: 20px;
+ .sdc-checkbox__label {
+ text-transform: capitalize;
+ }
+ }
+ }
+ textarea {
+ min-height: unset;
+ height: unset;
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.ts
new file mode 100644
index 0000000..3bafa42
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.component.ts
@@ -0,0 +1,81 @@
+import {Component} from '@angular/core';
+import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
+import {Capability, CapabilityTypeModel} from 'app/models';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {TranslateService} from 'app/ng2/shared/translator/translate.service';
+import {Subject} from "rxjs";
+
+@Component({
+ selector: 'capabilities-editor',
+ templateUrl: './capabilities-editor.component.html',
+ styleUrls: ['./capabilities-editor.component.less'],
+ providers: [ServiceServiceNg2]
+})
+
+export class CapabilitiesEditorComponent {
+ input: {
+ test: string,
+ capability: Capability,
+ capabilityTypesList: Array<CapabilityTypeModel>,
+ isReadonly: boolean;
+ };
+ capabilityData: Capability;
+ capabilityTypesMappedList: Array<DropdownValue>;
+ isUnboundedChecked: boolean;
+ isReadonly: boolean;
+ translatedUnboundTxt: string;
+
+ public onValidationChange: Subject<boolean> = new Subject();
+
+ constructor(private translateService: TranslateService) {
+ }
+
+ ngOnInit() {
+ this.capabilityData = new Capability(this.input.capability);
+ this.translatedUnboundTxt = '';
+ this.capabilityData.minOccurrences = this.capabilityData.minOccurrences || 0;
+ this.translateService.languageChangedObservable.subscribe(lang => {
+ this.translatedUnboundTxt = this.translateService.translate('REQ_CAP_OCCURRENCES_UNBOUNDED');
+ this.capabilityData.maxOccurrences = this.capabilityData.maxOccurrences || this.translatedUnboundTxt;
+ this.isUnboundedChecked = this.capabilityData.maxOccurrences === this.translatedUnboundTxt;
+ });
+ this.capabilityTypesMappedList = _.map(this.input.capabilityTypesList, capType => new DropdownValue(capType.toscaPresentation.type, capType.toscaPresentation.type));
+ this.isReadonly = this.input.isReadonly;
+ this.validityChanged();
+ }
+
+ onUnboundedChanged() {
+ this.isUnboundedChecked = !this.isUnboundedChecked;
+ this.capabilityData.maxOccurrences = this.isUnboundedChecked ? this.translatedUnboundTxt : null;
+ this.validityChanged();
+ }
+
+ checkFormValidForSubmit() {
+ return this.capabilityData.name && this.capabilityData.name.length &&
+ this.capabilityData.type && this.capabilityData.type.length && !_.isEqual(this.capabilityData.minOccurrences, "") && this.capabilityData.minOccurrences >= 0 &&
+ (
+ this.isUnboundedChecked ||
+ (this.capabilityData.maxOccurrences && (this.capabilityData.minOccurrences <= parseInt(this.capabilityData.maxOccurrences)))
+ );
+ }
+
+ onSelectCapabilityType(selectedCapType: DropdownValue) {
+ this.capabilityData.type = selectedCapType && selectedCapType.value;
+ if (selectedCapType && selectedCapType.value) {
+ let selectedCapabilityTypeObj: CapabilityTypeModel = this.input.capabilityTypesList.find(capType => capType.toscaPresentation.type === selectedCapType.value);
+ this.capabilityData.description = selectedCapabilityTypeObj.toscaPresentation.description;
+ this.capabilityData.validSourceTypes = selectedCapabilityTypeObj.toscaPresentation.validTargetTypes;
+ this.capabilityData.properties = _.forEach(
+ _.toArray(selectedCapabilityTypeObj.properties),
+ prop => prop.uniqueId = null //a requirement for the BE
+ );
+ }
+ this.validityChanged();
+ }
+
+ validityChanged = () => {
+ let validState = this.checkFormValidForSubmit();
+ this.onValidationChange.next(validState);
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.module.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.module.ts
new file mode 100644
index 0000000..38b104a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/capabilities/capabilityEditor/capabilities-editor.module.ts
@@ -0,0 +1,29 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {CapabilitiesEditorComponent} from './capabilities-editor.component';
+import {FormsModule} from '@angular/forms';
+import {FormElementsModule} from 'app/ng2/components/ui/form-components/form-elements.module';
+import {UiElementsModule} from 'app/ng2/components/ui/ui-elements.module';
+import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
+import {SdcUiComponentsModule} from 'onap-ui-angular';
+// import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
+
+@NgModule({
+ declarations: [
+ CapabilitiesEditorComponent
+ ],
+ imports: [CommonModule,
+ FormsModule,
+ FormElementsModule,
+ UiElementsModule,
+ TranslateModule,
+ SdcUiComponentsModule
+ ],
+ exports: [],
+ entryComponents: [
+ CapabilitiesEditorComponent
+ ],
+ providers: []
+})
+export class CapabilitiesEditorModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.html
new file mode 100644
index 0000000..73e0ae5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.html
@@ -0,0 +1,21 @@
+<div class="workspace-req-and-cap">
+ <div>
+ <span class="addTitle" *ngIf="selectTabName === 'REQUIREMENTS'" (click)="addRequiremnet()">Add Requirement</span>
+ <span class="addTitle" *ngIf="selectTabName !== 'REQUIREMENTS'" (click)="addCapability()">Add Capability</span>
+ <span class="req-and-cap-filter" *ngIf="notEmptyTable">
+ <sdc-filter-bar
+ [placeHolder]="'Search'"
+ (keyup)="updateFilter($event)"
+ [testId]="'search-box'">
+ </sdc-filter-bar>
+ </span>
+ </div>
+ <sdc-tabs (selectedTab)="selectTab($event)" [tabStyle]="'sdc-table-tab'">
+ <sdc-tab [title]="'Requirements('+(requirements.length||'0')+')'" [active]="true" [testId]="'req-tab'">
+ <div #requirmentsContainer></div>
+ </sdc-tab>
+ <sdc-tab [title]="'Capabilities('+(capabilities.length||'0')+')'" [active]="false" [testId]="'cap-tab'">
+ <div #capabilitiesContainer></div>
+ </sdc-tab>
+ </sdc-tabs>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.less
new file mode 100644
index 0000000..f3d39ca
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.less
@@ -0,0 +1,19 @@
+.req-and-cap-filter {
+ width: 336px;
+ float: right;
+ margin-right: 10px;
+}
+
+.addTitle {
+ float: right;
+ text-transform: uppercase;
+ font-family: OpenSans-Semibold, sans-serif;
+ color: #009fdb;
+ cursor: pointer;
+}
+
+:host ::ng-deep .sdc-tabs {
+ .sdc-tab-content {
+ margin-top: 0;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.spec.ts
new file mode 100644
index 0000000..b7fad04
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.spec.ts
@@ -0,0 +1,127 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import { NO_ERRORS_SCHEMA} from "@angular/core";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+
+import {Observable} from "rxjs/Observable";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {SdcUiServices, SdcUiCommon} from "onap-ui-angular";
+import 'rxjs/add/observable/of';
+import {ReqAndCapabilitiesComponent} from "./req-and-capabilities.component";
+import {ReqAndCapabilitiesService} from "./req-and-capabilities.service";
+import {WorkspaceService} from "../workspace.service";
+import {
+ capabilitiesMock,
+ filterRequirmentsMock,
+ requirementMock
+} from "../../../../../jest/mocks/req-and-capabilities.mock";
+import {ComponentMetadata} from "../../../../models/component-metadata";
+import { TopologyTemplateService } from "../../../services/component-services/topology-template.service";
+import {EventListenerService} from "../../../../services/event-listener-service";
+
+describe('req and capabilities component', () => {
+
+ let fixture: ComponentFixture<ReqAndCapabilitiesComponent>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let createDynamicComponentServiceMock: Partial<SdcUiServices.CreateDynamicComponentService>
+ let reqAndCapabilitiesService: Partial<ReqAndCapabilitiesService>;
+ let modalService: Partial<SdcUiServices.ModalService>;
+ let eventListenerService: Partial<EventListenerService>;
+
+
+
+ beforeEach(
+ async(() => {
+
+ workspaceServiceMock = {
+ metadata: new ComponentMetadata()
+ };
+
+ topologyTemplateServiceMock = {
+ getRequirementsAndCapabilitiesWithProperties: jest.fn().mockImplementation(() =>
+ Observable.of({requirements: {'tosca.requirements.Node': requirementMock},
+ capabilities: {'tosca.capabilities.Node': capabilitiesMock}}))
+ };
+
+ loaderServiceMock = {
+ activate : jest.fn(),
+ deactivate: jest.fn()
+ }
+ createDynamicComponentServiceMock = {
+ insertComponentDynamically: jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [ReqAndCapabilitiesComponent],
+ imports: [NgxDatatableModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: WorkspaceService, useValue: workspaceServiceMock },
+ { provide: SdcUiServices.LoaderService, useValue: loaderServiceMock },
+ { provide: TopologyTemplateService, useValue: topologyTemplateServiceMock },
+ { provide: SdcUiServices.CreateDynamicComponentService, useValue: createDynamicComponentServiceMock },
+ { provide: ReqAndCapabilitiesService, useValue: reqAndCapabilitiesService },
+ { provide: SdcUiServices.ModalService, useValue: modalService },
+ { provide: EventListenerService, useValue: eventListenerService }
+ ],
+ });
+ };
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(ReqAndCapabilitiesComponent);
+ });
+ })
+ );
+
+ it('should see exactly 2 requirement in requirements table when call initCapabilitiesAndRequirements and meta data requirements null', () => {
+ workspaceServiceMock.metadata.requirements = null;
+ fixture.componentInstance.initCapabilitiesAndRequirements();
+ expect(workspaceServiceMock.metadata.requirements["tosca.requirements.Node"].length).toBe(3);
+ });
+ it('should see exactly 2 capabilities in capabilities table when call initCapabilitiesAndRequirements and meta data capabilities null', () => {
+ workspaceServiceMock.metadata.capabilities = null;
+ fixture.componentInstance.initCapabilitiesAndRequirements();
+ expect(workspaceServiceMock.metadata.capabilities["tosca.capabilities.Node"].length).toBe(2);
+ });
+
+ it('capabilities array papulated when call populateReqOrCap with capabilities', () => {
+ workspaceServiceMock.metadata.capabilities = {"tosca.capabilities.Node": capabilitiesMock, "tosca.capabilities.Scalable": capabilitiesMock};
+ fixture.componentInstance.populateReqOrCap("capabilities");
+ expect(fixture.componentInstance.capabilities.length).toBe(4);
+ });
+
+ it('create requirements component when call loadReqOrCap with true', () => {
+ createDynamicComponentServiceMock.insertComponentDynamically.mockImplementation(() => { return {instance: {requirements: requirementMock}}});
+ fixture.componentInstance.requirements = requirementMock;
+ fixture.componentInstance.loadReqOrCap(true);
+ expect(fixture.componentInstance.instanceRef.instance.requirements.length).toEqual(3);
+ });
+
+ it('create capabilities component when call loadReqOrCap with false', () => {
+ fixture.componentInstance.instanceRef = {instance: {requirements: null}};
+ createDynamicComponentServiceMock.insertComponentDynamically.mockImplementation(() => { return {instance: {capabilities: capabilitiesMock}}});
+ fixture.componentInstance.capabilities = capabilitiesMock;
+ fixture.componentInstance.requirementsUI = filterRequirmentsMock;
+ let event = {
+ target : {
+ value : 'root'
+ }
+ }
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.instanceRef.instance.requirements.length).toBe(1);
+ });
+
+ it('should filter 1 capabilities when searching and call updateFilter function and instanceRef is capabilities component', () => {
+ fixture.componentInstance.instanceRef = {instance: {capabilities: null}};
+ fixture.componentInstance.capabilities = capabilitiesMock;
+ fixture.componentInstance.selectTabName = 'CAPABILITIES';
+ let event = {
+ target : {
+ value : '1source'
+ }
+ }
+ fixture.componentInstance.updateFilter(event);
+ expect(fixture.componentInstance.instanceRef.instance.capabilities[0].type).toBe("tosca.capabilities.Node");
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.ts
new file mode 100644
index 0000000..69999bf
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component.ts
@@ -0,0 +1,229 @@
+import { Component, ComponentRef, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
+import * as _ from 'lodash';
+import { SdcUiServices } from 'onap-ui-angular';
+import { Capability, CapabilityUI } from '../../../../models/capability';
+import { Requirement, RequirementUI } from '../../../../models/requirement';
+import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../../services/responses/component-generic-response';
+import { WorkspaceService } from '../workspace.service';
+import { CapabilitiesComponent } from './capabilities/capabilities.component';
+import { RequirmentsComponent } from './requirements/requirments.components';
+import {ReqAndCapabilitiesService} from "./req-and-capabilities.service";
+import {CapabilitiesEditorComponent} from "./capabilities/capabilityEditor/capabilities-editor.component";
+import {ModalComponent} from "onap-ui-angular/dist/modals/modal.component";
+import {EventListenerService} from "../../../../services/event-listener-service";
+import {RequirementsEditorComponent} from "./requirements/requirementEditor/requirements-editor.component";
+
+@Component({
+ selector: 'req-and-capabilities',
+ templateUrl: './req-and-capabilities.component.html',
+ styleUrls: ['./req-and-capabilities.component.less']
+})
+export class ReqAndCapabilitiesComponent implements OnInit {
+
+ @ViewChild('requirmentsContainer', { read: ViewContainerRef }) requirmentsContainer: ViewContainerRef;
+ @ViewChild('capabilitiesContainer', { read: ViewContainerRef }) capabilitiesContainer: ViewContainerRef;
+ private requirements: Requirement[] = [];
+ private requirementsUI: RequirementUI[] = [];
+ private capabilities: Capability[] = [];
+ private selectTabName: string = 'REQUIREMENTS';
+ private notEmptyTable: boolean = true;
+ private instanceRef: ComponentRef<any>;
+ private customModalInstance: ModalComponent;
+ readonly INPUTS_FOR_CAPABILITIES: string = 'INPUTS_FOR_CAPABILITIES';
+ readonly INPUTS_FOR_REQUIREMENTS: string = 'INPUTS_FOR_REQUIREMENTS';
+
+ constructor(private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService,
+ private topologyTemplateService: TopologyTemplateService,
+ private createDynamicComponentService: SdcUiServices.CreateDynamicComponentService,
+ private reqAndCapabilitiesService : ReqAndCapabilitiesService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService) {
+ }
+
+ ngOnInit(): void {
+ this.initCapabilitiesAndRequirements();
+
+ this.eventListenerService.registerObserverCallback('CAPABILITIES_UPDATED', () => {
+ this.loadReqOrCap();
+ });
+
+ this.eventListenerService.registerObserverCallback('REQUIREMENTS_UPDATED', () => {
+ this.loadReqOrCap();
+ });
+ }
+
+
+
+ private initCapabilitiesAndRequirements(): void {
+ if (!this.workspaceService.metadata.capabilities || !this.workspaceService.metadata.requirements) {
+ this.loaderService.activate();
+ this.topologyTemplateService.getRequirementsAndCapabilitiesWithProperties
+ (this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId)
+ .subscribe((response: ComponentGenericResponse) => {
+ this.workspaceService.metadata.capabilities = response.capabilities;
+ this.workspaceService.metadata.requirements = response.requirements;
+ this.initReqOrCap();
+ this.loaderService.deactivate();
+ }, (error) => {
+ this.loaderService.deactivate();
+ });
+ } else {
+ this.initReqOrCap();
+ }
+ }
+
+ private initReqOrCap() {
+ this.populateReqOrCap('requirements');
+ this.extendRequirementsToRequiremnetsUI(this.requirements);
+ this.populateReqOrCap('capabilities');
+ this.loadReqOrCap();
+ }
+
+ private populateReqOrCap(instanceName: string) {
+ _.forEach(this.workspaceService.metadata[instanceName], (concatArray: any[], name) => {
+ this[instanceName] = this[instanceName].concat(concatArray);
+ });
+ }
+
+ private updateFilter(event) {
+ const val = event.target.value.toLowerCase();
+ if (this.selectTabName === 'REQUIREMENTS') {
+ this.instanceRef.instance.requirements = this.requirementsUI.filter((req: Requirement) => {
+ return !val || this.filterRequirments(req, val);
+ });
+ } else {
+ this.instanceRef.instance.capabilities = this.capabilities.filter((cap: Capability) => {
+ return !val || this.filterCapabilities(cap, val);
+ });
+ }
+
+ }
+
+ private selectTab($event) {
+ this.selectTabName = $event.title.contains('Requirement') ? 'REQUIREMENTS' : 'CATPABILITIES';
+ this.loadReqOrCap();
+ }
+
+ private async loadReqOrCap() {
+ if (this.instanceRef) {
+ this.instanceRef.destroy();
+ }
+
+ if (this.selectTabName === 'REQUIREMENTS') {
+ this.notEmptyTable = this.requirementsUI.length !== 0;
+ this.instanceRef = this.createDynamicComponentService.
+ insertComponentDynamically(RequirmentsComponent, {requirements: this.requirementsUI}, this.requirmentsContainer);
+ // TODO - Keep the initInputs, so it will be called only for the first time - no need to wait to thse API's every time that a user switches tab
+ await this.reqAndCapabilitiesService.initInputs(this.INPUTS_FOR_REQUIREMENTS);
+ } else {
+ this.notEmptyTable = this.capabilities.length !== 0;
+ this.instanceRef = this.createDynamicComponentService.
+ insertComponentDynamically(CapabilitiesComponent, {capabilities: this.capabilities}, this.capabilitiesContainer);
+ // TODO - Keep the initInputs, so it will be called only for the first time - no need to wait to thse API's every time that a user switches tab
+ await this.reqAndCapabilitiesService.initInputs(this.INPUTS_FOR_CAPABILITIES);
+ }
+ }
+
+ private filterCapabilities(capability: Capability, val: string): boolean {
+ return _.includes([capability.name, capability.description, capability.validSourceTypes.join(),
+ capability.minOccurrences, capability.maxOccurrences].join('').toLowerCase(), val) ||
+ (capability.type && capability.type.replace('tosca.capabilities.', '').toLowerCase().indexOf(val) !== -1);
+ }
+
+ private filterRequirments(requirement: Requirement, val: string): boolean {
+ return _.includes([requirement.name, requirement.minOccurrences, requirement.maxOccurrences].join('').toLowerCase(), val) ||
+ (requirement.capability && requirement.capability.substring('tosca.capabilities.'.length).toLowerCase().indexOf(val) !== -1) ||
+ (requirement.node && requirement.node.substring('tosca.node.'.length).toLowerCase().indexOf(val) !== -1) ||
+ (requirement.relationship && requirement.relationship.substring('tosca.relationship.'.length)
+ .toLowerCase().indexOf(val) !== -1);
+ }
+
+ private addCapability() {
+ let modalConfig = {
+ size: 'md',
+ title: 'Add Capability',
+ type: 'custom',
+ buttons: [
+ {
+ id: 'saveButton',
+ text: ('Create'),
+ size: "'x-small'",
+ callback: () => this.createCapability(),
+ closeModal: true
+ },
+ {text: "Cancel", size: "'x-small'", closeModal: true}]
+ };
+ let modalInputs = {
+ capabilityTypesList: this.reqAndCapabilitiesService.getCapabilityTypesList(),
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(modalConfig, CapabilitiesEditorComponent, {input: modalInputs});
+ this.customModalInstance.innerModalContent.instance.
+ onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('saveButton').disabled = !isValid);
+ }
+
+ private createCapability() {
+ const capability = this.customModalInstance.innerModalContent.instance.capabilityData;
+ this.loaderService.activate();
+ if (!capability.uniqueId) {
+ this.topologyTemplateService.createCapability(this.workspaceService.metadata.getTypeUrl(), this.workspaceService.metadata.uniqueId, capability).subscribe((result) => {
+ this.capabilities.unshift(new CapabilityUI(result[0], this.workspaceService.metadata.uniqueId));
+ this.loadReqOrCap();
+ this.loaderService.deactivate();
+ }, () => {
+ this.loaderService.deactivate();
+ });
+ }
+ }
+
+ private addRequiremnet () {
+ let modalConfig = {
+ size: 'md',
+ title: 'Add Requirement',
+ type: 'custom',
+ buttons: [
+ {
+ id: 'saveButton',
+ text: ('Create'),
+ size: "'x-small'",
+ callback: () => this.createRequirement(),
+ closeModal: true
+ },
+ {text: "Cancel", size: "'x-small'", closeModal: true}]
+ };
+ let modalInputs = {
+ // requirement: req,
+ relationshipTypesList: this.reqAndCapabilitiesService.getRelationsShipeTypeList(),
+ nodeTypesList: this.reqAndCapabilitiesService.getNodeTypesList(),
+ capabilityTypesList: this.reqAndCapabilitiesService.getCapabilityTypesList(),
+ // isReadonly: this.$scope.isViewMode() || !this.$scope.isDesigner(),
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(modalConfig, RequirementsEditorComponent, {input: modalInputs});
+ this.customModalInstance.innerModalContent.instance.
+ onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('saveButton').disabled = !isValid);
+ }
+
+
+ private createRequirement() {
+ const requirement = this.customModalInstance.innerModalContent.instance.requirementData;
+ this.loaderService.activate();
+ if (!requirement.uniqueId) {
+ this.topologyTemplateService.createRequirement(this.workspaceService.metadata.getTypeUrl(), this.workspaceService.metadata.uniqueId, requirement).subscribe(result => {
+ this.requirementsUI.unshift(new RequirementUI(result[0], this.workspaceService.metadata.uniqueId));
+ this.loadReqOrCap();
+ this.loaderService.deactivate();
+ }, () => {
+ this.loaderService.deactivate();
+ });
+ }
+ }
+
+ private extendRequirementsToRequiremnetsUI(requirements: Requirement[]) {
+ this.requirements.map((requirement) => {
+ this.requirementsUI.push(new RequirementUI(requirement, this.workspaceService.metadata.uniqueId));
+ });
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.module.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.module.ts
new file mode 100644
index 0000000..aacb3a5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.module.ts
@@ -0,0 +1,49 @@
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import { ReqAndCapabilitiesComponent } from "./req-and-capabilities.component";
+import { CommonModule } from "@angular/common";
+
+import {RequirmentsComponent } from "./requirements/requirments.components";
+import { CapabilitiesComponent } from "./capabilities/capabilities.component";
+import { CapabilitiesPropertiesComponent } from "./capabilities/capabilities-properties/capabilities-properties";
+import {ReqAndCapabilitiesService} from "./req-and-capabilities.service";
+import {RequirementsEditorComponent} from "./requirements/requirementEditor/requirements-editor.component";
+import {CapabilitiesEditorComponent} from "./capabilities/capabilityEditor/capabilities-editor.component";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+import {ToscaTypesServiceNg2} from "../../../services/tosca-types.service";
+
+@NgModule({
+ declarations: [
+ ReqAndCapabilitiesComponent,
+ CapabilitiesComponent,
+ RequirmentsComponent,
+ CapabilitiesPropertiesComponent,
+ RequirementsEditorComponent,
+ CapabilitiesEditorComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ NgxDatatableModule,
+ TranslateModule
+ ],
+ exports: [
+ ReqAndCapabilitiesComponent,
+ CapabilitiesComponent,
+ RequirmentsComponent,
+ CapabilitiesPropertiesComponent
+ ],
+ entryComponents: [
+ ReqAndCapabilitiesComponent,
+ CapabilitiesComponent,
+ RequirmentsComponent,
+ CapabilitiesPropertiesComponent,
+ RequirementsEditorComponent,
+ CapabilitiesEditorComponent
+ ],
+ providers: [ ReqAndCapabilitiesService]
+})
+export class reqAndCapabilitiesModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.service.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.service.ts
new file mode 100644
index 0000000..470aac7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/req-and-capabilities.service.ts
@@ -0,0 +1,80 @@
+import { Injectable } from "@angular/core";
+import { TopologyTemplateService } from "../../../services/component-services/topology-template.service";
+import { Store } from "@ngxs/store";
+import { SdcUiServices } from "onap-ui-angular";
+import { CapabilityTypeModel } from "../../../../models/capability-types";
+import { RelationshipTypeModel } from "../../../../models/relationship-types";
+import { NodeTypeModel } from "../../../../models/node-types";
+import { WorkspaceService } from "../workspace.service";
+import { ToscaTypesServiceNg2 } from "../../../services/tosca-types.service";
+
+
+
+@Injectable()
+export class ReqAndCapabilitiesService {
+
+ private capabilityTypesList: CapabilityTypeModel[];
+ private relationshipTypesList: RelationshipTypeModel[];
+ private nodeTypesList: NodeTypeModel[];
+ private capabilitiesListUpdated: boolean = false;
+ private requirementsListUpdated: boolean = false;
+ private nodeTypeListUpdated: boolean = false;
+
+ readonly INPUTS_FOR_REQUIREMENTS: string = 'INPUTS_FOR_REQUIREMENTS';
+ readonly INPUTS_FOR_CAPABILITIES: string = 'INPUTS_FOR_CAPABILITIES';
+
+ constructor(
+ private workspaceService: WorkspaceService,
+ private modalService: SdcUiServices.ModalService,
+ private loaderService: SdcUiServices.LoaderService,
+ private topologyTemplateService: TopologyTemplateService,
+ private store: Store,
+ private toscaTypesServiceNg2: ToscaTypesServiceNg2){}
+
+ public isViewOnly = (): boolean => {
+ return this.store.selectSnapshot((state) => state.workspace.isViewOnly);
+ }
+
+ public isDesigner = (): boolean => {
+ return this.store.selectSnapshot((state) => state.workspace.isDesigner);
+ }
+
+ public async initInputs(initInputsFor: string) {
+
+ if (!this.capabilitiesListUpdated){
+ // -- COMMON for both --
+ this.capabilityTypesList = [];
+ let capabilityTypesResult = await this.toscaTypesServiceNg2.fetchCapabilityTypes();
+ Object.keys(capabilityTypesResult).forEach(key => {this.capabilityTypesList.push(capabilityTypesResult[key])})
+ this.capabilitiesListUpdated = true;
+ }
+
+ if (initInputsFor === 'INPUTS_FOR_REQUIREMENTS') {
+ if (!this.requirementsListUpdated){
+ this.relationshipTypesList = [];
+ let relationshipTypesResult = await this.toscaTypesServiceNg2.fetchRelationshipTypes();
+ Object.keys(relationshipTypesResult).forEach(key => {this.relationshipTypesList.push(relationshipTypesResult[key])});
+ this.requirementsListUpdated = true;
+ }
+
+ if (!this.nodeTypeListUpdated){
+ this.nodeTypesList = [];
+ let nodeTypesResult = await this.toscaTypesServiceNg2.fetchNodeTypes();
+ Object.keys(nodeTypesResult).forEach(key => {this.nodeTypesList.push(nodeTypesResult[key])})
+ this.nodeTypeListUpdated = true;
+ }
+ }
+ }
+
+ getCapabilityTypesList() {
+ return this.capabilityTypesList;
+ }
+
+ getRelationsShipeTypeList() {
+ return this.relationshipTypesList;
+ }
+
+ getNodeTypesList() {
+ return this.nodeTypesList;
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.html
new file mode 100644
index 0000000..330680d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.html
@@ -0,0 +1,91 @@
+<div class="requirement-editor">
+ <form class="w-sdc-form">
+ <div class="i-sdc-form-content-requirement-content">
+ <div class="content-row">
+ <div class="i-sdc-form-item">
+ <sdc-input
+ label="{{ 'REQ_NAME' | translate}}"
+ required="true"
+ testId="reqName"
+ [disabled]="isReadonly"
+ [(value)]="requirementData.name"
+ (valueChange)="validityChanged()">
+ </sdc-input>
+ </div>
+ </div>
+
+ <div class="group-with-border">
+ <div class="content-row i-sdc-form-item">
+ <sdc-dropdown
+ label="{{ 'REQ_RELATED_CAPABILITY' | translate }}"
+ testId="reqRelatedCapability"
+ required="true"
+ [disabled]="isReadonly"
+ [options]="capabilityTypesMappedList"
+ selectedOption="{{requirementData.capability}}"
+ [placeHolder] = "requirementData.capability"
+ (changed)="onCapabilityChanged($event)">
+ </sdc-dropdown>
+ </div>
+ <div class="content-row i-sdc-form-item">
+ <sdc-dropdown
+ label="{{ 'REQ_NODE' | translate }}"
+ testId="reqNode"
+ [disabled]="isReadonly"
+ [options]="nodeTypesMappedList"
+ selectedOption="{{requirementData.node}}"
+ [placeHolder] = "requirementData.node"
+ (changed)="onNodeChanged($event)">
+ </sdc-dropdown>
+ </div>
+ <div class="content-row i-sdc-form-item">
+ <sdc-dropdown
+ label="{{ 'REQ_RELATIONSHIP' | translate }}"
+ testId="reqRelationship"
+ [disabled]="isReadonly"
+ [options]="relationshipTypesMappedList"
+ selectedOption="{{requirementData.relationship}}"
+ [placeHolder] = "requirementData.relationship"
+ (changed)="onRelationshipChanged($event)">
+ </sdc-dropdown>
+ </div>
+ </div>
+
+ <label class="i-sdc-form-label occurrences-label"> {{ 'REQ_CAP_OCCURRENCES' | translate}} </label>
+ <div class="content-row occurrences-section">
+ <div class="min-occurrences-value">
+ <sdc-input
+ label="{{ 'REQ_CAP_OCCURRENCES_MIN' | translate}}"
+ testId="reqOccurrencesMin"
+ [disabled]="isReadonly"
+ [(value)]="requirementData.minOccurrences"
+ (valueChange)="validityChanged()"
+ type="number">
+ </sdc-input>
+ </div>
+ <div class="sdc-input">
+ <label class="sdc-input__label"> {{ 'REQ_CAP_OCCURRENCES_MAX' | translate}} </label>
+ <div class="max-occurrences-value">
+ <sdc-checkbox
+ class="checkbox-label unbounded-value"
+ testId="reqOccurrencesMaxUnbounded"
+ label="{{translatedUnboundTxt.toLowerCase()}}"
+ (checkedChange)="onUnboundedChanged()"
+ [checked]="isUnboundedChecked"
+ [disabled]="isReadonly">
+ </sdc-checkbox>
+ <sdc-input
+ *ngIf="!isUnboundedChecked"
+ testId="reqOccurrencesMax"
+ [disabled]="isReadonly"
+ [(value)]="requirementData.maxOccurrences"
+ (valueChange)="validityChanged()"
+ type="number">
+ </sdc-input>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.less
new file mode 100644
index 0000000..6e50eb7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.less
@@ -0,0 +1,35 @@
+@import '../../../../../../../assets/styles/variables.less';
+
+.requirement-editor {
+ .i-sdc-form-content-requirement-content {
+ padding: 10px 25px;
+
+ .group-with-border {
+ margin: 25px 0;
+ padding: 15px 0;
+ border-top: 1px solid @tlv_color_u;
+ border-bottom: 1px solid @tlv_color_u;
+ .content-row:not(:last-of-type) {
+ padding-bottom: 13px;
+ }
+ }
+
+ .occurrences-label {
+ font-family: @font-opensans-bold;
+ margin-bottom: 19px;
+ }
+ .occurrences-section, /deep/ .max-occurrences-value {
+ display: flex;
+ .min-occurrences-value {
+ padding-right: 30px;
+ }
+ .unbounded-value {
+ padding-top: 7px;
+ padding-right: 20px;
+ .sdc-checkbox__label {
+ text-transform: capitalize;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.ts
new file mode 100644
index 0000000..2c5c96f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.component.ts
@@ -0,0 +1,90 @@
+import {Component} from '@angular/core';
+import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
+import {Requirement, RelationshipTypeModel, NodeTypeModel, CapabilityTypeModel} from 'app/models';
+import {TranslateService} from 'app/ng2/shared/translator/translate.service';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {Subject} from "rxjs";
+
+@Component({
+ selector: 'requirements-editor',
+ templateUrl: 'requirements-editor.component.html',
+ styleUrls: ['requirements-editor.component.less'],
+ providers: [ServiceServiceNg2, TranslateService]
+})
+
+export class RequirementsEditorComponent {
+
+ input: {
+ requirement: Requirement,
+ relationshipTypesList: Array<RelationshipTypeModel>;
+ nodeTypesList: Array<NodeTypeModel>;
+ capabilityTypesList: Array<CapabilityTypeModel>;
+ isReadonly: boolean;
+ };
+ requirementData: Requirement;
+ capabilityTypesMappedList: Array<DropdownValue>;
+ relationshipTypesMappedList: Array<DropdownValue>;
+ nodeTypesMappedList: Array<DropdownValue>;
+ isUnboundedChecked: boolean;
+ isReadonly: boolean;
+ translatedUnboundTxt: string;
+
+ public onValidationChange: Subject<boolean> = new Subject();
+
+ constructor(private translateService: TranslateService) {
+ }
+
+ ngOnInit() {
+ this.requirementData = new Requirement(this.input.requirement);
+ this.requirementData.minOccurrences = this.requirementData.minOccurrences || 0;
+ this.translatedUnboundTxt = '';
+ this.capabilityTypesMappedList = _.map(this.input.capabilityTypesList, capType => new DropdownValue(capType.toscaPresentation.type, capType.toscaPresentation.type));
+ this.relationshipTypesMappedList = _.map(this.input.relationshipTypesList, rType => new DropdownValue(rType.toscaPresentation.type, rType.toscaPresentation.type));
+ this.nodeTypesMappedList = _.map(this.input.nodeTypesList, nodeType => {
+ return new DropdownValue(
+ nodeType.componentMetadataDefinition.componentMetadataDataDefinition.toscaResourceName,
+ nodeType.componentMetadataDefinition.componentMetadataDataDefinition.toscaResourceName)
+ });
+ this.translateService.languageChangedObservable.subscribe(lang => {
+ this.translatedUnboundTxt = this.translateService.translate('REQ_CAP_OCCURRENCES_UNBOUNDED');
+ this.requirementData.maxOccurrences = this.requirementData.maxOccurrences || this.translatedUnboundTxt;
+ this.isUnboundedChecked = this.requirementData.maxOccurrences === this.translatedUnboundTxt;
+ });
+ this.isReadonly = this.input.isReadonly;
+ this.validityChanged();
+ }
+
+ onUnboundedChanged() {
+ this.isUnboundedChecked = !this.isUnboundedChecked;
+ this.requirementData.maxOccurrences = this.isUnboundedChecked ? this.translatedUnboundTxt : null;
+ this.validityChanged();
+ }
+
+ onCapabilityChanged(selectedCapability: DropdownValue) {
+ this.requirementData.capability = selectedCapability && selectedCapability.value;
+ this.validityChanged();
+ }
+
+ onNodeChanged(selectedNode: DropdownValue) {
+ this.requirementData.node = selectedNode && selectedNode.value;
+ }
+
+ onRelationshipChanged(selectedRelationship: DropdownValue) {
+ this.requirementData.relationship = selectedRelationship && selectedRelationship.value;
+ }
+
+ checkFormValidForSubmit() {
+ return this.requirementData.name && this.requirementData.name.length &&
+ this.requirementData.capability && this.requirementData.capability.length && !_.isEqual(this.requirementData.minOccurrences, "") && this.requirementData.minOccurrences >= 0 &&
+ (
+ this.isUnboundedChecked ||
+ (this.requirementData.maxOccurrences && (this.requirementData.minOccurrences <= parseInt(this.requirementData.maxOccurrences)))
+ );
+ }
+
+ validityChanged = () => {
+ let validState = this.checkFormValidForSubmit();
+ this.onValidationChange.next(validState);
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.module.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.module.ts
new file mode 100644
index 0000000..b1d8db5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirementEditor/requirements-editor.module.ts
@@ -0,0 +1,28 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {RequirementsEditorComponent} from "./requirements-editor.component";
+import {FormsModule} from "@angular/forms";
+// import {FormElementsModule} from "../../../components/ui/form-components/form-elements.module";
+import {TranslateModule} from 'app/ng2/shared/translator/translate.module';
+import {SdcUiComponentsModule} from "onap-ui-angular/";
+import {FormElementsModule} from 'app/ng2/components/ui/form-components/form-elements.module';
+// import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index";
+
+@NgModule({
+ declarations: [
+ RequirementsEditorComponent
+ ],
+ imports: [CommonModule,
+ FormsModule,
+ FormElementsModule,
+ TranslateModule,
+ SdcUiComponentsModule
+ ],
+ exports: [],
+ entryComponents: [
+ RequirementsEditorComponent
+ ],
+ providers: []
+})
+export class RequirementsEditorModule {
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirements.component.less b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirements.component.less
new file mode 100644
index 0000000..19f1c9b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirements.component.less
@@ -0,0 +1,4 @@
+/deep/ .importedFromFile {
+ background-color: #f8f8f8;
+ color: #959595;
+ }
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.html b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.html
new file mode 100644
index 0000000..7606ed1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.html
@@ -0,0 +1,38 @@
+<div class="requirements-table">
+ <ngx-datatable #capabilitiesTable
+ columnMode="flex"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rowClass]="getRowClass"
+ [rows]="requirements">
+ <ngx-datatable-column name="Name" [flexGrow]="1" [resizeable]="false" >
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span [ngStyle]="{'cursor':row.isCreatedManually ? 'pointer' : 'null' }" data-tests-id="row.name" sdc-tooltip [tooltip-text]="row.name" [tooltip-placement]="3" (click)="editRequirement(row)">{{row.name}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Capability" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.capability" sdc-tooltip [tooltip-text]="row.capability" [tooltip-placement]="3">{{row.capability ? row.capability.substring("tosca.capabilities.".length) : ''}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Node" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.node" sdc-tooltip [tooltip-text]="row.node" [tooltip-placement]="3">{{row.node ? row.node.substring("tosca.nodes.".length) : ''}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Relationship" [flexGrow]="1" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.relationship" sdc-tooltip [tooltip-text]="row.relationship" [tooltip-placement]="3">{{row.relationship ? row.relationship.substring("tosca.relationships.".length): ''}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Connected To" [flexGrow]="1" [resizeable]="false">
+ </ngx-datatable-column>
+ <ngx-datatable-column name="Occurrences" [flexGrow]="1" [prop]="'minOccurrences'" [resizeable]="false">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <span data-tests-id="row.minOccurrences+','+row.maxOccurrences" sdc-tooltip
+ [tooltip-text]="row.minOccurrences+','+row.maxOccurrences" [tooltip-placement]="3">
+ {{row.minOccurrences}},{{row.maxOccurrences}}</span>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.ts b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.ts
new file mode 100644
index 0000000..b65489c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/req-and-capabilities/requirements/requirments.components.ts
@@ -0,0 +1,103 @@
+import {Input, Component, OnInit} from "@angular/core";
+import {Requirement, RequirementUI} from "../../../../../models/requirement";
+import {RequirementsEditorComponent} from "./requirementEditor/requirements-editor.component";
+import {WorkspaceService} from "../../workspace.service";
+import {TopologyTemplateService} from "../../../../services/component-services/topology-template.service";
+import {ReqAndCapabilitiesService} from "../req-and-capabilities.service";
+import {EventListenerService} from "../../../../../services/event-listener-service";
+import {ModalComponent} from "onap-ui-angular/dist/modals/modal.component";
+import {SdcUiServices} from "onap-ui-angular";
+import sortedIndexBy = require("lodash/sortedIndexBy");
+
+@Component({
+ selector: 'requirments',
+ templateUrl: './requirments.components.html',
+ styleUrls: ['../../../../../../assets/styles/table-style.less', './requirements.component.less']
+})
+
+
+
+export class RequirmentsComponent implements OnInit {
+ @Input() public requirements: Array<RequirementUI>;
+ private customModalInstance: ModalComponent;
+
+ constructor(
+ private workspaceService: WorkspaceService,
+ private loaderService: SdcUiServices.LoaderService,
+ private topologyTemplateService: TopologyTemplateService,
+ private reqAndCapabilitiesService : ReqAndCapabilitiesService,
+ private modalService: SdcUiServices.ModalService,
+ private eventListenerService: EventListenerService) {
+ }
+
+
+ ngOnInit(): void {
+ let isCreatedManually: RequirementUI[] = [];
+ let isImportedFromFile: RequirementUI[] = [];
+
+ isCreatedManually = this.requirements.filter((requirement) => requirement.isCreatedManually);
+ isImportedFromFile = this.requirements.filter((requirement) => !requirement.isCreatedManually);
+
+ this.requirements = [];
+
+ isCreatedManually.map((requirement) => this.requirements.push(requirement));
+ isImportedFromFile.map((requirement) => this.requirements.push(requirement));
+
+ }
+
+
+
+ editRequirement(req) {
+
+ let modalConfig = {
+ size: 'md',
+ title: 'Update Requirement',
+ type: 'custom',
+ buttons: [
+ {
+ id: 'saveButton',
+ text: ('Update'),
+ size: "'x-small'",
+ callback: () => this.updateRequirement(),
+ closeModal: true
+ },
+ {text: "Cancel", size: "'x-small'", closeModal: true}]
+ };
+ let modalInputs = {
+ requirement: req,
+ relationshipTypesList: this.reqAndCapabilitiesService.getRelationsShipeTypeList(),
+ nodeTypesList: this.reqAndCapabilitiesService.getNodeTypesList(),
+ capabilityTypesList: this.reqAndCapabilitiesService.getCapabilityTypesList(),
+ // isReadonly: this.$scope.isViewMode() || !this.$scope.isDesigner(),
+ };
+
+ this.customModalInstance = this.modalService.openCustomModal(modalConfig, RequirementsEditorComponent, {input: modalInputs});
+ this.customModalInstance.innerModalContent.instance.
+ onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('saveButton').disabled = !isValid);
+
+ }
+
+ private updateRequirement() {
+ const requirement = this.customModalInstance.innerModalContent.instance.requirementData;
+ this.loaderService.activate();
+ if (requirement.uniqueId) {
+ this.topologyTemplateService.updateRequirement(this.workspaceService.metadata.getTypeUrl(), this.workspaceService.metadata.uniqueId, requirement).subscribe(result => {
+ let index = this.requirements.findIndex(req => result[0].uniqueId === req.uniqueId);
+ this.requirements[index] = new RequirementUI(result[0], this.workspaceService.metadata.uniqueId);
+ this.eventListenerService.notifyObservers('REQUIREMENTS_UPDATED');
+ this.loaderService.deactivate();
+ }, () => {
+ this.loaderService.deactivate();
+ });
+ }
+ }
+
+ getRowClass(row) {
+ if (!row.isCreatedManually) {
+ return {
+ 'importedFromFile': true
+ };
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/__snapshots__/tosca-artifact-page.spec.ts.snap b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/__snapshots__/tosca-artifact-page.spec.ts.snap
new file mode 100644
index 0000000..14146d5
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/__snapshots__/tosca-artifact-page.spec.ts.snap
@@ -0,0 +1,35 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`tosca artifacts page should match current snapshot of tosca artifact pages component 1`] = `
+<tosca-artifact-page
+ serviceLoader={[Function Object]}
+ store={[Function Store]}
+ table={[Function DatatableComponent]}
+ workspaceService={[Function Object]}
+>
+ <div
+ class="tosca-artifact-page"
+ >
+ <ngx-datatable
+ class="ngx-datatable"
+ columnmode="flex"
+ >
+ <div
+ visibilityobserver=""
+ >
+
+ <datatable-body
+ class="datatable-body"
+ >
+ <datatable-selection>
+
+
+
+ </datatable-selection>
+ </datatable-body>
+
+ </div>
+ </ngx-datatable>
+ </div>
+</tosca-artifact-page>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.html b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.html
new file mode 100644
index 0000000..fece92e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.html
@@ -0,0 +1,50 @@
+<div class="tosca-artifact-page">
+ <ngx-datatable
+ columnMode="flex"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [reorderable]="false"
+ [swapColumns]="false"
+ [rows]="toscaArtifacts$ | async"
+ [sorts]="[{prop: 'artifactDisplayName', dir: 'desc'}]"
+ #toscaArtifactsTable
+ (activate)="onActivate($event)">
+ <ngx-datatable-row-detail [rowHeight]="80">
+ <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
+ <div>Label: {{row.artifactLabel}}</div>
+ <div>UUID: {{row.artifactUUID}}</div>
+ <div>Description: {{row.description}}</div>
+ </ng-template>
+ </ngx-datatable-row-detail>
+ <ngx-datatable-column [resizeable]="false" name="Name" [flexGrow]="3"
+ [prop]="'artifactDisplayName'">
+ <ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded">
+ <div class="expand-collapse-cell">
+ <svg-icon [clickable]="true" class="expand-collapse-icon"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [size]="'medium'"></svg-icon>
+ <span>{{row.artifactDisplayName }}</span>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false"name="Type" [flexGrow]="3">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{row.artifactType}}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false" name="Version" [flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ {{ row.artifactVersion }}
+ </ng-template>
+ </ngx-datatable-column>
+ <ngx-datatable-column [resizeable]="false"[flexGrow]="1">
+ <ng-template ngx-datatable-cell-template let-row="row">
+ <div class="download-artifact-button">
+ <download-artifact [artifact]="row" [componentId]="componentId"
+ [componentType]="componentType"
+ testId="download_{{row.artifactDisplayName}}"></download-artifact>
+ </div>
+ </ng-template>
+ </ngx-datatable-column>
+ </ngx-datatable>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.less b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.less
new file mode 100644
index 0000000..9c5dd47
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.less
@@ -0,0 +1,7 @@
+.tosca-artifact-page {
+ .download-artifact-button {
+ text-align: center;
+ padding-top: 4px;
+
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.ts b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.ts
new file mode 100644
index 0000000..e74e5db
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.component.ts
@@ -0,0 +1,46 @@
+import {Component, OnInit, ViewChild} from "@angular/core";
+import {WorkspaceService} from "../workspace.service";
+import {SdcUiServices} from "onap-ui-angular";
+import {ArtifactModel} from "../../../../models";
+import {Select, Store} from "@ngxs/store";
+import {WorkspaceState} from "../../../store/states/workspace.state";
+import * as _ from "lodash";
+import {ArtifactGroupType, COMPONENT_FIELDS} from "../../../../utils";
+import {GetArtifactsByTypeAction} from "../../../store/actions/artifacts.action";
+import {Observable} from "rxjs/index";
+import {ArtifactsState} from "../../../store/states/artifacts.state";
+import {ArtifactType} from "../../../../utils/constants";
+import {map} from "rxjs/operators";
+
+@Component({
+ selector: 'tosca-artifact-page',
+
+ templateUrl: './tosca-artifact-page.component.html',
+ styleUrls: ['./tosca-artifact-page.component.less', '../../../../../assets/styles/table-style.less']
+})
+export class ToscaArtifactPageComponent implements OnInit {
+
+ @Select(WorkspaceState.isViewOnly) isViewOnly$: boolean;
+ @ViewChild('toscaArtifactsTable') table: any;
+ public toscaArtifacts$: Observable<ArtifactModel[]>;
+ public componentId: string;
+ public componentType:string;
+
+ constructor(private serviceLoader: SdcUiServices.LoaderService, private workspaceService: WorkspaceService, private store: Store) {
+ }
+
+
+ ngOnInit(): void {
+ this.componentId = this.workspaceService.metadata.uniqueId;
+ this.componentType = this.workspaceService.metadata.componentType;
+
+ this.store.dispatch(new GetArtifactsByTypeAction({componentType:this.componentType, componentId:this.componentId, artifactType:ArtifactGroupType.TOSCA}));
+ this.toscaArtifacts$ = this.store.select(ArtifactsState.getArtifactsByType).pipe(map(filterFn => filterFn(ArtifactGroupType.TOSCA)));
+ }
+
+ onActivate(event) {
+ if(event.type === 'click'){
+ this.table.rowDetail.toggleExpandRow(event.row);
+ }
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.module.ts b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.module.ts
new file mode 100644
index 0000000..00c7b0b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.module.ts
@@ -0,0 +1,28 @@
+import {CommonModule} from "@angular/common";
+import {NgModule} from "@angular/core";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {GlobalPipesModule} from "../../../pipes/global-pipes.module";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {ToscaArtifactPageComponent} from "./tosca-artifact-page.component";
+import {UiElementsModule} from "../../../components/ui/ui-elements.module";
+
+@NgModule({
+ declarations: [
+ ToscaArtifactPageComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ NgxDatatableModule,
+ UiElementsModule
+ ],
+ exports: [
+ ToscaArtifactPageComponent
+ ],
+ entryComponents: [
+ ToscaArtifactPageComponent
+ ],
+
+})
+export class ToscaArtifactPageModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.spec.ts b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.spec.ts
new file mode 100644
index 0000000..af3558e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/tosca-artifacts/tosca-artifact-page.spec.ts
@@ -0,0 +1,71 @@
+import {async, ComponentFixture, TestBed} from "@angular/core/testing";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {ToscaArtifactPageComponent} from "./tosca-artifact-page.component";
+import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper";
+import {NgxDatatableModule} from "@swimlane/ngx-datatable";
+import {WorkspaceService} from "../workspace.service";
+import {SdcUiServices} from "onap-ui-angular";
+import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
+import {Observable} from "rxjs/Observable";
+import {ComponentMetadata} from "../../../../models/component-metadata";
+import 'rxjs/add/observable/of';
+import {NgxsModule, Store} from "@ngxs/store";
+import {ArtifactsState} from "../../../store/states/artifacts.state";
+import {toscaArtifactMock} from "../../../../../jest/mocks/artifacts-mock";
+
+describe('tosca artifacts page', () => {
+
+ let fixture: ComponentFixture<ToscaArtifactPageComponent>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let workspaceServiceMock: Partial<WorkspaceService>;
+ let loaderServiceMock: Partial<SdcUiServices.LoaderService>;
+ let store: Store;
+
+
+ beforeEach(
+ async(() => {
+
+ topologyTemplateServiceMock = {
+ getArtifactsByType: jest.fn().mockImplementation((componentType, id, artifactType) => Observable.of(toscaArtifactMock))
+ };
+ workspaceServiceMock = {metadata: <ComponentMetadata>{uniqueId: 'service_unique_id', componentType: 'SERVICE'}}
+
+ loaderServiceMock = {
+ activate : jest.fn(),
+ deactivate: jest.fn()
+ }
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [ToscaArtifactPageComponent],
+ imports: [NgxDatatableModule, NgxsModule.forRoot([ArtifactsState])],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: TopologyTemplateService, useValue: topologyTemplateServiceMock},
+ {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock }
+ ],
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(ToscaArtifactPageComponent);
+ store = testBed.get(Store);
+ });
+ })
+ );
+
+ it('should match current snapshot of tosca artifact pages component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should see exactly 2 tosca artifacts', () => {
+ fixture.componentInstance.ngOnInit();
+ fixture.componentInstance.toscaArtifacts$.subscribe((artifacts)=> {
+ expect(artifacts.length).toEqual(2);
+ })
+ store.selectOnce(state => state.artifacts.toscaArtifacts).subscribe(artifacts => {
+ expect(artifacts.length).toEqual(9);
+ });
+ })
+
+});
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts b/catalog-ui/src/app/ng2/pages/workspace/workspace-ng1-bridge-service.ts
similarity index 69%
copy from catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts
copy to catalog-ui/src/app/ng2/pages/workspace/workspace-ng1-bridge-service.ts
index 41f24dc..3d93b45 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.ts
+++ b/catalog-ui/src/app/ng2/pages/workspace/workspace-ng1-bridge-service.ts
@@ -1,3 +1,6 @@
+/**
+ * Created by ob0695 on 6/24/2018.
+ */
/*-
* ============LICENSE_START=======================================================
* SDC
@@ -7,9 +10,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.
@@ -17,18 +20,18 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
+import {Store} from "@ngxs/store";
+import {Injectable} from "@angular/core";
+import {UpdateIsViewOnly} from "../../store/actions/workspace.action";
-'use strict';
-import {ICompositionViewModelScope} from "../../composition-view-model";
+@Injectable()
+export class WorkspaceNg1BridgeService {
-interface IStructureViewModel extends ICompositionViewModelScope {
-}
+ constructor(private store: Store) {
+ };
-export class StructureViewModel {
- static '$inject' = [
- '$scope'
- ];
-
- constructor(private $scope:IStructureViewModel) {
+ public updateIsViewOnly = (isViewOnly: boolean):void => {
+ this.store.dispatch(new UpdateIsViewOnly(isViewOnly));
}
+
}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/workspace.component.ts b/catalog-ui/src/app/ng2/pages/workspace/workspace.component.ts
new file mode 100644
index 0000000..a209406
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/workspace.component.ts
@@ -0,0 +1,3 @@
+/**
+ * Created by ob0695 on 6/11/2018.
+ */
diff --git a/catalog-ui/src/app/ng2/pages/workspace/workspace.module.ts b/catalog-ui/src/app/ng2/pages/workspace/workspace.module.ts
new file mode 100644
index 0000000..cb64637
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/workspace.module.ts
@@ -0,0 +1,50 @@
+/**
+ * Created by ob0695 on 6/4/2018.
+ */
+/**
+ * Created by ob0695 on 6/4/2018.
+ */
+import {NgModule} from "@angular/core";
+import {CompositionPageModule} from "../composition/composition-page.module";
+
+import {NgxsModule} from "@ngxs/store";
+import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
+import {WorkspaceState} from "../../store/states/workspace.state";
+import {WorkspaceService} from "./workspace.service";
+import {DeploymentPageModule} from "./deployment/deployment-page.module";
+import {ToscaArtifactPageModule} from "./tosca-artifacts/tosca-artifact-page.module";
+import {InformationArtifactPageModule} from "./information-artifact/information-artifact-page.module";
+import { reqAndCapabilitiesModule } from "./req-and-capabilities/req-and-capabilities.module";
+import {AttributesModule} from "./attributes/attributes.module";
+import {ArtifactsState} from "../../store/states/artifacts.state";
+import {InstanceArtifactsState} from "../../store/states/instance-artifacts.state";
+import {DeploymentArtifactsPageModule} from "./deployment-artifacts/deployment-artifacts-page.module";
+import { DistributionModule } from './disribution/distribution.module';
+import { ActivityLogModule } from './activity-log/activity-log.module';
+
+@NgModule({
+ declarations: [],
+ imports: [
+ DeploymentPageModule,
+ CompositionPageModule,
+ AttributesModule,
+ reqAndCapabilitiesModule,
+ ToscaArtifactPageModule,
+ DeploymentArtifactsPageModule,
+ InformationArtifactPageModule,
+ DistributionModule,
+ ActivityLogModule,
+ NgxsModule.forFeature([WorkspaceState, ArtifactsState, InstanceArtifactsState])
+ ],
+
+ exports: [],
+ entryComponents: [],
+ providers: [TopologyTemplateService, WorkspaceService]
+})
+
+export class WorkspaceModule {
+
+ constructor() {
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/workspace/workspace.service.ts b/catalog-ui/src/app/ng2/pages/workspace/workspace.service.ts
new file mode 100644
index 0000000..9f98501
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/workspace/workspace.service.ts
@@ -0,0 +1,70 @@
+/**
+ * Created by ob0695 on 6/5/2018.
+ */
+/*-
+ * ============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 rc2122 on 5/23/2017.
+ */
+import { Injectable } from '@angular/core';
+import {WorkspaceMode, ComponentState, Role} from "../../../utils/constants";
+import {Component as TopologyTemplate, ComponentMetadata} from "app/models";
+import {CacheService} from "../../services/cache.service";
+import {IComponentMetadata} from "../../../models/component-metadata";
+import {ComponentType} from "../../../utils";
+
+@Injectable()
+export class WorkspaceService {
+
+ public metadata:ComponentMetadata;
+
+ constructor(private cacheService:CacheService) {
+
+ }
+
+ public setComponentMetadata = (metadata: ComponentMetadata) => {
+ this.metadata = metadata;
+ }
+
+ public getMetadataType(): string {
+ switch (this.metadata.componentType) {
+ case ComponentType.SERVICE:
+ return ComponentType.SERVICE;
+ default:
+ return this.metadata.resourceType;
+ }
+ }
+
+ public getComponentMode = (component:TopologyTemplate):WorkspaceMode => {//return if is edit or view for resource or service
+ let mode = WorkspaceMode.VIEW;
+
+ let user = this.cacheService.get("user");
+ if (component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
+ component.lastUpdaterUserId === user.userId) {
+ if ((component.isService() || component.isResource()) && user.role == Role.DESIGNER) {
+ mode = WorkspaceMode.EDIT;
+ }
+ }
+ return mode;
+ }
+}
+
+
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts b/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts
new file mode 100644
index 0000000..af107ed
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pipes/entity-filter.pipe.ts
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {Pipe, PipeTransform} from "@angular/core";
+import {Component, Resource} from "app/models";
+import {ComponentType} from "app/utils/constants";
+
+export interface ISearchFilter {
+ [key:string]: string;
+}
+
+export interface IEntityFilterObject {
+ // Types
+ selectedComponentTypes?:Array<string>;
+ selectedResourceSubTypes?:Array<string>;
+ // Categories
+ selectedCategoriesModel?:Array<string>;
+ // Statuses
+ selectedStatuses?:Array<string>;
+ // distributed
+ distributed?:Array<string>;
+ // search
+ search?:ISearchFilter;
+
+}
+
+@Pipe({name: 'entity-filter'})
+export class EntityFilterPipe implements PipeTransform{
+ constructor() {
+ }
+
+ public static transform(components:Array<Component>, filter:IEntityFilterObject) {
+ let filteredComponents:Array<Component> = components;
+
+ // filter by type
+ // --------------------------------------------------------------------------
+ if ((filter.selectedComponentTypes && filter.selectedComponentTypes.length > 0) || (filter.selectedResourceSubTypes && filter.selectedResourceSubTypes.length > 0)) {
+ let filteredTypes = [];
+ angular.forEach(components, (component:Component):void => {
+ // Filter by component type
+ let typeLower:string = component.componentType.toLowerCase();
+ let typeFirstCapital:string = typeLower.charAt(0).toUpperCase() + typeLower.slice(1);
+ if (filter.selectedComponentTypes.indexOf(typeFirstCapital) !== -1) {
+ filteredTypes.push(component);
+ }
+
+ // Filter by resource sub type, only in case the resource checkbox was not selected (because in this case we already added all the components in above section).
+ if (component.isResource() && filter.selectedComponentTypes.indexOf("Resource") === -1 && filter.selectedResourceSubTypes.length > 0) {
+ //filteredComponents.pop(); // Remove the last inserted component.
+ let resource:Resource = <Resource>component;
+ if (filter.selectedResourceSubTypes.indexOf(resource.getComponentSubType()) !== -1) {
+ filteredTypes.push(component);
+ }
+ }
+ });
+ filteredComponents = filteredTypes;
+ }
+
+ // filter by categories & subcategories & groupings
+ // --------------------------------------------------------------------------
+ if (filter.selectedCategoriesModel && filter.selectedCategoriesModel.length > 0) {
+ let filteredCategories = [];
+ angular.forEach(filteredComponents, (component:Component):void => {
+ let componentCategory = component.categoryNormalizedName +
+ ((component.subCategoryNormalizedName) ? '.' + component.subCategoryNormalizedName : '');
+ if (component.componentType === ComponentType.RESOURCE) {
+ componentCategory = 'resourceNewCategory.' + componentCategory;
+ } else if (component.componentType === ComponentType.SERVICE) {
+ componentCategory = 'serviceNewCategory.' + componentCategory;
+ }
+ if (filter.selectedCategoriesModel.indexOf(componentCategory) !== -1) {
+ filteredCategories.push(component);
+ }
+ });
+ filteredComponents = filteredCategories;
+ }
+
+ // filter by statuses
+ // --------------------------------------------------------------------------
+ if (filter.selectedStatuses && filter.selectedStatuses.length > 0) {
+
+ let filteredStatuses = [];
+ angular.forEach(filteredComponents, (component:Component):void => {
+ if (filter.selectedStatuses.indexOf(component.lifecycleState) > -1) {
+ filteredStatuses.push(component);
+ }
+ //if status DISTRIBUTED && CERTIFIED are selected the component will added in CERTIFIED status , not need to add twice
+ if (filter.selectedStatuses.indexOf('DISTRIBUTED') > -1 && !(filter.selectedStatuses.indexOf('CERTIFIED') > -1)) {
+ if (component.distributionStatus && component.distributionStatus.indexOf('DISTRIBUTED') > -1 && component.lifecycleState.indexOf('CERTIFIED') > -1) {
+ filteredStatuses.push(component);
+ }
+ }
+ });
+ filteredComponents = filteredStatuses;
+ }
+
+ // filter by statuses and distributed
+ // --------------------------------------------------------------------------
+ if (filter.distributed != undefined && filter.distributed.length > 0) {
+ let filterDistributed:Array<any> = filter.distributed;
+ let filteredDistributed = [];
+ angular.forEach(filteredComponents, (entity) => {
+ filterDistributed.forEach((distribute) => {
+ let distributeItem = distribute.split(',');
+ distributeItem.forEach((item) => {
+ if (item !== undefined && entity.distributionStatus === item) {
+ filteredDistributed.push(entity);
+ }
+ })
+ });
+ });
+ filteredComponents = filteredDistributed;
+ }
+
+ // filter by search
+ // --------------------------------------------------------------------------
+ if (filter.search != undefined) {
+ Object.keys(filter.search).forEach((searchKey) => {
+ let searchVal = filter.search[searchKey];
+ if (searchVal) {
+ searchVal = searchVal.toLowerCase();
+ filteredComponents = filteredComponents.filter((component:Component) =>
+ component[searchKey].toLowerCase().indexOf(searchVal) !== -1);
+ }
+ });
+ }
+
+ return filteredComponents;
+ }
+
+ public transform(components:Array<Component>, filter:IEntityFilterObject) {
+ return EntityFilterPipe.transform(components, filter);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts
index c44d71b..66f9518 100644
--- a/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts
+++ b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts
@@ -26,7 +26,10 @@
import {ResourceNamePipe} from "./resource-name.pipe";
import {NgModule} from "@angular/core";
import {SafeUrlSanitizerPipe} from "./safeUrlSanitizer.pipe";
-import {OrderByPipe} from "./orderBy.pipe";
+import {EntityFilterPipe} from "./entity-filter.pipe";
+import {KeyValuePipe} from "./key-value.pipe";
+import {PropertiesOrderByPipe} from "./properties-order-by.pipe";
+import {OrderByPipe} from "./order-by.pipe";
@NgModule({
declarations: [
@@ -36,6 +39,9 @@
SafeUrlSanitizerPipe,
SearchFilterPipe,
ResourceNamePipe,
+ EntityFilterPipe,
+ KeyValuePipe,
+ PropertiesOrderByPipe,
OrderByPipe
],
exports: [
@@ -45,7 +51,20 @@
SafeUrlSanitizerPipe,
SearchFilterPipe,
ResourceNamePipe,
- OrderByPipe
+ EntityFilterPipe,
+ PropertiesOrderByPipe,
+ OrderByPipe,
+ KeyValuePipe
+ ],
+ providers: [
+ ContentAfterLastDotPipe,
+ GroupByPipe,
+ KeysPipe,
+ SafeUrlSanitizerPipe,
+ SearchFilterPipe,
+ ResourceNamePipe,
+ EntityFilterPipe,
+ KeyValuePipe
]
})
diff --git a/catalog-ui/src/app/ng2/pipes/groupBy.pipe.ts b/catalog-ui/src/app/ng2/pipes/groupBy.pipe.ts
index 90dce23..19811f2 100644
--- a/catalog-ui/src/app/ng2/pipes/groupBy.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/groupBy.pipe.ts
@@ -26,6 +26,9 @@
@Pipe({name: 'groupBy'})
export class GroupByPipe implements PipeTransform {
transform(value: Array<any>, field: string): Array<any> {
+ if(!value) {
+ return null;
+ }
const groupedObj = value.reduce((prev, cur)=> {
if(!prev[cur[field]]) {
prev[cur[field]] = [cur];
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts b/catalog-ui/src/app/ng2/pipes/key-value.pipe.ts
similarity index 66%
rename from catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts
rename to catalog-ui/src/app/ng2/pipes/key-value.pipe.ts
index 2660222..4adb0b1 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/groups/group-information-tab.component.ts
+++ b/catalog-ui/src/app/ng2/pipes/key-value.pipe.ts
@@ -1,3 +1,6 @@
+/**
+ * Created by ob0695 on 7/3/2018.
+ */
/*-
* ============LICENSE_START=======================================================
* SDC
@@ -18,22 +21,21 @@
* ============LICENSE_END=========================================================
*/
-import * as _ from "lodash";
-import { Component, Inject, Input, Output, EventEmitter } from "@angular/core";
-import { GroupInstance } from 'app/models/graph/zones/group-instance';
+/**
+ * Created by rc2122 on 5/17/2017.
+ */
+import {Pipe, PipeTransform} from '@angular/core';
-@Component({
- selector: 'group-information-tab',
- templateUrl: './group-information-tab.component.html',
- styleUrls: ['./../base/base-tab.component.less']
-})
-export class GroupInformationTabComponent {
-
- @Input() group: GroupInstance;
- @Input() isViewOnly: boolean;
-
- constructor() {
-
+@Pipe({name: 'keyValue'})
+export class KeyValuePipe implements PipeTransform {
+ transform(value, field: string): Array<any> {
+ if(!value) {
+ return null;
+ }
+ let keyValueObject = [];
+ for (let key in value) {
+ keyValueObject.push({key:key, value: value[key]});
+ }
+ return keyValueObject;
}
-
}
diff --git a/catalog-ui/src/app/ng2/pipes/keys.pipe.ts b/catalog-ui/src/app/ng2/pipes/keys.pipe.ts
index 349e933..f8663ac 100644
--- a/catalog-ui/src/app/ng2/pipes/keys.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/keys.pipe.ts
@@ -23,6 +23,9 @@
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
+ if(!value) {
+ return null;
+ }
let keys = [];
for (let key in value) {
keys.push(key);
diff --git a/catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts b/catalog-ui/src/app/ng2/pipes/order-by.pipe.ts
similarity index 94%
rename from catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts
rename to catalog-ui/src/app/ng2/pipes/order-by.pipe.ts
index 4edbd60..6dc5d47 100644
--- a/catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/order-by.pipe.ts
@@ -20,10 +20,10 @@
import { Pipe, PipeTransform } from '@angular/core';
-@Pipe({ name: 'orderBy' })
+@Pipe({name: 'orderBy'})
export class OrderByPipe implements PipeTransform {
transform(records: Array<any>, args?: any): any {
- if (!records || !args.path) return records;
+ if (!records || !args.path) { return records; }
let len = args.path.length;
return records.sort((itemIdx1, itemIdx2) => {
var i = 0;
diff --git a/catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts b/catalog-ui/src/app/ng2/pipes/properties-order-by.pipe.ts
similarity index 93%
copy from catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts
copy to catalog-ui/src/app/ng2/pipes/properties-order-by.pipe.ts
index 4edbd60..98debd2 100644
--- a/catalog-ui/src/app/ng2/pipes/orderBy.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/properties-order-by.pipe.ts
@@ -20,8 +20,8 @@
import { Pipe, PipeTransform } from '@angular/core';
-@Pipe({ name: 'orderBy' })
-export class OrderByPipe implements PipeTransform {
+@Pipe({ name: 'propertiesOrderBy' })
+export class PropertiesOrderByPipe implements PipeTransform {
transform(records: Array<any>, args?: any): any {
if (!records || !args.path) return records;
let len = args.path.length;
diff --git a/catalog-ui/src/app/ng2/pipes/resource-name.pipe.ts b/catalog-ui/src/app/ng2/pipes/resource-name.pipe.ts
index fdf9526..0fdbbca 100644
--- a/catalog-ui/src/app/ng2/pipes/resource-name.pipe.ts
+++ b/catalog-ui/src/app/ng2/pipes/resource-name.pipe.ts
@@ -20,15 +20,20 @@
import { Pipe, PipeTransform } from '@angular/core';
+import * as _ from 'lodash';
@Pipe({name: 'resourceName'})
export class ResourceNamePipe implements PipeTransform {
+
+ public static getDisplayName (value:string): string {
+ const newName:string =
+ _.last(value.split(/tosca\.nodes\..*network\..*relationships\..*org\.openecomp\..*resource\.nfv\..*nodes\.module\..*cp\..*vl\./));
+ return (newName) ? newName : value;
+ }
+
transform(value) : any {
if (value) {
- //newName = _.last(newName.split('.'));
- const newName:string =
- _.last(value.split(/tosca\.nodes\..*network\..*relationships\..*org\.openecomp\..*resource\.nfv\..*nodes\.module\..*cp\..*vl\./));
- return (newName) ? newName : value;
+ return ResourceNamePipe.getDisplayName(value);
}
}
}
diff --git a/catalog-ui/src/app/ng2/services/activity-log.service.ts b/catalog-ui/src/app/ng2/services/activity-log.service.ts
new file mode 100644
index 0000000..deabbee
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/activity-log.service.ts
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable} from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import { Activity } from '../../models/activity';
+import { ServerTypeUrl } from '../../utils/constants';
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+import { HttpHelperService } from './http-hepler.service';
+
+@Injectable()
+export class ActivityLogService {
+ url: string;
+
+ constructor(private httpClient: HttpClient, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
+ this.url = this.sdcConfig.api.root + this.sdcConfig.api.GET_activity_log;
+ }
+
+ public getActivityLog(componentType: string, uid: string): Observable<Activity[]> {
+
+ // Compose URL: audit-records/services_or_resources/uid
+ const url = HttpHelperService.replaceUrlParams(this.url, {
+ type: ServerTypeUrl.toServerTypeUrl(componentType),
+ id: uid
+ });
+
+ return this.httpClient.get<Activity[]>(url);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/services/archive.service.ts b/catalog-ui/src/app/ng2/services/archive.service.ts
deleted file mode 100644
index 83f1c50..0000000
--- a/catalog-ui/src/app/ng2/services/archive.service.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import { Injectable, Inject } from "@angular/core";
-import { Observable } from "rxjs/Observable";
-import { HttpService } from "./http.service";
-import { SdcConfigToken, ISdcConfig } from "../config/sdc-config.config";
-import { Component } from "../../models";
-import { ComponentFactory } from 'app/utils/component-factory';
-
-
-@Injectable()
-export class ArchiveService {
- protected baseUrl;
-
- constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig, private componentFactory:ComponentFactory/*, @Inject(ComponentFactory) componentFactory */) {
- this.baseUrl = sdcConfig.api.root ;
- }
-
- public getArchiveCatalog() {
- let archiveCatalogItems:Component[] = [];
- let archiveCatalogResourceItems:Component[] = [];
- let archiveCatalogServiceItems:Component[] = [];
-
- return this.http.get(this.baseUrl + '/v1/catalog/archive/', {}).map(res => {
- let archiveCatalogObject = res.json();
- if (archiveCatalogObject.resources) archiveCatalogResourceItems = this.getResourceItems(archiveCatalogObject.resources);
- if (archiveCatalogObject.services) archiveCatalogServiceItems = this.getServiceItems(archiveCatalogObject.services);
- archiveCatalogItems = [].concat(archiveCatalogResourceItems, archiveCatalogServiceItems);
-
- return archiveCatalogItems;
- });
- }
-
-
- private getResourceItems(resources){
- let resourceItems = resources.map((resource)=>{
- return this.componentFactory.createResource(resource)
- })
- return resourceItems;
- }
-
- private getServiceItems(services){
- let serviceItems = services.map((service)=>{
- return this.componentFactory.createService(service)
- })
- return serviceItems;
- }
-
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/authentication.service.ts b/catalog-ui/src/app/ng2/services/authentication.service.ts
index 1c6502d..52ca643 100644
--- a/catalog-ui/src/app/ng2/services/authentication.service.ts
+++ b/catalog-ui/src/app/ng2/services/authentication.service.ts
@@ -20,38 +20,44 @@
import {Injectable, Inject} from '@angular/core';
import {IAppConfigurtaion, ICookie} from "../../models/app-config";
-import {Response, Headers, RequestOptions, Http} from '@angular/http';
import {Cookie2Service} from "./cookie.service";
import { Observable } from 'rxjs/Observable';
import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
+import { IUserProperties } from "app/models";
+import { CacheService } from "app/ng2/services/cache.service";
+import { HttpClient, HttpHeaders } from '@angular/common/http';
@Injectable()
export class AuthenticationService {
- constructor(private cookieService:Cookie2Service, private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
+ private _loggedinUser:IUserProperties;
+
+ constructor(private cookieService:Cookie2Service, private http: HttpClient, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig, private cacheService: CacheService) {
this.cookieService = cookieService;
- this.http = http;
}
- private getAuthHeaders():any {
+ private getAuthHeaders():HttpHeaders {
let cookie:ICookie = this.sdcConfig.cookie;
- let authHeaders:any = {};
- authHeaders[cookie.userFirstName] = this.cookieService.getFirstName();
- authHeaders[cookie.userLastName] = this.cookieService.getLastName();
- authHeaders[cookie.userEmail] = this.cookieService.getEmail();
- authHeaders[cookie.userIdSuffix] = this.cookieService.getUserId();
+ let authHeaders: HttpHeaders = new HttpHeaders();
+ authHeaders = authHeaders.set(cookie.userFirstName, this.cookieService.getFirstName())
+ .set(cookie.userLastName, this.cookieService.getLastName())
+ .set(cookie.userEmail, this.cookieService.getEmail())
+ .set(cookie.userIdSuffix, this.cookieService.getUserId())
return authHeaders;
}
- public authenticate(): Observable<JSON> {
- let options = new RequestOptions({
- headers: new Headers(this.getAuthHeaders())
- });
-
+ public authenticate(): Observable<IUserProperties> {
let authUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize;
- return this.http
- .get(authUrl, options)
- .map((res: Response) => res.json());
+ return this.http.get<IUserProperties>(authUrl, {headers: this.getAuthHeaders()});
}
+ public getLoggedinUser():IUserProperties {
+ return this._loggedinUser;
+ }
+
+ public setLoggedinUser(loggedinUser:IUserProperties) {
+ this._loggedinUser = loggedinUser;
+ this.cacheService.set('user', loggedinUser);
+ };
+
}
diff --git a/catalog-ui/src/app/services/cache-service.ts b/catalog-ui/src/app/ng2/services/cache.service.ts
similarity index 78%
rename from catalog-ui/src/app/services/cache-service.ts
rename to catalog-ui/src/app/ng2/services/cache.service.ts
index 4d10db0..e876ec1 100644
--- a/catalog-ui/src/app/services/cache-service.ts
+++ b/catalog-ui/src/app/ng2/services/cache.service.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.
@@ -18,37 +18,32 @@
* ============LICENSE_END=========================================================
*/
-'use strict';
+import {Injectable} from "@angular/core";
import {Dictionary} from "app/utils";
-interface ICacheService {
- get(key:string):any;
- set(key:string, value:any):void;
-}
-
-export class CacheService implements ICacheService {
-
+@Injectable()
+export class CacheService {
private storage:Dictionary<string, any>;
constructor() {
this.storage = new Dictionary<string, any>();
};
- public get = (key:string):any => {
+ public get(key:string): any {
return this.storage.getValue(key);
- };
+ }
- public set = (key:string, value:any):void => {
+ public set(key:string, value:any): void {
this.storage.setValue(key, value);
- };
+ }
- public remove = (key:string):void => {
+ public remove(key:string): void {
if (this.storage.containsKey(key)) {
this.storage.remove(key);
}
- };
+ }
- public contains = (key:string):boolean => {
+ public contains(key:string): boolean {
return this.storage.containsKey(key);
- };
+ }
}
diff --git a/catalog-ui/src/app/ng2/services/catalog.service.ts b/catalog-ui/src/app/ng2/services/catalog.service.ts
new file mode 100644
index 0000000..bbdfa1b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/catalog.service.ts
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import { Injectable, Inject } from "@angular/core";
+import { Observable } from "rxjs/Observable";
+import { SdcConfigToken, ISdcConfig } from "../config/sdc-config.config";
+import { Component, IApi, IComponentsArray } from "app/models";
+import { ComponentFactory } from 'app/utils/component-factory';
+import {ResourceType} from "../../utils/constants";
+import {SharingService} from "./sharing.service";
+import { HttpClient, HttpParams } from "@angular/common/http";
+
+@Injectable()
+export class CatalogService {
+ protected api:IApi;
+ protected baseUrl:string;
+ protected baseMicroServiceUrl:string;
+
+ constructor(private http: HttpClient,
+ @Inject(SdcConfigToken) sdcConfig:ISdcConfig,
+ private componentFactory:ComponentFactory,
+ private sharingService:SharingService) {
+ this.api = sdcConfig.api;
+ this.baseUrl = sdcConfig.api.root ;
+ this.baseMicroServiceUrl = sdcConfig.api.uicache_root;
+ }
+
+ public getCatalog(): Observable<Array<Component>> {
+ let searchParams = new HttpParams();
+ searchParams = searchParams.append('excludeTypes', ResourceType.VFCMT).append('excludeTypes', ResourceType.CONFIGURATION);
+ return this.http.get<IComponentsArray>(this.baseMicroServiceUrl + this.api.GET_uicache_catalog, {params: searchParams})
+ .map(res => this.processComponentsResponse(res, true));
+ }
+
+ public getArchiveCatalog() {
+ return this.http.get<IComponentsArray>(this.baseUrl + '/v1/catalog/archive/', {})
+ .map(res => this.processComponentsResponse(res));
+ }
+
+ private processComponentsResponse(componentsArr: IComponentsArray, addSharing:boolean = false) {
+ const componentsList: Component[] = [];
+ if (componentsArr.resources) {
+ componentsList.push(...this.getResourceItems(componentsArr.resources));
+ }
+ if (componentsArr.services) {
+ componentsList.push(...this.getServiceItems(componentsArr.services));
+ }
+ if (addSharing) {
+ componentsList.forEach((item) => this.sharingService.addUuidValue(item.uniqueId, item.uuid));
+ }
+ return componentsList;
+ }
+
+ private getResourceItems(resources){
+ let resourceItems = resources.map((resource)=>{
+ return this.componentFactory.createResource(resource)
+ })
+ return resourceItems;
+ }
+
+ private getServiceItems(services){
+ let serviceItems = services.map((service)=>{
+ return this.componentFactory.createService(service)
+ })
+ return serviceItems;
+ }
+
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts
index 1575002..cc382a3 100644
--- a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts
@@ -19,62 +19,102 @@
*/
import {Injectable, Inject} from '@angular/core';
-import {Response, RequestOptions, Headers} from '@angular/http';
import { Observable } from 'rxjs/Observable';
import {PropertyFEModel, PropertyBEModel} from "app/models";
-import {CommonUtils} from "app/utils";
-import {Component, ComponentInstance, Capability, PropertyModel} from "app/models";
-import { HttpService } from '../http.service';
+import {CommonUtils, ComponentType, ServerTypeUrl, ComponentInstanceFactory} from "app/utils";
+import {Component, ComponentInstance, Capability, PropertyModel, ArtifactGroupModel, ArtifactModel, AttributeModel, IFileDownload} from "app/models";
import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config";
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { InputBEModel } from '../../../models/properties-inputs/input-be-model';
+import { HttpHelperService } from '../http-hepler.service';
@Injectable()
export class ComponentInstanceServiceNg2 {
protected baseUrl;
- constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
+ constructor(private http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
}
+ private getServerTypeUrl = (componentType:string):string => {
+ switch (componentType) {
+ case ComponentType.SERVICE:
+ return ServerTypeUrl.SERVICES;
+ default:
+ return ServerTypeUrl.RESOURCES;
+ }
+ }
getComponentInstanceProperties(component: Component, componentInstanceId: string): Observable<Array<PropertyBEModel>> {
-
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/properties')
- .map((res: Response) => {
- return CommonUtils.initBeProperties(res.json());
+ return this.http.get<Array<PropertyBEModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/properties')
+ .map(res => {
+ return CommonUtils.initBeProperties(res);
})
}
getComponentInstanceInputs(component: Component, componentInstance: ComponentInstance): Observable<Array<PropertyBEModel>> {
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstance.uniqueId + '/' + componentInstance.componentUid + '/inputs')
- .map((res: Response) => {
- return CommonUtils.initInputs(res.json());
+ return this.http.get<Array<InputBEModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstance.uniqueId + '/' + componentInstance.componentUid + '/inputs')
+ .map(res => {
+ return CommonUtils.initInputs(res);
})
}
- updateInstanceProperties(component: Component, componentInstanceId: string, properties: PropertyBEModel[]) {
+ getComponentInstanceArtifactsByGroupType = (componentType:string, componentId:string, componentInstanceId:string, artifactGroupType:string):Observable<ArtifactGroupModel> => {
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/properties', properties)
- .map((res: Response) => {
- return res.json().map((resProperty) => new PropertyBEModel(resProperty));
+ return this.http.get<ArtifactGroupModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + "/resourceInstances/" + componentInstanceId + "/artifactsByType/" + artifactGroupType)
+ .map(res => {
+ return new ArtifactGroupModel(res);
+ });
+ };
+
+ getArtifactByGroupType = (componentType:string, componentId:string, artifactGroupType:string):Observable<ArtifactGroupModel> => {
+
+ return this.http.get<ArtifactGroupModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + "/artifactsByType/" + artifactGroupType)
+ .map(response => new ArtifactGroupModel(response));
+ };
+
+ changeResourceInstanceVersion = (componentType:string, componentId:string, componentInstanceId:string, componentUid:string):Observable<ComponentInstance> => {
+ return this.http.post<ComponentInstance>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + componentInstanceId + '/changeVersion', {'componentUid': componentUid})
+ .map((res) => {
+ return ComponentInstanceFactory.createComponentInstance(res);
+ })
+ };
+
+ updateComponentInstance = (componentType:string, componentId:string, componentInstance:ComponentInstance):Observable<ComponentInstance> => {
+ return this.http.post<ComponentInstance>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + componentInstance.uniqueId, componentInstance.toJSON())
+ .map((response) => {
+ return ComponentInstanceFactory.createComponentInstance(response);
+ });
+ };
+
+ updateInstanceProperties(componentType:string, componentId:string, componentInstanceId: string, properties: PropertyBEModel[]) {
+
+ return this.http.post<Array<PropertyModel>>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + componentInstanceId + '/properties', properties)
+ .map((res) => {
+ return res.map((resProperty) => {
+ let newProp = new PropertyModel(resProperty);
+ newProp.resourceInstanceUniqueId = componentInstanceId
+ return newProp;
+ });
});
}
- getInstanceCapabilityProperties(component: Component, componentInstanceId: string, capability: Capability): Observable<Array<PropertyModel>> {
+ getInstanceCapabilityProperties(componentType: string, componentId: string, componentInstanceId: string, capability: Capability): Observable<Array<PropertyModel>> {
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capability.type +
+ return this.http.get<Array<PropertyModel>>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/componentInstances/' + componentInstanceId + '/capability/' + capability.type +
'/capabilityName/' + capability.name + '/ownerId/' + capability.ownerId + '/properties')
- .map((res: Response) => {
- capability.properties = res.json().map((capProp) => new PropertyModel(capProp)); // update capability properties
+ .map((res) => {
+ capability.properties = res.map((capProp) => new PropertyModel(capProp)); // update capability properties
return capability.properties;
})
}
updateInstanceCapabilityProperties(component: Component, componentInstanceId: string, capability: Capability, properties: PropertyBEModel[]): Observable<Array<PropertyModel>> {
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capability.type +
+ return this.http.put<Array<PropertyModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capability.type +
'/capabilityName/' + capability.name + '/ownerId/' + capability.ownerId + '/properties', properties)
- .map((res: Response) => {
- const savedProperties: PropertyModel[] = res.json().map((resProperty) => new PropertyModel(resProperty));
+ .map((res) => {
+ const savedProperties: PropertyModel[] = res.map((resProperty) => new PropertyModel(resProperty));
savedProperties.forEach((savedProperty) => {
const propIdx = capability.properties.findIndex((p) => p.uniqueId === savedProperty.uniqueId);
if (propIdx !== -1) {
@@ -87,37 +127,87 @@
updateInstanceInputs(component: Component, componentInstanceId: string, inputs: PropertyBEModel[]): Observable<PropertyBEModel[]> {
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/inputs', inputs)
- .map((res: Response) => {
- return res.json().map((resInput) => new PropertyBEModel(resInput));
+ return this.http.post<Array<PropertyModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/inputs', inputs)
+ .map((res) => {
+ return res.map((resInput) => new PropertyBEModel(resInput));
});
}
getComponentGroupInstanceProperties(component: Component, groupInstanceId: string): Observable<Array<PropertyBEModel>> {
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/groups/' + groupInstanceId + '/properties')
- .map((res: Response) => {
- return CommonUtils.initBeProperties(res.json());
+ return this.http.get<Array<PropertyBEModel>>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/groups/' + groupInstanceId + '/properties')
+ .map((res) => {
+ return CommonUtils.initBeProperties(res);
});
}
- updateComponentGroupInstanceProperties(component: Component, groupInstanceId: string, properties: PropertyBEModel[]): Observable<Array<PropertyBEModel>> {
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/groups/' + groupInstanceId + '/properties', properties)
- .map((res: Response) => {
- return res.json().map((resProperty) => new PropertyBEModel(resProperty));
+ updateComponentGroupInstanceProperties(componentType:string, componentId:string, groupInstanceId: string, properties: PropertyBEModel[]): Observable<Array<PropertyBEModel>> {
+ return this.http.put<Array<PropertyBEModel>>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/groups/' + groupInstanceId + '/properties', properties)
+ .map((res) => {
+ return res.map((resProperty) => new PropertyBEModel(resProperty));
});
}
- getComponentPolicyInstanceProperties(component: Component, policyInstanceId: string): Observable<Array<PropertyBEModel>> {
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policyInstanceId + '/properties')
- .map((res: Response) => {
- return CommonUtils.initBeProperties(res.json());
+ getComponentPolicyInstanceProperties(componentType:string, componentId:string, policyInstanceId: string): Observable<Array<PropertyBEModel>> {
+ return this.http.get<Array<PropertyBEModel>>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/policies/' + policyInstanceId + '/properties')
+ .map((res) => {
+ return CommonUtils.initBeProperties(res);
});
}
- updateComponentPolicyInstanceProperties(component: Component, policyInstanceId: string, properties: PropertyBEModel[]): Observable<Array<PropertyBEModel>> {
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policyInstanceId + '/properties', properties)
- .map((res: Response) => {
- return res.json().map((resProperty) => new PropertyBEModel(resProperty));
+ updateComponentPolicyInstanceProperties(componentType:string, componentId:string, policyInstanceId: string, properties: PropertyBEModel[]): Observable<Array<PropertyBEModel>> {
+ return this.http.put<Array<PropertyBEModel>>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/policies/' + policyInstanceId + '/properties', properties)
+ .map((res) => {
+ return res.map((resProperty) => new PropertyBEModel(resProperty));
});
}
+
+ addInstanceArtifact = (componentType:string, componentId:string, instanceId:string, artifact:ArtifactModel):Observable<ArtifactModel> => {
+ // let deferred = this.$q.defer<ArtifactModel>();
+ let headerObj = new HttpHeaders();
+ if (artifact.payloadData) {
+ headerObj = headerObj.set('Content-MD5', HttpHelperService.getHeaderMd5(artifact));
+ }
+ return this.http.post<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + instanceId + '/artifacts', JSON.stringify(artifact), {headers: headerObj})
+ .map((res) => {
+ return new ArtifactModel(res);
+ });
+ };
+
+ updateInstanceArtifact = (componentType:string, componentId:string, instanceId:string, artifact:ArtifactModel):Observable<ArtifactModel> => {
+ return this.http.post<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + instanceId + '/artifacts/' + artifact.uniqueId, artifact).map((res) => {
+ return new ArtifactModel(res);
+ });;
+ };
+
+ deleteInstanceArtifact = (componentId:string, componentType:string, instanceId:string, artifactId:string, artifactLabel:string):Observable<ArtifactModel> => {
+ return this.http.delete<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + "/resourceInstance/" + instanceId + '/artifacts/' + artifactId + '?operation=' + artifactLabel)
+ .map((res) => {
+ return new ArtifactModel(res);
+ });
+ }
+
+ downloadInstanceArtifact = (componentType:string, componentId:string, instanceId:string, artifactId:string):Observable<IFileDownload> => {
+ return this.http.get<IFileDownload>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + "/resourceInstances/" + instanceId + "/artifacts/" + artifactId);
+ };
+
+ uploadInstanceEnvFile = (componentType:string, componentId:string, instanceId:string, artifact:ArtifactModel):Observable<ArtifactModel> => {
+ let headerObj = new HttpHeaders();
+ if (artifact.payloadData) {
+ headerObj = headerObj.set('Content-MD5', HttpHelperService.getHeaderMd5(artifact));
+ }
+ return this.http.post<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + instanceId + '/artifacts/' + artifact.uniqueId, JSON.stringify(artifact), {headers: headerObj});
+ };
+
+
+ updateInstanceAttribute = (componentType:string, componentId:string, attribute:AttributeModel):Observable<AttributeModel> => {
+ let instanceId = attribute.resourceInstanceUniqueId;
+ return this.http.post<AttributeModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + "/resourceInstance/" + instanceId + "/attribute", attribute)
+ .map((response) => {
+ let newAttribute = new AttributeModel(response);
+ newAttribute.readonly = true;
+ newAttribute.resourceInstanceUniqueId = instanceId;
+ return newAttribute;
+ });
+ };
+
}
diff --git a/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts
index b0cc1b8..9952b03 100644
--- a/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts
@@ -24,7 +24,7 @@
import { Injectable } from '@angular/core';
import {WorkspaceMode, ComponentState, Role} from "../../../utils/constants";
import { Component as ComponentData } from "app/models";
-import { CacheService } from "app/services/cache-service"
+import { CacheService } from "app/services-ng2";
@Injectable()
diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.factory.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.factory.ts
index 6e9d0e8..15e5a79 100644
--- a/catalog-ui/src/app/ng2/services/component-services/component.service.factory.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/component.service.factory.ts
@@ -20,15 +20,18 @@
import {Injectable} from "@angular/core";
-import {Component} from "../../../models/components/component";
+import {Component} from "app/models";
import {ComponentServiceNg2} from "./component.service";
import {ServiceServiceNg2} from "./service.service";
+import {CacheService} from "app/services-ng2";
@Injectable()
export class ComponentServiceFactoryNg2 {
+
componentService: ComponentServiceNg2;
serviceService: ServiceServiceNg2;
- constructor(componentService: ComponentServiceNg2, serviceService: ServiceServiceNg2) {
+
+ constructor(componentService: ComponentServiceNg2, serviceService: ServiceServiceNg2, private cacheService:CacheService) {
this.serviceService = serviceService;
this.componentService = componentService;
}
diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts
index 445e123..760bfc5 100644
--- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts
@@ -23,51 +23,52 @@
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
-import {Response, URLSearchParams, Headers} from '@angular/http';
-import { Component, ComponentInstance, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData,
- PropertyBEModel, InterfaceModel, OperationModel, BEOperationModel, Capability, Requirement, PolicyInstance} from "app/models";
-import {COMPONENT_FIELDS, CommonUtils, SERVICE_FIELDS} from "app/utils";
-import {downgradeInjectable} from '@angular/upgrade/static';
+import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, OperationModel, CreateOperationResponse, ArtifactModel} from "app/models";
+import {COMPONENT_FIELDS} from "app/utils";
import {ComponentGenericResponse} from "../responses/component-generic-response";
import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map";
import {API_QUERY_PARAMS} from "app/utils";
-import { ComponentType, ServerTypeUrl } from "../../../utils/constants";
-import { HttpService } from '../http.service';
+import {ComponentType, ServerTypeUrl, SERVICE_FIELDS} from "../../../utils/constants";
import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config";
-import {ConstraintObject} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component';
import {IDependenciesServerResponse} from "../responses/dependencies-server-response";
import {AutomatedUpgradeGenericResponse} from "../responses/automated-upgrade-response";
import {IAutomatedUpgradeRequestObj} from "../../pages/automated-upgrade/automated-upgrade.service";
+import {ComponentInstance} from "../../../models/componentsInstances/componentInstance";
+import {CommonUtils} from "../../../utils/common-utils";
+import {RelationshipModel} from "../../../models/graph/relationship";
+import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
+import { BEOperationModel, InterfaceModel } from "../../../models/operation";
+import { PropertyBEModel } from "../../../models/properties-inputs/property-be-model";
+import { PolicyInstance } from "../../../models/graph/zones/policy-instance";
+import { ConstraintObject } from "../../components/logic/service-dependencies/service-dependencies.component";
+import { Requirement } from "../../../models/requirement";
+import { Capability } from "../../../models/capability";
-declare var angular:angular.IAngularStatic;
-
+/*
+PLEASE DO NOT USE THIS SERVICE IN ANGULAR2! Use the topology-template.service instead
+ */
@Injectable()
export class ComponentServiceNg2 {
protected baseUrl;
- constructor(protected http:HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
}
- protected getComponentDataByFieldsName(componentType:string, componentId: string, fields:Array<string>):Observable<ComponentGenericResponse> {
+ protected getComponentDataByFieldsName(componentType:string, componentId:string, fields:Array<string>):Observable<ComponentGenericResponse> {
- let params:URLSearchParams = new URLSearchParams();
+ let params: HttpParams = new HttpParams();
_.forEach(fields, (field:string):void => {
- params.append(API_QUERY_PARAMS.INCLUDE, field);
+ params = params.append(API_QUERY_PARAMS.INCLUDE, field);
});
- return this.http.get(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/filteredDataByParams', {search: params})
- .map((res:Response) => {
- return this.analyzeComponentDataResponse(res);
+ return this.http.get<ComponentGenericResponse>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/filteredDataByParams', {params: params})
+ .map((res) => {
+ return new ComponentGenericResponse().deserialize(res);
});
}
-
- protected analyzeComponentDataResponse(res: Response):ComponentGenericResponse {
- return new ComponentGenericResponse().deserialize(res.json());
- }
-
- private getServerTypeUrl = (componentType:string):string => {
+ protected getServerTypeUrl = (componentType:string):string => {
switch (componentType) {
case ComponentType.SERVICE:
return ServerTypeUrl.SERVICES;
@@ -76,15 +77,23 @@
}
}
- getComponentMetadata(component:Component):Observable<ComponentGenericResponse> {
- return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_METADATA]);
+ getFullComponent(uniqueId:string):Observable<ComponentGenericResponse> {
+ return this.http.get<ComponentGenericResponse>(this.baseUrl + uniqueId)
+ .map((res) => {
+ return new ComponentGenericResponse().deserialize(res);
+ });
}
+ getComponentMetadata(uniqueId:string, type:string):Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(type, uniqueId, [COMPONENT_FIELDS.COMPONENT_METADATA]);
+ }
+
+
getComponentInstanceAttributesAndProperties(component:Component):Observable<ComponentGenericResponse> {
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_ATTRIBUTES]);
}
- getComponentInstanceProperties(component:Component):Observable<ComponentGenericResponse> {
+ getComponentInstanceProperties(component:Component): Observable<ComponentGenericResponse> {
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES]);
}
@@ -132,17 +141,15 @@
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_PROPERTIES]);
}
- getInterfaces(component:Component):Observable<ComponentGenericResponse> {
+ getInterfaceOperations(component:Component):Observable<ComponentGenericResponse> {
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INTERFACE_OPERATIONS]);
}
getInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaces/' + operation.interfaceId + '/operations/' + operation.uniqueId)
- .map((res:Response) => {
- return res.json();
- });
+ return this.http.get<OperationModel>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations/' + operation.uniqueId);
}
+ // tslint:disable-next-line:member-ordering
createInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
const operationList = {
'interfaces': {
@@ -154,9 +161,9 @@
}
}
};
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
- .map((res:Response) => {
- const interf:InterfaceModel = _.find(res.json().interfaces, interf => interf.type === operation.interfaceType);
+ return this.http.post<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
+ .map((res:any) => {
+ const interf:InterfaceModel = _.find(res.interfaces, interf => interf.type === operation.interfaceType);
const newOperation:OperationModel = _.find(interf.operations, op => op.name === operation.name);
return new OperationModel({
...newOperation,
@@ -167,21 +174,22 @@
});
}
+ // tslint:disable-next-line:member-ordering
updateInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
const operationList = {
- 'interfaces': {
+ interfaces: {
[operation.interfaceType]: {
- 'type': operation.interfaceType,
- 'operations': {
+ type: operation.interfaceType,
+ operations: {
[operation.name]: new BEOperationModel(operation)
}
}
}
};
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
- .map((res:Response) => {
- const interf:InterfaceModel = _.find(res.json().interfaces, interf => interf.type === operation.interfaceType);
- const newOperation:OperationModel = _.find(interf.operations, op => op.name === operation.name);
+ return this.http.put<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
+ .map((res: any) => {
+ const interf: InterfaceModel = _.find(res.interfaces, interf => interf.type === operation.interfaceType);
+ const newOperation: OperationModel = _.find(interf.operations, op => op.name === operation.name);
return new OperationModel({
...newOperation,
interfaceType: interf.type,
@@ -191,18 +199,16 @@
});
}
- deleteInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
- return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaces/' + operation.interfaceId + '/operations/' + operation.uniqueId)
- .map((res:Response) => {
- return res.json();
- });
+
+ deleteInterfaceOperation(component: Component, operation:OperationModel):Observable<OperationModel> {
+ return this.http.delete<OperationModel>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaces/' + operation.interfaceId + '/operations/' + operation.uniqueId);
}
getInterfaceTypes(component:Component):Observable<{[id:string]: Array<string>}> {
- return this.http.get(this.baseUrl + 'interfaceLifecycleTypes')
- .map((res:Response) => {
+ return this.http.get<any>(this.baseUrl + 'interfaceLifecycleTypes')
+ .map((res: any) => {
const interfaceMap = {};
- _.forEach(res.json(), (interf:any) => {
+ _.forEach(res, (interf: any) => {
interfaceMap[interf.toscaPresentation.type] = _.keys(interf.toscaPresentation.operations);
});
return interfaceMap;
@@ -217,19 +223,18 @@
payloadData: oldOperation.artifactData
};
- const headers = new Headers();
+ const headers = new HttpHeaders();
JSON.stringify(payload);
const payloadString = JSON.stringify(payload, null, ' ');
const md5Result = md5(payloadString).toLowerCase();
headers.append('Content-MD5', btoa(md5Result));
return this.http.post(this.baseUrl + component.getTypeUrl() + component.uuid + '/interfaces/' + newOperation.interfaceId + '/operations/' + newOperation.uniqueId + '/artifacts/' + newOperation.implementation.artifactUUID,
- payload,
- {headers}
- ).map((res: Response) => {
- const fileName = res.json().artifactDisplayName || res.json().artifactName;
+ payload, {headers}
+ ).map((res: any) => {
+ const fileName = res.artifactDisplayName || res.artifactName;
newOperation.artifactFileName = fileName;
- return res.json();
+ return res;
});
}
@@ -237,78 +242,17 @@
return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_REQUIREMENTS, COMPONENT_FIELDS.COMPONENT_CAPABILITIES]);
}
- createCapability(component: Component, capabilityData: Capability): Observable<Array<Capability>> {
- let capBEObj = {
- 'capabilities': {
- [capabilityData.type]: [capabilityData]
- }
- };
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/capabilities', capBEObj)
- .map((res: Response) => {
- return res.json();
- });
- }
- updateCapability(component: Component, capabilityData: Capability): Observable<Array<Capability>> {
- let capBEObj = {
- 'capabilities': {
- [capabilityData.type]: [capabilityData]
- }
- };
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/capabilities', capBEObj)
- .map((res: Response) => {
- return res.json();
- });
- }
- deleteCapability(component: Component, capId: string): Observable<Capability> {
- return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/capabilities/' + capId)
- .map((res: Response) => {
- return res.json();
- });
- }
- createRequirement(component: Component, requirementData: Requirement): Observable<any> {
- let reqBEObj = {
- 'requirements': {
- [requirementData.capability]: [requirementData]
- }
- };
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/requirements', reqBEObj)
- .map((res: Response) => {
- return res.json();
- });
- }
-
- updateRequirement(component: Component, requirementData: Requirement): Observable<any> {
- let reqBEObj = {
- 'requirements': {
- [requirementData.capability]: [requirementData]
- }
- };
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/requirements', reqBEObj)
- .map((res: Response) => {
- return res.json();
- });
- }
-
- deleteRequirement(component: Component, reqId: string): Observable<Requirement> {
- return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/requirements/' + reqId)
- .map((res: Response) => {
- return res.json();
- });
- }
getDeploymentGraphData(component:Component):Observable<ComponentGenericResponse> {
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_GROUPS]);
}
createInput(component:Component, inputsToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> {
- let inputs = isSelf ? { serviceProperties: inputsToCreate.componentInstanceProperties } : inputsToCreate;
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputs)
- .map(res => {
- return res.json();
- })
+ const inputs = isSelf ? { serviceProperties: inputsToCreate.componentInstanceProperties } : inputsToCreate;
+ return this.http.post<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputs);
}
createListInput(component:Component, input:any, isSelf:boolean):Observable<any> {
@@ -324,10 +268,7 @@
} else {
inputs = input;
}
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/listInput', inputs)
- .map(res => {
- return res.json();
- })
+ return this.http.post<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/listInput', inputs);
}
createPolicy(component:Component, policiesToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> {
@@ -341,78 +282,71 @@
...policiesToCreate.componentInstanceProperties
}
};
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/policies', policiesList)
- .map(res => {
- return res.json();
- });
+ return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/policies', policiesList);
}
deletePolicy(component:Component, policy: PolicyInstance) {
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policy.uniqueId + '/undeclare', policy)
- .map(res => {
- return res.json();
- });
+ return this.http.put<PolicyInstance>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policy.uniqueId + '/undeclare', policy);
}
- restoreComponent(componentType:string, componentId:string){
+ restoreComponent(componentType:string, componentId:string) {
return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/restore', {})
}
- archiveComponent(componentType:string, componentId:string){
+ archiveComponent(componentType:string, componentId:string) {
return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/archive', {})
}
deleteInput(component:Component, input:InputBEModel):Observable<InputBEModel> {
- return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/delete/' + input.uniqueId + '/input')
- .map((res:Response) => {
- return new InputBEModel(res.json());
- });
- }
- updateComponentInputs(component:Component, inputs:InputBEModel[]):Observable<InputBEModel[]> {
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/update/inputs', inputs)
- .map((res:Response) => {
- return res.json().map((input) => new InputBEModel(input));
+ return this.http.delete<InputBEModel>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/delete/' + input.uniqueId + '/input')
+ .map((res) => {
+ return new InputBEModel(res);
})
}
- filterComponentInstanceProperties(component: Component, filterData:FilterPropertiesAssignmentData): Observable<InstanceBePropertiesMap> {//instance-property-be-map
- let params: URLSearchParams = new URLSearchParams();
+ updateComponentInputs(component:Component, inputs:InputBEModel[]):Observable<InputBEModel[]> {
+
+ return this.http.post<InputBEModel[]>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/update/inputs', inputs)
+ .map((res) => {
+ return res.map((input) => new InputBEModel(input));
+ })
+ }
+
+ filterComponentInstanceProperties(component:Component, filterData:FilterPropertiesAssignmentData):Observable<InstanceBePropertiesMap> {//instance-property-be-map
+ let params: HttpParams = new HttpParams();
_.forEach(filterData.selectedTypes, (type:string) => {
- params.append('resourceType', type);
+ params = params.append('resourceType', type);
});
- return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/filteredproperties/' + filterData.propertyName, {search: params})
- .map((res: Response) => {
- return res.json();
- });
+ return this.http.get<InstanceBePropertiesMap>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/filteredproperties/' + filterData.propertyName, {params: params});
}
createServiceProperty(component: Component, propertyModel:PropertyBEModel): Observable<PropertyBEModel> {
let serverObject = {};
serverObject[propertyModel.name] = propertyModel;
return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', serverObject)
- .map(res => {
- let property:PropertyBEModel = new PropertyBEModel(res.json());
+ .map((res: PropertyBEModel) => {
+ const property: PropertyBEModel = new PropertyBEModel(res);
return property;
})
}
- getServiceProperties(component: Component): Observable<Array<PropertyBEModel>> {
+ getServiceProperties(component: Component): Observable<PropertyBEModel[]> {
return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties')
- .map((res: Response) => {
- if (!res.text()){
+ .map((res: PropertyBEModel[]) => {
+ if (!res) {
return new Array<PropertyBEModel>();
}
- return CommonUtils.initBeProperties(res.json());
+ return CommonUtils.initBeProperties(res);
});
}
updateServiceProperties(component: Component, properties: PropertyBEModel[]) {
- return this.http.put( this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', properties)
- .map((res: Response) => {
- const resJson = res.json();
+ return this.http.put<PropertyBEModel[]>( this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', properties)
+ .map((res) => {
+ const resJson = res;
return _.map(resJson,
(resValue:PropertyBEModel) => new PropertyBEModel(resValue));
});
@@ -425,25 +359,16 @@
})
}
- getDependencies(componentType:string, componentId: string):Observable<Array<IDependenciesServerResponse>> {
- return this.http.get(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies')
- .map((res:Response) => {
- return res.json();
- });
+ getDependencies(componentType:string, componentId: string):Observable<IDependenciesServerResponse[]> {
+ return this.http.get<IDependenciesServerResponse[]>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies');
}
- automatedUpgrade(componentType:string, componentId: string, componentsIdsToUpgrade:Array<IAutomatedUpgradeRequestObj>):Observable<AutomatedUpgradeGenericResponse> {
- return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/automatedupgrade', componentsIdsToUpgrade)
- .map((res:Response) => {
- return res.json();
- });
+ automatedUpgrade(componentType:string, componentId:string, componentsIdsToUpgrade:IAutomatedUpgradeRequestObj[]):Observable<AutomatedUpgradeGenericResponse> {
+ return this.http.post<AutomatedUpgradeGenericResponse>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/automatedupgrade', componentsIdsToUpgrade);
}
- updateComponentInstance(component:Component, componentInstance:ComponentInstance):Observable<ComponentInstance> {
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstance.uniqueId, componentInstance)
- .map((res:Response) => {
- return res.json();
- });
+ updateMultipleComponentInstances(componentId:string, instances:ComponentInstance[]):Observable<ComponentInstance[]> {
+ return this.http.post<ComponentInstance[]>(this.baseUrl + componentId + '/resourceInstance/multipleComponentInstance', instances);
}
getServiceFilterConstraints(component:Component):Observable<ComponentGenericResponse> {
@@ -451,24 +376,18 @@
}
createServiceFilterConstraints(component:Component, componentInstance:ComponentInstance, constraint:ConstraintObject):Observable<any> {
- return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter', constraint)
- .map((res:Response) => {
- return res.json();
- });
+ return this.http.post<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter', constraint);
}
- updateServiceFilterConstraints(component:Component, componentInstance:ComponentInstance, constraints:Array<ConstraintObject>):Observable<any> {
- return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter/', constraints)
- .map((res:Response) => {
- return res.json();
- });
+ updateServiceFilterConstraints(component:Component, componentInstance:ComponentInstance, constraints:ConstraintObject[]):Observable<any> {
+ return this.http.put<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter/', constraints);
}
deleteServiceFilterConstraints(component:Component, componentInstance:ComponentInstance, constraintIndex:number) {
- return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter/' + constraintIndex)
- .map((res:Response) => {
- return res.json();
- });
+ return this.http.delete<any>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter/' + constraintIndex);
+ }
+
+ protected analyzeComponentDataResponse(res: Response):ComponentGenericResponse {
+ return new ComponentGenericResponse().deserialize(res);
}
}
-
diff --git a/catalog-ui/src/app/ng2/services/component-services/resource.service.ts b/catalog-ui/src/app/ng2/services/component-services/resource.service.ts
index 699e762..d20f541 100644
--- a/catalog-ui/src/app/ng2/services/component-services/resource.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/resource.service.ts
@@ -21,14 +21,14 @@
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
-import { Http, Response, Headers, RequestOptions } from '@angular/http';
+import { HttpClient } from '@angular/common/http';
@Injectable()
export class ResourceServiceNg2 {
protected baseUrl = "";
- constructor(private http: Http) {
+ constructor(private http: HttpClient) {
}
diff --git a/catalog-ui/src/app/ng2/services/component-services/service.service.ts b/catalog-ui/src/app/ng2/services/component-services/service.service.ts
index dce4e81..9460a32 100644
--- a/catalog-ui/src/app/ng2/services/component-services/service.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/service.service.ts
@@ -22,9 +22,7 @@
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
-import { Response, URLSearchParams } from '@angular/http';
-import {Service, OperationModel} from "app/models";
-import { HttpService } from '../http.service';
+import {Service} from "app/models";
import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config";
import {ForwardingPath} from "app/models/forwarding-path";
@@ -34,77 +32,53 @@
import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response";
import {COMPONENT_FIELDS, SERVICE_FIELDS} from "app/utils/constants";
import {ComponentServiceNg2} from "./component.service";
-import {ServiceGenericResponse} from "app/ng2/services/responses/service-generic-response";
import {ServicePathMapItem} from "app/models/graph/nodes-and-links-map";
-import {ConsumptionInput} from 'app/ng2/components/logic/service-consumption/service-consumption.component';
-
+import { HttpClient, HttpParams } from '@angular/common/http';
+import { OperationModel } from '../../../models/operation';
+import { ConsumptionInput } from '../../components/logic/service-consumption/service-consumption.component';
@Injectable()
export class ServiceServiceNg2 extends ComponentServiceNg2 {
protected baseUrl = "";
- constructor(protected http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
super(http, sdcConfig);
this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
}
validateConformanceLevel(service: Service): Observable<boolean> {
- return this.http.get(this.baseUrl + service.getTypeUrl() + service.uuid + '/conformanceLevelValidation')
- .map((res: Response) => {
- return res.json();
- });
+ return this.http.get<boolean>(this.baseUrl + service.getTypeUrl() + service.uuid + '/conformanceLevelValidation');
}
- getNodesAndLinksMap(service: Service):Observable<Array<ServicePathMapItem>> {
- return this.http.get(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/linksMap').map(res => {
- return <Array<ServicePathMapItem>>res.json();
- });
+ getNodesAndLinksMap(serviceId: string):Observable<Array<ServicePathMapItem>> {
+ return this.http.get<Array<ServicePathMapItem>>(this.baseUrl + 'services/' + serviceId + '/linksMap');
}
- getServicePath(service: Service, id: string):Observable<any> {
- return this.http.get(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths/' + id)
- .map(res => {
- return res.json();
- })
- }
-
- getServicePaths(service: Service):Observable<any> {
- return this.http.get(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths')
- .map(res => {
- return res.json();
- })
- }
-
- createOrUpdateServicePath(service: Service, inputsToCreate: ForwardingPath):Observable<ForwardingPath> {
+ createOrUpdateServicePath(serviceId: string, inputsToCreate: ForwardingPath):Observable<ForwardingPath> {
if (inputsToCreate.uniqueId) {
- return this.updateServicePath(service, inputsToCreate);
+ return this.updateServicePath(serviceId, inputsToCreate);
} else {
- return this.createServicePath(service, inputsToCreate);
+ return this.createServicePath(serviceId, inputsToCreate);
}
}
- createServicePath(service: Service, inputsToCreate: ForwardingPath):Observable<ForwardingPath> {
+ createServicePath(serviceId: string, inputsToCreate: ForwardingPath):Observable<ForwardingPath> {
let input = new ServicePathRequestData(inputsToCreate);
-
- return this.http.post(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths', input)
- .map(res => {
- return this.parseServicePathResponse(res);
- });
+ return this.http.post<ForwardingPath>(this.baseUrl + 'services/' + serviceId + '/paths', input).map((res:any) => {
+ return this.parseServicePathResponse(res);
+ });
}
- deleteServicePath(service: Service, id: string):Observable<any> {
- return this.http.delete(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths/' + id )
- .map((res) => {
- return res.json();
- });
+ deleteServicePath(serviceId: string, id: string):Observable<any> {
+ return this.http.delete<any>(this.baseUrl + 'services/' + serviceId + '/paths/' + id);
}
- updateServicePath(service: Service, inputsToUpdate:ForwardingPath):Observable<ForwardingPath> {
+ updateServicePath(serviceId: string, inputsToUpdate:ForwardingPath):Observable<ForwardingPath> {
let input = new ServicePathRequestData(inputsToUpdate);
- return this.http.put(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths', input)
+ return this.http.put<{[key:string]:ForwardingPath}>(this.baseUrl + 'services/' + serviceId + '/paths', input)
.map((res) => {
return this.parseServicePathResponse(res);
});
@@ -122,28 +96,25 @@
}
getServiceConsumptionInputs(service: Service, serviceInstanceId: String, interfaceId: string, operation: OperationModel): Observable<any> {
- return this.http.get(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/consumption/' + serviceInstanceId + '/interfaces/' + interfaceId + '/operations/' + operation.uniqueId + '/inputs')
- .map(res => {
- return res.json();
- });
+ return this.http.get<any>(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/consumption/' + serviceInstanceId + '/interfaces/' + interfaceId +
+ '/operations/' + operation.uniqueId + '/inputs');
}
createOrUpdateServiceConsumptionInputs(service: Service, serviceInstanceId: String, consumptionInputsList: Array<{[id: string]: Array<ConsumptionInput>}>): Observable<any> {
return this.http.post(this.baseUrl + service.getTypeUrl() + service.uniqueId + '/consumption/' + serviceInstanceId, consumptionInputsList);
}
- checkComponentInstanceVersionChange(service: Service, newVersionId: string):Observable<Array<string>> {
- let instanceId = service.selectedInstance.uniqueId;
- let queries = {componentInstanceId: instanceId, newComponentInstanceId: newVersionId};
+ checkComponentInstanceVersionChange(componentType:string, componentId:string, instanceId:string, newInstanceId:string):Observable<Array<string>> {
+ let queries = {componentInstanceId: instanceId, newComponentInstanceId: newInstanceId};
- let params:URLSearchParams = new URLSearchParams();
+ let params:HttpParams = new HttpParams();
_.map(_.keys(queries), (key:string):void => {
- params.append(key, queries[key]);
+ params = params.append(key, queries[key]);
});
- let url = this.baseUrl + service.getTypeUrl() + service.uniqueId + '/paths-to-delete';
- return this.http.get(url, {search: params}).map((res: Response) => {
- return res.json().forwardingPathToDelete;
+ let url = this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/paths-to-delete';
+ return this.http.get<any>(url, {params: params}).map((res) => {
+ return res.forwardingPathToDelete;
});
}
@@ -151,12 +122,8 @@
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES, SERVICE_FIELDS.FORWARDING_PATHS, COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_POLICIES, COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_GROUPS]);
}
- protected analyzeComponentDataResponse(res: Response):ComponentGenericResponse {
- return new ServiceGenericResponse().deserialize(res.json());
- }
-
- private parseServicePathResponse(res: Response):ForwardingPath {
- let resJSON = res.json();
+ private parseServicePathResponse(res: { [key:string]:ForwardingPath }):ForwardingPath {
+ let resJSON = res;
let pathId = Object.keys(resJSON.forwardingPaths)[0];
let forwardingPath = resJSON.forwardingPaths[pathId];
let path:ForwardingPath = new ForwardingPath();
diff --git a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
new file mode 100644
index 0000000..0abb1634
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
@@ -0,0 +1,515 @@
+/**
+ * Created by ob0695 on 6/26/2018.
+ */
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import {Injectable, Inject} from '@angular/core';
+import {Observable} from 'rxjs/Observable';
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/toPromise';
+import {
+ Component,
+ InputBEModel,
+ InstancePropertiesAPIMap,
+ FilterPropertiesAssignmentData,
+ ArtifactModel,
+ PropertyModel,
+ IFileDownload,
+ AttributeModel,
+ IAttributeModel, Capability, Requirement
+} from "app/models";
+import {ArtifactGroupType, COMPONENT_FIELDS} from "app/utils";
+import {ComponentGenericResponse} from "../responses/component-generic-response";
+import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map";
+import {API_QUERY_PARAMS} from "app/utils";
+import {ComponentType, ServerTypeUrl, SERVICE_FIELDS} from "../../../utils/constants";
+import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config";
+import {IDependenciesServerResponse} from "../responses/dependencies-server-response";
+import {AutomatedUpgradeGenericResponse} from "../responses/automated-upgrade-response";
+import {IAutomatedUpgradeRequestObj} from "../../pages/automated-upgrade/automated-upgrade.service";
+import {ComponentInstance} from "../../../models/componentsInstances/componentInstance";
+import {CommonUtils} from "../../../utils/common-utils";
+import {RelationshipModel} from "../../../models/graph/relationship";
+import {ServiceGenericResponse} from "../responses/service-generic-response";
+import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
+import { HttpHelperService } from "../http-hepler.service";
+import {
+ Component as TopologyTemplate,
+ FullComponentInstance,
+ Service,
+ OperationModel,
+} from 'app/models';
+import { ConsumptionInput } from "../../components/logic/service-consumption/service-consumption.component";
+import { ConstraintObject } from "../../components/logic/service-dependencies/service-dependencies.component";
+import { ComponentMetadata } from "../../../models/component-metadata";
+import { PolicyInstance } from "../../../models/graph/zones/policy-instance";
+import { PropertyBEModel } from "../../../models/properties-inputs/property-be-model";
+
+/* we need to use this service from now, we will remove component.service when we finish remove the angular1.
+ The service is duplicated since we can not use downgrades service with NGXS*/
+
+@Injectable()
+export class TopologyTemplateService {
+
+ protected baseUrl;
+
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
+ }
+
+ getFullComponent(componentType: string, uniqueId: string): Observable<Component> {
+ return this.http.get<Component>(this.baseUrl + this.getServerTypeUrl(componentType) + uniqueId);
+ }
+
+ getComponentMetadata(uniqueId: string, type: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(type, uniqueId, [COMPONENT_FIELDS.COMPONENT_METADATA]);
+ }
+
+ getComponentInstanceAttributesAndProperties(uniqueId: string, type: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(type, uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_ATTRIBUTES]);
+ }
+
+ async getComponentAttributes(componentType: string, componentId: string): Promise<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_ATTRIBUTES]).toPromise();
+ }
+
+ getComponentCompositionData(componentUniqueId: string, componentType: string): Observable<ComponentGenericResponse> {
+ const params: string[] = [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES,
+ COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_POLICIES, COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_GROUPS];
+ if (componentType === ComponentType.SERVICE) {
+ params.push(COMPONENT_FIELDS.FORWARDING_PATHS);
+ }
+ return this.getComponentDataByFieldsName(componentType, componentUniqueId, params);
+ }
+
+ getComponentResourcePropertiesData(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId,
+ [COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_POLICIES, COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_GROUPS]);
+ }
+
+ getComponentResourceInstances(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES]);
+ }
+
+ getComponentInputs(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INPUTS]);
+ }
+
+ getComponentInputsWithProperties(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId,
+ [COMPONENT_FIELDS.COMPONENT_INPUTS, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_PROPERTIES]);
+ }
+
+ getComponentDeploymentArtifacts(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_DEPLOYMENT_ARTIFACTS]);
+ }
+
+ getComponentInformationalArtifacts(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INFORMATIONAL_ARTIFACTS]);
+ }
+
+ getComponentInformationalArtifactsAndInstances(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INFORMATIONAL_ARTIFACTS, COMPONENT_FIELDS.COMPONENT_INSTANCES]);
+ }
+
+ getComponentToscaArtifacts(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_TOSCA_ARTIFACTS]);
+ }
+
+ getComponentProperties(component: Component): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_PROPERTIES]);
+ }
+
+ getCapabilitiesAndRequirements(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_REQUIREMENTS, COMPONENT_FIELDS.COMPONENT_CAPABILITIES]);
+ }
+
+ getRequirementsAndCapabilitiesWithProperties(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId,
+ [COMPONENT_FIELDS.COMPONENT_REQUIREMENTS, COMPONENT_FIELDS.COMPONENT_CAPABILITIES, COMPONENT_FIELDS.COMPONENT_CAPABILITIES_PROPERTIES]);
+ }
+
+ getDeploymentGraphData(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_GROUPS]);
+ }
+
+ createInput(component: Component, inputsToCreate: InstancePropertiesAPIMap, isSelf: boolean): Observable<any> {
+ const inputs = isSelf ? { serviceProperties: inputsToCreate.componentInstanceProperties } : inputsToCreate;
+ return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputs);
+ }
+
+ restoreComponent(componentType: string, componentId: string) {
+ return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/restore', {});
+ }
+
+ archiveComponent(componentType: string, componentId: string) {
+ return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/archive', {});
+ }
+
+ deleteInput(component: Component, input: InputBEModel): Observable<InputBEModel> {
+ return this.http.delete<InputBEModel>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/delete/' + input.uniqueId + '/input')
+ .map((res) => {
+ return new InputBEModel(res);
+ });
+ }
+
+ updateComponentInputs(component: Component, inputs: InputBEModel[]): Observable<InputBEModel[]> {
+ return this.http.post<InputBEModel[]>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/update/inputs', inputs)
+ .map((res) => {
+ return res.map((input) => new InputBEModel(input));
+ });
+ }
+
+ filterComponentInstanceProperties(component: Component, filterData: FilterPropertiesAssignmentData): Observable<InstanceBePropertiesMap> {// instance-property-be-map
+ let params: HttpParams = new HttpParams();
+ _.forEach(filterData.selectedTypes, (type: string) => {
+ params = params.append('resourceType', type);
+ });
+
+ // tslint:disable-next-line:object-literal-shorthand
+ return this.http.get<InstanceBePropertiesMap>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/filteredproperties/' + filterData.propertyName, {params: params});
+ }
+
+ createServiceProperty(componentId: string, propertyModel: PropertyBEModel): Observable<PropertyBEModel> {
+ const serverObject = {};
+ serverObject[propertyModel.name] = propertyModel;
+ return this.http.post<PropertyBEModel>(this.baseUrl + 'services/' + componentId + '/properties', serverObject)
+ .map((res) => {
+ const property: PropertyBEModel = new PropertyBEModel(res);
+ return property;
+ });
+ }
+
+ getServiceProperties(componentId: string): Observable<PropertyBEModel[]> {
+ return this.http.get<any>(this.baseUrl + 'services/' + componentId + '/properties')
+ .map((res) => {
+ if (!res) {
+ return new Array<PropertyBEModel>();
+ }
+ return CommonUtils.initBeProperties(res);
+ });
+ }
+
+ updateServiceProperties(componentId: string, properties: PropertyBEModel[]) {
+ return this.http.put<any>( this.baseUrl + 'services/' + componentId + '/properties', properties)
+ .map((res) => {
+ const resJson = res;
+ return _.map(resJson,
+ (resValue: PropertyBEModel) => new PropertyBEModel(resValue));
+ });
+ }
+
+ deleteServiceProperty(componentId: string, property: PropertyBEModel): Observable<string> {
+ return this.http.delete(this.baseUrl + 'services/' + componentId + '/properties/' + property.uniqueId )
+ .map((res: Response) => {
+ return property.uniqueId;
+ });
+ }
+
+ getDependencies(componentType: string, componentId: string): Observable<IDependenciesServerResponse[]> {
+ return this.http.get<IDependenciesServerResponse[]>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies');
+ }
+
+ automatedUpgrade(componentType: string, componentId: string, componentsIdsToUpgrade: IAutomatedUpgradeRequestObj[]): Observable<AutomatedUpgradeGenericResponse> {
+ return this.http.post<AutomatedUpgradeGenericResponse>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/automatedupgrade', componentsIdsToUpgrade);
+ }
+
+ updateComponentInstance(componentMetaDataId: string, componentInstance:ComponentInstance): Observable<ComponentInstance> {
+ return this.http.post<ComponentInstance>(this.baseUrl + 'services/' + componentMetaDataId + '/resourceInstance/' + componentInstance.uniqueId, componentInstance);
+ }
+
+ updateMultipleComponentInstances(componentId: string, componentType: string, instances: ComponentInstance[]): Observable<ComponentInstance[]> {
+ return this.http.post<ComponentInstance[]>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/multipleComponentInstance', instances)
+ .map((res) => {
+ return CommonUtils.initComponentInstances(res);
+ });
+ }
+
+ createRelation(componentId: string, componentType: string, link: RelationshipModel): Observable<RelationshipModel> {
+ return this.http.post<RelationshipModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/associate', link)
+ .map((res) => {
+ return new RelationshipModel(res);
+ });
+ }
+
+ deleteRelation(componentId: string, componentType: string, link: RelationshipModel): Observable<RelationshipModel> {
+ return this.http.put<RelationshipModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/dissociate', link)
+ .map((res) => {
+ return new RelationshipModel(res);
+ });
+ }
+
+ createComponentInstance(componentType: string, componentId: string, componentInstance: ComponentInstance): Observable<ComponentInstance> {
+ return this.http.post<ComponentInstance>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance', componentInstance)
+ .map((res) => {
+ return new ComponentInstance(res);
+ });
+ }
+
+ deleteComponentInstance(componentType: string, componentId: string, componentInstanceId: string): Observable<ComponentInstance> {
+ return this.http.delete<ComponentInstance>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/resourceInstance/' + componentInstanceId)
+ .map((res) => {
+ return new ComponentInstance(res);
+ });
+ }
+
+ fetchRelation(componentType: string, componentId: string, linkId: string): Observable<RelationshipModel> {
+ return this.http.get<RelationshipModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/relationId/' + linkId)
+ .map((res) => {
+ return new RelationshipModel(res);
+ });
+ }
+
+ addOrUpdateArtifact = (componentType: string, componentId: string, artifact: ArtifactModel): Observable<ArtifactModel> => {
+ let headerObj: HttpHeaders = new HttpHeaders();
+ if (artifact.payloadData) {
+ headerObj = headerObj.append('Content-MD5', HttpHelperService.getHeaderMd5(artifact));
+ }
+
+ let artifactID: string = '';
+ if (artifact.uniqueId) {
+ artifactID = '/' + artifact.uniqueId;
+ }
+ return this.http.post<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/artifacts' + artifactID, JSON.stringify(artifact), {headers: headerObj}).map(
+ (res) => new ArtifactModel(res)
+ );
+ }
+
+ deleteArtifact = (componentId: string, componentType: string, artifactId: string, artifactLabel: string): Observable<ArtifactModel> => {
+ return this.http.delete<ArtifactModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/artifacts/' + artifactId + '?operation=' + artifactLabel)
+ .map((res) => new ArtifactModel(res));
+ }
+
+ downloadArtifact = (componentType: string, componentId: string, artifactId: string): Observable<IFileDownload> => {
+ return this.http.get<IFileDownload>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/artifacts/' + artifactId);
+ }
+
+ // ------------------------------------------------ Properties API --------------------------------------------------//
+ addProperty = (componentType: string, componentId: string, property: PropertyModel):Observable<PropertyModel> => {
+ return this.http.post<PropertyModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/properties', property.convertToServerObject()).map((response) => {
+ return new PropertyModel(response[Object.keys(response)[0]]);
+ });
+ }
+
+ updateProperty = (componentType: string, componentId: string, property: PropertyModel): Observable<PropertyModel> => {
+ var propertiesList:PropertyBEModel[] = [property];
+ return this.http.put<PropertyModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/properties', propertiesList)
+ .map((response) => {
+ return new PropertyModel(response[Object.keys(response)[0]]);
+ });
+ }
+
+ deleteProperty = (componentType: string, componentId: string, propertyId: string): Observable<PropertyModel> => {
+ return this.http.delete<PropertyModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/properties/' + propertyId);
+ }
+
+ // ------------------------------------------------ Attributes API --------------------------------------------------//
+ addAttribute = (componentType: string, componentId: string, attribute: AttributeModel): Observable<AttributeModel> => {
+ return this.http.post<AttributeModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/attributes', attribute.convertToServerObject())
+ .map((response) => {
+ return new AttributeModel(response);
+ });
+ }
+
+ updateAttribute = (componentType: string, componentId: string, attribute: AttributeModel): Observable<AttributeModel> => {
+ const payload = attribute.convertToServerObject();
+
+ return this.http.put<AttributeModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/attributes/' + attribute.uniqueId, payload)
+ .map((response) => {
+ return new AttributeModel(response);
+ });
+ }
+
+ // Async Methods
+ addAttributeAsync = async (componentType: string, componentId: string, attribute: AttributeModel): Promise<AttributeModel> => {
+ return this.addAttribute(componentType, componentId, attribute).toPromise();
+ }
+
+ updateAttributeAsync = async (componentType: string, componentId: string, attribute: AttributeModel): Promise<AttributeModel> => {
+ return this.updateAttribute(componentType, componentId, attribute).toPromise();
+ }
+
+ deleteAttributeAsync = async (componentType: string, componentId: string, attribute: AttributeModel): Promise<any> => {
+ return this.http.delete<any>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/attributes/' + attribute.uniqueId, {}).toPromise();
+ }
+
+ getArtifactsByType(componentType: string, componentId: string, artifactsType: ArtifactGroupType) {
+ return this.getComponentDataByFieldsName(componentType, componentId, [this.convertArtifactTypeToUrl(artifactsType)]);
+ }
+
+ getServiceConsumptionData(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [
+ // COMPONENT_FIELDS.COMPONENT_INSTANCES_INTERFACES,
+ COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES,
+ // COMPONENT_FIELDS.COMPONENT_INSTANCES_INPUTS,
+ COMPONENT_FIELDS.COMPONENT_INPUTS,
+ COMPONENT_FIELDS.COMPONENT_INSTANCES,
+ COMPONENT_FIELDS.COMPONENT_CAPABILITIES
+ ]);
+ }
+
+ getServiceConsumptionInputs(componentMetaDataId: string, serviceInstanceId: string, interfaceId: string, operation: OperationModel): Observable<ConsumptionInput[]> {
+ return this.http.get<ConsumptionInput[]>
+ (this.baseUrl + 'services/' + componentMetaDataId + '/consumption/' + serviceInstanceId + '/interfaces/' + interfaceId + '/operations/' + operation.uniqueId + '/inputs');
+ }
+
+ createOrUpdateServiceConsumptionInputs(componentMetaDataId: string, serviceInstanceId: string, consumptionInputsList: Array<{[id: string]: ConsumptionInput[]}>): Observable<any> {
+ return this.http.post(this.baseUrl + 'services/' + componentMetaDataId + '/consumption/' + serviceInstanceId, consumptionInputsList);
+ }
+
+ getServiceFilterConstraints(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [SERVICE_FIELDS.NODE_FILTER]);
+ }
+
+ getComponentInstanceProperties(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES]);
+ }
+
+ createServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: ConstraintObject): Observable<any> {
+ return this.http.post<any>(this.baseUrl + 'services/' + componentMetaDataId + '/resourceInstances/' + componentInstanceId + '/nodeFilter', constraint);
+ }
+
+ updateServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraints: ConstraintObject[]):Observable<any> {
+ return this.http.put<any>(this.baseUrl + 'services/' + componentMetaDataId + '/resourceInstances/' + componentInstanceId + '/nodeFilter', constraints)
+ }
+
+ deleteServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraintIndex: number): Observable<any>{
+ return this.http.delete<any>(this.baseUrl + 'services/' + componentMetaDataId + '/resourceInstances/' + componentInstanceId + '/nodeFilter/' + constraintIndex)
+ }
+
+ deletePolicy(component: Component, policy: PolicyInstance): Observable<PolicyInstance> {
+ return this.http.put<PolicyInstance>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policy.uniqueId + '/undeclare', policy)
+ }
+
+ createListInput(componentId: string, input: any, isSelf: boolean): Observable<any> {
+ let inputs: any;
+ if (isSelf) {
+ // change componentInstanceProperties -> serviceProperties
+ inputs = {
+ componentInstInputsMap: {
+ serviceProperties: input.componentInstInputsMap.componentInstanceProperties
+ },
+ listInput: input.listInput
+ };
+ } else {
+ inputs = input;
+ }
+ return this.http.post<any>(this.baseUrl + 'services/' + componentId + '/create/listInput', inputs);
+ }
+
+ createPolicy(component: Component, policiesToCreate: InstancePropertiesAPIMap, isSelf: boolean): Observable<any> {
+ const policiesList =
+ isSelf ?
+ // tslint:disable-next-line:object-literal-key-quotes
+ {'componentPropertiesToPolicies': {
+ ...policiesToCreate.componentInstanceProperties
+ }
+ } :
+ // tslint:disable-next-line:object-literal-key-quotes
+ {'componentInstancePropertiesToPolicies': {
+ ...policiesToCreate.componentInstanceProperties
+ }
+ };
+ return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/policies', policiesList);
+ }
+
+ protected getComponentDataByFieldsName(componentType: string, componentId: string, fields: string[]): Observable<ComponentGenericResponse> {
+ let params: HttpParams = new HttpParams();
+ _.forEach(fields, (field: string): void => {
+ params = params.append(API_QUERY_PARAMS.INCLUDE, field);
+ });
+ // tslint:disable-next-line:object-literal-shorthand
+ return this.http.get<ComponentGenericResponse>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/filteredDataByParams', {params: params})
+ .map((res) => {
+ return componentType === ComponentType.SERVICE ? new ServiceGenericResponse().deserialize(res) :
+ new ComponentGenericResponse().deserialize(res);
+ });
+ }
+
+ private getServerTypeUrl = (componentType: string): string => {
+ switch (componentType) {
+ case ComponentType.SERVICE:
+ case ComponentType.SERVICE_PROXY:
+ return ServerTypeUrl.SERVICES;
+ default:
+ return ServerTypeUrl.RESOURCES;
+ }
+ }
+
+ private convertArtifactTypeToUrl = (artifactType: ArtifactGroupType): string => {
+ switch (artifactType) {
+ case ArtifactGroupType.TOSCA:
+ return COMPONENT_FIELDS.COMPONENT_TOSCA_ARTIFACTS;
+ case ArtifactGroupType.INFORMATION:
+ return COMPONENT_FIELDS.COMPONENT_INFORMATIONAL_ARTIFACTS;
+ case ArtifactGroupType.DEPLOYMENT:
+ return COMPONENT_FIELDS.COMPONENT_DEPLOYMENT_ARTIFACTS;
+ case ArtifactGroupType.SERVICE_API:
+ return COMPONENT_FIELDS.SERVICE_API_ARTIFACT;
+ }
+ }
+
+ // createCapability(component: Component, capabilityData: Capability): Observable<Capability[]> {
+ createCapability(type: string, uniqueId: string, capabilityData: Capability): Observable<Capability[]> {
+ let capBEObj = {
+ 'capabilities': {
+ [capabilityData.type]: [capabilityData]
+ }
+ };
+ return this.http.post<any>(this.baseUrl + type + uniqueId + '/capabilities', capBEObj);
+ }
+
+ updateCapability(type: string, uniqueId: string, capabilityData: Capability): Observable<Capability[]> {
+ let capBEObj = {
+ 'capabilities': {
+ [capabilityData.type]: [capabilityData]
+ }
+ };
+ return this.http.put<any>(this.baseUrl + type + uniqueId + '/capabilities', capBEObj);
+ }
+
+ deleteCapability(component: Component, capId: string): Observable<Capability> {
+ return this.http.delete<Capability>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/capabilities/' + capId);
+ }
+
+ createRequirement(type: string, uniqueId: string, requirementData: Requirement): Observable<any> {
+ let reqBEObj = {
+ 'requirements': {
+ [requirementData.capability]: [requirementData]
+ }
+ };
+ return this.http.post(this.baseUrl + type + uniqueId + '/requirements', reqBEObj);
+ }
+
+ updateRequirement(type: string, uniqueId: string, requirementData: Requirement): Observable<any> {
+ let reqBEObj = {
+ 'requirements': {
+ [requirementData.capability]: [requirementData]
+ }
+ };
+ return this.http.put(this.baseUrl + type + uniqueId + '/requirements', reqBEObj);
+ }
+
+ deleteRequirement(component: Component, reqId: string): Observable<Requirement> {
+ return this.http.delete<Requirement>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/requirements/' + reqId);
+ }
+}
diff --git a/catalog-ui/src/app/ng2/services/config.service.ts b/catalog-ui/src/app/ng2/services/config.service.ts
index 11fe395..2b9b49c 100644
--- a/catalog-ui/src/app/ng2/services/config.service.ts
+++ b/catalog-ui/src/app/ng2/services/config.service.ts
@@ -16,62 +16,80 @@
*
*/
-import { Injectable, Inject } from '@angular/core';
-import { Http, Response } from '@angular/http';
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable, Injector } from '@angular/core';
+import { IAppConfigurtaion, Plugins, PluginsConfiguration, ValidationConfiguration, Validations } from 'app/models';
+import { IApi } from 'app/models/app-config';
import 'rxjs/add/operator/toPromise';
-import {IAppConfigurtaion, ValidationConfiguration, Validations, Plugins, PluginsConfiguration} from "app/models";
-import {IApi} from "app/models/app-config";
-import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+import { CacheService } from './cache.service';
@Injectable()
export class ConfigService {
- private baseUrl;
public configuration: IAppConfigurtaion;
- public api:IApi;
+ public api: IApi;
+ private baseUrl;
- constructor(private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
- this.api = this.sdcConfig.api;
- this.baseUrl = this.api.root + this.sdcConfig.api.component_api_root;
+ constructor(
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
+ private cacheService: CacheService,
+ private injector: Injector,
+ private http: HttpClient
+ ) {
+ this.api = this.sdcConfig.api;
+ this.baseUrl = this.api.root + this.sdcConfig.api.component_api_root;
+ }
+
+ loadSdcSetupData = (): Promise<void> => {
+ const url: string = this.api.root + this.api.GET_SDC_Setup_Data;
+ const promise: Promise<any> = this.http.get<any>(url).toPromise();
+ promise.then((response) => {
+ this.cacheService.set('version', response.version);
+ this.cacheService.set('serviceCategories', response.categories.serviceCategories);
+ this.cacheService.set('resourceCategories', response.categories.resourceCategories);
+ this.cacheService.set('UIConfiguration', response.configuration);
+ });
+ return promise;
}
loadValidationConfiguration(): Promise<ValidationConfiguration> {
- let url: string = this.sdcConfig.validationConfigPath;
- let promise: Promise<ValidationConfiguration> = this.http.get(url).map((res: Response) => res.json()).toPromise();
+ const url: string = this.sdcConfig.validationConfigPath;
+ const promise: Promise<ValidationConfiguration> = this.http.get<ValidationConfiguration>(url).toPromise();
promise.then((validationData: Validations) => {
ValidationConfiguration.validation = validationData;
+ this.cacheService.set('validation', validationData);
}).catch((ex) => {
console.error('Error loading validation.json configuration file, using fallback data', ex);
- let fallback:Validations = {
- "propertyValue": {
- "max": 2500,
- "min": 0
+ const fallback = {
+ propertyValue: {
+ max: 2500,
+ min: 0
},
-
- "validationPatterns": {
- "string": "^[\\sa-zA-Z0-9+-]+$",
- "comment": "^[\\sa-zA-Z0-9+-_\\{\\}\"]+$",
- "integer": "^(([-+]?\\d+)|([-+]?0x[0-9a-fA-F]+))$"
+ validationPatterns: {
+ string: '^[\\sa-zA-Z0-9+-]+$',
+ stringOrEmpty: '^[\\sa-zA-Z0-9&-]*$',
+ comment: '^[\\sa-zA-Z0-9+-_\\{\\}"]+$',
+ integer: '^(([-+]?\\d+)|([-+]?0x[0-9a-fA-F]+))$'
}
};
- ValidationConfiguration.validation = fallback;
-
+ this.cacheService.set('validation', fallback);
});
return promise;
}
- loadPluginsConfiguration(): Promise<PluginsConfiguration> {
- let url:string = this.api.no_proxy_root + this.api.GET_plugins_configuration;
- let promise: Promise<any> = this.http.get(url).map((res: Response) => res.json()).toPromise();
+ loadPluginsConfiguration = (): Promise<PluginsConfiguration> => {
+ const url: string = this.api.no_proxy_root + this.api.GET_plugins_configuration;
+ const promise: Promise<any> = this.http.get<PluginsConfiguration>(url).toPromise();
return new Promise<PluginsConfiguration>((resolve) => {
promise.then((pluginsData: Plugins) => {
PluginsConfiguration.plugins = pluginsData;
resolve();
}).catch((ex) => {
- console.error("Error loading plugins configuration from FE", ex);
+ console.error('Error loading plugins configuration from FE', ex);
PluginsConfiguration.plugins = [] as Plugins;
resolve();
diff --git a/catalog-ui/src/app/ng2/services/cookie.service.ts b/catalog-ui/src/app/ng2/services/cookie.service.ts
index 2a783fd..61d1318 100644
--- a/catalog-ui/src/app/ng2/services/cookie.service.ts
+++ b/catalog-ui/src/app/ng2/services/cookie.service.ts
@@ -19,7 +19,7 @@
*/
import {Injectable, Inject} from '@angular/core';
-import {IAppConfigurtaion, ICookie} from "../../models/app-config";
+import {ICookie} from "../../models/app-config";
import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
@Injectable()
diff --git a/catalog-ui/src/app/ng2/services/data-type.service.ts b/catalog-ui/src/app/ng2/services/data-type.service.ts
index cabaccd..0559f35 100644
--- a/catalog-ui/src/app/ng2/services/data-type.service.ts
+++ b/catalog-ui/src/app/ng2/services/data-type.service.ts
@@ -20,9 +20,9 @@
import * as _ from "lodash";
import { Injectable } from '@angular/core';
-import { DataTypeModel, DataTypesMap, PropertyBEModel, PropertyFEModel, DerivedFEProperty, DerivedFEPropertyMap } from "app/models";
+import { DataTypeModel, DataTypesMap, PropertyFEModel, DerivedFEProperty} from "app/models";
import { DataTypesService } from "app/services/data-types-service";
-import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils";
+import { PROPERTY_DATA } from "app/utils";
/** This is a new service for NG2, to eventually replace app/services/data-types-service.ts
*
@@ -32,13 +32,16 @@
@Injectable()
export class DataTypeService {
- private dataTypes: DataTypesMap;
+ public dataTypes: DataTypesMap;
constructor(private dataTypeService: DataTypesService) {
this.dataTypes = dataTypeService.getAllDataTypes(); //This should eventually be replaced by an NG2 call to the backend instead of utilizing Angular1 downgraded component.
}
public getDataTypeByTypeName(typeName: string): DataTypeModel {
+ if(!this.dataTypes){
+ this.dataTypes = this.dataTypeService.getAllDataTypes();
+ }
if (!this.dataTypes[typeName]) console.log("MISSING Datatype: " + typeName);
return this.dataTypes[typeName];
}
@@ -47,6 +50,13 @@
return this.dataTypes;
}
+ public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName){
+ // const property = this.dataTypes[rootPropertyType].properties.filter(property =>
+ // property.name == propertyName);
+ // return property[0] && property[0].constraints ? property[0].constraints[0].validValues : null;
+ return null;
+ }
+
public getDerivedDataTypeProperties(dataTypeObj: DataTypeModel, propertiesArray: Array<DerivedFEProperty>, parentName: string) {
//push all child properties to array
diff --git a/catalog-ui/src/app/ng2/services/event-bus.service.ts b/catalog-ui/src/app/ng2/services/event-bus.service.ts
index cc53d79..2a15ca2 100644
--- a/catalog-ui/src/app/ng2/services/event-bus.service.ts
+++ b/catalog-ui/src/app/ng2/services/event-bus.service.ts
@@ -1,5 +1,5 @@
import {Injectable} from '@angular/core';
-import {BasePubSub, IPubSubEvent} from 'sdc-pubsub';
+import {BasePubSub, IPubSubEvent} from "sdc-pubsub";
@Injectable()
export class EventBusService extends BasePubSub {
diff --git a/catalog-ui/src/app/ng2/services/file-utils.service.ts b/catalog-ui/src/app/ng2/services/file-utils.service.ts
new file mode 100644
index 0000000..5789749
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/file-utils.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from "@angular/core";
+import { WindowRef } from "./window.service";
+
+@Injectable()
+export class FileUtilsService {
+ constructor(private windowRef: WindowRef){}
+
+ public byteCharactersToBlob = (byteCharacters, contentType):any => {
+ contentType = contentType || '';
+ let sliceSize = 1024;
+ let bytesLength = byteCharacters.length;
+ let slicesCount = Math.ceil(bytesLength / sliceSize);
+ let byteArrays = new Array(slicesCount);
+
+ for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
+ let begin = sliceIndex * sliceSize;
+ let end = Math.min(begin + sliceSize, bytesLength);
+
+ let bytes = new Array(end - begin);
+ for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
+ bytes[i] = byteCharacters[offset].charCodeAt(0);
+ }
+ byteArrays[sliceIndex] = new Uint8Array(bytes);
+ }
+ return new Blob(byteArrays, {type: contentType});
+ };
+
+ public base64toBlob = (base64Data, contentType):any => {
+ let byteCharacters = atob(base64Data);
+ return this.byteCharactersToBlob(byteCharacters, contentType);
+ };
+
+ public downloadFile = (blob, fileName):void=> {
+ let url = this.windowRef.nativeWindow.URL.createObjectURL(blob);
+ let downloadLink = document.createElement("a");
+
+ downloadLink.setAttribute('href', url);
+ downloadLink.setAttribute('download', fileName);
+ document.body.appendChild(downloadLink);
+
+ var clickEvent = new MouseEvent("click", {
+ "view": window,
+ "bubbles": true,
+ "cancelable": true
+ });
+ downloadLink.dispatchEvent(clickEvent);
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/gab.service.ts b/catalog-ui/src/app/ng2/services/gab.service.ts
index d903d20..b62c566 100644
--- a/catalog-ui/src/app/ng2/services/gab.service.ts
+++ b/catalog-ui/src/app/ng2/services/gab.service.ts
@@ -18,12 +18,13 @@
* ============LICENSE_END=========================================================
*/
-import {Injectable, Inject} from "@angular/core";
-import {Response} from '@angular/http';
-import {HttpService} from "./http.service";
-import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
-import {Observable} from "rxjs";
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { Response } from '@angular/http';
+import { Observable } from 'rxjs';
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+// tslint:disable-next-line:interface-name
export interface IServerResponse {
data: [{ [key: string]: string }];
}
@@ -36,24 +37,25 @@
}
}
+// tslint:disable-next-line:max-classes-per-file
@Injectable()
export class GabService {
baseUrl: string;
gabUrl: string;
- constructor(@Inject(SdcConfigToken) sdcConfig: ISdcConfig, private http: HttpService) {
+ constructor(@Inject(SdcConfigToken) sdcConfig: ISdcConfig, protected http: HttpClient) {
this.baseUrl = sdcConfig.api.root;
this.gabUrl = sdcConfig.api.POST_GAB_Search;
}
public getArtifact(artifactUniqueId: string, resourceId: string, columns: string[]): Observable<Response> {
- let finalUrl: string = this.baseUrl + this.gabUrl;
- let request: GabRequest = {
+ const finalUrl: string = this.baseUrl + this.gabUrl;
+ const request: GabRequest = {
fields: columns,
parentId: resourceId,
- artifactUniqueId: artifactUniqueId
+ artifactUniqueId
};
- return this.http.post(finalUrl, request);
+ return this.http.post<Response>(finalUrl, request);
}
}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/groups.service.ts b/catalog-ui/src/app/ng2/services/groups.service.ts
index e3b3d85..8b2bcd3 100644
--- a/catalog-ui/src/app/ng2/services/groups.service.ts
+++ b/catalog-ui/src/app/ng2/services/groups.service.ts
@@ -1,11 +1,11 @@
import {IZoneInstanceAssignment} from '../../models/graph/zones/zone-instance';
import {Injectable, Inject} from "@angular/core";
import {Observable} from "rxjs/Observable";
-import {HttpService} from "./http.service";
import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
import {GroupInstance} from '../../models/graph/zones/group-instance';
import {UiBaseObject} from "../../models/ui-models/ui-base-object";
import {IZoneService} from "../../models/graph/zones/zone";
+import { HttpClient } from '@angular/common/http';
@Injectable()
export class GroupsService implements IZoneService {
@@ -17,13 +17,13 @@
'SERVICE': 'services'
}
- constructor(private http:HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
+ constructor(private http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
this.baseUrl = sdcConfig.api.root;
}
- public createGroupInstance(componentType:string, componentUniqueId:string, groupType:string) {
- return this.http.post(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[componentType.toUpperCase()] + '/' + componentUniqueId + '/groups/' + groupType, {}).map(resp => {
- return resp.json();
+ public createGroupInstance(componentType:string, componentUniqueId:string, groupType:string): Observable<GroupInstance>{
+ return this.http.post<GroupInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[componentType.toUpperCase()] + '/' + componentUniqueId + '/groups/' + groupType, {}).map(resp => {
+ return new GroupInstance(resp);
});
};
@@ -40,8 +40,7 @@
}
public updateGroupMembers(topologyTemplateType:string, topologyTemplateId:string, groupId:string, members:Array<string>):Observable<Array<string>> {
- return this.http.post(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId + '/members', members)
- .map(response => response.json());
+ return this.http.post<Array<string>>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId + '/members', members);
}
public updateMembers(topologyTemplateType:string, topologyTemplateId:string, groupId:string, members:Array<UiBaseObject>):Observable<Array<string>> {
@@ -50,22 +49,18 @@
}
public getSpecificGroup(topologyTemplateType:string, topologyTemplateId:string, groupId:string):Observable<GroupInstance> {
- return this.http.get(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId)
+ return this.http.get<GroupInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId)
.map(res => {
- return new GroupInstance(res.json());
+ return new GroupInstance(res);
});
}
public updateName(topologyTemplateType:string, topologyTemplateId:string, groupId:string, newName:string):Observable<GroupInstance> {
- return this.http.put(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId, {name: newName}).map(resp => {
- return resp.json();
- });
+ return this.http.put<GroupInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId, {name: newName});
};
public deleteGroup(topologyTemplateType:string, topologyTemplateId:string, groupId:string) {
- return this.http.delete(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId).map(resp => {
- return resp.json();
- });
+ return this.http.delete<GroupInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/groups/' + groupId);
};
public updateZoneInstanceAssignments(topologyTemplateType:string, topologyTemplateId:string, policyId:string, members:Array<IZoneInstanceAssignment>):Observable<any> {
@@ -75,4 +70,6 @@
public deleteZoneInstance(topologyTemplateType:string, topologyTemplateId:string, policyId:string):Observable<any> {
return this.deleteGroup(topologyTemplateType, topologyTemplateId, policyId);
};
-}
\ No newline at end of file
+
+
+}
diff --git a/catalog-ui/src/app/ng2/services/home.service.ts b/catalog-ui/src/app/ng2/services/home.service.ts
new file mode 100644
index 0000000..c472aa8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/home.service.ts
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { Component, IApi, Resource, Service } from 'app/models';
+import { ComponentFactory } from 'app/utils/component-factory';
+import { Observable } from 'rxjs';
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+import { SharingService } from './sharing.service';
+
+// tslint:disable-next-line:interface-name
+interface IComponentsArray {
+ services: Service[];
+ resources: Resource[];
+}
+
+@Injectable()
+export class HomeService {
+ private api: IApi;
+ private smallObjectAttributes = [
+ 'uniqueId', 'name', 'componentType', 'resourceType', 'lastUpdateDate', 'lifecycleState', 'distributionStatus',
+ 'icon', 'version'
+ ];
+
+ constructor(private http: HttpClient,
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
+ private sharingService: SharingService,
+ private componentFactory: ComponentFactory) {
+ this.api = sdcConfig.api;
+ }
+
+ public getAllComponents(smallObjects?: boolean): Observable<Component[]> {
+ return this.http.get<IComponentsArray>(this.api.root + this.api.GET_element)
+ .map((response) => {
+ const componentResponse: IComponentsArray = response;
+ let componentsList: Component[] = [];
+
+ componentResponse.services && componentResponse.services.forEach((serviceResponse: Service) => {
+ serviceResponse = (smallObjects) ? _.pick(serviceResponse, this.smallObjectAttributes) : serviceResponse;
+ const component: Service = this.componentFactory.createService(serviceResponse);
+ componentsList.push(component);
+ this.sharingService.addUuidValue(component.uniqueId, component.uuid);
+ });
+
+ componentResponse.resources && componentResponse.resources.forEach((resourceResponse: Resource) => {
+ resourceResponse = (smallObjects) ? _.pick(resourceResponse, this.smallObjectAttributes) : resourceResponse;
+ const component: Resource = this.componentFactory.createResource(resourceResponse);
+ componentsList.push(component);
+ this.sharingService.addUuidValue(component.uniqueId, component.uuid);
+ });
+
+ componentsList = _.orderBy(componentsList, ['lastUpdateDate'], ['desc']);
+
+ return componentsList;
+ });
+ }
+}
diff --git a/catalog-ui/src/app/ng2/services/http-hepler.service.ts b/catalog-ui/src/app/ng2/services/http-hepler.service.ts
new file mode 100644
index 0000000..2b11067
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/http-hepler.service.ts
@@ -0,0 +1,31 @@
+import { Injectable, Inject } from "@angular/core";
+import { Dictionary } from "../../utils/dictionary/dictionary";
+import { SharingService } from "../services/sharing.service";
+import { SdcConfigToken, ISdcConfig } from "../config/sdc-config.config";
+
+
+@Injectable()
+export class HttpHelperService {
+ constructor( private sharingService: SharingService,
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig){}
+
+ public getUuidValue = (url: string): string => {
+ let map: Dictionary<string, string> = this.sharingService.getUuidMap();
+ if (map && url.indexOf(this.sdcConfig.api.root) > 0) {
+ map.forEach((key: string) => {
+ if (url.indexOf(key) !== -1) {
+ return this.sharingService.getUuidValue(key);
+ }
+ });
+ }
+ return '';
+ }
+ public static replaceUrlParams(url: string, urlParams: { [index: string]: any }): string {
+ return url.replace(/:(\w+)/g, (m, p1): string => urlParams[p1] || '');
+ }
+ public static getHeaderMd5 = (object:any):string => {
+ let componentString:string = JSON.stringify(object);
+ let md5Result = md5(componentString).toLowerCase();
+ return btoa(md5Result);
+ };
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/http.service.ts b/catalog-ui/src/app/ng2/services/http.service.ts
deleted file mode 100644
index 2785688a..0000000
--- a/catalog-ui/src/app/ng2/services/http.service.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {Injectable, Inject} from '@angular/core';
-import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http';
-import {Observable} from 'rxjs/Observable';
-import {UUID} from 'angular2-uuid';
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/catch';
-import 'rxjs/add/observable/throw';
-import {Dictionary} from "../../utils/dictionary/dictionary";
-import {SharingService, CookieService} from "app/services";
-import { ModalService } from "app/ng2/services/modal.service";
-import { ServerErrorResponse } from "app/models";
-import {ErrorMessageComponent} from "../components/ui/modal/error-message/error-message.component";
-import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
-
-@Injectable()
-export class HttpService extends Http {
-
- constructor(backend: XHRBackend, options: RequestOptions, private sharingService: SharingService, private cookieService: CookieService, private modalService: ModalService, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
- super(backend, options);
- this._defaultOptions.withCredentials = true;
- this._defaultOptions.headers.append(cookieService.getUserIdSuffix(), cookieService.getUserId());
- }
-
- request(request:string|Request, options?:RequestOptionsArgs):Observable<Response> {
- /**
- * For every request to the server, that the service id, or resource id is sent in the URL, need to pass UUID in the header.
- * Check if the unique id exists in uuidMap, and if so get the UUID and add it to the header.
- */
- if (typeof request === 'string') { // meaning we have to add the token to the options, not in url
- if (!options) {
- // make option object
- options = {headers: new Headers()};
- }
-
- var uuidValue = this.getUuidValue(request);
- if(uuidValue!= ''){
- options.headers['X-ECOMP-ServiceID'] = uuidValue;
-
- }
- options.headers.set('X-ECOMP-RequestID', UUID.UUID());
-
- } else {
- // we have to add the token to the url object
- var uuidValue = this.getUuidValue((<Request>request).url);
- if(uuidValue!= ''){
- request.headers.set('X-ECOMP-ServiceID',uuidValue);
-
- }
- request.headers.set('X-ECOMP-RequestID', UUID.UUID());
- }
- return super.request(request, options).catch((err) => this.catchError(err));
- }
-
- private getUuidValue = (url: string) :string => {
- let map:Dictionary<string, string> = this.sharingService.getUuidMap();
- if (map && url.indexOf(this.sdcConfig.api.root) > 0) {
- map.forEach((key:string) => {
- if (url.indexOf(key) !== -1) {
- return this.sharingService.getUuidValue(key);
- }
- });
- }
- return '';
- }
-
- private catchError = (response: Response): Observable<any> => {
-
- let modalInstance = this.modalService.createErrorModal("OK");
- let errorResponse: ServerErrorResponse = new ServerErrorResponse(response);
- this.modalService.addDynamicContentToModal(modalInstance, ErrorMessageComponent, errorResponse);
- modalInstance.instance.open();
-
- return Observable.throw(response);
- };
-
- public static replaceUrlParams(url:string, urlParams:{[index:string]:any}):string {
- return url.replace(/:(\w+)/g, (m, p1):string => urlParams[p1] || '');
- }
-
-}
diff --git a/catalog-ui/src/app/ng2/services/modules.service.ts b/catalog-ui/src/app/ng2/services/modules.service.ts
new file mode 100644
index 0000000..857f071
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/modules.service.ts
@@ -0,0 +1,34 @@
+import {Inject, Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {ISdcConfig, SdcConfigToken} from "../config/sdc-config.config";
+import {DisplayModule, Module} from "../../models/modules/base-module";
+import {Observable} from "rxjs/Observable";
+import {ServerTypeUrl} from "../../utils/constants";
+
+@Injectable()
+export class ModulesService {
+
+ protected baseUrl;
+
+ constructor(private http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
+ }
+
+ getComponentInstanceModule = (topologyTemplateType: string, topologyTemplateId: string, componentInstanceId: string, moduleId: string):Observable<DisplayModule> => {
+ return this.http.get<DisplayModule>(this.baseUrl + ServerTypeUrl.toServerTypeUrl(topologyTemplateType) + "/" + topologyTemplateId + "/resourceInstance/" + componentInstanceId + "/groupInstance/" + moduleId)
+ .map((response) => {
+ return new DisplayModule(response);
+ })
+ };
+
+ getModuleForDisplay = (topologyTemplateType: string, topologyTemplateId: string, moduleId: string):Observable<DisplayModule> => {
+ return this.http.get<DisplayModule>(this.baseUrl + ServerTypeUrl.toServerTypeUrl(topologyTemplateType) + "/" + topologyTemplateId + "/groups/" + moduleId)
+ .map((response) => {
+ return new DisplayModule(response);
+ })
+ };
+
+ public updateModuleMetadata = (topologyTemplateType: string, topologyTemplateId: string, module: Module):Observable<Module> => {
+ return this.http.put<Module>(this.baseUrl + ServerTypeUrl.toServerTypeUrl(topologyTemplateType) + "/" + topologyTemplateId + "/groups/" + module.uniqueId + "/metadata", module)
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/services/onboarding.service.ts b/catalog-ui/src/app/ng2/services/onboarding.service.ts
new file mode 100644
index 0000000..0ec4875
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/onboarding.service.ts
@@ -0,0 +1,151 @@
+/**
+ * Created by rc2122 on 6/4/2018.
+ */
+/*-
+ * ============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=========================================================
+ */
+
+'use strict';
+import {Inject, Injectable} from "@angular/core";
+import {SdcConfigToken, ISdcConfig} from "app/ng2/config/sdc-config.config";
+import {Observable} from "rxjs/Observable";
+import { HttpClient, HttpResponse } from "@angular/common/http";
+import { ComponentFactory } from "../../utils/component-factory";
+import { DEFAULT_ICON, ComponentType } from "../../utils/constants";
+import { ICsarComponent } from "../../models/csar-component";
+import { IApi } from "../../models/app-config";
+import { CacheService } from "./cache.service";
+import { IComponentMetadata, ComponentMetadata } from "../../models/component-metadata";
+import { IMainCategory, ISubCategory } from "../../models/category";
+import { Resource } from "../../models/components/resource";
+
+export interface OnboardingComponents {
+ listCount: number;
+ results: Array<ICsarComponent>
+}
+
+@Injectable()
+export class OnboardingService {
+ private api:IApi;
+
+ constructor(protected http: HttpClient,
+ private cacheService:CacheService,
+ @Inject(SdcConfigToken) sdcConfig:ISdcConfig,
+ private componentFactory: ComponentFactory) {
+ this.api = sdcConfig.api;
+ }
+
+ getOnboardingVSPs = (): Observable<Array<ICsarComponent>> =>{
+ return this.http.get<OnboardingComponents>(this.api.GET_onboarding).map((onboardingVSPs) =>{
+ return onboardingVSPs.results
+ });
+ }
+
+ getOnboardingComponents = ():Observable<Array<IComponentMetadata>> => {
+ return this.getOnboardingVSPs().map((onboardingComponents) => {
+ let componentsMetadataList: Array<IComponentMetadata> = new Array();
+ onboardingComponents.forEach((obc:ICsarComponent) => {
+ let componentMetaData: ComponentMetadata = this.createFromCsarComponent(obc);
+ componentsMetadataList.push(componentMetaData);
+ });
+ return componentsMetadataList;
+ });
+ };
+
+ public createFromCsarComponent = (csar:ICsarComponent): ComponentMetadata => {
+ let newMetadata = new ComponentMetadata();
+ newMetadata.name = csar.vspName;
+
+ /**
+ * Onboarding CSAR contains category and sub category that are uniqueId.
+ * Need to find the category and sub category and extract the name from them.
+ * First concat all sub categories to one array.
+ * Then find the selected sub category and category.
+ * @type {any}
+ */
+ let availableCategories = angular.copy(this.cacheService.get('resourceCategories'));
+ let allSubs = [];
+ _.each(availableCategories, (main:IMainCategory)=> {
+ if (main.subcategories) {
+ allSubs = allSubs.concat(main.subcategories);
+ }
+ });
+
+ let selectedCategory:IMainCategory = _.find(availableCategories, function (main:IMainCategory) {
+ return main.uniqueId === csar.category;
+ });
+
+ let selectedSubCategory:ISubCategory = _.find(allSubs, (sub:ISubCategory)=> {
+ return sub.uniqueId === csar.subCategory;
+ });
+
+ // Build the categories and sub categories array (same format as component category)
+ let categories:Array<IMainCategory> = new Array();
+ let subcategories:Array<ISubCategory> = new Array();
+ if (selectedCategory && selectedSubCategory) {
+ subcategories.push(selectedSubCategory);
+ selectedCategory.subcategories = subcategories;
+ categories.push(selectedCategory);
+ }
+
+ // Fill the component with details from CSAR
+
+ newMetadata.categories = categories;
+ newMetadata.vendorName = csar.vendorName;
+ newMetadata.vendorRelease = csar.vendorRelease;
+ newMetadata.csarUUID = csar.packageId;
+ newMetadata.csarPackageType = csar.packageType;
+ newMetadata.csarVersion = csar.version;
+ newMetadata.packageId = csar.packageId;
+ newMetadata.description = csar.description;
+ newMetadata.selectedCategory = selectedCategory && selectedSubCategory ? selectedCategory.name + "_#_" + selectedSubCategory.name : '';
+ newMetadata.filterTerm = newMetadata.name + ' ' + newMetadata.description + ' ' + newMetadata.vendorName + ' ' + newMetadata.csarVersion;
+ newMetadata.resourceType = "VF";
+ newMetadata.componentType = ComponentType.RESOURCE;
+ newMetadata.tags = [];
+ newMetadata.icon = DEFAULT_ICON;
+ newMetadata.iconSprite = "sprite-resource-icons";
+ return newMetadata;
+ };
+
+ downloadOnboardingCsar = (packageId:string):Observable<HttpResponse<Blob>> => {
+ return this.http.get(this.api.GET_onboarding + "/" + packageId, {observe: 'response', responseType: 'blob'});
+ };
+
+ getComponentFromCsarUuid = (csarUuid:string):Observable<ComponentMetadata> => {
+ return this.http.get<ComponentMetadata>(this.api.root + this.api.GET_component_from_csar_uuid.replace(':csar_uuid', csarUuid))
+ .map((response: any) => {
+ // If the status is 400, this means that the component not found.
+ // I do not want to return error from server, because a popup will appear in client with the error.
+ // So returning success (200) with status 400.
+ if (response.status !== 400) {
+ let componentMetadata = new ComponentMetadata();
+ componentMetadata = response;
+ return componentMetadata;
+ }
+ });
+ };
+
+ //TODO remove when workspace page convert to angular5
+ convertMetaDataToComponent(componentMetadata: ComponentMetadata) {
+ let newResource: Resource = <Resource>this.componentFactory.createEmptyComponent(ComponentType.RESOURCE);
+ newResource.setComponentMetadata(componentMetadata);
+ return newResource;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/services/plugins.service.ts b/catalog-ui/src/app/ng2/services/plugins.service.ts
index 2a3b68f..0f71eee 100644
--- a/catalog-ui/src/app/ng2/services/plugins.service.ts
+++ b/catalog-ui/src/app/ng2/services/plugins.service.ts
@@ -1,40 +1,40 @@
-import { Injectable, Inject } from '@angular/core';
+import {Inject, Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Http, Response} from '@angular/http';
-import {IApi, IAppConfigurtaion, Plugin, Plugins, PluginsConfiguration} from "app/models";
+import {IApi, IAppConfigurtaion, Plugin, PluginsConfiguration} from "app/models";
import {ISdcConfig, SdcConfigToken} from "../config/sdc-config.config";
@Injectable()
export class PluginsService {
- private baseUrl;
public configuration: IAppConfigurtaion;
public api: IApi;
+ private baseUrl;
- constructor(private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
+ constructor(private http: Http, @Inject(SdcConfigToken) private sdcConfig: ISdcConfig) {
this.api = this.sdcConfig.api;
this.baseUrl = this.api.root + this.sdcConfig.api.component_api_root;
}
public getPluginByStateUrl = (stateUrl: string) => {
- let pluginKey: any = _.findKey(PluginsConfiguration.plugins, (pluginConfig: Plugin) =>{
- return pluginConfig.pluginStateUrl === stateUrl;
+ let pluginKey: any = _.findKey(PluginsConfiguration.plugins, (pluginConfig: Plugin) => {
+ return pluginConfig.pluginStateUrl === stateUrl;
});
return PluginsConfiguration.plugins[pluginKey];
};
- public isPluginDisplayedInContext = (plugin: Plugin ,userRole: string, contextType: string) => {
+ public isPluginDisplayedInContext = (plugin: Plugin, userRole: string, contextType: string) => {
return plugin.pluginDisplayOptions["context"] &&
- plugin.pluginDisplayOptions["context"].displayRoles.includes(userRole) &&
- plugin.pluginDisplayOptions["context"].displayContext.indexOf(contextType) !== -1
+ plugin.pluginDisplayOptions["context"].displayRoles.includes(userRole) &&
+ plugin.pluginDisplayOptions["context"].displayContext.indexOf(contextType) !== -1
};
public isPluginOnline = (pluginId: string): Observable<boolean> => {
- let url:string = this.api.no_proxy_root + this.api.GET_plugin_online_state.replace(':pluginId', pluginId);
+ let url: string = this.api.no_proxy_root + this.api.GET_plugin_online_state.replace(':pluginId', pluginId);
return this.http.get(url).map((res: Response) => {
return res.json()
})
- .catch(error => Observable.of(false));
+ .catch(error => Observable.of(false));
}
}
diff --git a/catalog-ui/src/app/ng2/services/policies.service.ts b/catalog-ui/src/app/ng2/services/policies.service.ts
index 3675a7b..a1a9013 100644
--- a/catalog-ui/src/app/ng2/services/policies.service.ts
+++ b/catalog-ui/src/app/ng2/services/policies.service.ts
@@ -20,13 +20,13 @@
import {Injectable, Inject} from "@angular/core";
import {Observable} from "rxjs/Observable";
-import {HttpService} from "./http.service";
import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
import {PolicyInstance, PolicyTargetsRequest} from '../../models/graph/zones/policy-instance';
import {IZoneInstanceAssignment} from "../../models/graph/zones/zone-instance";
import {IZoneService} from "../../models/graph/zones/zone";
import {TargetUiObject} from "../../models/ui-models/ui-target-object";
import {TargetOrMemberType} from "../../utils/constants";
+import { HttpClient } from "@angular/common/http";
@Injectable()
@@ -38,14 +38,12 @@
'SERVICE': 'services'
}
- constructor(private http:HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
+ constructor(private http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
this.baseUrl = sdcConfig.api.root;
}
- public createPolicyInstance(topologyTemplateType:string, topologyTemplateId:string, policyType:string) {
- return this.http.post(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyType, {}).map(resp => {
- return resp.json();
- });
+ public createPolicyInstance(topologyTemplateType:string, topologyTemplateId:string, policyType:string): Observable<PolicyInstance> {
+ return this.http.post<PolicyInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyType, {});
}
public addPolicyTarget(topologyTemplateType:string, topologyTemplateId:string, policy:PolicyInstance, targetId:string, targetType:TargetOrMemberType) {
@@ -76,8 +74,8 @@
}
public updatePolicyTargets(topologyTemplateType:string, topologyTemplateId:string, policyId:string, targets:PolicyTargetsRequest): Observable<PolicyInstance> {
- return this.http.post(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId + '/targets', targets.requestItems)
- .map(response => new PolicyInstance(response.json()));
+ return this.http.post<PolicyInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId + '/targets', targets.requestItems)
+ .map(response => new PolicyInstance(response));
}
public updateTargets(topologyTemplateType:string, topologyTemplateId:string, policyId:string, targets:Array<TargetUiObject>):Observable<PolicyInstance> {
@@ -94,22 +92,18 @@
}
public getSpecificPolicy(topologyTemplateType:string, topologyTemplateId:string, policyId:string):Observable<PolicyInstance> {
- return this.http.get(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId)
+ return this.http.get<PolicyInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId)
.map(res => {
- return new PolicyInstance(res.json());
+ return new PolicyInstance(res);
});
}
public updateName(topologyTemplateType:string, topologyTemplateId:string, policyId:string, newName:string):Observable<any> {
- return this.http.put(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId, {name: newName}).map(res => {
- return res.json();
- });
+ return this.http.put<PolicyInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId, {name: newName});
};
public deletePolicy(topologyTemplateType:string, topologyTemplateId:string, policyId:string) {
- return this.http.delete(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId).map(resp => {
- return resp.json();
- });
+ return this.http.delete<PolicyInstance>(this.baseUrl + '/v1/catalog/' + this.mapApiDirections[topologyTemplateType.toUpperCase()] + '/' + topologyTemplateId + '/policies/' + policyId);
};
public updateZoneInstanceAssignments(topologyTemplateType:string, topologyTemplateId:string, policyId:string, targets:Array<IZoneInstanceAssignment>):Observable<PolicyInstance>{
diff --git a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
index d297ea0..f161bab 100644
--- a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
+++ b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
@@ -22,12 +22,15 @@
* Created by ob0695 on 4/18/2017.
*/
-import { ArtifactGroupModel, PropertyModel, PropertiesGroup, InputsGroup, AttributeModel, AttributesGroup, ComponentInstance, OperationModel,
- InputBEModel, Module, ComponentMetadata, RelationshipModel, RequirementsGroup, CapabilitiesGroup, InterfaceModel} from "app/models";
+import { ArtifactGroupModel, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance, OperationModel,
+ InputBEModel, Module, ComponentMetadata, RelationshipModel, RequirementsGroup, CapabilitiesGroup} from "app/models";
import {CommonUtils} from "app/utils";
import {Serializable} from "../utils/serializable";
+import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model";
import { PolicyInstance } from "app/models/graph/zones/policy-instance";
import { GroupInstance } from "../../../models/graph/zones/group-instance";
+import { InputsGroup } from "../../../models/inputs";
+import { InterfaceModel } from "../../../models/operation";
export class ComponentGenericResponse implements Serializable<ComponentGenericResponse> {
@@ -40,7 +43,7 @@
public componentInstancesAttributes:AttributesGroup;
public componentInstancesRelations:Array<RelationshipModel>;
public componentInstances:Array<ComponentInstance>;
- public componentInstancesInterfaces:Map<string,Array<InterfaceModel>>;
+ public componentInstancesInterfaces: Map<string, Array<InterfaceModel>>;
public inputs:Array<InputBEModel>;
public capabilities:CapabilitiesGroup;
public requirements:RequirementsGroup;
@@ -75,7 +78,7 @@
if(response.deploymentArtifacts) {
this.deploymentArtifacts = new ArtifactGroupModel(response.deploymentArtifacts);
}
- if(response.inputs) {
+ if(response.inputs) {
this.inputs = CommonUtils.initInputs(response.inputs);
}
if(response.attributes) {
@@ -97,10 +100,9 @@
this.toscaArtifacts = new ArtifactGroupModel(response.toscaArtifacts);
}
if(response.interfaces) {
- this.interfaces = CommonUtils.initInterfaces(response.interfaces);
this.interfaceOperations = CommonUtils.initInterfaceOperations(response.interfaces);
}
- if(response.componentInstancesInterfaces) {
+ if (response.componentInstancesInterfaces) {
this.componentInstancesInterfaces = new Map();
for (let resourceId in response.componentInstancesInterfaces) {
this.componentInstancesInterfaces[resourceId] = CommonUtils.initInterfaces(response.componentInstancesInterfaces[resourceId]);
diff --git a/catalog-ui/src/app/ng2/services/responses/service-generic-response.ts b/catalog-ui/src/app/ng2/services/responses/service-generic-response.ts
index d32ed26..0fe8571 100644
--- a/catalog-ui/src/app/ng2/services/responses/service-generic-response.ts
+++ b/catalog-ui/src/app/ng2/services/responses/service-generic-response.ts
@@ -2,12 +2,15 @@
import {Serializable} from "../utils/serializable";
import {ComponentGenericResponse} from "./component-generic-response";
import {ForwardingPath} from "../../../models/forwarding-path";
+import {ArtifactGroupModel} from "../../../models/artifacts";
export class ServiceGenericResponse extends ComponentGenericResponse implements Serializable<ServiceGenericResponse> {
public forwardingPaths: { [key:string]:ForwardingPath } = {};
+ public serviceApiArtifacts: ArtifactGroupModel;
deserialize (response): ServiceGenericResponse {
super.deserialize(response);
+ this.serviceApiArtifacts = new ArtifactGroupModel(response.serviceApiArtifacts);
if(response.forwardingPaths) {
_.forEach(response.forwardingPaths, (pathResponse, id) => {
let pathId = id;
diff --git a/catalog-ui/src/app/services/sharing-service.ts b/catalog-ui/src/app/ng2/services/sharing.service.ts
similarity index 81%
rename from catalog-ui/src/app/services/sharing-service.ts
rename to catalog-ui/src/app/ng2/services/sharing.service.ts
index f4cc2e6..0a6b8cb 100644
--- a/catalog-ui/src/app/services/sharing-service.ts
+++ b/catalog-ui/src/app/ng2/services/sharing.service.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.
@@ -18,23 +18,25 @@
* ============LICENSE_END=========================================================
*/
-'use strict';
+import {Injectable} from "@angular/core";
import {Dictionary} from "app/utils";
+@Injectable()
export class SharingService {
-
private uuidMap:Dictionary<string, string> = new Dictionary<string,string>();
- public getUuidValue = (uniqueId:string):string => {
+ constructor() {
+ }
+
+ public getUuidValue(uniqueId:string): string {
return this.uuidMap.getValue(uniqueId);
- };
+ }
- public addUuidValue = (uniqueId:string, uuid:string):void => {
+ public addUuidValue(uniqueId:string, uuid:string): void {
this.uuidMap.setValue(uniqueId, uuid);
- };
+ }
- public getUuidMap = ():Dictionary<string, string> => {
+ public getUuidMap() :Dictionary<string, string> {
return this.uuidMap;
- };
-
+ }
}
diff --git a/catalog-ui/src/app/ng2/services/tosca-types.service.ts b/catalog-ui/src/app/ng2/services/tosca-types.service.ts
index 66826c0..83b833b 100644
--- a/catalog-ui/src/app/ng2/services/tosca-types.service.ts
+++ b/catalog-ui/src/app/ng2/services/tosca-types.service.ts
@@ -14,12 +14,19 @@
* permissions and limitations under the License.
*/
-import {Injectable, Inject} from '@angular/core';
-import {Observable} from 'rxjs/Observable';
-import {HttpService} from './http.service';
-import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
-import {CapabilityTypesMap, NodeTypesMap, RelationshipTypesMap} from "app/models";
-import {Response} from '@angular/http';
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { Response } from '@angular/http';
+import {
+ CapabilityTypeModel,
+ CapabilityTypesMap,
+ IComponentsArray,
+ NodeTypesMap,
+ RelationshipTypesMap
+} from 'app/models';
+import { Observable } from 'rxjs/Observable';
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+import 'rxjs/add/operator/toPromise';
declare var angular: angular.IAngularStatic;
@@ -28,28 +35,20 @@
protected baseUrl;
- constructor(protected http: HttpService, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root;
}
- fetchRelationshipTypes(): Observable<RelationshipTypesMap> {
- return this.http.get(this.baseUrl + 'relationshipTypes')
- .map((res: Response) => {
- return res.json();
- });
+ async fetchRelationshipTypes(): Promise<RelationshipTypesMap> {
+ return this.http.get<RelationshipTypesMap>(this.baseUrl + 'relationshipTypes').toPromise();
}
- fetchNodeTypes(): Observable<NodeTypesMap> {
- return this.http.get(this.baseUrl + 'nodeTypes')
- .map((res: Response) => {
- return res.json();
- });
+ async fetchNodeTypes(): Promise<NodeTypesMap> {
+ return this.http.get<NodeTypesMap>(this.baseUrl + 'nodeTypes').toPromise();
}
- fetchCapabilityTypes(): Observable<CapabilityTypesMap> {
- return this.http.get(this.baseUrl + 'capabilityTypes')
- .map((res: Response) => {
- return res.json();
- });
+ async fetchCapabilityTypes(): Promise<CapabilityTypesMap>{
+ return this.http.get<CapabilityTypesMap>(this.baseUrl + 'capabilityTypes').toPromise();
}
}
+
diff --git a/catalog-ui/src/app/ng2/services/user.service.ts b/catalog-ui/src/app/ng2/services/user.service.ts
index 87e9043..f4186a1 100644
--- a/catalog-ui/src/app/ng2/services/user.service.ts
+++ b/catalog-ui/src/app/ng2/services/user.service.ts
@@ -19,80 +19,34 @@
*/
import { Injectable, Inject } from "@angular/core";
-import { Headers } from "@angular/http";
import { Observable } from "rxjs/Observable";
-import { HttpService } from "./http.service";
-import { Cookie2Service } from "./cookie.service";
import { IUserProperties } from "../../models/user";
-import {ICookie} from "../../models/app-config";
import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config";
-
+import { HttpClient } from "@angular/common/http";
+import { HttpHelperService } from "./http-hepler.service";
+/**
+ * User Service provides CRUD for Users. See authentication service for authentication/login.
+ */
@Injectable()
-export class UserService {
+export class UserService {
private url:string;
- private authorizeUrl:string;
- private _loggedinUser:IUserProperties;
-
- constructor(private httpService:HttpService,
- private cookieService:Cookie2Service,
+ constructor(private http: HttpClient,
@Inject(SdcConfigToken) private sdcConfig:ISdcConfig) {
this.url = this.sdcConfig.api.root + this.sdcConfig.api.GET_user;
- this.authorizeUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize;
}
- public authorize() :Observable<IUserProperties> {
- let cookie:ICookie = this.sdcConfig.cookie;
- let authorizeHeaders:Headers = new Headers();
- authorizeHeaders.set(cookie.userFirstName, this.cookieService.getFirstName());
- authorizeHeaders.set(cookie.userLastName, this.cookieService.getLastName());
- authorizeHeaders.set(cookie.userEmail, this.cookieService.getEmail());
- authorizeHeaders.set(cookie.userIdSuffix, this.cookieService.getUserId());
-
- return this.httpService.get(
- this.authorizeUrl,
- { headers: authorizeHeaders }
- ).map(resp => resp.json());
- }
public getAllUsers() :Observable<IUserProperties[]> {
- return this.httpService.get(
+ return this.http.get(
this.sdcConfig.api.root + this.sdcConfig.api.GET_all_users
- ).map(resp => resp.json());
+ ).map(resp => <IUserProperties[]> resp) ;
}
public getUser(userId:string) :Observable<IUserProperties> {
- return this.httpService.get(
- HttpService.replaceUrlParams(this.url, { id: userId })
- ).map(resp => resp.json());
+ return this.http.get(
+ HttpHelperService.replaceUrlParams(this.url, { id: userId })
+ ).map(resp => <IUserProperties> resp);
}
-
- public createUser(userData:{[index:string]: any}) :Observable<IUserProperties> {
- return this.httpService.post(
- this.sdcConfig.api.root + this.sdcConfig.api.POST_create_user,
- userData
- ).map(resp => resp.json());
- }
-
- public deleteUser(userId:string) :Observable<IUserProperties> {
- return this.httpService.delete(
- HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.DELETE_delete_user, { id: userId })
- ).map(resp => resp.json());
- }
-
- public editUserRole(userId:string, role:string) :Observable<IUserProperties> {
- return this.httpService.post(
- HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.POST_edit_user_role, { id: userId }),
- { role: role }
- ).map(resp => resp.json());
- }
-
- public getLoggedinUser():IUserProperties {
- return this._loggedinUser;
- }
-
- public setLoggedinUser(loggedinUser:IUserProperties) {
- this._loggedinUser = loggedinUser;
- };
}
diff --git a/catalog-ui/src/app/ng2/services/workflow.service.ts b/catalog-ui/src/app/ng2/services/workflow.service.ts
index 81a2ea3..044ca37 100644
--- a/catalog-ui/src/app/ng2/services/workflow.service.ts
+++ b/catalog-ui/src/app/ng2/services/workflow.service.ts
@@ -1,14 +1,13 @@
import { Injectable, Inject } from "@angular/core";
-import { Response } from "@angular/http";
import { Observable } from "rxjs/Observable";
-import { HttpService } from "./http.service";
import { SdcConfigToken, ISdcConfig } from "../config/sdc-config.config";
+import { HttpClient } from "@angular/common/http";
import { Component, OperationModel } from "app/models";
interface WorkflowOutputParameter {
- name: string,
- type: string,
- mandatory: boolean
+ name: string;
+ type: string;
+ mandatory: boolean;
}
interface WorkflowInputParameter extends WorkflowOutputParameter {
@@ -25,40 +24,31 @@
WF_STATE_ARCHIVED = 'ARCHIVED';
VERSION_STATE_CERTIFIED = 'CERTIFIED';
- constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ constructor(private http: HttpClient, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) {
this.baseUrl = sdcConfig.api.workflow_root;
this.catalogBaseUrl = sdcConfig.api.POST_workflow_artifact;
}
public associateWorkflowArtifact(component: Component, operation: OperationModel): Observable<any> {
- return this.http.post(this.baseUrl + '/workflows/' + operation.workflowId + '/versions/' + operation.workflowVersionId + '/artifact-deliveries', {
- endpoint: this.catalogBaseUrl + '/' + component.getTypeUrl() + component.uuid + '/interfaces/' + operation.interfaceId + '/operations/' + operation.uniqueId + '/artifacts/' + operation.implementation.artifactUUID,
- method: 'POST'
- })
- .map((res:Response) => {
- return res.json();
+ return this.http.post<any>(this.baseUrl + '/workflows/' + operation.workflowId + '/versions/' + operation.workflowVersionId + '/artifact-deliveries', {
+ endpoint: this.catalogBaseUrl + '/' + component.getTypeUrl() + component.uuid + '/interfaces/' + operation.interfaceId + '/operations/'
+ + operation.uniqueId + '/artifacts/' + operation.implementation.artifactUUID, method: 'POST'
});
}
public getWorkflows(filterCertified: boolean = true): Observable<any> {
- return this.http.get(this.baseUrl + '/workflows' + (filterCertified ? '?versionState=' + this.VERSION_STATE_CERTIFIED : ''))
- .map((res:Response) => {
- return res.json().items;
- });
+ return this.http.get<any>(this.baseUrl + '/workflows' + (filterCertified ? '?versionState=' + this.VERSION_STATE_CERTIFIED : ''));
}
public getWorkflowVersions(workflowId: string, filterCertified: boolean = true): Observable<any> {
- return this.http.get(this.baseUrl + '/workflows/' + workflowId + '/versions' + (filterCertified ? '?state=' + this.VERSION_STATE_CERTIFIED : ''))
- .map((res:Response) => {
- return _.map(res.json().items, version => version);
+ return this.http.get<any>(this.baseUrl + '/workflows/' + workflowId + '/versions' + (filterCertified ? '?state=' + this.VERSION_STATE_CERTIFIED : ''))
+ .map((res) => {
+ return res.items;
});
}
public updateWorkflowVersion(workflowId: string, versionId: string, payload: any): Observable<any> {
- return this.http.put(this.baseUrl + '/workflows/' + workflowId + '/versions/' + versionId, payload)
- .map((res:Response) => {
- return res.json();
- });
+ return this.http.put<any>(this.baseUrl + '/workflows/' + workflowId + '/versions/' + versionId, payload);
}
}
diff --git a/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.html b/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.html
index bee493f..7b9a5ff 100644
--- a/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.html
+++ b/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="multiline-ellipsis-container" [ngClass]="className" [ngStyle]="stylesContainer" #multilineEllipsisContainer>
<div class="multiline-ellipsis-content" [ngStyle]="stylesContent" #multilineEllipsisContent>
<ng-content></ng-content>
diff --git a/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.ts b/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.ts
index 68cfedb..4cff9de 100644
--- a/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.ts
+++ b/catalog-ui/src/app/ng2/shared/multiline-ellipsis/multiline-ellipsis.component.ts
@@ -1,4 +1,4 @@
-import {Component, OnChanges, AfterViewChecked, ViewChild, ElementRef, Input, Output, SimpleChanges, EventEmitter} from "@angular/core";
+import {Component, OnChanges, AfterContentInit, ViewChild, ElementRef, Input, Output, SimpleChanges, EventEmitter} from "@angular/core";
import {WindowRef} from "../../services/window.service";
@Component({
@@ -6,7 +6,7 @@
templateUrl: 'multiline-ellipsis.component.html',
styleUrls: ['multiline-ellipsis.component.less']
})
-export class MultilineEllipsisComponent implements OnChanges, AfterViewChecked {
+export class MultilineEllipsisComponent implements OnChanges, AfterContentInit {
@Input() public lines: number;
@Input() public lineHeight: string;
@@ -30,7 +30,7 @@
this.prepareStyles()
}
- public ngAfterViewChecked() {
+ public ngAfterContentInit() {
const hasEllipsis = (this.elmContainer.nativeElement.offsetHeight < this.elmContent.nativeElement.offsetHeight);
if (hasEllipsis !== this.hasEllipsis) {
this.hasEllipsis = hasEllipsis;
diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts
index 4ec756b..04f6650 100644
--- a/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts
+++ b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts
@@ -19,38 +19,32 @@
*/
import { Pipe, PipeTransform } from '@angular/core';
-import { TranslateService, ITranslateArgs } from "./translate.service";
+import { ITranslateArgs, TranslateService } from './translate.service';
+// tslint:disable-next-line:interface-name
+interface ITranslateParams {
+ phrase: string;
+ args: ITranslateArgs;
+ language: string;
+}
@Pipe({
name: 'translate',
pure: false
})
export class TranslatePipe implements PipeTransform {
- private translated:string;
- private lastParams: {
- phrase: string;
- args: {[index: string]: any};
- language: string;
- } = {
+ private translated: string;
+ private lastParams: ITranslateParams = {
phrase: undefined,
args: undefined,
language: undefined
};
- constructor(private translateService:TranslateService) {
+ constructor(private translateService: TranslateService) {
}
- private shouldUpdate(curParams:{[index:string]: any}) : boolean {
- return (
- curParams.language !== this.lastParams.language ||
- curParams.args !== this.lastParams.args ||
- curParams.phrase !== this.lastParams.phrase
- );
- }
-
- public transform(phrase:string, args:ITranslateArgs, language:string=this.translateService.activeLanguage) : string {
- const curParams = { phrase, args, language };
+ public transform(phrase: string, args: ITranslateArgs, language: string = this.translateService.activeLanguage): string {
+ const curParams: ITranslateParams = { phrase, args, language };
if (this.shouldUpdate(curParams)) {
this.lastParams = curParams;
this.translated = this.translateService.translate(phrase, args, language);
@@ -58,4 +52,12 @@
return this.translated;
}
+
+ private shouldUpdate(curParams: ITranslateParams): boolean {
+ return (
+ curParams.language !== this.lastParams.language ||
+ curParams.args !== this.lastParams.args ||
+ curParams.phrase !== this.lastParams.phrase
+ );
+ }
}
diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts
index a1d7833..6413f6a 100644
--- a/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts
+++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts
@@ -18,9 +18,9 @@
* ============LICENSE_END=========================================================
*/
-import { OpaqueToken } from "@angular/core";
+import { InjectionToken } from "@angular/core";
-export const TranslateServiceConfigToken = new OpaqueToken('TranslateServiceConfigToken');
+export const TranslateServiceConfigToken = new InjectionToken('TranslateServiceConfigToken');
export interface ITranslateServiceConfig {
filePrefix:string;
diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts
index ff7c643..0b5ddae 100644
--- a/catalog-ui/src/app/ng2/shared/translator/translate.service.ts
+++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts
@@ -19,9 +19,9 @@
*/
import { Injectable, Inject } from "@angular/core";
-import { Response, Http } from "@angular/http";
-import { Observable, Observer, ConnectableObservable, Subscription } from "rxjs";
import { ITranslateServiceConfig, TranslateServiceConfigToken } from "./translate.service.config";
+import { Observer, Subscription, Observable, ConnectableObservable } from 'rxjs/Rx';
+import { HttpClient } from "@angular/common/http";
export { ITranslateServiceConfig, TranslateServiceConfigToken };
@@ -145,7 +145,7 @@
private _cacheLanguagesJsons:{[index:string]:ITranslateLanguageJson} = {};
private _cacheLanguagesLoaders:{[index:string]:Observable<ITranslateLanguageJson>} = {};
- constructor(@Inject(TranslateServiceConfigToken) private config:ITranslateServiceConfig, private http:Http) {
+ constructor(@Inject(TranslateServiceConfigToken) private config:ITranslateServiceConfig, private http: HttpClient) {
this.initLanguageObservable();
this.loadAndActivateLanguage(this.config.defaultLanguage);
}
@@ -176,8 +176,7 @@
if (!(language in this._cacheLanguagesLoaders)) {
const filePath = `${this.config.filePrefix}${language}${this.config.fileSuffix}`;
- this._cacheLanguagesLoaders[language] = this.http.get(filePath)
- .map<Response, ITranslateLanguageJson>(resp => resp.json())
+ this._cacheLanguagesLoaders[language] = this.http.get<ITranslateLanguageJson>(filePath)
.catch(() => Observable.throw(`Failed to load language file for "${language}"`))
.publish();
(<ConnectableObservable<ITranslateLanguageJson>>this._cacheLanguagesLoaders[language]).connect();
@@ -204,12 +203,12 @@
return false;
}
- public loadAndActivateLanguage(language:string) : Observable<ITranslateLanguageJson> {
+ public loadAndActivateLanguage(language:string) : void {
+
const loadLanguageObservable = this.loadLanguageJsonFile(language, false);
loadLanguageObservable.subscribe(() => {
this.activateLanguage(language);
}, () => {});
- return loadLanguageObservable;
}
public translate(phraseKey:string, args:ITranslateArgs={}, language:string=this._activeLanguage) : string {
diff --git a/catalog-ui/src/app/ng2/store/actions/artifacts.action.ts b/catalog-ui/src/app/ng2/store/actions/artifacts.action.ts
new file mode 100644
index 0000000..a00cc3a
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/actions/artifacts.action.ts
@@ -0,0 +1,25 @@
+/**
+ * Created by ob0695
+ */
+import {ArtifactModel} from "../../../models/artifacts";
+
+export class GetArtifactsByTypeAction {
+ static readonly type = '[ARTIFACTS] GetArtifactsByType';
+
+ constructor(public payload: {componentType:string, componentId:string, artifactType: string}) {
+ }
+}
+
+export class CreateOrUpdateArtifactAction {
+ static readonly type = '[ARTIFACTS] CreateOrUpdateArtifactAction';
+
+ constructor(public payload: {componentType:string, componentId:string, artifact:ArtifactModel}) {
+ }
+}
+
+export class DeleteArtifactAction {
+ static readonly type = '[ARTIFACTS] DeleteArtifactAction';
+
+ constructor(public payload: {componentType:string, componentId:string, artifact: ArtifactModel}) {
+ }
+}
diff --git a/catalog-ui/src/app/ng2/store/actions/instance-artifacts.actions.ts b/catalog-ui/src/app/ng2/store/actions/instance-artifacts.actions.ts
new file mode 100644
index 0000000..0f1df78
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/actions/instance-artifacts.actions.ts
@@ -0,0 +1,32 @@
+/**
+ * Created by ob0695
+ */
+import {ArtifactModel} from "../../../models/artifacts";
+
+export class GetInstanceArtifactsByTypeAction {
+ static readonly type = '[INSTANCE_ARTIFACTS] GetInstanceArtifactsByTypeAction';
+
+ constructor(public payload: { componentType: string, componentId: string, artifactType: string, instanceId: string }) {
+ }
+}
+
+export class CreateInstanceArtifactAction {
+ static readonly type = '[INSTANCE_ARTIFACTS] CreateInstanceArtifactAction';
+
+ constructor(public payload: { componentType: string, componentId: string, instanceId: string, artifact: ArtifactModel }) {
+ }
+}
+
+export class UpdateInstanceArtifactAction {
+ static readonly type = '[INSTANCE_ARTIFACTS] UpdateInstanceArtifactAction';
+
+ constructor(public payload: { componentType: string, componentId: string, instanceId: string, artifact: ArtifactModel }) {
+ }
+}
+
+export class DeleteInstanceArtifactAction {
+ static readonly type = '[INSTANCE_ARTIFACTS] DeleteInstanceArtifactAction';
+
+ constructor(public payload: { componentType: string, componentId: string, instanceId: string, artifact: ArtifactModel }) {
+ }
+}
diff --git a/catalog-ui/src/app/ng2/store/actions/workspace.action.ts b/catalog-ui/src/app/ng2/store/actions/workspace.action.ts
new file mode 100644
index 0000000..c7f18e0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/actions/workspace.action.ts
@@ -0,0 +1,17 @@
+/**
+ * Created by ob0695 on 7/17/2018.
+ */
+
+export class UpdateIsViewOnly {
+ static readonly type = '[WORKSPACE] UpdateIsViewOnly';
+
+ constructor(public isViewOnly:boolean) {
+ }
+}
+
+export class UpdateIsDesigner {
+ static readonly type = '[WORKSPACE] UpdateIsDesigner';
+
+ constructor(public isDesigner:boolean) {
+ }
+}
diff --git a/catalog-ui/src/app/ng2/store/states/artifacts.state.spec.ts b/catalog-ui/src/app/ng2/store/states/artifacts.state.spec.ts
new file mode 100644
index 0000000..c59a445
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/states/artifacts.state.spec.ts
@@ -0,0 +1,62 @@
+import { Store } from '@ngxs/store';
+import { Observable } from 'rxjs/Rx';
+import { Mock } from 'ts-mockery';
+import { ArtifactModel } from '../../../models/artifacts';
+import { ArtifactGroupType } from '../../../utils/constants';
+import { ComponentInstanceServiceNg2 } from '../../services/component-instance-services/component-instance.service';
+import { GetInstanceArtifactsByTypeAction, UpdateInstanceArtifactAction } from '../actions/instance-artifacts.actions';
+import { InstanceArtifactsState } from './instance-artifacts.state';
+
+describe('Test Artifact State', () => {
+
+ const heat1 = Mock.of<ArtifactModel>({
+ uniqueId: '1', artifactName: 'heat1', timeout: 0, artifactDisplayName: 'heat1', artifactGroupType: ArtifactGroupType.DEPLOYMENT
+ });
+
+ const heat1env = Mock.of<ArtifactModel>({
+ uniqueId: '2', artifactName: 'heat1env', timeout: 0, generatedFromId: '1', artifactDisplayName: 'heat1env', artifactGroupType: ArtifactGroupType.DEPLOYMENT
+ });
+
+ const storeMock = Mock.of<Store>( { dispatch : jest.fn() });
+
+ const artifacts = [
+ heat1,
+ heat1env
+ ];
+
+ /**
+ * NGXS Store state before we run the update
+ */
+ const ngxsState = {
+ deploymentArtifacts : artifacts
+ };
+
+ /**
+ * The ENV artifact that we wish to update
+ */
+ const updatedArtifact = Mock.of<ArtifactModel>({
+ uniqueId: '2', artifactName: 'heat1env', timeout: 33, generatedFromId: '1', artifactDisplayName: 'heat1env-UPDATE', artifactGroupType: ArtifactGroupType.DEPLOYMENT
+ });
+
+ const componentInstanceServiceMock: ComponentInstanceServiceNg2 = Mock.of<ComponentInstanceServiceNg2>({
+ updateInstanceArtifact: jest.fn().mockImplementation(() => Observable.of(updatedArtifact)),
+ getComponentInstanceArtifactsByGroupType: jest.fn().mockImplementation(() => Observable.of([heat1, updatedArtifact]))
+ });
+
+ const actionMock: UpdateInstanceArtifactAction = Mock.of<UpdateInstanceArtifactAction>({
+ payload: {
+ componentType: '',
+ componentId: '',
+ instanceId: '',
+ artifact: updatedArtifact
+ }
+ });
+
+ it('Test that HEAT timeout is updated', () => {
+ const state: InstanceArtifactsState = new InstanceArtifactsState(storeMock, componentInstanceServiceMock);
+ const context = { getState: jest.fn().mockImplementation(() => ngxsState), patchState: jest.fn(), setState: jest.fn(), dispatch: jest.fn() };
+ state.updateArtifact(context, actionMock ).subscribe( (v) => console.log('OK'));
+ expect(storeMock.dispatch).toBeCalled();
+ });
+
+});
diff --git a/catalog-ui/src/app/ng2/store/states/artifacts.state.ts b/catalog-ui/src/app/ng2/store/states/artifacts.state.ts
new file mode 100644
index 0000000..64efbe9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/states/artifacts.state.ts
@@ -0,0 +1,140 @@
+/**
+ * Created by ob0695 on 7/17/2018.
+ */
+import { Action, Selector, State, StateContext } from '@ngxs/store';
+import * as _ from 'lodash';
+import { tap } from 'rxjs/operators';
+import { ArtifactModel } from '../../../models/artifacts';
+import { ArtifactGroupType } from '../../../utils/constants';
+import { TopologyTemplateService } from '../../services/component-services/topology-template.service';
+import { ComponentGenericResponse } from '../../services/responses/component-generic-response';
+import { ServiceGenericResponse } from '../../services/responses/service-generic-response';
+import { CreateOrUpdateArtifactAction, DeleteArtifactAction, GetArtifactsByTypeAction } from '../actions/artifacts.action';
+
+export interface ArtifactsStateModel {
+ artifacts: ArtifactModel[];
+ deploymentArtifacts: ArtifactModel[];
+ toscaArtifacts: ArtifactModel[];
+ serviceApiArtifacts: ArtifactModel[];
+}
+
+@State<ArtifactsStateModel>({
+ name: 'artifacts',
+ defaults: {
+ artifacts: [],
+ deploymentArtifacts: [],
+ toscaArtifacts: [],
+ serviceApiArtifacts: []
+ }
+})
+
+export class ArtifactsState {
+
+ constructor(protected topologyTemplateService: TopologyTemplateService) {
+ }
+
+ @Selector()
+ static getEnvArtifact(state: ArtifactsStateModel, heatEnvArtifact: ArtifactModel) {
+ return (heatEnvArtifact: ArtifactModel) => {
+ _.find(state.deploymentArtifacts, (artifact)=> {
+ return artifact.generatedFromId === heatEnvArtifact.uniqueId
+ })
+ };
+ }
+
+ @Selector()
+ static getArtifactsByType(state: ArtifactsStateModel, type: string) {
+ return (type: string) => {
+ switch (type) {
+ case ArtifactGroupType.TOSCA:
+ return state.toscaArtifacts;
+ case ArtifactGroupType.INFORMATION:
+ return state.artifacts;
+ case ArtifactGroupType.DEPLOYMENT:
+ return state.deploymentArtifacts;
+ case ArtifactGroupType.SERVICE_API:
+ return state.serviceApiArtifacts;
+ }
+ };
+ }
+
+ private updateArtifactState = (artifactsState: ArtifactModel[], artifactToUpdate: ArtifactModel, updatedArtifact: ArtifactModel) => {
+ if (!artifactToUpdate.uniqueId) { // Create Artifact
+ return [...artifactsState, updatedArtifact]
+ } else { // Update Artifact
+ let artifactToUpdateIndex = _.findIndex(artifactsState, (artifact) => {
+ return artifact.uniqueId === artifactToUpdate.uniqueId
+ })
+ let artifacts = Array.from(artifactsState);
+ artifacts[artifactToUpdateIndex] = updatedArtifact;
+ return [...artifacts];
+ }
+ }
+
+ @Action(GetArtifactsByTypeAction)
+ getArtifactsByType({getState, patchState}: StateContext<ArtifactsStateModel>, action: GetArtifactsByTypeAction) {
+ const state = getState();
+ return this.topologyTemplateService.getArtifactsByType(action.payload.componentType, action.payload.componentId, action.payload.artifactType)
+ .pipe(tap((resp: ComponentGenericResponse) => {
+ switch (action.payload.artifactType) {
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: <ArtifactModel[]>_.values(resp.artifacts)
+ });
+
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: <ArtifactModel[]>_.values(resp.deploymentArtifacts)
+ });
+
+ case ArtifactGroupType.TOSCA:
+ patchState({
+ toscaArtifacts: <ArtifactModel[]>_.values(resp.toscaArtifacts)
+ });
+
+ case ArtifactGroupType.SERVICE_API:
+ patchState({
+ serviceApiArtifacts: <ArtifactModel[]>_.values((<ServiceGenericResponse>resp).serviceApiArtifacts)
+ });
+ }
+ }));
+ }
+
+ @Action(CreateOrUpdateArtifactAction)
+ createOrUpdateArtifact({getState, patchState}: StateContext<ArtifactsStateModel>, action: CreateOrUpdateArtifactAction) {
+ const state = getState();
+ return this.topologyTemplateService.addOrUpdateArtifact(action.payload.componentType, action.payload.componentId, action.payload.artifact)
+ .pipe(tap((resp: ArtifactModel) => {
+
+ switch (resp.artifactGroupType) {
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: this.updateArtifactState(state.deploymentArtifacts, action.payload.artifact, resp)
+ });
+
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: this.updateArtifactState(state.artifacts, action.payload.artifact, resp)
+ });
+ }
+ }));
+ }
+
+ @Action(DeleteArtifactAction)
+ deleteArtifact({getState, patchState}: StateContext<ArtifactsStateModel>, action: DeleteArtifactAction) {
+ const state = getState();
+ return this.topologyTemplateService.deleteArtifact(action.payload.componentId, action.payload.componentType, action.payload.artifact.uniqueId, action.payload.artifact.artifactLabel)
+ .pipe(tap((resp: ArtifactModel) => {
+ switch (resp.artifactGroupType) {
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: state.deploymentArtifacts.filter(({uniqueId}) => uniqueId !== action.payload.artifact.uniqueId)
+ });
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: state.artifacts.filter(({uniqueId}) => uniqueId !== action.payload.artifact.uniqueId)
+ });
+ }
+ }));
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/store/states/instance-artifacts.state.ts b/catalog-ui/src/app/ng2/store/states/instance-artifacts.state.ts
new file mode 100644
index 0000000..12ba1ae
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/states/instance-artifacts.state.ts
@@ -0,0 +1,145 @@
+/**
+ * Created by ob0695 on 7/17/2018.
+ */
+import { Action, Selector, State, StateContext, Store } from '@ngxs/store';
+import * as _ from 'lodash';
+import { tap } from 'rxjs/operators';
+import { ArtifactModel } from '../../../models/artifacts';
+import { ArtifactGroupType } from '../../../utils/constants';
+import { ComponentInstanceServiceNg2 } from '../../services/component-instance-services/component-instance.service';
+import { ComponentGenericResponse } from '../../services/responses/component-generic-response';
+import {
+ CreateInstanceArtifactAction,
+ DeleteInstanceArtifactAction,
+ GetInstanceArtifactsByTypeAction,
+ UpdateInstanceArtifactAction
+} from '../actions/instance-artifacts.actions';
+import { ArtifactsStateModel } from './artifacts.state';
+
+export interface InstanceArtifactsStateModel {
+ artifacts: ArtifactModel[];
+ deploymentArtifacts: ArtifactModel[];
+}
+
+@State<InstanceArtifactsStateModel>({
+ name: 'instance_artifacts',
+ defaults: {
+ artifacts: [],
+ deploymentArtifacts: []
+ }
+})
+export class InstanceArtifactsState {
+
+ constructor(private store: Store, protected componentInstanceService: ComponentInstanceServiceNg2) {
+ }
+
+ @Selector()
+ static getArtifactsByType(state: InstanceArtifactsStateModel) {
+ return (type: string) => {
+ switch (type) {
+ case ArtifactGroupType.INFORMATION:
+ return state.artifacts;
+ case ArtifactGroupType.DEPLOYMENT:
+ return state.deploymentArtifacts;
+ }
+ };
+ }
+
+ @Action(GetInstanceArtifactsByTypeAction)
+ getInstanceArtifactsByType({getState, patchState}: StateContext<InstanceArtifactsStateModel>, action: GetInstanceArtifactsByTypeAction) {
+ const state = getState();
+ return this.componentInstanceService.getComponentInstanceArtifactsByGroupType(action.payload.componentType, action.payload.componentId, action.payload.instanceId, action.payload.artifactType)
+ .pipe(tap((resp: ComponentGenericResponse) => {
+ switch (action.payload.artifactType) {
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: _.values(resp) as ArtifactModel[]
+ });
+ break;
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: _.values(resp) as ArtifactModel[]
+ });
+ break;
+ }
+ }));
+ }
+
+ @Action(CreateInstanceArtifactAction)
+ createArtifact({getState, patchState}: StateContext<ArtifactsStateModel>, action: CreateInstanceArtifactAction) {
+ const state = getState();
+ return this.componentInstanceService.addInstanceArtifact(action.payload.componentType, action.payload.componentId, action.payload.instanceId, action.payload.artifact)
+ .pipe(tap((resp: ArtifactModel) => {
+ switch (resp.artifactGroupType) {
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: [...state.deploymentArtifacts, resp]
+ });
+ break;
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: [...state.artifacts, resp]
+ });
+ break;
+ }
+ }));
+ }
+
+ @Action(UpdateInstanceArtifactAction)
+ updateArtifact({getState, patchState}: StateContext<ArtifactsStateModel>, action: UpdateInstanceArtifactAction) {
+ const state = getState();
+ return this.componentInstanceService.updateInstanceArtifact(action.payload.componentType, action.payload.componentId, action.payload.instanceId, action.payload.artifact)
+ .pipe(tap((resp: ArtifactModel) => {
+ switch (resp.artifactGroupType) {
+ case ArtifactGroupType.DEPLOYMENT:
+ // We cannot simply update the updated artifact state because updating a deployment ENV file may cause an update to his parent HEAT
+ // file.
+ // Just dispatch an action to refresh the deployment artifacts list
+ this.store.dispatch(new GetInstanceArtifactsByTypeAction(({
+ componentType: action.payload.componentType,
+ componentId: action.payload.componentId,
+ instanceId: action.payload.instanceId,
+ artifactType: ArtifactGroupType.DEPLOYMENT
+ })));
+ break;
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: this.updateInstanceArtifactState(state.artifacts, action.payload.artifact, resp)
+ });
+ break;
+ }
+ }));
+ }
+
+ @Action(DeleteInstanceArtifactAction)
+ deleteInstanceArtifact({getState, patchState}: StateContext<ArtifactsStateModel>, action: DeleteInstanceArtifactAction) {
+ const state = getState();
+ return this.componentInstanceService.
+ deleteInstanceArtifact(action.payload.componentId, action.payload.componentType, action.payload.instanceId, action.payload.artifact.uniqueId, action.payload.artifact.artifactLabel)
+ .pipe(tap((resp: ArtifactModel) => {
+ switch (resp.artifactGroupType) {
+ case ArtifactGroupType.DEPLOYMENT:
+ patchState({
+ deploymentArtifacts: state.deploymentArtifacts.filter(({uniqueId}) => uniqueId !== action.payload.artifact.uniqueId)
+ });
+ break;
+ case ArtifactGroupType.INFORMATION:
+ patchState({
+ artifacts: state.artifacts.filter(({uniqueId}) => uniqueId !== action.payload.artifact.uniqueId)
+ });
+ break;
+ }
+ }));
+ }
+
+ private updateInstanceArtifactState = (artifactsState: ArtifactModel[], artifactToUpdate: ArtifactModel, updatedArtifact: ArtifactModel) => {
+ const artifactToUpdateIndex = _.findIndex(artifactsState, (artifact) => {
+ return artifact.uniqueId === artifactToUpdate.uniqueId;
+ });
+ const artifacts = Array.from(artifactsState);
+ artifacts[artifactToUpdateIndex] = updatedArtifact;
+ const ret = [...artifacts];
+ return ret;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/store/states/workspace.state.ts b/catalog-ui/src/app/ng2/store/states/workspace.state.ts
new file mode 100644
index 0000000..eb8200f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/store/states/workspace.state.ts
@@ -0,0 +1,48 @@
+/**
+ * Created by ob0695 on 7/17/2018.
+ */
+import {State, Action, StateContext} from '@ngxs/store';
+import {UpdateIsDesigner, UpdateIsViewOnly} from "../actions/workspace.action";
+import {Selector} from "@ngxs/store";
+
+export interface WorkspaceStateModel {
+ isViewOnly: boolean;
+ isDesigner: boolean;
+}
+
+@State<WorkspaceStateModel>({
+ name: 'workspace',
+ defaults: {
+ isViewOnly: false,
+ isDesigner: true
+ }
+})
+
+export class WorkspaceState {
+
+ constructor(){}
+
+ @Selector() static isViewOnly(state: WorkspaceStateModel):boolean {
+ return state.isViewOnly;
+ }
+ @Selector() static isDesigner(state: WorkspaceStateModel): boolean {
+ return state.isDesigner;
+ }
+
+ @Action(UpdateIsViewOnly)
+ updateIsViewOnly({getState, setState}: StateContext<WorkspaceStateModel>, action:UpdateIsViewOnly) {
+ const state = getState();
+ setState({
+ ...state,
+ isViewOnly: action.isViewOnly
+ });
+ }
+
+ @Action(UpdateIsDesigner)
+ updateIsDesigner({getState, patchState}: StateContext<WorkspaceStateModel>, action:UpdateIsDesigner) {
+ const state = getState();
+ patchState({
+ isDesigner: action.isDesigner
+ });
+ }
+}
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts
index fcb21c0..aab531d 100644
--- a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts
+++ b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts
@@ -23,13 +23,12 @@
*/
import { DataTypesService } from "../../services/data-types-service";
import ICacheObject = angular.ICacheObject;
-import { SharingService } from "../../services/sharing-service";
import { CookieService } from "../../services/cookie-service";
-import { CacheService } from "../../services/cache-service";
import {ComponentFactory} from "../../utils/component-factory"
import { EventListenerService } from "app/services/event-listener-service";
import { ModalsHandler } from "app/utils";
import IScope = angular.IScope;
+import { SharingService } from "../services/sharing.service";
/** Services we need to upgrade from angular1 to angular2 - in the future we need to rewrite them all to angular2 **/
@@ -61,10 +60,6 @@
return cacheObj.get('$scope');
}
-export function cacheServiceFactory(cacheObj: ICacheObject) {
- return cacheObj.get('Sdc.Services.CacheService');
-}
-
export function eventListenerServiceServiceFactory(cacheObj: ICacheObject) {
return cacheObj.get('EventListenerService');
}
@@ -73,6 +68,10 @@
return cacheObj.get('Notification');
}
+export function ModalsHandlerFactory(cacheObj: ICacheObject) {
+ return cacheObj.get('ModalsHandler');
+}
+
export const ComponentFactoryProvider = {
provide: ComponentFactory,
@@ -80,18 +79,12 @@
deps: ['$injector']
};
-
-export function ModalsHandlerFactory(cacheObj: ICacheObject) {
- return cacheObj.get('ModalsHandler');
-}
-
export const DataTypesServiceProvider = {
provide: DataTypesService,
useFactory: dataTypesServiceFactory,
deps: ['$injector']
};
-
export const SharingServiceProvider = {
provide: SharingService,
useFactory: sharingServiceFactory,
@@ -122,17 +115,12 @@
useFactory: stateParamsServiceFactory,
deps: ['$injector']
};
-export const CacheServiceProvider = {
- provide: CacheService,
- useFactory: cacheServiceFactory,
- deps: ['$injector']
-};
-
-export const EventListenerServiceProvider = {
- provide: EventListenerService,
- useFactory: eventListenerServiceServiceFactory,
- deps: ['$injector']
-};
+//
+// export const EventListenerServiceProvider = {
+// provide: EventListenerService,
+// useFactory: eventListenerServiceServiceFactory,
+// deps: ['$injector']
+// };
export const NotificationServiceProvider = {
provide: 'Notification',
@@ -144,4 +132,4 @@
provide: ModalsHandler,
useFactory: ModalsHandlerFactory,
deps: ['$injector']
-}
+};
diff --git a/catalog-ui/src/app/ng2/utils/queue-service-utils.ts b/catalog-ui/src/app/ng2/utils/queue-service-utils.ts
new file mode 100644
index 0000000..8cf7f98
--- /dev/null
+++ b/catalog-ui/src/app/ng2/utils/queue-service-utils.ts
@@ -0,0 +1,58 @@
+/**
+ * Created by ob0695 on 6/3/2018.
+ */
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+import {Injectable} from "@angular/core";
+
+@Injectable()
+export class QueueServiceUtils {
+
+ private executionQueue:any;
+
+ constructor() {
+ if(!this.executionQueue) {
+ this.executionQueue = this.getQueue();
+ }
+ }
+
+ private getQueue = () => new Promise((resolve, reject) => {
+ resolve(true);
+ });
+
+ private addMethodToQueue = (runMe:Function):void => {
+ this.executionQueue = this.executionQueue.then(runMe, runMe);
+ };
+
+ addNonBlockingUIAction = (update:Function, releaseUIcallBack?:Function):void => {
+ // releaseUIcallBack();
+ this.addMethodToQueue(update);
+ };
+
+ // The Method call is responsible for releasing the UI
+ addBlockingUIAction = (blockingServerRequest:Function):void => {
+ this.addMethodToQueue(blockingServerRequest);
+ };
+
+ addBlockingUIActionWithReleaseCallback = (blockingServerRequest:Function, releaseUIcallBack:Function):void=> {
+ this.addMethodToQueue(blockingServerRequest);
+ // this.addMethodToQueue(releaseUIcallBack);
+ };
+}
diff --git a/catalog-ui/src/app/services-ng2.ts b/catalog-ui/src/app/services-ng2.ts
new file mode 100644
index 0000000..e2811ba
--- /dev/null
+++ b/catalog-ui/src/app/services-ng2.ts
@@ -0,0 +1,27 @@
+// Angular 2 services
+export * from './ng2/services/config.service';
+export * from './ng2/services/authentication.service';
+export * from './ng2/services/user.service';
+export * from './ng2/services/data-type.service';
+export * from './ng2/services/modal.service';
+export * from './ng2/services/plugins.service';
+export * from './ng2/services/sharing.service';
+export * from './ng2/services/cache.service';
+export * from './ng2/services/cookie.service';
+export * from './ng2/services/home.service';
+export * from './ng2/services/catalog.service';
+export * from './ng2/services/policies.service';
+export * from './ng2/services/properties.service';
+export * from './ng2/services/window.service';
+export * from './ng2/services/dynamic-component.service';
+export * from './ng2/services/event-bus.service';
+export * from './ng2/services/groups.service';
+
+export * from './ng2/services/component-services/component.service';
+export * from './ng2/services/component-services/component.service.factory';
+export * from './ng2/services/component-services/service.service';
+export * from './ng2/services/component-services/resource.service';
+export * from './ng2/services/component-services/component-mode.service';
+
+export * from './ng2/services/onboarding.service';
+export * from './ng2/components/modals/onboarding-modal/import-vsp.service'
diff --git a/catalog-ui/src/app/services.ts b/catalog-ui/src/app/services.ts
index 79b5132..be77fed 100644
--- a/catalog-ui/src/app/services.ts
+++ b/catalog-ui/src/app/services.ts
@@ -21,9 +21,7 @@
/**
* Created by ob0695 on 2/23/2017.
*/
-export * from './services/activity-log-service';
export * from './services/available-icons-service';
-export * from './services/cache-service';
export * from './services/configuration-ui-service';
export * from './services/category-resource-service';
export * from './services/components/component-service';
@@ -37,14 +35,10 @@
export * from './services/cookie-service';
export * from './services/data-types-service';
export * from './services/ecomp-service';
-export * from './services/entity-service';
export * from './services/event-listener-service';
export * from './services/header-interceptor';
export * from './services/loader-service';
-export * from './services/onboarding-service';
export * from './services/progress-service';
export * from './services/sdc-version-service';
-export * from './services/sharing-service';
export * from './services/url-tobase64-service';
export * from './services/angular-js-bridge-service';
-
diff --git a/catalog-ui/src/app/services/activity-log-service.ts b/catalog-ui/src/app/services/activity-log-service.ts
deleted file mode 100644
index 97d26d4..0000000
--- a/catalog-ui/src/app/services/activity-log-service.ts
+++ /dev/null
@@ -1,48 +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=========================================================
- */
-
-'use strict';
-import {Activity} from "../models/activity";
-import {IAppConfigurtaion, IApi} from "../models/app-config";
-
-// Define an interface of the object you want to use, providing it's properties
-export interface IActivityLogService {
- getActivityLogService(type:string, id:string):ng.IPromise<Array<Activity>>;
-}
-
-export class ActivityLogService implements IActivityLogService {
-
-
- static '$inject' = ['$http', '$q', 'sdcConfig'];
- private api:IApi;
-
- constructor(private $http:ng.IHttpService, private $q:ng.IQService, sdcConfig:IAppConfigurtaion) {
- this.api = sdcConfig.api;
- }
-
- getActivityLogService = (type:string, id:string):ng.IPromise<Array<Activity>> => {
- let defer = this.$q.defer<any>();
- this.$http.get(this.api.root + this.api.GET_activity_log.replace(':type', type).replace(':id', id))
- .then((activityLog:any) => {
- defer.resolve(activityLog.data);
- });
- return defer.promise;
- }
-}
diff --git a/catalog-ui/src/app/services/components/component-service.ts b/catalog-ui/src/app/services/components/component-service.ts
index 25203e7..c7ab975 100644
--- a/catalog-ui/src/app/services/components/component-service.ts
+++ b/catalog-ui/src/app/services/components/component-service.ts
@@ -22,7 +22,7 @@
import {ArtifactModel, IFileDownload, InstancesInputsPropertiesMap, InputModel, IValidate, RelationshipModel, PropertyModel, Component, ComponentInstance,
AttributeModel, IAppConfigurtaion, Resource, Module, DisplayModule, ArtifactGroupModel, InputsAndProperties} from "app/models";
import {ComponentInstanceFactory, CommonUtils} from "app/utils";
-import {SharingService} from "../sharing-service";
+import {SharingService} from "app/services-ng2";
import {ComponentMetadata} from "../../models/component-metadata";
export interface IComponentService {
@@ -683,7 +683,6 @@
public getComponentInstanceProperties = (componentId:string, instanceId:string):ng.IPromise<Array<PropertyModel>> => {
-
let deferred = this.$q.defer<Array<PropertyModel>>();
this.restangular.one(componentId).one("componentInstances").one(instanceId).one("properties").get().then((response:any) => {
console.log("component instance properties return successfully: ", response);
diff --git a/catalog-ui/src/app/services/components/resource-service.ts b/catalog-ui/src/app/services/components/resource-service.ts
index cb30107..3a00da1 100644
--- a/catalog-ui/src/app/services/components/resource-service.ts
+++ b/catalog-ui/src/app/services/components/resource-service.ts
@@ -25,7 +25,7 @@
import * as _ from "lodash";
import {IComponentService, ComponentService} from "./component-service";
import {PropertyModel, IAppConfigurtaion, Resource, Component} from "../../models";
-import {SharingService} from "../sharing-service";
+import {SharingService} from "app/services-ng2";
export interface IResourceService extends IComponentService {
updateResourceGroupProperties(uniqueId:string, groupId:string, properties:Array<PropertyModel>):ng.IPromise<Array<PropertyModel>>
diff --git a/catalog-ui/src/app/services/components/service-service.ts b/catalog-ui/src/app/services/components/service-service.ts
index f258c7b..6c318bd 100644
--- a/catalog-ui/src/app/services/components/service-service.ts
+++ b/catalog-ui/src/app/services/components/service-service.ts
@@ -25,7 +25,7 @@
import * as _ from "lodash";
import {IComponentService, ComponentService} from "./component-service";
import {Distribution, DistributionComponent, Service, PropertyModel, Component, IAppConfigurtaion} from "app/models";
-import {SharingService} from "../sharing-service";
+import {SharingService} from "app/services-ng2";
export interface IServiceService extends IComponentService {
getDistributionsList(uuid:string):ng.IPromise<Array<Distribution>>;
diff --git a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts
index 99be788..b47c5e0 100644
--- a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts
+++ b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts
@@ -32,11 +32,13 @@
import {GroupMetadata, GroupTpes} from "app/models/group-metadata";
import {PolicyMetadata, PolicyTpes} from "app/models/policy-metadata";
import {Resource} from "app/models/components/resource";
+import IHttpPromiseCallbackArg = angular.IHttpPromiseCallbackArg;
export class LeftPaletteLoaderService {
static '$inject' = [
'Restangular',
+ '$http',
'sdcConfig',
'$q',
'ComponentFactory',
@@ -45,6 +47,7 @@
];
constructor(protected restangular:restangular.IElement,
+ protected $http:ng.IHttpService,
protected sdcConfig:IAppConfigurtaion,
protected $q:ng.IQService,
protected ComponentFactory:ComponentFactory,
@@ -64,7 +67,9 @@
private updateLeftPalette = (componentInternalType:string):void => {
/* add components */
- this.restangular.one("resources").one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array<ComponentMetadata>) => {
+ const leftPaletteUrl = this.sdcConfig.api.uicache_root + this.sdcConfig.api.GET_uicache_left_palette;
+ this.$http.get(leftPaletteUrl, {params: {'internalComponentType': componentInternalType}}).then((res) => res.data).then((leftPaletteComponentMetadata:Array<ComponentMetadata>) => {
+ // this.restangular.one("resources").one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array<ComponentMetadata>) => {
_.forEach(leftPaletteComponentMetadata, (componentMetadata:ComponentMetadata) => {
this.leftPanelComponents.push(new LeftPaletteComponent(LeftPaletteMetadataTypes.Component, componentMetadata));
});
diff --git a/catalog-ui/src/app/services/entity-service.ts b/catalog-ui/src/app/services/entity-service.ts
deleted file mode 100644
index 2e7b2e1..0000000
--- a/catalog-ui/src/app/services/entity-service.ts
+++ /dev/null
@@ -1,104 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import { Service, IApi, IAppConfigurtaion, Resource, Component} from "../models";
-import {SharingService} from "./sharing-service";
-import {ComponentFactory} from "../utils/component-factory";
-import {CacheService} from "./cache-service";
-import {ResourceType} from "app/utils";
-
-interface IEntityService {
- getAllComponents(smallObjects?:boolean):ng.IPromise<Array<Component>>;
-}
-
-interface IComponentsArray {
- services:Array<Service>;
- resources:Array<Resource>;
-}
-
-export class EntityService implements IEntityService {
- static '$inject' = ['$http', '$q', 'sdcConfig', 'Sdc.Services.SharingService', 'ComponentFactory', 'Sdc.Services.CacheService'];
- private _smallObjectAttributes = ['uniqueId', 'name', 'componentType', 'resourceType', 'lastUpdateDate', 'lifecycleState', 'distributionStatus', 'icon', 'version'];
- private api:IApi;
-
- constructor(private $http:ng.IHttpService,
- private $q:ng.IQService,
- private sdcConfig:IAppConfigurtaion,
- private sharingService:SharingService,
- private ComponentFactory:ComponentFactory,
- private cacheService:CacheService) {
- this.api = sdcConfig.api;
- }
-
- getCatalog = ():ng.IPromise<Array<Component>> => {
- let defer = this.$q.defer<Array<Component>>();
- this.$http.get(this.api.root + this.api.GET_catalog, {params: {excludeTypes: [ResourceType.VFCMT, ResourceType.CONFIGURATION]}})
- .then((response:any) => {
- let followedResponse: IComponentsArray = response.data;
- let componentsList:Array<Component> = new Array();
-
- followedResponse.services && followedResponse.services.forEach((serviceResponse:Service) => {
- let component:Service = this.ComponentFactory.createService(serviceResponse); // new Service(serviceResponse);
- componentsList.push(component);
- this.sharingService.addUuidValue(component.uniqueId, component.uuid);
- });
-
- followedResponse.resources && followedResponse.resources.forEach((resourceResponse:Resource) => {
- let component:Resource = this.ComponentFactory.createResource(resourceResponse);
- componentsList.push(component);
- this.sharingService.addUuidValue(component.uniqueId, component.uuid);
- });
-
- defer.resolve(componentsList);
- },(responce) => {
- defer.reject(responce);
- });
- return defer.promise;
- };
-
- getAllComponents = (smallObjects?:boolean):ng.IPromise<Array<Component>> => {
- let defer = this.$q.defer<Array<Component>>();
- this.$http.get(this.api.root + this.api.GET_element)
- .then((response:any) => {
- let componentResponse:IComponentsArray = response.data;
- let componentsList:Array<Component> = [];
-
- componentResponse.services && componentResponse.services.forEach((serviceResponse:Service) => {
- serviceResponse = (smallObjects) ? _.pick(serviceResponse, this._smallObjectAttributes) : serviceResponse;
- let component:Service = this.ComponentFactory.createService(serviceResponse);
- componentsList.push(component);
- this.sharingService.addUuidValue(component.uniqueId, component.uuid);
- });
-
- componentResponse.resources && componentResponse.resources.forEach((resourceResponse:Resource) => {
- resourceResponse = (smallObjects) ? _.pick(resourceResponse, this._smallObjectAttributes) : resourceResponse;
- let component:Resource = this.ComponentFactory.createResource(resourceResponse);
- componentsList.push(component);
- this.sharingService.addUuidValue(component.uniqueId, component.uuid);
- });
-
- defer.resolve(componentsList);
- });
-
- return defer.promise;
- };
-}
diff --git a/catalog-ui/src/app/services/event-listener-service.ts b/catalog-ui/src/app/services/event-listener-service.ts
index 360edad..2d3c4a6 100644
--- a/catalog-ui/src/app/services/event-listener-service.ts
+++ b/catalog-ui/src/app/services/event-listener-service.ts
@@ -23,22 +23,21 @@
'use strict';
import * as _ from "lodash";
import {Dictionary} from "../utils/dictionary/dictionary";
+import {Injectable} from "@angular/core";
-interface IEventListenerService {
-
-}
interface ICallbackData {
- callback:Function;
- args:any[];
+ callback: Function;
+ args: any[];
}
-export class EventListenerService implements IEventListenerService {
+@Injectable()
+export class EventListenerService {
- public observerCallbacks:Dictionary<string, ICallbackData[]> = new Dictionary<string, Array<ICallbackData>>();
+ public observerCallbacks: Dictionary<string, ICallbackData[]> = new Dictionary<string, Array<ICallbackData>>();
//register an observer + callback
- public registerObserverCallback = (eventName:string, callback:Function, ...args) => {
+ public registerObserverCallback = (eventName: string, callback: Function, ...args) => {
let callbackData = {
callback: callback,
args: args
@@ -62,11 +61,11 @@
};
//unregister an observer
- public unRegisterObserver = (eventName:string, callbackFunc?:Function) => {
+ public unRegisterObserver = (eventName: string, callbackFunc?: Function) => {
if (this.observerCallbacks.containsKey(eventName)) {
- let callbacks: ICallbackData[] = this.observerCallbacks.getValue(eventName);
- if(callbacks.length === 1) {
+ let callbacks: ICallbackData[] = this.observerCallbacks.getValue(eventName);
+ if (callbacks.length === 1) {
this.observerCallbacks.remove(eventName);
} else {
let filterCallbacks = _.filter(callbacks, (callBackObj) => {
@@ -74,13 +73,12 @@
});
this.observerCallbacks.setValue(eventName, filterCallbacks);
}
-
}
};
- public notifyObservers = function (eventName:string, ...args) {
- _.forEach(this.observerCallbacks.getValue(eventName), (callbackData:ICallbackData) => {
- callbackData.callback(...args);
- });
+ public notifyObservers = function (eventName: string, ...args) {
+ _.forEach(this.observerCallbacks.getValue(eventName), (callbackData: ICallbackData) => {
+ callbackData.callback(...args);
+ });
};
}
diff --git a/catalog-ui/src/app/services/header-interceptor.ts b/catalog-ui/src/app/services/header-interceptor.ts
index 931b292..5f4819a 100644
--- a/catalog-ui/src/app/services/header-interceptor.ts
+++ b/catalog-ui/src/app/services/header-interceptor.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.
@@ -19,17 +19,19 @@
*/
'use strict';
-import {IAppConfigurtaion} from "../models/app-config";
-import {Dictionary} from "../utils/dictionary/dictionary";
-import {SharingService} from "./sharing-service";
+import { SharingService } from 'app/services-ng2';
+import { IAppConfigurtaion } from '../models/app-config';
+import { ServerErrorResponse } from '../models/server-error-response';
+import { Dictionary } from '../utils/dictionary/dictionary';
-//Method name should be exactly "response" - http://docs.angularjs.org/api/ng/service/$http
-export interface IInterceptor {
- request:Function;
-
+// Method name should be exactly "response" - http://docs.angularjs.org/api/ng/service/$http
+export interface Interceptor {
+ request: Function;
+ response: Function;
+ responseError: Function;
}
-export class HeaderInterceptor implements IInterceptor {
+export class HeaderInterceptor implements Interceptor {
public static $inject = [
'$injector',
'$q',
@@ -39,51 +41,55 @@
'$location'
];
- public static Factory($injector:ng.auto.IInjectorService,
- $q:ng.IQService,
- uuid4:any,
- sharingService:SharingService,
- sdcConfig:IAppConfigurtaion,
- $location:ng.ILocationService) {
- return new HeaderInterceptor($injector, $q, uuid4, sharingService, sdcConfig, $location);
+ constructor(private $injector: ng.auto.IInjectorService,
+ private $q: ng.IQService,
+ private uuid4: any,
+ private sharingService: SharingService,
+ private sdcConfig: IAppConfigurtaion,
+ private $location: ng.ILocationService) {
}
- constructor(private $injector:ng.auto.IInjectorService,
- private $q:ng.IQService,
- private uuid4:any,
- private sharingService:SharingService,
- private sdcConfig:IAppConfigurtaion,
- private $location:ng.ILocationService) {
- console.debug('header-interceptor: initializing AuthenticationInterceptor');
- }
-
- public request = (requestSuccess):ng.IPromise<any> => {
+ public request = (requestSuccess): ng.IPromise<any> => {
requestSuccess.headers['X-ECOMP-RequestID'] = this.uuid4.generate();
/**
* For every request to the server, that the service id, or resource id is sent in the URL, need to pass UUID in the header.
* Check if the unique id exists in uuidMap, and if so get the UUID and add it to the header.
*/
- let map:Dictionary<string, string> = this.sharingService.getUuidMap();
+ const map: Dictionary<string, string> = this.sharingService.getUuidMap();
if (map && requestSuccess.url.indexOf(this.sdcConfig.api.root) === 0) {
- console.log("header-interceptor: url: " + requestSuccess.url);
- map.forEach((key:string) => {
+ map.forEach((key: string) => {
if (requestSuccess.url.indexOf(key) !== -1) {
requestSuccess.headers['X-ECOMP-ServiceID'] = this.sharingService.getUuidValue(key);
}
});
}
return requestSuccess;
- };
+ }
- public response = (responseSuccess):ng.IPromise<any> => {
- let responseData = responseSuccess.data;
+ public response = (responseSuccess): ng.IPromise<any> => {
+ const responseData = responseSuccess.data;
if (responseData) {
- let data = JSON.stringify(responseData);
- if (data && (data.indexOf("Global Logon: Login") > 0)) {
+ const data = JSON.stringify(responseData);
+ if (data && (data.indexOf('Global Logon: Login') > 0)) {
this.$location.path('dashboard/welcome');
window.location.reload();
}
}
return responseSuccess;
}
+
+ public responseError = (response): ng.IPromise<any> => {
+ const errorResponse: ServerErrorResponse = new ServerErrorResponse(response, true);
+ const modalService = this.$injector.get('ModalServiceSdcUI');
+
+ const errorDetails = {
+ 'Error Code': errorResponse.messageId,
+ 'Status Code': errorResponse.status
+ };
+ if (errorResponse.ecompRequestId) {
+ errorDetails['Transaction ID'] = errorResponse.ecompRequestId;
+ }
+ modalService.openErrorDetailModal('Error', errorResponse.message, 'error-modal', errorDetails);
+ return this.$q.reject(errorResponse);
+ }
}
diff --git a/catalog-ui/src/app/services/http-error-interceptor.ts b/catalog-ui/src/app/services/http-error-interceptor.ts
deleted file mode 100644
index cef8c30..0000000
--- a/catalog-ui/src/app/services/http-error-interceptor.ts
+++ /dev/null
@@ -1,119 +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=========================================================
- */
-
-'use strict';
-import {IServerMessageModalModel} from "../view-models/modals/message-modal/message-server-modal/server-message-modal-view-model";
-import {SEVERITY} from "../utils/constants";
-import 'app/utils/prototypes.ts';
-
-export class HttpErrorInterceptor {
- public static $inject = ['$injector', '$q'];
-
- public static Factory($injector:ng.auto.IInjectorService, $q:angular.IQService) {
- return new HttpErrorInterceptor($injector, $q);
- }
-
- constructor(private $injector:ng.auto.IInjectorService, private $q:angular.IQService) {
- }
-
- public formatMessageArrays = (message:string, variables:Array<string>)=> {
- return message.replace(/\[%(\d+)\]/g, function (_, m) {
- let tmp = [];
- let list = variables[--m].split(";");
- list.forEach(function (item) {
- tmp.push("<li>" + item + "</li>");
- });
- return "<ul>" + tmp.join("") + "</ul>";
- });
- };
-
- public responseError = (rejection:any)=> {
-
- let text:string;
- let variables;
- let messageId:string = "";
- let isKnownException = false;
-
- if (rejection.data && rejection.data.serviceException) {
- text = rejection.data.serviceException.text;
- variables = rejection.data.serviceException.variables;
- messageId = rejection.data.serviceException.messageId;
- isKnownException = true;
- } else if (rejection.data && rejection.data.requestError && rejection.data.requestError.serviceException) {
- text = rejection.data.requestError.serviceException.text;
- variables = rejection.data.requestError.serviceException.variables;
- messageId = rejection.data.requestError.serviceException.messageId;
- isKnownException = true;
- } else if (rejection.data && rejection.data.requestError && rejection.data.requestError.policyException) {
- text = rejection.data.requestError.policyException.text;
- variables = rejection.data.requestError.policyException.variables;
- messageId = rejection.data.requestError.policyException.messageId;
- isKnownException = true;
- } else if (rejection.data) {
- text = 'Wrong error format from server';
- console.error(text);
- isKnownException = false;
- }
-
- let data:IServerMessageModalModel;
- if (isKnownException) {
- // Remove the "Error: " text at the begining
- if (text.trim().indexOf("Error:") === 0) {
- text = text.replace("Error:", "").trim();
- }
-
- //mshitrit DE199895 bug fix
- let count:number = 0;
- variables.forEach(function (item) {
- variables[count] = item ? item.replace('<', '<').replace('>', '>') : '';
- count++;
- });
-
- // Format the message in case has array to <ul><li>
- text = this.formatMessageArrays(text, variables);
-
- // Format the message %1 %2
- text = text.format(variables);
-
- // Need to inject the MessageService manually to prevent circular componentsToUpgrade (because MessageService use $templateCache that use $http).
- data = {
- title: 'Error',
- message: text,
- messageId: messageId,
- status: rejection.status,
- severity: SEVERITY.ERROR
- };
- } else {
- // Need to inject the MessageService manually to prevent circular componentsToUpgrade (because MessageService use $templateCache that use $http).
- data = {
- title: 'Error',
- message: rejection.status !== -1 ? rejection.statusText : "Error getting response from server",
- messageId: messageId,
- status: rejection.status,
- severity: SEVERITY.ERROR
- };
- }
-
- let modalsHandler = this.$injector.get('ModalsHandler');
- modalsHandler.openServerMessageModal(data);
-
- return this.$q.reject(rejection);
- }
-}
diff --git a/catalog-ui/src/app/services/onboarding-service.ts b/catalog-ui/src/app/services/onboarding-service.ts
deleted file mode 100644
index 3a6e940..0000000
--- a/catalog-ui/src/app/services/onboarding-service.ts
+++ /dev/null
@@ -1,112 +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=========================================================
- */
-
-'use strict';
-import {Component, IComponent} from "../models/components/component";
-import {ICsarComponent} from "../models/csar-component";
-import {IAppConfigurtaion, IApi} from "../models/app-config";
-import {IFileDownload} from "../models/file-download";
-import {Resource} from "../models/components/resource";
-import {ComponentFactory} from "../utils/component-factory";
-
-interface IOnboardingService {
- getOnboardingComponents():ng.IPromise<Array<IComponent>>;
- getComponentFromCsarUuid(csarUuid:string):ng.IPromise<Component>;
- downloadOnboardingCsar(packageId:string):ng.IPromise<IFileDownload>;
-}
-
-export class OnboardingService implements IOnboardingService {
-
- static '$inject' = ['$http', '$q', 'sdcConfig', 'ComponentFactory'];
- private api:IApi;
-
- constructor(private $http:ng.IHttpService,
- private $q:ng.IQService,
- private sdcConfig:IAppConfigurtaion,
- private ComponentFactory:ComponentFactory) {
- this.api = sdcConfig.api;
- }
-
- getOnboardingVSPs = ():ng.IPromise<Array<ICsarComponent>> =>{
- let defer = this.$q.defer<Array<ICsarComponent>>();
- this.$http.get(this.api.GET_onboarding)
- .then((response:any) => {
- defer.resolve(response.data.results);
- },(response) => {
- defer.reject(response);
- });
-
- return defer.promise;
- };
-
- getOnboardingComponents = ():ng.IPromise<Array<IComponent>> => {
- let defer = this.$q.defer<Array<IComponent>>();
- this.getOnboardingVSPs().then((onboardingComponents:Array<ICsarComponent>) => {
- let componentsList:Array<IComponent> = new Array();
-
- onboardingComponents.forEach((obc:ICsarComponent) => {
- let component:Component = this.ComponentFactory.createFromCsarComponent(obc);
- componentsList.push(component);
- });
-
- defer.resolve(componentsList);
- },(response) => {
- defer.reject(response);
- });
-
- return defer.promise;
- };
-
- downloadOnboardingCsar = (packageId:string):ng.IPromise<IFileDownload> => {
- let defer = this.$q.defer<IFileDownload>();
- this.$http({
- url: this.api.GET_onboarding + "/" + packageId,
- method: "get",
- responseType: "blob"
- })
- .then((response:any) => {
- defer.resolve(response.data);
- }, (err) => {
- defer.reject(err);
- });
-
- return defer.promise;
- };
-
- getComponentFromCsarUuid = (csarUuid:string):ng.IPromise<Component> => {
- let defer = this.$q.defer<Component>();
- this.$http.get(this.api.root + this.api.GET_component_from_csar_uuid.replace(':csar_uuid', csarUuid))
- .then((response:any) => {
- let component:Resource;
- // If the status is 400, this means that the component not found.
- // I do not want to return error from server, because a popup will appear in client with the error.
- // So returning success (200) with status 400.
- if (response.data.status !== 400) {
- component = new Resource(null, this.$q, <Resource>response.data);
- }
- defer.resolve(component);
- },(response) => {
- defer.reject(response.data);
- });
-
- return defer.promise;
- };
-
-}
diff --git a/catalog-ui/src/app/utils.ts b/catalog-ui/src/app/utils.ts
index 1d2eafb..27c805a 100644
--- a/catalog-ui/src/app/utils.ts
+++ b/catalog-ui/src/app/utils.ts
@@ -22,7 +22,6 @@
* Created by ob0695 on 2/23/2017.
*/
export * from './utils/dictionary/dictionary';
-export * from './utils/artifacts-utils';
export * from'./utils/file-utils'
export * from './utils/validation-utils'
export * from './utils/component-factory';
diff --git a/catalog-ui/src/app/utils/artifacts-utils.ts b/catalog-ui/src/app/utils/artifacts-utils.ts
deleted file mode 100644
index e99b641..0000000
--- a/catalog-ui/src/app/utils/artifacts-utils.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import * as _ from "lodash";
-import {ArtifactModel} from "../models/artifacts";
-import {IArtifactResourceFormViewModelScope} from "../view-models/forms/artifact-form/artifact-form-view-model";
-import {Component} from "../models/components/component";
-import {ArtifactGroupType, ArtifactType} from "./constants";
-
-export class ArtifactsUtils {
-
- static '$inject' = [
- '$filter'
- ];
-
- constructor(private $filter:ng.IFilterService) {
-
- }
-
- public getArtifactTypeByState(currentState:string):string {
- switch (currentState) {
- case "workspace.composition.lifecycle":
- return "interface";
- case "workspace.composition.api":
- return "api";
- case "workspace.deployment_artifacts":
- case "workspace.composition.deployment":
- return "deployment";
- case "workspace.composition.artifacts":
- return "informational";
- default:
- return "informational";
- }
- }
-
- public getTitle(artifactType:string, selectedComponent:Component):string {
- switch (artifactType) {
- case "interface":
- return "Lifecycle Management";
- case "api":
- return "API Artifacts";
- case "deployment":
- return "Deployment Artifacts";
- case "informational":
- return "Informational Artifacts";
- default:
- if (!selectedComponent) {
- return "";
- } else {
- return this.$filter("resourceName")(selectedComponent.name) + ' Artifacts';
- }
- }
- }
-
- public setArtifactType = (artifact:ArtifactModel, artifactType:string):void => {
- switch (artifactType) {
- case "api":
- artifact.artifactGroupType = ArtifactGroupType.SERVICE_API;
- break;
- case "deployment":
- artifact.artifactGroupType = ArtifactGroupType.DEPLOYMENT;
- break;
- default:
- artifact.artifactGroupType = ArtifactGroupType.INFORMATION;
- break;
- }
- };
-
- public isLicenseType = (artifactType:string):boolean => {
- let isLicense:boolean = false;
-
- if (ArtifactType.VENDOR_LICENSE === artifactType || ArtifactType.VF_LICENSE === artifactType) {
- isLicense = true;
- }
-
- return isLicense;
- };
-
- public removeArtifact = (artifact:ArtifactModel, artifactsArr:Array<ArtifactModel>):void => {
-
- if (!artifact.mandatory && (ArtifactGroupType.INFORMATION == artifact.artifactGroupType ||
- ArtifactGroupType.DEPLOYMENT == artifact.artifactGroupType)) {
- _.remove(artifactsArr, {uniqueId: artifact.uniqueId});
- }
- else {
- let artifactToDelete = _.find(artifactsArr, {uniqueId: artifact.uniqueId});
-
- delete artifactToDelete.esId;
- delete artifactToDelete.description;
- delete artifactToDelete.artifactName;
- delete artifactToDelete.apiUrl;
- }
- };
-
- public addAnotherAfterSave(scope:IArtifactResourceFormViewModelScope) {
- let newArtifact = new ArtifactModel();
- this.setArtifactType(newArtifact, scope.artifactType);
- scope.editArtifactResourceModel.artifactResource = newArtifact;
-
- scope.forms.editForm['description'].$setPristine();
- if (scope.forms.editForm['artifactLabel']) {
- scope.forms.editForm['artifactLabel'].$setPristine();
- }
- if (scope.forms.editForm['type']) {
- scope.forms.editForm['type'].$setPristine();
- }
-
- }
-}
diff --git a/catalog-ui/src/app/utils/change-lifecycle-state-handler.ts b/catalog-ui/src/app/utils/change-lifecycle-state-handler.ts
index 54497ba..6a37864 100644
--- a/catalog-ui/src/app/utils/change-lifecycle-state-handler.ts
+++ b/catalog-ui/src/app/utils/change-lifecycle-state-handler.ts
@@ -17,18 +17,16 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-
-import {ComponentFactory} from "./component-factory";
-import {Component, Service,IAppMenu, IAppConfigurtaion} from "../models";
-import {IEmailModalModel, IEmailModalModel_Email, IEmailModalModel_Data} from "../view-models/modals/email-modal/email-modal-view-model";
-import {AsdcComment} from "../models/comments";
-import {ModalsHandler} from "./modals-handler";
-import {ServiceServiceNg2} from "../ng2/services/component-services/service.service";
-import {EventBusService} from "../ng2/services/event-bus.service";
-
-/**
- * Created by obarda on 2/11/2016.
- */
+import { ServiceServiceNg2 } from 'app/ng2/services/component-services/service.service';
+import { EventBusService } from 'app/ng2/services/event-bus.service';
+import { EVENTS, ValidationUtils } from 'app/utils';
+import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
+import { Component, IAppConfigurtaion, IAppMenu, Service } from '../models';
+import { AsdcComment } from '../models/comments';
+import { CommentModalComponent } from '../ng2/components/modals/comment-modal/comment-modal.component';
+import { EventListenerService } from '../services/event-listener-service';
+import { ComponentFactory } from './component-factory';
+import { ModalsHandler } from './modals-handler';
export class ChangeLifecycleStateHandler {
@@ -39,141 +37,25 @@
'$filter',
'ModalsHandler',
'ServiceServiceNg2',
- 'EventBusService'
+ 'EventBusService',
+ 'ModalServiceSdcUI',
+ 'ValidationUtils',
+ 'EventListenerService'
];
- constructor(private sdcConfig:IAppConfigurtaion,
- private sdcMenu:IAppMenu,
- private ComponentFactory:ComponentFactory,
- private $filter:ng.IFilterService,
- private ModalsHandler:ModalsHandler,
- private ServiceServiceNg2:ServiceServiceNg2,
- private eventBusService:EventBusService) {
-
+ constructor(private sdcConfig: IAppConfigurtaion,
+ private sdcMenu: IAppMenu,
+ private componentFactory: ComponentFactory,
+ private $filter: ng.IFilterService,
+ private modalsHandler: ModalsHandler,
+ private serviceServiceNg2: ServiceServiceNg2,
+ private eventBusService: EventBusService,
+ private modalService: SdcUiServices.ModalService,
+ private validationUtils: ValidationUtils,
+ private eventListenerService: EventListenerService) {
}
- private actualChangeLifecycleState = (component:Component, data:any, scope:any, onSuccessCallback?:Function, onErrorCallback?:Function):void => {
-
- let self = this;
-
- let getContacts = (component:Component):string => {
- let testers = this.sdcConfig.testers;
- let result:string = testers[component.componentType][component.categories[0].name] ?
- testers[component.componentType][component.categories[0].name] :
- testers[component.componentType]['default'];
- return result;
- };
-
- let onSuccess = (newComponent:Component):void => {
- //scope.isLoading = false;
- console.info(component.componentType.toLowerCase + ' change state ', newComponent);
- if (onSuccessCallback) {
- onSuccessCallback(self.ComponentFactory.createComponent(newComponent), data.url);
- }
- };
-
- let onError = (error):void => {
- scope.isLoading = false;
- console.info('Failed to changeLifecycleState to ', data.url);
- if (onErrorCallback) {
- onErrorCallback(error);
- }
- };
-
- let comment:AsdcComment = new AsdcComment();
- if (data.alertModal) {
- // Show alert dialog if defined in menu.json
- //-------------------------------------------------
- let onOk = (confirmationText):void => {
- comment.userRemarks = confirmationText;
- scope.isLoading = true;
- component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
- };
-
- let onCancel = ():void => {
- console.info('Cancel pressed');
- scope.isLoading = false;
- };
-
- let modalTitle = this.sdcMenu.alertMessages[data.alertModal].title;
- let modalMessage = this.sdcMenu.alertMessages[data.alertModal].message.format([component.componentType.toLowerCase()]);
- this.ModalsHandler.openAlertModal(modalTitle, modalMessage).then(onOk, onCancel);
- } else if (data.confirmationModal) {
- // Show confirmation dialog if defined in menu.json
- //-------------------------------------------------
- let onOk = (confirmationText):void => {
- comment.userRemarks = confirmationText;
-
- if (data.url === "lifecycleState/CHECKIN") {
- this.eventBusService.notify("CHECK_IN").subscribe(() => {
- scope.isLoading = true;
- component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
- });
- }
- else {
- scope.isLoading = true;
- component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
- }
- };
-
- let onCancel = ():void => {
- console.info('Cancel pressed');
- scope.isLoading = false;
- };
-
- let modalTitle = this.sdcMenu.confirmationMessages[data.confirmationModal].title;
- let modalMessage = this.sdcMenu.confirmationMessages[data.confirmationModal].message.format([component.componentType.toLowerCase()]);
- let modalShowComment = this.sdcMenu.confirmationMessages[data.confirmationModal].showComment;
- this.ModalsHandler.openConfirmationModal(modalTitle, modalMessage, modalShowComment).then(onOk, onCancel);
-
- } else if (data.emailModal) {
- // Show email dialog if defined in menu.json
- //-------------------------------------------------
- let onOk = (resource):void => {
- if (data.url === "lifecycleState/certificationRequest") {
- this.eventBusService.notify("SUBMIT_FOR_TESTING").subscribe(() => {
- if (resource) {
- onSuccess(resource);
- } else {
- onError("Error changing life cycle state");
- }
- });
- }
- else {
- if (resource) {
- onSuccess(resource);
- } else {
- onError("Error changing life cycle state");
- }
- }
- };
-
- let onCancel = ():void => {
- scope.isLoading = false;
- };
-
- let emailModel:IEmailModalModel = <IEmailModalModel>{};
- emailModel.email = <IEmailModalModel_Email>{};
- emailModel.data = <IEmailModalModel_Data>{};
- emailModel.title = this.$filter('translate')("EMAIL_MODAL_TITLE");
- emailModel.email.to = getContacts(component);
- emailModel.email.subject = this.$filter('translate')("EMAIL_MODAL_SUBJECT", "{'entityName': '" + this.$filter('resourceName')(component.name) + "','entityVersion': '" + component.version + "'}");
- emailModel.email.message = '';
- emailModel.data.component = component;
- emailModel.data.stateUrl = data.url;
-
- this.ModalsHandler.openEmailModal(emailModel).then(onOk, onCancel);
-
- } else {
- // Submit to server only (no modal is shown).
- scope.isLoading = true;
- component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
- }
-
- }
-
- public changeLifecycleState = (component:Component, data:any, scope:any, onSuccessCallback?:Function, onErrorCallback?:Function):void => {
-
+ public changeLifecycleState = (component: Component, data: any, scope: any, onSuccessCallback?: Function, onErrorCallback?: Function) => {
if (data.conformanceLevelModal) {
this.validateConformanceLevel(component, data, scope, onSuccessCallback, onErrorCallback);
} else {
@@ -181,25 +63,104 @@
}
}
- private validateConformanceLevel = (component:Component, data:any, scope:any, onSuccessCallback?:Function, onErrorCallback?:Function):void => {
+ private actualChangeLifecycleState = (component: Component, data: any, scope: any, onSuccessCallback?: Function, onErrorCallback?: Function) => {
+ const self = this;
+
+ const onSuccess = (newComponent: Component) => {
+ if (onSuccessCallback) {
+ onSuccessCallback(self.componentFactory.createComponent(newComponent), data.url);
+ if (data.url === 'distribution/PROD/activate') {
+ this.eventListenerService.notifyObservers(EVENTS.ON_DISTRIBUTION_SUCCESS);
+ }
+ }
+ };
+
+ const onError = (error) => {
+ scope.isLoading = false;
+ if (onErrorCallback) {
+ onErrorCallback(error);
+ }
+ };
+
+ const comment: AsdcComment = new AsdcComment();
+ if (data.alertModal) {
+ // Show alert dialog if defined in menu.json
+ const onOk: Function = (confirmationText) => {
+ comment.userRemarks = confirmationText;
+ scope.isLoading = true;
+ component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
+ };
+
+ const modalTitle = this.sdcMenu.alertMessages[data.alertModal].title;
+ const modalMessage = this.sdcMenu.alertMessages[data.alertModal].message.format([component.componentType.toLowerCase()]);
+ const modalButton = {
+ testId: 'OK',
+ text: this.sdcMenu.alertMessages.okButton,
+ type: SdcUiCommon.ButtonType.warning,
+ callback: onOk,
+ closeModal: true
+ } as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openWarningModal(modalTitle, modalMessage, 'alert-modal', [modalButton]);
+ } else if (data.confirmationModal) {
+ // Show confirmation dialog if defined in menu.json
+ let commentModalInstance: SdcUiComponents.ModalComponent;
+ const onOk = () => {
+ const confirmationText: string = commentModalInstance.innerModalContent.instance.comment.text;
+ commentModalInstance.closeModal();
+ comment.userRemarks = this.validationUtils.stripAndSanitize(confirmationText);
+
+ if (data.url === 'lifecycleState/CHECKIN') {
+ this.eventBusService.notify('CHECK_IN').subscribe(() => {
+ scope.isLoading = true;
+ component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
+ });
+ } else {
+ scope.isLoading = true;
+ component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
+ }
+ };
+
+ const modalTitle = this.sdcMenu.confirmationMessages[data.confirmationModal].title;
+ const modalMessage = this.sdcMenu.confirmationMessages[data.confirmationModal].message.format([component.componentType.toLowerCase()]);
+ const modalConfig = {
+ size: 'md',
+ title: modalTitle,
+ type: SdcUiCommon.ModalType.custom,
+ testId: 'confirm-modal',
+ buttons: [
+ { id: 'OK', text: 'OK', callback: onOk, closeModal: false, testId: 'OK' },
+ { id: 'cancel', text: 'Cancel', size: 'x-small', type: 'secondary', closeModal: true, testId: 'Cancel' }
+ ] as SdcUiCommon.IModalButtonComponent[]
+ } as SdcUiCommon.IModalConfig;
+ commentModalInstance = this.modalService.openCustomModal(modalConfig, CommentModalComponent, { message: modalMessage });
+ commentModalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => {
+ commentModalInstance.getButtonById('OK').disabled = !isValid;
+ });
+ } else {
+ // Submit to server only (no modal is shown).
+ scope.isLoading = true;
+ component.changeLifecycleState(data.url, comment).then(onSuccess, onError);
+ }
+ }
+
+ private validateConformanceLevel = (component: Component, data: any, scope: any, onSuccessCallback?: Function, onErrorCallback?: Function) => {
// Validate conformance level if defined in menu.json
- //-------------------------------------------------
- this.ServiceServiceNg2.validateConformanceLevel(<Service>component).subscribe((res:boolean) => {
+ this.serviceServiceNg2.validateConformanceLevel(component as Service).subscribe((res: boolean) => {
if (res === true) {
- //conformance level is ok - continue
+ // Conformance level is ok - continue
this.actualChangeLifecycleState(component, data, scope, onSuccessCallback, onErrorCallback);
-
} else {
- //show warning modal
- this.ModalsHandler.openConformanceLevelModal()
- .then(() => {
- //continue distribute
- this.actualChangeLifecycleState(component, data, scope, onSuccessCallback, onErrorCallback);
-
- }).catch(() => {
- //reject distribution
- this.actualChangeLifecycleState(component, data.conformanceLevelModal, scope, onSuccessCallback, onErrorCallback);
- });
+ // Show warning modal
+ const onContinue: Function = () => {
+ this.actualChangeLifecycleState(component, data, scope, onSuccessCallback, onErrorCallback);
+ };
+ const reject: Function = () => {
+ this.actualChangeLifecycleState(component, data.conformanceLevelModal, scope, onSuccessCallback, onErrorCallback);
+ };
+ const continueButton = {testId: 'Continue', text: 'Continue', type: SdcUiCommon.ButtonType.primary, callback: onContinue, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ const rejectButton = {testId: 'Reject', text: 'Reject', type: SdcUiCommon.ButtonType.secondary, callback: reject, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openInfoModal(this.$filter('translate')('CONFORMANCE_LEVEL_MODAL_TITLE'),
+ this.$filter('translate')('CONFORMANCE_LEVEL_MODAL_TEXT'), 'conformance-modal', [continueButton, rejectButton]);
}
});
}
diff --git a/catalog-ui/src/app/utils/common-utils.ts b/catalog-ui/src/app/utils/common-utils.ts
index 99f7c49..eadb92b 100644
--- a/catalog-ui/src/app/utils/common-utils.ts
+++ b/catalog-ui/src/app/utils/common-utils.ts
@@ -19,11 +19,12 @@
*/
import * as _ from "lodash";
-import {Module, AttributeModel, ResourceInstance, PropertyModel, InterfaceModel, OperationModel} from "../models";
+import {Module, AttributeModel, ResourceInstance, PropertyModel, InputFEModel, OperationModel} from "../models";
import {ComponentInstanceFactory} from "./component-instance-factory";
import {InputBEModel, PropertyBEModel, RelationshipModel} from "app/models";
import { PolicyInstance } from "app/models/graph/zones/policy-instance";
import { GroupInstance } from "../models/graph/zones/group-instance";
+import { InterfaceModel } from "../models/operation";
export class CommonUtils {
@@ -167,7 +168,7 @@
});
}
-
+
static initInterfaceOperations(interfaces: Array<InterfaceModel>): Array<OperationModel> {
return _.reduce(interfaces, (acc, interf: InterfaceModel) => {
@@ -194,5 +195,6 @@
}, []);
}
+
}
diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts
index 2b134bd..889f6fb 100644
--- a/catalog-ui/src/app/utils/component-factory.ts
+++ b/catalog-ui/src/app/utils/component-factory.ts
@@ -21,7 +21,8 @@
'use strict';
import * as _ from "lodash";
import {DEFAULT_ICON, ResourceType, ComponentType} from "./constants";
-import {ServiceService, CacheService, ResourceService} from "app/services";
+import {ServiceService, ResourceService} from "app/services";
+import {CacheService} from "app/services-ng2";
import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service} from "app/models";
import {ComponentMetadata} from "../models/component-metadata";
import {ComponentServiceNg2} from "../ng2/services/component-services/component.service";
@@ -71,23 +72,23 @@
return newResource;
};
- public updateComponentFromCsar = (csarComponent:Resource, oldComponent:Resource):Component => {
- _.pull(oldComponent.tags, oldComponent.name);
- if (!oldComponent.isAlreadyCertified()) {
+ public updateComponentFromCsar = (csarComponent:Resource, oldComponent: Resource): Component => {
+ _.pull(oldComponent.tags, oldComponent.name);
+ if (!oldComponent.isAlreadyCertified()) {
oldComponent.name = csarComponent.name;
oldComponent.categories = csarComponent.categories;
oldComponent.selectedCategory = csarComponent.selectedCategory;
}
- oldComponent.vendorName = csarComponent.vendorName;
- oldComponent.vendorRelease = csarComponent.vendorRelease;
- oldComponent.csarUUID = csarComponent.csarUUID;
- oldComponent.csarPackageType = csarComponent.csarPackageType;
- oldComponent.csarVersion = csarComponent.csarVersion;
- oldComponent.packageId = csarComponent.packageId;
- oldComponent.description = csarComponent.description;
- oldComponent.filterTerm = oldComponent.name + ' ' + oldComponent.description + ' ' + oldComponent.vendorName + ' ' + oldComponent.csarVersion
- return oldComponent;
- };
+ oldComponent.vendorName = csarComponent.vendorName;
+ oldComponent.vendorRelease = csarComponent.vendorRelease;
+ oldComponent.csarUUID = csarComponent.csarUUID;
+ oldComponent.csarPackageType = csarComponent.csarPackageType;
+ oldComponent.csarVersion = csarComponent.csarVersion;
+ oldComponent.packageId = csarComponent.packageId;
+ oldComponent.description = csarComponent.description;
+ oldComponent.filterTerm = oldComponent.name + ' ' + oldComponent.description + ' ' + oldComponent.vendorName + ' ' + oldComponent.csarVersion;
+ return oldComponent;
+ }
public createFromCsarComponent = (csar:ICsarComponent):Component => {
let newResource:Resource = <Resource>this.createEmptyComponent(ComponentType.RESOURCE);
@@ -126,7 +127,7 @@
}
// Fill the component with details from CSAR
- newResource.selectedCategory = selectedCategory && selectedSubCategory ? selectedCategory.name + "_#_" + selectedSubCategory.name : '';
+
newResource.categories = categories;
newResource.vendorName = csar.vendorName;
newResource.vendorRelease = csar.vendorRelease;
@@ -136,7 +137,8 @@
newResource.packageId = csar.packageId;
newResource.description = csar.description;
newResource.resourceType = csar.resourceType;
- newResource.filterTerm = newResource.name + ' ' + newResource.description + ' ' + newResource.vendorName + ' ' + newResource.csarVersion
+ newResource.selectedCategory = selectedCategory && selectedSubCategory ? selectedCategory.name + "_#_" + selectedSubCategory.name : '';
+ newResource.filterTerm = newResource.name + ' ' + newResource.description + ' ' + newResource.vendorName + ' ' + newResource.csarVersion;
return newResource;
};
@@ -183,7 +185,7 @@
let deferred = this.$q.defer<Component>();
let component = this.createEmptyComponent(componentType);
component.setUniqueId(componentId);
- this.ComponentServiceNg2.getComponentMetadata(component).subscribe((response:ComponentGenericResponse) => {
+ this.ComponentServiceNg2.getComponentMetadata(component.uniqueId, component.componentType).subscribe((response:ComponentGenericResponse) => {
component.setComponentMetadata(response.metadata);
deferred.resolve(component);
});
diff --git a/catalog-ui/src/app/utils/component-instance-factory.ts b/catalog-ui/src/app/utils/component-instance-factory.ts
index 25916cc..03abd96 100644
--- a/catalog-ui/src/app/utils/component-instance-factory.ts
+++ b/catalog-ui/src/app/utils/component-instance-factory.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.
@@ -21,14 +21,14 @@
* Created by obarda on 3/7/2016.
*/
'use strict';
-import {ComponentInstance, ServiceInstance, ResourceInstance, Component, ServiceProxyInstance} from "../models";
-import {ComponentType} from "app/utils";
-import {LeftPaletteComponent} from "../models/components/displayComponent";
+import { ComponentType } from 'app/utils';
+import { Component, ComponentInstance, ResourceInstance, ServiceInstance, ServiceProxyInstance } from '../models';
+import { LeftPaletteComponent } from '../models/components/displayComponent';
export class ComponentInstanceFactory {
- static createComponentInstance(componentInstance:ComponentInstance):ComponentInstance {
- let newComponentInstance:ComponentInstance;
+ static createComponentInstance(componentInstance: ComponentInstance): ComponentInstance {
+ let newComponentInstance: ComponentInstance;
switch (componentInstance.originType) {
case ComponentType.SERVICE:
newComponentInstance = new ServiceInstance(componentInstance);
@@ -41,10 +41,10 @@
break;
}
return newComponentInstance;
- };
+ }
- public createEmptyComponentInstance = (componentInstanceType?:string):ComponentInstance => {
- let newComponentInstance:ComponentInstance;
+ static createEmptyComponentInstance = (componentInstanceType?: string): ComponentInstance => {
+ let newComponentInstance: ComponentInstance;
switch (componentInstanceType) {
case ComponentType.SERVICE:
newComponentInstance = new ServiceInstance();
@@ -57,25 +57,32 @@
break;
}
return newComponentInstance;
- };
+ }
- public createComponentInstanceFromComponent = (component:LeftPaletteComponent):ComponentInstance => {
- let newComponentInstance:ComponentInstance = this.createEmptyComponentInstance(component.componentType);
+ static createComponentInstanceFromComponent = (component: LeftPaletteComponent): ComponentInstance => {
+ const newComponentInstance: ComponentInstance = ComponentInstanceFactory.createEmptyComponentInstance(component.componentType);
newComponentInstance.uniqueId = component.uniqueId + (new Date()).getTime();
newComponentInstance.posX = 0;
newComponentInstance.posY = 0;
newComponentInstance.name = component.name;
newComponentInstance.componentVersion = component.version;
- newComponentInstance.originType = component.getComponentSubType();
- if(component.getComponentSubType() === ComponentType.SERVICE){
- newComponentInstance.originType = ComponentType.SERVICE_PROXY
- }
- //new component instance -> req. & cap. are added on successful instance creation
+ newComponentInstance.originType = getOriginType(component);
newComponentInstance.requirements = component.requirements;
newComponentInstance.capabilities = component.capabilities;
newComponentInstance.icon = component.icon;
newComponentInstance.componentUid = component.uniqueId;
return newComponentInstance;
- };
+ function getOriginType(component: LeftPaletteComponent): string {
+ if (component.componentSubType) {
+ return component.componentSubType;
+ } else {
+ if (component.componentType === ComponentType.SERVICE) {
+ return ComponentType.SERVICE_PROXY;
+ } else {
+ return component.resourceType;
+ }
+ }
+ }
+ }
}
diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts
index 9d3bf10..e82322e 100644
--- a/catalog-ui/src/app/utils/constants.ts
+++ b/catalog-ui/src/app/utils/constants.ts
@@ -43,8 +43,20 @@
export class ServerTypeUrl {
static RESOURCES = 'resources/';
static SERVICES = 'services/';
+
+ public static toServerTypeUrl(componentType: ComponentType) : string {
+ if (componentType == ComponentType.SERVICE) {
+ return ServerTypeUrl.SERVICES.slice(0,-1);
+ } else if (componentType == ComponentType.RESOURCE) {
+ return ServerTypeUrl.RESOURCES.slice(0,-1);
+ } else {
+ return undefined;
+ }
+ }
}
+
+
export class ResourceType {
static VF = 'VF';
static VL = 'VL';
@@ -57,6 +69,11 @@
static CR = 'CR';
}
+export class SdcElementType {
+ static GROUP = 'GROUP';
+ static POLICY = 'POLICY';
+ static SERVICE_PROXY = 'ServiceProxy'
+}
export class ComponentState {
static CERTIFICATION_IN_PROGRESS = 'CERTIFICATION_IN_PROGRESS';
static CERTIFIED = 'CERTIFIED';
@@ -76,9 +93,15 @@
static DEPLOYMENT = "DEPLOYMENT";
static INFORMATION = "INFORMATIONAL";
static SERVICE_API = "SERVICE_API";
+ static TOSCA = "TOSCA";
}
export class ArtifactType {
+
+ static DEPLOYMENT = "DEPLOYMENT";
+ static INFORMATION = "INFORMATIONAL";
+ static SERVICE_API = "SERVICE_API";
+ static HEAT_ENV = "HEAT_ENV";
static HEAT = "HEAT";
static HEAT_VOL = "HEAT_VOL";
static HEAT_NET = "HEAT_NET";
@@ -202,6 +225,7 @@
static ERROR_TITLE = 'Error';
static DEFAULT_ERROR = 'Error getting response from server';
static MESSAGE_ERROR = 'Wrong error format from server';
+ static DOWNLOAD_ERROR = 'Download error';
}
export class GraphColors {
@@ -255,6 +279,8 @@
public static WORKSPACE_ACTIVITY_LOG = 'workspace.activity_log';
public static WORKSPACE_DEPLOYMENT_ARTIFACTS = 'workspace.deployment_artifacts';
public static WORKSPACE_PROPERTIES = 'workspace.properties';
+ public static WORKSPACE_SERVICE_INPUTS = 'workspace.service_inputs';
+ public static WORKSPACE_RESOURCE_INPUTS = 'workspace.resource_inputs';
public static WORKSPACE_ATTRIBUTES = 'workspace.attributes';
public static WORKSPACE_INFORMATION_ARTIFACTS = 'workspace.information_artifacts';
public static WORKSPACE_TOSCA_ARTIFACTS = 'workspace.tosca_artifacts';
@@ -287,6 +313,7 @@
static SHOW_LOADER_EVENT = "showLoaderEvent";
static HIDE_LOADER_EVENT = "hideLoaderEvent";
static UPDATE_PANEL = 'updatePanel';
+ static ON_DISTRIBUTION_SUCCESS = 'onDistributionSuccess';
}
@@ -312,6 +339,7 @@
static ON_PALETTE_COMPONENT_HOVER_OUT = 'onPaletteComponentHoverOut';
static ON_PALETTE_COMPONENT_DRAG_START = 'onPaletteComponentDragStart';
static ON_PALETTE_COMPONENT_DRAG_ACTION = 'onPaletteComponentDragAction';
+ static ON_PALETTE_COMPONENT_DROP = 'onPaletteComponentDrop';
static ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL = 'onPaletteComponentShowPopupPanel';
static ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL = 'onPaletteComponentHidePopupPanel';
static ON_COMPONENT_INSTANCE_NAME_CHANGED = 'onComponentInstanceNameChanged';
@@ -329,6 +357,7 @@
static ON_CANVAS_TAG_END = 'onCanvasTagEnd';
static ON_POLICY_INSTANCE_UPDATE = 'onPolicyInstanceUpdate';
static ON_GROUP_INSTANCE_UPDATE = 'onGroupInstanceUpdate';
+ static ON_SERVICE_PATH_CREATED = 'onServicePathCreated';
}
export class DEPENDENCY_EVENTS {
@@ -349,6 +378,7 @@
static COMPONENT_INFORMATIONAL_ARTIFACTS = "artifacts";
static COMPONENT_PROPERTIES = "properties";
static COMPONENT_CAPABILITIES = "capabilities";
+ static COMPONENT_CAPABILITIES_PROPERTIES = "instanceCapabiltyProperties";
static COMPONENT_REQUIREMENTS = "requirements";
static COMPONENT_TOSCA_ARTIFACTS = "toscaArtifacts";
static COMPONENT_POLICIES = "policies";
@@ -357,6 +387,8 @@
static COMPONENT_INSTANCES_INTERFACES = "componentInstancesInterfaces";
static COMPONENT_NON_EXCLUDED_GROUPS = "nonExcludedGroups";
static COMPONENT_NON_EXCLUDED_POLICIES = "nonExcludedPolicies";
+ static FORWARDING_PATHS = "forwardingPaths";
+ static SERVICE_API_ARTIFACT = "serviceApiArtifacts";
}
export class SERVICE_FIELDS {
diff --git a/catalog-ui/src/app/utils/menu-handler.ts b/catalog-ui/src/app/utils/menu-handler.ts
index eaef63f..e17012a 100644
--- a/catalog-ui/src/app/utils/menu-handler.ts
+++ b/catalog-ui/src/app/utils/menu-handler.ts
@@ -40,7 +40,6 @@
alertModal:string;
conformanceLevelModal: boolean; // Call validateConformanceLevel API and shows conformanceLevelModal if necessary, then continue with action or invokes another action
confirmationModal:string; // Open confirmation modal (user should select "OK" or "Cancel"), and continue with the action.
- emailModal:string; // Open email modal (user should fill email details), and continue with the action.
url:string; // Data added to menu item, in case the function need to use it, example: for function "changeLifecycleState", I need to pass also the state "CHECKOUT" that I want the state to change to.
diff --git a/catalog-ui/src/app/utils/modals-handler.ts b/catalog-ui/src/app/utils/modals-handler.ts
index 903175f..342f03f 100644
--- a/catalog-ui/src/app/utils/modals-handler.ts
+++ b/catalog-ui/src/app/utils/modals-handler.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.
@@ -18,25 +18,13 @@
* ============LICENSE_END=========================================================
*/
-import {PropertyModel, Component, ArtifactModel, Distribution, InputModel, DisplayModule, InputPropertyBase} from "../models";
-import {IEmailModalModel} from "../view-models/modals/email-modal/email-modal-view-model";
-import {IClientMessageModalModel} from "../view-models/modals/message-modal/message-client-modal/client-message-modal-view-model";
-import {IServerMessageModalModel} from "../view-models/modals/message-modal/message-server-modal/server-message-modal-view-model";
-import {IConfirmationModalModel} from "../view-models/modals/confirmation-modal/confirmation-modal-view-model";
-import {ModalType} from "./constants";
-import {AttributeModel} from "../models/attributes";
+import { Component, DisplayModule , PropertyModel } from '../models';
+import { ComponentMetadata } from '../models/component-metadata';
export interface IModalsHandler {
-
- openDistributionStatusModal (distribution:Distribution, status:string, component:Component):ng.IPromise<any>;
- openConfirmationModal (title:string, message:string, showComment:boolean, size?:string):ng.IPromise<any>;
- openAlertModal (title:string, message:string, size?:string):ng.IPromise<any>;
- openEmailModal(emailModel:IEmailModalModel):ng.IPromise<any>;
- openServerMessageModal(data:IServerMessageModalModel):ng.IPromise<any>;
- openClientMessageModal(data:IClientMessageModalModel):ng.IPromise<ng.ui.bootstrap.IModalServiceInstance>;
- openArtifactModal(artifact:ArtifactModel, component:Component):ng.IPromise<any>;
- openEditPropertyModal(property:PropertyModel, component:Component, filteredProperties:Array<PropertyModel>, isPropertyOwnValue:boolean, propertyOwnerType:string, propertyOwnerId:string):ng.IPromise<any>;
+ openEditPropertyModal(property: PropertyModel, component: Component, filteredProperties: PropertyModel[], isPropertyOwnValue: boolean,
+ propertyOwnerType: string, propertyOwnerId: string): ng.IPromise<any>;
}
export class ModalsHandler implements IModalsHandler {
@@ -46,230 +34,27 @@
'$q'
];
- constructor(private $uibModal:ng.ui.bootstrap.IModalService,
- private $q:ng.IQService) {
+ constructor(private $uibModal: ng.ui.bootstrap.IModalService,
+ private $q: ng.IQService) {
}
-
-
-
- openDistributionStatusModal = (distribution:Distribution, status:string, component:Component):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view.html',
- controller: 'Sdc.ViewModels.DistributionStatusModalViewModel',
- size: 'sdc-xl',
- backdrop: 'static',
- resolve: {
- data: ():any => {
- return {
- 'distribution': distribution,
- 'status': status,
- 'component': component
- };
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
-
- openAlertModal = (title:string, message:string, size?:string):ng.IPromise<any> => {
- return this.openConfirmationModalBase(title, message, false, ModalType.ALERT, size);
- };
-
- openConfirmationModal = (title:string, message:string, showComment:boolean, size?:string):ng.IPromise<any> => {
- return this.openConfirmationModalBase(title, message, showComment, ModalType.STANDARD, size);
- };
-
- private openConfirmationModalBase = (title:string, message:string, showComment:boolean, type:ModalType, size?:string):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/confirmation-modal/confirmation-modal-view.html',
- controller: 'Sdc.ViewModels.ConfirmationModalViewModel',
- size: size ? size : 'sdc-sm',
- backdrop: 'static',
- resolve: {
- confirmationModalModel: ():IConfirmationModalModel => {
- let model:IConfirmationModalModel = {
- title: title,
- message: message,
- showComment: showComment,
- type: type
- };
- return model;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- openEmailModal = (emailModel:IEmailModalModel):ng.IPromise<any> => {
-
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/email-modal/email-modal-view.html',
- controller: 'Sdc.ViewModels.EmailModalViewModel',
- size: 'sdc-sm',
- backdrop: 'static',
- resolve: {
- emailModalModel: ():IEmailModalModel => {
- return emailModel;
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
-
- };
-
- openServerMessageModal = (data:IServerMessageModalModel):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/message-modal/message-server-modal/server-message-modal-view.html',
- controller: 'Sdc.ViewModels.ServerMessageModalViewModel',
- size: 'sdc-sm',
- backdrop: 'static',
- resolve: {
- serverMessageModalModel: ():IServerMessageModalModel => {
- return data;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- openClientMessageModal = (data:IClientMessageModalModel):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/message-modal/message-client-modal/client-message-modal-view.html',
- controller: 'Sdc.ViewModels.ClientMessageModalViewModel',
- size: 'sdc-sm',
- backdrop: 'static',
- resolve: {
- clientMessageModalModel: ():IClientMessageModalModel => {
- return data;
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance);
- return deferred.promise;
- };
-
- openOnboadrdingModal = (okButtonText:string, currentCsarUUID?:string, currentCsarVersion?:string):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/onboarding-modal/onboarding-modal-view.html',
- controller: 'Sdc.ViewModels.OnboardingModalViewModel',
- size: 'sdc-xl',
- backdrop: 'static',
- resolve: {
- okButtonText: ():string=> {
- return okButtonText;
- },
- currentCsarUUID: ():string=> {
- return currentCsarUUID || null;
- },
- currentCsarVersion: ():string=> {
- return currentCsarVersion || null;
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- openUpdateIconModal = (component: Component):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
+ openUpdateIconModal = (component: Component): ng.IPromise<any> => {
+ const deferred = this.$q.defer();
+ const modalOptions: ng.ui.bootstrap.IModalSettings = {
templateUrl: '../view-models/modals/icons-modal/icons-modal-view.html',
controller: 'Sdc.ViewModels.IconsModalViewModel',
size: 'sdc-auto',
backdrop: 'static',
resolve: {
- component: ():Component => {
+ component: (): Component => {
return component;
}
}
};
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
+ const modalInstance: ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
deferred.resolve(modalInstance.result);
return deferred.promise;
- };
-
- openEditEnvParametersModal = (artifactResource:ArtifactModel, component?:Component):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/env-parameters-form/env-parameters-form.html',
- controller: 'Sdc.ViewModels.EnvParametersFormViewModel',
- size: 'sdc-xl',
- backdrop: 'static',
- resolve: {
- artifact: ():ArtifactModel => {
- return artifactResource;
- },
- component: ():Component => {
- return component;
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- openEditInputValueModal = (input:InputModel):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/input-form/input-form-view.html',
- controller: 'Sdc.ViewModels.InputFormViewModel',
- size: 'sdc-md',
- backdrop: 'static',
- resolve: {
- input: ():InputModel => {
- return input;
- }
- }
- };
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- openArtifactModal = (artifact:ArtifactModel, component:Component):ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/artifact-form/artifact-form-view.html',
- controller: 'Sdc.ViewModels.ArtifactResourceFormViewModel',
- size: 'sdc-md',
- backdrop: 'static',
- keyboard: false,
- resolve: {
- artifact: ():ArtifactModel => {
- return artifact;
- },
- component: ():Component => {
- return component;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
+ }
/**
*
@@ -281,158 +66,113 @@
* @param isPropertyValueOwner - boolean telling if the component is eligible of editing the property
* @returns {IPromise<T>} - Promise telling if the modal has opened or not
*/
- openEditPropertyModal = (property:PropertyModel, component:Component, filteredProperties:Array<PropertyModel>, isPropertyValueOwner:boolean, propertyOwnerType:string, propertyOwnerId:string):ng.IPromise<any> => {
- let deferred = this.$q.defer();
+ openEditPropertyModal = (property: PropertyModel, component: Component | ComponentMetadata, filteredProperties: PropertyModel[],
+ isPropertyValueOwner: boolean, propertyOwnerType: string, propertyOwnerId: string): ng.IPromise<any> => {
+ const deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
+ const modalOptions: ng.ui.bootstrap.IModalSettings = {
templateUrl: '../view-models/forms/property-forms/component-property-form/property-form-view.html',
controller: 'Sdc.ViewModels.PropertyFormViewModel',
size: 'sdc-l',
backdrop: 'static',
keyboard: false,
resolve: {
- property: ():PropertyModel => {
+ property: (): PropertyModel => {
return property;
},
- component: ():Component => {
- return <Component> component;
+ component: (): Component => {
+ return component as Component;
},
- filteredProperties: ():Array<PropertyModel> => {
+ filteredProperties: (): PropertyModel[] => {
return filteredProperties;
},
- isPropertyValueOwner: ():boolean => {
+ isPropertyValueOwner: (): boolean => {
return isPropertyValueOwner;
},
- propertyOwnerType: ():string => {
+ propertyOwnerType: (): string => {
return propertyOwnerType;
},
- propertyOwnerId: ():string => {
+ propertyOwnerId: (): string => {
return propertyOwnerId;
}
}
};
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
+ const modalInstance: ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
deferred.resolve(modalInstance.result);
return deferred.promise;
- };
+ }
+ /**
+ *
+ * This function openes up the edit property modal
+ *
+ * @param property - the property to edit
+ * @param filteredProperties - the filtered properties list to scroll between in the edit modal
+ * @param isPropertyValueOwner - boolean telling if the component is eligible of editing the property
+ * @returns {IPromise<T>} - Promise telling if the modal has opened or not
+ */
+ newOpenEditPropertyModal = (property: PropertyModel, filteredProperties: PropertyModel[], isPropertyValueOwner: boolean, propertyOwnerType: string, propertyOwnerId: string): ng.IPromise<any> => {
+ const deferred = this.$q.defer();
- openEditModulePropertyModal = (property:PropertyModel, component:Component, selectedModule:DisplayModule, filteredProperties:Array<PropertyModel>):ng.IPromise<any> => {
- let deferred = this.$q.defer();
+ const modalOptions: ng.ui.bootstrap.IModalSettings = {
+ templateUrl: '../view-models/forms/property-forms/component-property-form/property-form-view.html',
+ controller: 'Sdc.ViewModels.PropertyFormViewModel',
+ size: 'sdc-l',
+ backdrop: 'static',
+ keyboard: false,
+ resolve: {
+ property: (): PropertyModel => {
+ return property;
+ },
+ filteredProperties: (): PropertyModel[] => {
+ return filteredProperties;
+ },
+ isPropertyValueOwner: (): boolean => {
+ return isPropertyValueOwner;
+ },
+ propertyOwnerType: (): string => {
+ return propertyOwnerType;
+ },
+ propertyOwnerId: (): string => {
+ return propertyOwnerId;
+ }
+ }
+ };
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
+ const modalInstance: ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
+ deferred.resolve(modalInstance.result);
+ return deferred.promise;
+ }
+
+ openEditModulePropertyModal = (property: PropertyModel, component: Component, selectedModule: DisplayModule, filteredProperties: PropertyModel[]): ng.IPromise<any> => {
+ const deferred = this.$q.defer();
+
+ const modalOptions: ng.ui.bootstrap.IModalSettings = {
templateUrl: '../view-models/forms/property-forms/base-property-form/property-form-base-view.html',
controller: 'Sdc.ViewModels.ModulePropertyView',
size: 'sdc-l',
backdrop: 'static',
keyboard: false,
resolve: {
- originalProperty: ():PropertyModel => {
+ originalProperty: (): PropertyModel => {
return property;
},
- component: ():Component => {
- return <Component> component;
+ component: (): Component => {
+ return component as Component;
},
- selectedModule: ():DisplayModule => {
+ selectedModule: (): DisplayModule => {
return selectedModule;
},
- filteredProperties: ():Array<PropertyModel> => {
+ filteredProperties: (): PropertyModel[] => {
return filteredProperties;
}
}
};
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
+ const modalInstance: ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
deferred.resolve(modalInstance.result);
return deferred.promise;
- };
-
- openSelectDataTypeModal = (property:PropertyModel, component:Component, filteredProperties:Array<PropertyModel>, propertiesMap:Array<InputPropertyBase>):ng.IPromise<any> => {
- let deferred = this.$q.defer();
-
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/property-forms/base-property-form/property-form-base-view.html',
- controller: 'Sdc.ViewModels.SelectDataTypeViewModel',
- size: 'sdc-l',
- backdrop: 'static',
- keyboard: false,
- resolve: {
- originalProperty: ():PropertyModel => {
- return property;
- },
- component: ():Component => {
- return <Component> component;
- },
- filteredProperties: ():Array<PropertyModel> => {
- return filteredProperties;
- },
- propertiesMap: ():Array<InputPropertyBase>=> {
- return propertiesMap;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- public openEditAttributeModal = (attribute:AttributeModel, component: Component):void => {
-
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/attribute-form/attribute-form-view.html',
- controller: 'Sdc.ViewModels.AttributeFormViewModel',
- size: 'sdc-md',
- backdrop: 'static',
- keyboard: false,
- resolve: {
- attribute: ():AttributeModel => {
- return attribute;
- },
- component: ():Component => {
- return component;
- }
- }
- };
- this.$uibModal.open(modalOptions);
- };
-
- public openUpdateComponentInstanceNameModal = (currentComponent: Component):ng.IPromise<any> => {
- let deferred = this.$q.defer();
-
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/forms/resource-instance-name-form/resource-instance-name-view.html',
- controller: 'Sdc.ViewModels.ResourceInstanceNameViewModel',
- size: 'sdc-sm',
- backdrop: 'static',
- resolve: {
- component: ():Component => {
- return currentComponent;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
-
- public openConformanceLevelModal = ():ng.IPromise<any> => {
- let deferred = this.$q.defer();
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../view-models/modals/conformance-level-modal/conformance-level-modal-view.html',
- controller: 'Sdc.ViewModels.ConformanceLevelModalViewModel',
- size: 'sdc-sm',
- backdrop: 'static',
- resolve: {
-
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- deferred.resolve(modalInstance.result);
- return deferred.promise;
- };
+ }
}
diff --git a/catalog-ui/src/app/utils/validation-utils.ts b/catalog-ui/src/app/utils/validation-utils.ts
index cd90ba7..b7e43f7 100644
--- a/catalog-ui/src/app/utils/validation-utils.ts
+++ b/catalog-ui/src/app/utils/validation-utils.ts
@@ -97,25 +97,25 @@
}
};
- public getPropertyListPatterns():IMapRegex {
+ public static getPropertyListPatterns():IMapRegex {
return {
- integer: /^(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)(,?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+))*$/,
- string: /^"[\u0000-\u0021\u0023-\u00BF]+"(\s*,?\s*"[\u0000-\u0021\u0023-\u00BF]+")*$/,
- boolean: /^([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])(,?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]))*$/,
- float: /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?(,?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?)*$/
+ integer: /^$|^(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)(,?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+))*$/,
+ string: /^$|^"[\u0000-\u0021\u0023-\u00BF]+"(\s*,?\s*"[\u0000-\u0021\u0023-\u00BF]+")*$/,
+ boolean: /^$|^([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])(,?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]))*$/,
+ float: /^$|^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?(,?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?)*$/
};
}
- public getPropertyMapPatterns():IMapRegex {
+ public static getPropertyMapPatterns():IMapRegex {
return {
- integer: /^"\w+"\s*:\s?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)+(\s*,?\s*"\w+"\s?:\s?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)+)*$/,
- string: /^"\w+"\s?:\s?"[\u0000-\u0021\u0023-\u00BF]*"(\s*,?\s*"\w+"\s?:\s?"[\u0000-\u0021\u0023-\u00BF]*")*$/,
- boolean: /^"\w+"\s?:\s?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])(\s*,?\s*"\w+"\s?:\s?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]))*$/,
- float: /^"\w+"\s?:\s?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?(\s*,?\s*"\w+"\s?:\s?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?)*$/
+ integer: /^$|^"\w+"\s*:\s?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)+(\s*,?\s*"\w+"\s?:\s?(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)+)*$/,
+ string: /^$|^"\w+"\s?:\s?"[\u0000-\u0021\u0023-\u00BF]*"(\s*,?\s*"\w+"\s?:\s?"[\u0000-\u0021\u0023-\u00BF]*")*$/,
+ boolean: /^$|^"\w+"\s?:\s?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])(\s*,?\s*"\w+"\s?:\s?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]))*$/,
+ float: /^$|^"\w+"\s?:\s?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?(\s*,?\s*"\w+"\s?:\s?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?)*$/
};
}
- public validateUniqueKeys(viewValue:string):boolean {
+ public static validateUniqueKeys(viewValue: string): boolean {
if (!viewValue) {
return true; //allow empty value
}
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view-model.ts b/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view-model.ts
index c9ffe47..40a9e8f 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view-model.ts
+++ b/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view-model.ts
@@ -19,7 +19,7 @@
*/
'use strict';
-import {CacheService} from "app/services";
+import {CacheService} from "app/services-ng2";
import {IAppConfigurtaion} from "app/models";
interface IAdminDashboardViewModelScope extends ng.IScope {
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view-model.ts b/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view-model.ts
index c99f9e8..bb4c44d 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view-model.ts
+++ b/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view-model.ts
@@ -20,7 +20,8 @@
'use strict';
import {ModalsHandler, ValidationUtils} from "app/utils";
-import {CacheService, ICategoryResource} from "app/services";
+import {ICategoryResource} from "app/services";
+import {CacheService} from "app/services-ng2";
import {IAppConfigurtaion} from "app/models";
import {ComponentType} from "../../../utils/constants";
@@ -138,58 +139,6 @@
};
- scope.deleteCategory = (category:ICategoryResource, subCategory:ICategoryResource):void => {
-
- let onOk = ():void => {
-
- scope.isLoading = true;
- let type:string = scope.type;
-
- let onError = (response):void => {
- scope.isLoading = false;
- console.info('onFaild', response);
- };
-
- let onSuccess = (response:any):void => {
- let arr:Array<ICategoryResource>;
-
- if (!subCategory) {
- arr = this.$scope[type + 'Categories'];
- arr.splice(arr.indexOf(category), 1);
- if (category === scope.selectedCategory) {
- scope.selectedCategory = null;
- scope.selectedSubCategory = null;
- }
- } else {
- arr = category.subcategories;
- arr.splice(arr.indexOf(subCategory), 1);
- }
-
- scope.isLoading = false;
- };
-
- if (!subCategory) {
- category.$delete({
- types: type + "s",
- categoryId: category.uniqueId
- }
- , onSuccess, onError);
- } else {
- category.$deleteSubCategory({
- types: type + "s",
- categoryId: category.uniqueId,
- subCategoryId: subCategory.uniqueId,
- }
- , onSuccess, onError);
- }
- };
- let modelType:string = subCategory ? 'sub category' : 'category';
- let title:string = this.$filter('translate')("DELETE_CATEGORY_MODAL_HEADER", "{'modelType': '" + modelType + "' }");
- let message:string = this.$filter('translate')("DELETE_CATEGORY_MODAL_CATEGORY_NAME", "{'modelType': '" + modelType + "' }");
-
- this.ModalsHandler.openConfirmationModal(title, message, false, 'sdc-xsm').then(onOk);
- };
-
this.$scope.serviceCategories = this.cacheService.get('serviceCategories');
this.$scope.resourceCategories = this.cacheService.get('resourceCategories');
}
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view.html b/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view.html
index d7ee87e..30b71f2 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view.html
+++ b/catalog-ui/src/app/view-models/admin-dashboard/category-management/category-management-view.html
@@ -36,9 +36,6 @@
data-ng-click="selectCategory(category)"
data-tests-id="{{ type === SERVICE ? 'servicecategory' : 'resourcecategory' }}">
{{category.name}}
-
- <!--<button class="sprite e-sdc-small-icons-delete" data-ng-click="deleteCategory(category, null)" type="button"></button>-->
- <!--button class="sprite e-sdc-small-icons-pad" data-ng-click="" type="button"></button-->
</li>
</ul>
</perfect-scrollbar>
@@ -56,9 +53,6 @@
data-ng-click="selectSubCategory(subcategory)"
data-tests-id="subcategory">
{{subcategory.name}}
-
- <!--<button class="sprite e-sdc-small-icons-delete" data-ng-click="deleteCategory(selectedCategory, subcategory)" type="button"></button>-->
- <!--button class="sprite e-sdc-small-icon-pad" data-ng-click="" type="button"></button-->
</li>
</ul>
</perfect-scrollbar>
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts
index 45232b7..43ae75e 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts
+++ b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts
@@ -20,55 +20,40 @@
'use strict';
import * as _ from "lodash";
-import {ModalsHandler} from "app/utils";
-import {User, IUserProperties, IUser, IAppConfigurtaion} from "app/models";
-import {UserService} from "../../../ng2/services/user.service";
+import { User, IUserProperties, IUser, IAppConfigurtaion } from "app/models";
+import { UserService } from "../../../ng2/services/user.service";
+import { SdcUiCommon, SdcUiServices, SdcUiComponents } from "onap-ui-angular";
+import { AuthenticationService } from "app/ng2/services/authentication.service";
interface IUserManagementViewModelScope extends ng.IScope {
- sdcConfig:IAppConfigurtaion;
usersList:Array<IUserProperties>;
isLoading:boolean;
- isNewUser:boolean;
sortBy:string;
reverse:boolean;
tableHeadersList:any;
- roles:Array<string>;
- newUser:IUser;
- currentUser:IUserProperties;
- userIdValidationPattern:RegExp;
- editForm:ng.IFormController;
getAllUsers():void;
- editUserRole(user:IUserProperties);
sort(sortBy:string):void;
- createUser():void;
- deleteUser(userId:string):void;
- onEditUserPressed(user:IUserProperties):void;
- saveUserChanges(user:IUserProperties):void;
getTitle(role:string):string;
- clearForm():void;
-
}
export class UserManagementViewModel {
static '$inject' = [
'$scope',
- 'sdcConfig',
'UserServiceNg2',
- 'UserIdValidationPattern',
+ 'AuthenticationServiceNg2',
'$filter',
- 'ModalsHandler'
+ 'ModalServiceSdcUI'
];
constructor(private $scope:IUserManagementViewModelScope,
- private sdcConfig:IAppConfigurtaion,
private userService:UserService,
- private UserIdValidationPattern:RegExp,
+ private authService:AuthenticationService,
private $filter:ng.IFilterService,
- private ModalsHandler:ModalsHandler) {
+ private modalService:SdcUiServices.ModalService) {
- this.initScope();
+ setTimeout(this.initScope, 1000);
}
@@ -89,13 +74,8 @@
this.userService.getAllUsers().subscribe(onSuccess, onError);
};
- private updateUserFilterTerm = (user:IUserProperties):void => {
- user.filterTerm = user.firstName + ' ' + user.lastName + ' ' + user.userId + ' ' + user.email + ' ' + user.role + ' ' + this.$filter('date')(user.lastLoginTime, "MM/dd/yyyy");
- };
-
private initScope = ():void => {
let self = this;
-
this.$scope.tableHeadersList = [{title: "First Name", property: 'firstName'}, {
title: "Last Name",
property: 'lastName'
@@ -107,116 +87,18 @@
title: "Last Active",
property: 'lastLoginTime'
}];
- this.$scope.userIdValidationPattern = this.UserIdValidationPattern;
this.$scope.sortBy = 'lastLoginTime';
this.$scope.reverse = false;
- this.$scope.roles = this.sdcConfig.roles;
- this.$scope.isNewUser = false;
- this.$scope.currentUser = this.userService.getLoggedinUser();
this.getAllUsers();
- let userInfo:IUserProperties = <IUserProperties>{};
- this.$scope.newUser = new User(userInfo);
-
this.$scope.sort = (sortBy:string):void => {//default sort by descending last update. default for alphabetical = ascending
- this.$scope.isNewUser = false;
this.$scope.reverse = (this.$scope.sortBy === sortBy) ? ( !this.$scope.reverse) : this.$scope.reverse = false;
this.$scope.sortBy = sortBy;
};
- this.$scope.createUser = ():void => {
-
- let onError = (response) => {
- this.$scope.isLoading = false;
- console.info('onFaild', response);
- };
-
- let onSuccess = (response:IUserProperties) => {
- this.$scope.newUser.userInfo.lastLoginTime = "0";
- this.$scope.newUser.userInfo.status = response.status;
- this.updateUserFilterTerm(this.$scope.newUser.userInfo);
- this.$scope.usersList.push(this.$scope.newUser.userInfo);
- this.$scope.isNewUser = true;
- this.$scope.sortBy = null;
- this.$scope.reverse = true;
- this.$scope.isLoading = false;
- this.$scope.newUser = new User(null);
- this.$scope.editForm.$setPristine();
- let _self = this;
- setTimeout(function () {
- _self.$scope.isNewUser = false;
- }, 7000);
- };
- this.userService.createUser({
- userId: this.$scope.newUser.userInfo.userId,
- role: this.$scope.newUser.userInfo.role
- }).subscribe(onSuccess, onError);
- };
-
-
- this.$scope.onEditUserPressed = (user:IUserProperties):void => {
- user.isInEditMode = true;
- user.tempRole = user.role;
- };
-
- this.$scope.editUserRole = (user:IUserProperties):void => {
- let roleBeforeUpdate:string = user.role;
- user.role = user.tempRole;
-
- let onError = (response) => {
- this.$scope.isLoading = false;
- user.role = roleBeforeUpdate;
- console.info('onFaild', response);
- };
- let onSuccess = (response:any) => {
- this.$scope.isLoading = false;
- user.tempRole = user.role;
- this.updateUserFilterTerm(user);
- };
-
- this.userService.editUserRole(user.userId, user.role).subscribe(onSuccess, onError);
- };
-
- this.$scope.saveUserChanges = (user:IUserProperties):void => {
- if (user.tempRole != user.role) {
- this.$scope.editUserRole(user)
- }
- user.isInEditMode = false;
- };
-
- this.$scope.deleteUser = (userId:string):void => {
-
- let onOk = ():void => {
- this.$scope.isLoading = true;
-
- let onError = (response):void => {
- this.$scope.isLoading = false;
- console.info('onFaild', response);
- };
-
- let onSuccess = (response:any):void => {
- _.remove(this.$scope.usersList, {userId: userId});
- this.$scope.isLoading = false;
- };
- this.userService.deleteUser(userId).subscribe(onSuccess, onError);
- };
-
- let title:string = this.$filter('translate')("USER_MANAGEMENT_VIEW_DELETE_MODAL_TITLE");
- let message:string = this.$filter('translate')("USER_MANAGEMENT_VIEW_DELETE_MODAL_TEXT");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
-
this.$scope.getTitle = (role:string):string => {
return role.toLowerCase().replace('governor', 'governance_Rep').replace('_', ' ');
};
- this.$scope.clearForm = ():void => {
- if (!this.$scope.editForm['contactId'].$viewValue && !this.$scope.editForm['role'].$viewValue) {
- this.$scope.editForm.$setPristine();
- }
- //if(this.$scope.editForm['contactId'].$viewValue === '' && this.$scope.editForm['role'].$viewValue){
- // this.$scope.editForm.$setPristine();
- //}
- };
}
}
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html
index 9322ab0..89fd280 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html
+++ b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div ng-controller="Sdc.ViewModels.UserManagementViewModel">
<loader data-display="isLoading"></loader>
<div class="sdc-user-management-top-bar">
@@ -22,48 +21,6 @@
<input type="text" class="sdc-user-management-top-bar-form-input" placeholder="Search user by name, userId, email or role" data-ng-model="search.filterTerm" ng-model-options="{ debounce: 500 }" data-tests-id="searchbox" />
<span class="w-sdc-search-icon" data-ng-class="{'cancel':search.filterTerm, 'magnification':!search.filterTerm}" data-ng-click="search.filterTerm=''" ></span>
</div>
- <div class="vertical-border-container">
- <div class="vertical-border"></div>
- </div>
- <form class="sdc-user-management-top-bar-create-user-container w-sdc-form" name="editForm">
- <label class="sdc-user-management-top-bar-title">Create New User</label>
- <div class="sdc-user-management-top-bar-wrapper">
- <div class="i-sdc-form-item sdc-user-management-top-bar-form-container" data-ng-class="{error:(editForm.contactId.$dirty && editForm.contactId.$invalid)}">
- <input ng-focus="search.filterTerm=''" type="text"
- data-ng-model="newUser.userInfo.userId"
- class="i-sdc-form-input"
- placeholder="{{ USER_MANAGEMENT_SEARCH_TEXT | translate}}"
- data-ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 750, 'blur': 0 } }"
- name="contactId"
- data-ng-pattern="userIdValidationPattern"
- data-ng-change="clearForm()"
- data-ng-blur="clearForm()"
- data-required
- data-tests-id="newuserId" />
-
- <div class="input-error" data-ng-show="editForm.contactId.$dirty && editForm.contactId.$invalid">
- <span ng-show="editForm.contactId.$error.required" translate="NEW_USER_ERROR_USER_ID_REQUIRED"></span>
- <span ng-show="editForm.contactId.$error.pattern" translate="NEW_USER_ERROR_USER_ID_NOT_VALID"></span>
- </div>
- </div>
- <div class="i-sdc-form-item sdc-user-management-top-bar-form-container" data-ng-class="{error:(editForm.role.$dirty && editForm.role.$invalid
- && editForm.contactId.$viewValue)}">
- <select class="i-sdc-form-select capitalize"
- data-required
- name="role"
- data-tests-id="selectrole"
- data-ng-model = "newUser.userInfo.role"
- data-ng-options="role as (getTitle(role)) for role in roles | orderBy:'role'"
- ng-focus="search.filterTerm=''">
- <option value="">Select Role</option>
- </select>
- <div class="input-error" data-ng-show="editForm.role.$dirty && editForm.role.$invalid && editForm.contactId.$viewValue">
- <span ng-show="editForm.role.$error.required" translate="NEW_USER_ERROR_ROLE_REQUIRED"></span>
- </div>
- </div>
- <button data-tests-id="creategreen" data-ng-disabled="editForm.$invalid" class="sdc-user-management-top-bar-create-btn" ng-click="search.filterTerm = '' ; createUser()">Create</button>
- </div>
- </form>
</div>
@@ -74,15 +31,13 @@
<div class="sdc-user-management-table-header head-row hand sdc-user-management-flex-item" data-tests-id="th{{header.title}}" ng-repeat="header in tableHeadersList" ng-click="sort(header.property)">{{header.title}}
<span ng-if="sortBy === header.property" class="sdc-user-management-table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
</div>
- <div class="sdc-user-management-table-no-text-header head-row sdc-user-management-flex-item"></div>
- <div class="sdc-user-management-table-no-text-header head-row sdc-user-management-flex-item"></div>
</div>
<div class="body">
<perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
<div ng-init="user.filterTerm = user.firstName + ' ' + user.lastName + ' ' + user.userId + ' ' + user.email + ' ' + user.role + ' ' + (user.lastLoginTime | date: 'MM/dd/yyyy')"
ng-repeat="user in usersList | filter: search | orderBy:sortBy:reverse"
- data-ng-class="{'sdc-user-management-table-new-user-row': (isNewUser && $first), 'sdc-user-management-table-row-edit-mode': user.isInEditMode}"
+ data-ng-class="{'sdc-user-management-table-new-user-row': $first}"
class="sdc-user-management-flex-container data-row" data-tests-id="row_{{$index}}">
<div sdc-smart-tooltip class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="firstName_{{$index}}">{{user.firstName || '---'}}</div>
@@ -91,25 +46,10 @@
<div sdc-smart-tooltip class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="email_{{$index}}">{{user.email || '---'}}</div>
<div class="sdc-user-management-table-col-general sdc-user-management-flex-item">
<div class="sdc-user-management-table-role-select capitalize sdc-user-management-table-role-label"
- data-ng-if="!user.isInEditMode"
data-tests-id="role_{{$index}}"
data-ng-bind="getTitle(user.role)"></div>
- <select class="sdc-user-management-table-role-select capitalize"
- data-tests-id="selectRole_{{$index}}"
- data-ng-if="user.isInEditMode"
- data-ng-model="user.tempRole"
- data-ng-options="role as (getTitle(role)) for role in roles | orderBy:'role'">
- </select>
</div>
<div class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="lastActive_{{$index}}">{{user.lastLoginTime == 0 ? 'Waiting' : (user.lastLoginTime | date:'MM/dd/yyyy')}}</div>
- <div class="sdc-user-management-table-btn-col sdc-user-management-flex-item">
- <button data-ng-disabled="user.isInEditMode" data-ng-hide="user.isInEditMode || currentUser.userId === user.userId" class="sdc-user-management-table-edit-btn" ng-click="onEditUserPressed(user)" data-tests-id="updateUser_{{$index}}"> </button>
- <button data-ng-show="user.isInEditMode" class="sdc-user-management-table-save-btn" ng-click="saveUserChanges(user)" data-tests-id="save_{{$index}}"> </button>
- </div>
- <div class="sdc-user-management-table-btn-col sdc-user-management-flex-item">
- <button data-ng-hide="currentUser.userId === user.userId" class="sdc-user-management-table-delete-btn" ng-click="deleteUser(user.userId)" data-tests-id="delete_{{$index}}"> </button>
- </div>
-
</div>
</perfect-scrollbar>
</div>
diff --git a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management.less b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management.less
index 934faab..d152849 100644
--- a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management.less
+++ b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management.less
@@ -4,8 +4,7 @@
label {
.i_17;
}
- .sdc-user-management-top-bar-form-input,
- .sdc-user-management-top-bar-form-select {
+ .sdc-user-management-top-bar-form-input {
.b_9;
color: @color_b;
height: 28px;
@@ -29,57 +28,6 @@
top: 49px;
}
}
- .vertical-border-container {
- min-width: 50px;
- margin: 0px auto;
-
- .vertical-border {
-
- width: 1px;
- height: 70px;
- background-color: @color_e;
- display: table;
- margin: 0 auto;
- }
- }
-
- .sdc-user-management-top-bar-wrapper {
- display: flex;
- }
-
- .sdc-user-management-top-bar-title {
- .i_17;
- font-weight: bold;
- }
-
- .sdc-user-management-top-bar-create-user-container {
-
- display: flex;
- flex-direction: column;
- position: relative;
- float: right;
- padding-top: 0px;
- text-align: left;
- width: 650px;
-
- label {
- margin-bottom: 20px;
- }
-
- .sdc-user-management-top-bar-form-container {
- width: 233px;
- margin-right: 35px;
- }
-
- .sdc-user-management-top-bar-create-btn {
- .w-sdc-btn-light-green;
- height: 30px;
- width: 100px;
- line-height: 0px;
- padding-bottom: 3px;
- margin-right: 0px;
- }
- }
}
@@ -147,9 +95,6 @@
}
}
}
- &.sdc-user-management-table-row-edit-mode {
- .bg_j;
- }
div {
border-right: 1px solid @border_color_d;
@@ -176,33 +121,6 @@
}
}
-
- .sdc-user-management-table-btn-col {
-
- line-height: 0px;
- text-align: center;
- .sdc-user-management-table-delete-btn {
- background-color: transparent;
- border: none;
- .sprite;
- .sprite.e-sdc-small-icon-delete;
- opacity: 0.7;
- }
- .sdc-user-management-table-edit-btn {
- background-color: transparent;
- border: none;
- .sprite;
- .e-sdc-small-icon-pencil;
- opacity: 0.7;
- }
- .sdc-user-management-table-save-btn {
- background-color: transparent;
- border: none;
- .sprite;
- .sprite.e-sdc-green-save;
- }
- }
-
}
.sdc-user-management-flex-container {
diff --git a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts b/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts
deleted file mode 100644
index 8840afd..0000000
--- a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts
+++ /dev/null
@@ -1,680 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {Component, IMainCategory, IGroup, IConfigStatuses, IAppMenu, IAppConfigurtaion, IUserProperties, ISubCategory, ICategoryBase} from "app/models";
-import {EntityService, CacheService} from "app/services";
-import {ComponentFactory, ResourceType, MenuHandler, ChangeLifecycleStateHandler} from "app/utils";
-import {UserService} from "../../ng2/services/user.service";
-import {ArchiveService} from "../../ng2/services/archive.service";
-import { ICatalogSelector, CatalogSelectorTypes } from "../../models/catalogSelector";
-import {IConfigStatus} from "../../models/app-config";
-
-interface Checkboxes {
- componentTypes:Array<string>;
- resourceSubTypes:Array<string>;
-}
-
-interface CheckboxesFilter {
- // Types
- selectedComponentTypes:Array<string>;
- selectedResourceSubTypes:Array<string>;
- // Categories
- selectedCategoriesModel:Array<string>;
- // Statuses
- selectedStatuses:Array<Array<string>>;
-}
-
-interface Gui {
- isLoading:boolean;
- onComponentSubTypesClick:Function;
- onComponentTypeClick:Function;
- onCategoryClick:Function;
- onStatusClick:Function;
- changeFilterTerm:Function;
-}
-
-interface IFilterParams {
- components: string[];
- categories: string[];
- statuses: (string)[];
- order: [string, boolean];
- term: string;
- active: boolean;
-}
-
-interface ICategoriesMap {
- [key: string]: {
- category: ICategoryBase,
- parent: ICategoryBase
- }
-}
-
-export interface ICatalogViewModelScope extends ng.IScope {
- checkboxes:Checkboxes;
- checkboxesFilter:CheckboxesFilter;
- gui:Gui;
-
- categories:Array<IMainCategory>;
- confStatus:IConfigStatuses;
- sdcMenu:IAppMenu;
- catalogFilterdItems:Array<Component>;
- expandedSection:Array<string>;
- actionStrategy:any;
- user:IUserProperties;
- catalogMenuItem:any;
- version:string;
- sortBy:string;
- reverse:boolean;
- vfcmtType:string;
-
- //this is for UI paging
- numberOfItemToDisplay:number;
- isAllItemDisplay:boolean;
- catalogFilteredItemsNum:number;
- changeLifecycleState(entity:any, state:string):void;
- sectionClick (section:string):void;
- order(sortBy:string):void;
- getElementFoundTitle(num:number):string;
- goToComponent(component:Component):void;
- raiseNumberOfElementToDisplay():void;
-
- selectedCatalogItem: ICatalogSelector;
- catalogSelectorItems: Array<ICatalogSelector>;
- showCatalogSelector: boolean;
- catalogAllItems:Array<Component>; /* fake data */
- elementFoundTitle: string;
- elementTypeTitle: string;
-
- selectLeftSwitchItem (item: ICatalogSelector): void;
-}
-
-export class CatalogViewModel {
- static '$inject' = [
- '$scope',
- '$filter',
- 'Sdc.Services.EntityService',
- 'sdcConfig',
- 'sdcMenu',
- '$state',
- '$q',
- 'UserServiceNg2',
- 'Sdc.Services.CacheService',
- 'ComponentFactory',
- 'ChangeLifecycleStateHandler',
- 'MenuHandler',
- 'ArchiveServiceNg2'
- ];
-
- private defaultFilterParams:IFilterParams = {
- components: [],
- categories: [],
- statuses: [],
- order: ['lastUpdateDate', true],
- term: '',
- active: true
- };
- private categoriesMap:ICategoriesMap;
-
- constructor(private $scope:ICatalogViewModelScope,
- private $filter:ng.IFilterService,
- private EntityService:EntityService,
- private sdcConfig:IAppConfigurtaion,
- private sdcMenu:IAppMenu,
- private $state:ng.ui.IStateService,
- private $q:ng.IQService,
- private userService:UserService,
- private cacheService:CacheService,
- private ComponentFactory:ComponentFactory,
- private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
- private MenuHandler:MenuHandler,
- private ArchiveService:ArchiveService
- ) {
-
-
- this.initLeftSwitch();
- this.initScopeMembers();
- this.loadFilterParams();
- this.initCatalogData(); // Async task to get catalog from server.
- this.initScopeMethods();
- }
-
-
- private initLeftSwitch = ():void => {
- this.$scope.showCatalogSelector = false;
-
- this.$scope.catalogSelectorItems = [
- {value: CatalogSelectorTypes.Active, title: "Active Items", header: "Active"},
- {value: CatalogSelectorTypes.Archive, title: "Archive", header: "Archived"}
- ];
- // set active items is default
- this.$scope.selectedCatalogItem = this.$scope.catalogSelectorItems[0];
- };
-
- private initCatalogData = ():void => {
- if(this.$scope.selectedCatalogItem.value === CatalogSelectorTypes.Archive){
- this.getArchiveCatalogItems();
- } else {
- this.getActiveCatalogItems();
- }
- };
-
- private initScopeMembers = ():void => {
- // Gui init
- this.$scope.gui = <Gui>{};
- this.$scope.numberOfItemToDisplay = 0;
- this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')).map((cat) => <IMainCategory>cat);
- this.$scope.sdcMenu = this.sdcMenu;
- this.$scope.confStatus = this.sdcMenu.statuses;
- this.$scope.expandedSection = ["type", "category", "status"];
- this.$scope.user = this.userService.getLoggedinUser();
- this.$scope.catalogMenuItem = this.sdcMenu.catalogMenuItem;
-
- // Checklist init
- this.$scope.checkboxes = <Checkboxes>{};
- this.$scope.checkboxes.componentTypes = ['Resource', 'Service'];
- this.$scope.checkboxes.resourceSubTypes = ['VF', 'VFC', 'CR', 'PNF', 'CP', 'VL'];
- this.categoriesMap = this.initCategoriesMap();
-
- this.initCheckboxesFilter();
- this.$scope.version = this.cacheService.get('version');
- this.$scope.sortBy = 'lastUpdateDate';
- this.$scope.reverse = true;
-
- };
-
- private initCheckboxesFilter() {
- // Checkboxes filter init
- this.$scope.checkboxesFilter = <CheckboxesFilter>{};
- this.$scope.checkboxesFilter.selectedComponentTypes = [];
- this.$scope.checkboxesFilter.selectedResourceSubTypes = [];
- this.$scope.checkboxesFilter.selectedCategoriesModel = [];
- this.$scope.checkboxesFilter.selectedStatuses = [];
- }
-
- private initCategoriesMap(categoriesList?:(ICategoryBase)[], parentCategory:ICategoryBase=null): ICategoriesMap {
- categoriesList = (categoriesList) ? categoriesList : this.$scope.categories;
-
- // Init categories map
- return categoriesList.reduce((acc, cat) => {
- acc[cat.uniqueId] = {
- category: cat,
- parent: parentCategory
- };
- const catChildren = ((<IMainCategory>cat).subcategories)
- ? (<IMainCategory>cat).subcategories
- : (((<ISubCategory>cat).groupings)
- ? (<ISubCategory>cat).groupings
- : null);
- if (catChildren) {
- Object.assign(acc, this.initCategoriesMap(catChildren, cat));
- }
- return acc;
- }, <ICategoriesMap>{});
- }
-
- private initScopeMethods = ():void => {
- this.$scope.selectLeftSwitchItem = (item: ICatalogSelector): void => {
-
- if (this.$scope.selectedCatalogItem.value !== item.value) {
- this.$scope.selectedCatalogItem = item;
- switch (item.value) {
- case CatalogSelectorTypes.Active:
- this.getActiveCatalogItems(true);
- break;
-
- case CatalogSelectorTypes.Archive:
- this.getArchiveCatalogItems(true);
- break;
- }
- this.changeFilterParams({active: (item.value === CatalogSelectorTypes.Active)})
- }
- };
-
- this.$scope.sectionClick = (section: string): void => {
- let index: number = this.$scope.expandedSection.indexOf(section);
- if (index !== -1) {
- this.$scope.expandedSection.splice(index, 1);
- } else {
- this.$scope.expandedSection.push(section);
- }
- };
-
-
- this.$scope.order = (sortBy: string): void => {//default sort by descending last update. default for alphabetical = ascending
- this.changeFilterParams({
- order: (this.$scope.filterParams.order[0] === sortBy)
- ? [sortBy, !this.$scope.filterParams.order[1]]
- : [sortBy, sortBy === 'lastUpdateDate']
- });
- };
-
-
- this.$scope.goToComponent = (component: Component): void => {
- this.$scope.gui.isLoading = true;
- this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()});
- };
-
-
- // Will print the number of elements found in catalog
- this.$scope.getNumOfElements = (num:number):string => {
- if (!num || num === 0) {
- return `No <b>${this.$scope.selectedCatalogItem.header}</b> Elements found`;
- } else if (num === 1) {
- return `1 <b>${this.$scope.selectedCatalogItem.header}</b> Element found`;
- } else {
- return num + ` <b>${this.$scope.selectedCatalogItem.header}</b> Elements found`;
- }
- };
-
- /**
- * Select | unselect sub resource when resource is clicked | unclicked.
- * @param type
- */
- this.$scope.gui.onComponentTypeClick = (compType: string, checked?: boolean): void => {
- let components = angular.copy(this.$scope.filterParams.components);
- const compIdx = components.indexOf(compType);
- checked = (checked !== undefined) ? checked : compIdx === -1;
- if (checked && compIdx === -1) {
- components.push(compType);
- components = this.cleanSubsFromList(components);
- } else if (!checked && compIdx !== -1) {
- components.splice(compIdx, 1);
- }
- this.changeFilterParams({
- components: components
- });
- };
-
- /**
- * Selecting | unselect resources when sub resource is clicked | unclicked.
- */
- this.$scope.gui.onComponentSubTypesClick = (compSubType: string, compType: string, checked?: boolean): void => {
- const componentSubTypesCheckboxes = this.$scope.checkboxes[compType.toLowerCase() + 'SubTypes'];
- if (componentSubTypesCheckboxes) {
- let components = angular.copy(this.$scope.filterParams.components);
- let componentSubTypes = components.filter((st) => st.startsWith(compType + '.'));
-
- const compSubTypeValue = compType + '.' + compSubType;
- const compSubTypeValueIdx = components.indexOf(compSubTypeValue);
- checked = (checked !== undefined) ? checked : compSubTypeValueIdx === -1;
- if (checked && compSubTypeValueIdx === -1) {
- components.push(compSubTypeValue);
- componentSubTypes.push(compSubTypeValue);
-
- // if all sub types are checked, then check the main component type
- if (componentSubTypes.length === componentSubTypesCheckboxes.length) {
- this.$scope.gui.onComponentTypeClick(compType, true);
- return;
- }
- } else if (!checked) {
- const compIdx = components.indexOf(compType);
- // if sub type exists, then remove it
- if (compSubTypeValueIdx !== -1) {
- components.splice(compSubTypeValueIdx, 1);
- }
- // else, if sub type doesn't exists, but its parent main component type exists,
- // then remove the main type and push all sub types except the current
- else if (compIdx !== -1) {
- components.splice(compIdx, 1);
- componentSubTypesCheckboxes.forEach((st) => {
- if (st !== compSubType) {
- components.push(compType + '.' + st);
- }
- });
- }
- }
-
- this.changeFilterParams({
- components
- });
- }
- };
-
- this.$scope.gui.onCategoryClick = (category: ICategoryBase, checked?: boolean): void => {
- let categories: string[] = angular.copy(this.$scope.filterParams.categories);
- let parentCategory: ICategoryBase = this.categoriesMap[category.uniqueId].parent;
-
- // add the category to selected categories list
- const categoryIdx = categories.indexOf(category.uniqueId);
- checked = (checked !== undefined) ? checked : categoryIdx === -1;
- if (checked && categoryIdx === -1) {
- categories.push(category.uniqueId);
-
- // check if all parent category children are checked, then check the parent category
- if (parentCategory) {
- if (this.getParentCategoryChildren(parentCategory).every((ch) => categories.indexOf(ch.uniqueId) !== -1)) {
- this.$scope.gui.onCategoryClick(parentCategory, true);
- return;
- }
- }
-
- categories = this.cleanSubsFromList(categories);
- } else if (!checked) {
- // if category exists, then remove it
- if (categoryIdx !== -1) {
- categories.splice(categoryIdx, 1);
- }
- // else, if category doesn't exists, but one of its parent categories exists,
- // then remove that parent category and push all its children categories except the current
- else {
- let prevParentCategory: ICategoryBase = category;
- let additionalCategories: string[] = [];
- while (parentCategory) {
- // add parent category children to list for replacing the parent category (if will be found later)
- additionalCategories = additionalCategories.concat(
- this.getParentCategoryChildren(parentCategory)
- .filter((ch) => ch.uniqueId !== prevParentCategory.uniqueId)
- .map((ch) => ch.uniqueId));
-
- const parentCategoryIdx = categories.indexOf(parentCategory.uniqueId);
- if (parentCategoryIdx !== -1) {
- categories.splice(parentCategoryIdx, 1);
- categories = categories.concat(additionalCategories);
- break;
- } else {
- prevParentCategory = parentCategory;
- parentCategory = this.categoriesMap[parentCategory.uniqueId].parent;
- }
- }
- }
- }
-
- this.changeFilterParams({
- categories
- });
- };
-
- this.$scope.gui.onStatusClick = (statusKey: string, status: IConfigStatus, checked?: boolean) => {
- const statuses = angular.copy(this.$scope.filterParams.statuses);
-
- // add the status key to selected statuses list
- const statusIdx = statuses.indexOf(statusKey);
- checked = (checked !== undefined) ? checked : statusIdx === -1;
- if (checked && statusIdx === -1) {
- statuses.push(statusKey);
- } else if (!checked && statusIdx !== -1) {
- statuses.splice(statusIdx, 1);
- }
-
- this.changeFilterParams({
- statuses
- });
- };
-
- this.$scope.gui.changeFilterTerm = (filterTerm: string) => {
- this.changeFilterParams({
- term: filterTerm
- });
- };
-
- this.$scope.raiseNumberOfElementToDisplay = (): void => {
- this.$scope.numberOfItemToDisplay = this.$scope.numberOfItemToDisplay + 35;
- if (this.$scope.catalogFilterdItems) {
- this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.catalogFilterdItems.length;
- }
- };
-
- }
-
- private getAllCategoryChildrenIdsFlat(category:ICategoryBase) {
- let catChildrenIds = [];
- if ((<IMainCategory>category).subcategories) {
- catChildrenIds = (<IMainCategory>category).subcategories.reduce((acc, scat) => {
- return acc.concat(this.getAllCategoryChildrenIdsFlat(scat));
- }, (<IMainCategory>category).subcategories.map((scat) => scat.uniqueId));
- }
- else if ((<ISubCategory>category).groupings) {
- catChildrenIds = (<ISubCategory>category).groupings.map((g) => g.uniqueId);
- }
- return catChildrenIds;
- }
-
- private getParentCategoryChildren(parentCategory:ICategoryBase): ICategoryBase[] {
- if ((<IMainCategory>parentCategory).subcategories) {
- return (<IMainCategory>parentCategory).subcategories;
- } else if ((<ISubCategory>parentCategory).groupings) {
- return (<ISubCategory>parentCategory).groupings;
- }
- return [];
- }
-
- private cleanSubsFromList(list:Array<string>, delimiter:string='.', removeSubsList?:Array<string>) {
- let curRemoveSubsList = (removeSubsList || list).slice().sort(); // by default remove any children of any item in list
- while (curRemoveSubsList.length) {
- const curRemoveSubItem = curRemoveSubsList.shift();
- const removeSubListFilter = (x) => !x.startsWith(curRemoveSubItem + delimiter);
- list = list.filter(removeSubListFilter);
- curRemoveSubsList = curRemoveSubsList.filter(removeSubListFilter);
- }
- return list;
- }
-
- private applyFilterParamsToView(filterParams:IFilterParams) {
- // reset checkboxes filter
- this.initCheckboxesFilter();
-
- this.applyFilterParamsComponents(filterParams);
- this.applyFilterParamsCategories(filterParams);
- this.applyFilterParamsStatuses(filterParams);
- this.applyFilterParamsOrder(filterParams);
- this.applyFilterParamsTerm(filterParams);
- }
-
- private applyFilterParamsComponents(filterParams:IFilterParams) {
- const componentList = [];
- const componentSubTypesLists = {};
- filterParams.components.forEach((compStr) => {
- const compWithSub = compStr.split('.', 2);
- const mainComp = compWithSub[0];
- const subComp = compWithSub[1];
- if (!subComp) { // main component type
- componentList.push(mainComp);
-
- // if component type has sub types list, then add all component sub types
- const checkboxesSubTypeKey = mainComp.toLowerCase() + 'SubTypes';
- if (this.$scope.checkboxes.hasOwnProperty(checkboxesSubTypeKey)) {
- componentSubTypesLists[mainComp] = angular.copy(this.$scope.checkboxes[checkboxesSubTypeKey]);
- }
- } else { // sub component type
- // init component sub types list
- if (!componentSubTypesLists.hasOwnProperty(mainComp)) {
- componentSubTypesLists[mainComp] = [];
- }
- // add sub type to list if not exist
- if (componentSubTypesLists[mainComp].indexOf(subComp) === -1) {
- componentSubTypesLists[mainComp].push(subComp);
- }
- }
- });
- this.$scope.checkboxesFilter.selectedComponentTypes = componentList;
- Object.keys(componentSubTypesLists).forEach((tKey) => {
- const compSelectedSubTypeKey = 'selected' + tKey + 'SubTypes';
- if (this.$scope.checkboxesFilter.hasOwnProperty(compSelectedSubTypeKey)) {
- this.$scope.checkboxesFilter[compSelectedSubTypeKey] = componentSubTypesLists[tKey];
- }
- });
-
- let selectedCatalogIndex = filterParams.active ? CatalogSelectorTypes.Active : CatalogSelectorTypes.Archive;
- this.$scope.selectedCatalogItem = this.$scope.catalogSelectorItems[selectedCatalogIndex];
-
- }
-
- private applyFilterParamsCategories(filterParams:IFilterParams) {
- this.$scope.checkboxesFilter.selectedCategoriesModel = filterParams.categories.reduce((acc, c) => {
- acc.push(c);
- const cat = this.categoriesMap[c].category;
- if (cat) {
- acc = acc.concat(this.getAllCategoryChildrenIdsFlat(cat));
- }
- return acc;
- }, []);
- }
-
- private getActiveCatalogItems(forceReload?: boolean): void {
-
- if (forceReload || this.componentShouldReload()) {
- this.$scope.gui.isLoading = true;
- let onSuccess = (followedResponse:Array<Component>):void => {
- this.updateCatalogItems(followedResponse);
- this.$scope.gui.isLoading = false;
- this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); //catalog
- this.cacheService.set('breadcrumbsComponents', followedResponse);
- };
-
- let onError = ():void => {
- console.info('Failed to load catalog CatalogViewModel::getActiveCatalogItems');
- this.$scope.gui.isLoading = false;
- };
- this.EntityService.getCatalog().then(onSuccess, onError);
- } else {
- let cachedComponents = this.cacheService.get('breadcrumbsComponents');
- this.updateCatalogItems(cachedComponents);
- }
- }
-
- private getArchiveCatalogItems(forceReload?: boolean): void {
- if(forceReload || !this.cacheService.contains("archiveComponents")) {
- this.$scope.gui.isLoading = true;
- let onSuccess = (followedResponse:Array<Component>):void => {
- this.cacheService.set("archiveComponents", followedResponse);
- this.updateCatalogItems(followedResponse);
- this.$scope.gui.isLoading = false;
- };
-
- let onError = ():void => {
- console.info('Failed to load catalog CatalogViewModel::getArchiveCatalogItems');
- this.$scope.gui.isLoading = false;
- };
-
- this.ArchiveService.getArchiveCatalog().subscribe(onSuccess, onError);
- } else {
- let archiveCache = this.cacheService.get("archiveComponents");
- this.updateCatalogItems(archiveCache);
- }
-
- }
-
- private updateCatalogItems = (items:Array<Component>):void => {
- this.$scope.catalogFilterdItems = items;
- this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.catalogFilterdItems.length;
- this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories'));
- }
-
- private componentShouldReload = ():boolean => {
- let breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
- return !breadcrumbsValid || this.isDefaultFilter();
- }
-
- private isDefaultFilter = (): boolean => {
- return angular.equals(this.defaultFilterParams, this.$scope.filterParams);
- }
-
- private applyFilterParamsStatuses(filterParams: IFilterParams) {
- this.$scope.checkboxesFilter.selectedStatuses = filterParams.statuses.reduce((acc, stKey:string) => {
- const status = this.$scope.confStatus[stKey];
- if (status) {
- acc.push(status.values);
- }
- return acc;
- }, []);
- }
-
- private applyFilterParamsOrder(filterParams: IFilterParams) {
- this.$scope.sortBy = filterParams.order[0];
- this.$scope.reverse = filterParams.order[1];
- }
-
- private applyFilterParamsTerm(filterParams: IFilterParams) {
- this.$scope.search = {
- filterTerm: filterParams.term
- };
- }
-
- private loadFilterParams() {
- const params = this.$state.params;
- this.$scope.filterParams = angular.copy(this.defaultFilterParams);
- Object.keys(params).forEach((k) => {
- if (!angular.isUndefined(params[k])) {
- let newVal;
- let filterKey = k.substr('filter.'.length);
- switch (k) {
- case 'filter.components':
- case 'filter.categories':
- newVal = _.uniq(params[k].split(','));
- newVal = this.cleanSubsFromList(newVal);
- break;
- case 'filter.statuses':
- newVal = _.uniq(params[k].split(','));
- break;
- case 'filter.order':
- newVal = params[k].startsWith('-') ? [params[k].substr(1), true] : [params[k], false];
- break;
- case 'filter.term':
- newVal = params[k];
- break;
- case 'filter.active':
- newVal = (params[k] === "true" || params[k] === true);
- break;
- default:
- // unknown filter key
- filterKey = null;
- }
- if (filterKey) {
- this.$scope.filterParams[filterKey] = newVal;
- }
- }
- });
- // re-set filter params with valid values
- this.applyFilterParamsToView(this.$scope.filterParams);
-
- }
-
- private changeFilterParams(changedFilterParams) {
- const newParams = {};
- Object.keys(changedFilterParams).forEach((k) => {
- let newVal;
- switch (k) {
- case 'components':
- case 'categories':
- case 'statuses':
- newVal = changedFilterParams[k] && changedFilterParams[k].length ? changedFilterParams[k].join(',') : null;
- break;
- case 'order':
- newVal = (changedFilterParams[k][1] ? '-' : '') + changedFilterParams[k][0];
- break;
- case 'term':
- newVal = changedFilterParams[k] ? changedFilterParams[k] : null;
- break;
- case 'active':
- newVal = changedFilterParams[k];
- break;
- default:
- return;
- }
- this.$scope.filterParams[k] = changedFilterParams[k];
- newParams['filter.' + k] = newVal;
- });
- this.$state.go('.', newParams, {location: 'replace', notify: false}).then(() => {
- this.applyFilterParamsToView(this.$scope.filterParams);
- });
- }
-}
diff --git a/catalog-ui/src/app/view-models/catalog/catalog-view.html b/catalog-ui/src/app/view-models/catalog/catalog-view.html
deleted file mode 100644
index 25fa561..0000000
--- a/catalog-ui/src/app/view-models/catalog/catalog-view.html
+++ /dev/null
@@ -1,209 +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="sdc-catalog-container">
-
- <loader data-display="gui.isLoading"></loader>
-<!--
- <ecomp-header menu-data="menuItems" version="{{version}}"></ecomp-header>
--->
-
- <div class="w-sdc-main-container">
-
- <div
- class="i-sdc-designer-leftbar-section-left-switch-header"
- data-tests-id="catalog-selector-button"
- data-ng-click="showCatalogSelector=!showCatalogSelector">
- <div class="i-sdc-designer-leftbar-section-left-switch-header-text">
- {{selectedCatalogItem.title}}
- </div>
- <div class="i-sdc-designer-leftbar-section-left-switch-header-icon sprite-new arrow-up-small"> </div>
-
- <div
- class="sdc-catalog-selector-wrapper"
- data-ng-show="showCatalogSelector">
- <div
- class="sdc-catalog-selector-item"
- data-ng-repeat="leftSwitchItem in catalogSelectorItems track by $index"
- data-tests-id="catalog-selector-{{leftSwitchItem.value}}"
- data-ng-click="selectLeftSwitchItem(leftSwitchItem)">
- <span>{{leftSwitchItem.title}}</span>
- </div>
- </div>
- </div>
-
- <!-- LEFT SIDE -->
- <perfect-scrollbar scroll-y-margin-offset="0" class="sdc-catalog-body-container w-sdc-left-sidebar i-sdc-designer-left-sidebar" include-padding="true">
- <div class="sdc-catalog-leftbar-container">
- <div class="sdc-catalog-type-filter-container">
- <div
- class="i-sdc-designer-leftbar-section-title pointer"
- data-ng-click="sectionClick('type')"
- data-ng-class="{'expanded': expandedSection.indexOf('type') !== -1}">
- <span class="i-sdc-designer-leftbar-section-title-icon"></span>
- <span class="i-sdc-designer-leftbar-section-title-text" data-tests-id="typeFilterTitle">Type</span>
- </div>
- <div class="i-sdc-designer-leftbar-section-content">
- <ul class="list-unstyled i-sdc-designer-leftbar-section-content-ul">
- <li class="i-sdc-designer-leftbar-section-content-ul-li" data-ng-repeat="type in checkboxes.componentTypes">
-
- <ng1-checkbox elem-id="checkbox-{{type | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedComponentTypes"
- sdc-checklist-value="type"
- sdc-checked-change="gui.onComponentTypeClick(type, checked)"
- text="{{type}}"></ng1-checkbox>
-
- <ul class="list-unstyled i-sdc-catalog-subcategories-checkbox" data-ng-if="type==='Resource'">
- <li data-ng-repeat="subType in checkboxes.resourceSubTypes">
-
- <ng1-checkbox elem-id="checkbox-{{subType | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedResourceSubTypes"
- sdc-checklist-value="subType"
- sdc-checked-change="gui.onComponentSubTypesClick(subType, type, checked)"
- text="{{subType}}"></ng1-checkbox>
-
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
-
- <div class="sdc-catalog-categories-filter-container">
- <div
- class="i-sdc-designer-leftbar-section-title pointer"
- data-ng-click="sectionClick('category')"
- data-ng-class="{'expanded': expandedSection.indexOf('category') !== -1}">
- <span class="i-sdc-designer-leftbar-section-title-icon"></span>
- <span class="i-sdc-designer-leftbar-section-title-text" data-tests-id="categoriesFilterTitle">Categories</span>
- </div>
- <div class="i-sdc-designer-leftbar-section-content">
- <!-- CATEGORY CHECKBOX -->
- <ul class="list-unstyled i-sdc-designer-leftbar-section-content-ul">
- <li class="i-sdc-designer-leftbar-section-content-ul-li"
- data-ng-repeat="category in categories | categoryTypeFilter:checkboxesFilter.selectedComponentTypes:checkboxesFilter.selectedResourceSubTypes | orderBy: category">
-
- <ng1-checkbox elem-id="checkbox-{{category.uniqueId | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedCategoriesModel"
- sdc-checklist-value="category.uniqueId"
- sdc-checked-change="gui.onCategoryClick(category, checked)"
- data-tests-id="{{category.uniqueId}}"
- text="{{category.name}}"></ng1-checkbox>
-
- <!-- SUB CATEGORY CHECKBOX -->
- <ul class="list-unstyled i-sdc-catalog-subcategories-checkbox" data-ng-if="category.subcategories && category.subcategories.length>0">
- <li ng-repeat="subcategory in category.subcategories track by subcategory.uniqueId | orderBy:'name'">
-
- <ng1-checkbox elem-id="checkbox-{{subcategory.uniqueId | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedCategoriesModel"
- sdc-checklist-value="subcategory.uniqueId"
- sdc-checked-change="gui.onCategoryClick(subcategory, checked)"
- data-tests-id="{{subcategory.uniqueId}}"
- text="{{subcategory.name}}"></ng1-checkbox>
-
- <!-- GROUPING CHECKBOX -->
- <ul class=" list-unstyled i-sdc-catalog-grouping-checkbox" data-ng-if="subcategory.groupings && subcategory.groupings.length>0">
- <li ng-repeat="grouping in subcategory.groupings track by grouping.uniqueId | orderBy:'name'">
-
- <ng1-checkbox elem-id="checkbox-{{grouping.uniqueId | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedCategoriesModel"
- sdc-checklist-value="grouping.uniqueId"
- sdc-checked-change="gui.onCategoryClick(grouping, checked)"
- text="{{grouping.name}}"></ng1-checkbox>
-
- </li>
- </ul>
- </li><!-- Close subcategory -->
- </ul><!-- Close subcategories -->
- </li><!-- Close main category -->
- </ul><!-- Close main categories -->
-
- </div>
- </div>
-
- <!-- STATUS -->
- <div class="sdc-catalog-status-filter-container">
- <div
- class="i-sdc-designer-leftbar-section-title pointer"
- data-ng-click="sectionClick('status')"
- data-ng-class="{'expanded': expandedSection.indexOf('status') !== -1}">
- <span class="i-sdc-designer-leftbar-section-title-icon"></span>
- <span class="i-sdc-designer-leftbar-section-title-text" data-tests-id="statusFilterTitle">Status</span>
- </div>
-
- <div class="i-sdc-designer-leftbar-section-content">
- <ul class="list-unstyled i-sdc-designer-leftbar-section-content-ul">
- <!--li data-ng-repeat="(key, value) in confStatus" -->
-
- <li class="i-sdc-designer-leftbar-section-content-ul-li"
- data-ng-repeat="(key, state) in confStatus">
-
- <ng1-checkbox elem-id="checkbox-{{key | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="checkboxesFilter.selectedStatuses"
- sdc-checklist-value="state.values"
- sdc-checked-change="gui.onStatusClick(key, state, checked)"
- text="{{state.name}}"></ng1-checkbox>
-
- <div class="i-sdc-categories-list-item-icon"></div>
- </li>
- </ul>
- </div>
- </div>
-
- </div>
- </perfect-scrollbar>
-
- <!-- RIGHT SIDE -->
- <perfect-scrollbar id="catalog-main-scroll" include-padding="true" class="w-sdc-main-right-container w-sdc-catalog-main">
-
- <!-- HEADER -->
- <div>
- <div class="w-sdc-dashboard-catalog-items-header"
- ng-bind-html="getNumOfElements((catalogFilterdItems| entityFilter:checkboxesFilter | filter:search).length)"
- ></div>
- <div class="w-sdc-dashboard-catalog-header-right">
- <span class="w-sdc-dashboard-catalog-header-order1" translate="SORT_CAPTION"></span>
- <a class="w-sdc-dashboard-catalog-sort" data-tests-id="sort-by-last-update" data-ng-class="{'blue' : sortBy==='lastUpdateDate'}"
- ng-click="order('lastUpdateDate')" translate="SORT_BY_UPDATE_DATE"></a>
- <span data-ng-show="sortBy === 'lastUpdateDate'" class="w-sdc-catalog-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"></span>
- |
- <a class="w-sdc-dashboard-catalog-sort" data-tests-id="sort-by-alphabetical" data-ng-class="{'blue' : sortBy!=='lastUpdateDate'}"
- ng-click="order('name|resourceName')" translate="SORT_ALPHABETICAL"></a>
- <span data-ng-show="sortBy !== 'lastUpdateDate'" class="w-sdc-catalog-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"></span>
- </div>
- </div>
-
- <div infinite-scroll-disabled='isAllItemDisplay' infinite-scroll="raiseNumberOfElementToDisplay()" infinite-scroll-container="'#catalog-main-scroll'" infinite-scroll-distance="'0.2'" infinite-scroll-parent>
-
- <div class='w-sdc-row-flex-items'>
-
- <!-- Tile new -->
- <ng2-ui-tile data-ng-repeat="component in catalogFilterdItems| entityFilter:checkboxesFilter | filter:search | orderBy:sortBy:reverse | limitTo:numberOfItemToDisplay"
- data-ng-init="component.filterTerm = component.name + ' ' + component.description + ' ' + component.tags.toString() + ' ' + component.version;"
- [component]="component" (on-tile-click)="gui.isLoading || goToComponent(component)"></ng2-ui-tile>
- <!-- Tile new -->
-
- </div>
-
- </div>
- </perfect-scrollbar>
-
- </div>
-
- <top-nav [top-lvl-selected-index]="1" [search-term]="search.filterTerm" (search-term-change)="gui.changeFilterTerm($event)" [version]="version"></top-nav>
-
-
-</div>
diff --git a/catalog-ui/src/app/view-models/catalog/catalog.less b/catalog-ui/src/app/view-models/catalog/catalog.less
deleted file mode 100644
index 4555603..0000000
--- a/catalog-ui/src/app/view-models/catalog/catalog.less
+++ /dev/null
@@ -1,362 +0,0 @@
-.sdc-catalog-container {
-
- .i-sdc-categories-list-item {
- font-weight: normal;
- }
-
- // Checkboxes
- .i-sdc-designer-leftbar-section-content-ul {
- padding: 0;
- margin: 0;
-
- .i-sdc-designer-leftbar-section-content-ul-li {
- margin-top: 5px;
-
- .tlv-checkbox {
- font-size: 13px;
- font-family: @font-opensans-medium;
- color: @func_color_s;
- }
- }
-
- .i-sdc-catalog-subcategories-checkbox {
- padding: 0 0 0 20px;
- margin: 0;
-
- > li {
- margin-top: 5px;
-
- .tlv-checkbox {
- font-size:13px;
- font-family: @font-opensans-regular;
- }
- }
-
- .i-sdc-catalog-grouping-checkbox {
- padding: 0 0 0 20px;
- margin: 0;
- }
-
- }
-
- }
-
- .i-sdc-designer-leftbar-section-content-li {
- &:last-child {
- .i-sdc-categories-list-item {
- margin: 0;
- }
- }
- }
-
- .i-sdc-categories-list-item {
- display: block;
- //margin-bottom: 5px;
- //padding-left: 15px;
- //text-indent: -24px;
- vertical-align: top;
- font-weight: bold;
- }
-
- .i-sdc-subcategories-list-item {
- display: block;
- //padding-left: 20px;
- vertical-align: top;
- font-weight: normal;
- margin: 0;
- //text-indent: -10px;
- }
-
- .i-sdc-categories-list-item-icon {
- display: inline-block;
- float: right;
- position: relative;
- right: -8px;
- top: 6px;
- }
-
- .i-sdc-categories-list-item {
- margin-top: 7px;
- &.NOT_CERTIFIED_CHECKOUT,
- &.NOT_CERTIFIED_CHECKIN {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2889px;
- width: 14px;
- height: 14px;
-
- }
- }
-
- &.CERTIFIED {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -3034px;
- width: 14px;
- height: 16px;
- }
- }
-
- &.READY_FOR_CERTIFICATION {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2985px;
- width: 14px;
- height: 16px;
- }
- }
-
- &.CERTIFICATION_IN_PROGRESS {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2934px;
- width: 14px;
- height: 16px;
- }
- }
-
- &.DISTRIBUTED,
- &.TBD {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -43px -3087px;
- width: 24px;
- height: 14px;
-
- }
- }
- }
-
- .i-sdc-categories-list-input {
- margin: 8px;
-
- }
-
- .i-sdc-subcategories-list-input {
-
- margin: 8px;
- }
- .i-sdc-subcategories-list-input-container {
- margin: 0px 0px 0px 20px;
- padding: 2px;
- }
-
- .w-sdc-header-catalog-search-container {
- display: table;
- padding: 21px 0;
- position: relative;
-
- .w-sdc-designer-leftbar-search-input {
- color: #000;
- width: 300px;
- }
- }
-
- .w-sdc-catalog-main {
- padding: 10px 12px;
- }
- .w-sdc-dashboard-catalog-items-header {
- .b_3;
- color: @main_color_m;
- font-family: OpenSans-Regular, sans-serif;
- font-size: 14px;
- display: inline-block;
- font-style: normal;
- margin-left: 11px;
- b {
- font-family: OpenSans-Bold, sans-serif;
- color: @main_color_l;
- font-weight: bold;
- }
- font-weight: normal;
- /* padding-left: 10px; */
- }
-
- .w-sdc-dashboard-catalog-header-order1 {
- .b_3;
- font-weight: 800;
- }
-
- .w-sdc-dashboard-catalog-sort {
- .b_3;
- font-weight: bold;
- white-space:pre;
- &:hover{
- .hand;
- text-decoration: none;
- .a_3;
- }
- &.blue {
- .a_3;
- }
- }
-
- .w-sdc-catalog-sort-arrow{
- display: inline-block;
- &.up{
- .b_3;
- width: 0;
- height: 0;
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- border-bottom: 5px solid ;
- }
- &.down{
- .b_3;
- width: 0;
- height: 0;
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- border-top: 5px solid;
- }
- }
-
-
- .w-sdc-dashboard-catalog-header-right{
- float: right;
- display: inline-block;
- padding-right:34px;
- }
-
- .w-sdc-header-catalog-search-input {
- width: 420px;
- display: table-cell;
- padding: 0 25px 1px 10px;
- border: 1px solid #bcbcbc;
- .border-radius(10px);
- height: 30px;
- margin: 10px 30px;
- outline: none;
- }
-
- .sdc-catalog-type-filter-container {
- margin-top: -1px;
- }
-
- .i-sdc-designer-leftbar-section-title {
- text-transform: uppercase;
- .l_14_m;
- line-height: 30px;
- }
-
- .i-sdc-designer-leftbar-section-title-icon {
- .hand;
- .tlv-sprite;
- .footer-close;
- transition: .3s all;
- margin-top: -4px;
- }
-
- .i-sdc-designer-leftbar-section-title-text {
- margin-left: 20px;
- }
-
- /* added Michael */
- .i-sdc-designer-left-sidebar {
- margin-top: 43px;
- }
- .i-sdc-designer-leftbar-section-left-switch-header {
- text-transform: uppercase;
- .l_14_m;
- line-height: 40px;
- width: 243px;
-
- font-family: OpenSans-Bold, sans-serif;
- font-size: 14px;
-
- color: @main_color_a;
- background-color: @tlv_color_t;
- border: solid 1px fade(@main_color_t, 40%);
- cursor: pointer;
- opacity: 1;
- z-index: 9999;
- position: relative;
- //box-shadow: 1px 0 2px #00000036;
- }
- .i-sdc-designer-leftbar-section-left-switch-header-text {
- display: inline-block;
- width: 180px;
- margin-left: 20px;
- }
- .i-sdc-designer-leftbar-section-left-switch-header-icon {
- display: inline-block;
- vertical-align: middle;
- }
-
-
- .seperator-left,
- .seperator-right {
- border-right: solid 1px @color_m;
- display: table-cell;
- width: 2px;
- }
-
- // Rotate catalog left side arrows
- .i-sdc-designer-leftbar-section-title.expanded .i-sdc-designer-leftbar-section-title-icon {
- transform: rotate(180deg);
- }
-
- // Transform catalog left side sections
- .i-sdc-designer-leftbar-section-title + .i-sdc-designer-leftbar-section-content {
- max-height: 0px;
- margin: 0 auto;
- transition: all .3s;
- overflow: hidden;
- padding: 0 10px 0 18px;
- }
-
- .i-sdc-designer-leftbar-section-title.expanded + .i-sdc-designer-leftbar-section-content {
- max-height: 9999px;
- margin: 0 auto 1px;
- transition: all .3s;
- padding: 10px 18px 10px 18px;
- overflow: hidden;
- }
-
-}
-
-.w-sdc-search-icon{
- position: absolute;
- right: 40px;
- top: 40px;
- &.leftbar{
- top: 19px;
- right: 18px;
- }
- &.magnification {
- .sprite;
- .sprite.magnification-glass;
- .hand;
- }
-
- &.cancel {
- .sprite;
- .sprite.clear-text;
- .hand;
- }
-}
-
-/* added Michael */
-.sdc-catalog-selector-wrapper {
- position: absolute;
- left: 0px;
- top: 42px;
- width: 241px;
- height: auto;
- cursor: pointer;
- opacity: 1;
- z-index: 1000;
- box-shadow: 1px 2px 3px #b1b1b1;
-}
-
-.sdc-catalog-selector-item {
- text-transform: none;
- line-height: 40px;
- font-family: OpenSans-Bold, sans-serif;
- font-size: 14px;
- color: @main_color_l;
- background-color: @main_color_p;
- padding-left: 20px;
-}
-
-.sdc-catalog-selector-item:hover {
- color: @main_color_a;
- background-color: @tlv_color_v;
-}
-
-
diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts b/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts
deleted file mode 100644
index 4d08404..0000000
--- a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts
+++ /dev/null
@@ -1,497 +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=========================================================
- */
-
-'use strict';
-import {IConfigRoles, IAppConfigurtaion, IAppMenu, IUserProperties, Component} from "app/models";
-import {EntityService, SharingService, CacheService} from "app/services";
-import {ComponentType, ResourceType, MenuHandler, ModalsHandler, ChangeLifecycleStateHandler, SEVERITY, ComponentFactory, CHANGE_COMPONENT_CSAR_VERSION_FLAG} from "app/utils";
-import {IClientMessageModalModel} from "../modals/message-modal/message-client-modal/client-message-modal-view-model";
-import {UserService} from "../../ng2/services/user.service";
-
-
-export interface IDashboardViewModelScope extends ng.IScope {
-
- isLoading:boolean;
- numberOfItemToDisplay:number;
- components:Array<Component>;
- folders:FoldersMenu;
- roles:IConfigRoles;
- user:IUserProperties;
- sdcConfig:IAppConfigurtaion;
- sdcMenu:IAppMenu;
- sharingService:SharingService;
- showTutorial:boolean;
- isFirstTime:boolean;
- version:string;
- filterParams:DashboardFilter;
- vfcmtType:string;
-
- changeFilterParams():void;
- updateSearchTerm(newTerm:string):void;
- onImportVfc(file:any):void;
- onImportVf(file:any):void;
- openCreateModal(componentType:ComponentType, importedFile:any):void;
- openWhatsNewModal(version:string):void;
- openDesignerModal(isResource:boolean, uniqueId:string):void;
- setSelectedFolder(folderItem:FoldersItemsMenu):void;
- entitiesCount(folderItem:FoldersItemsMenu):number;
- getCurrentFolderDistributed():Array<Component>;
- changeLifecycleState(entity:any, data:any):void;
- goToComponent(component:Component):void;
- raiseNumberOfElementToDisplay():void;
- wizardDebugEdit:Function;
- notificationIconCallback:Function;
-}
-
-interface ICheckboxesFilter {
- // Statuses
- selectedStatuses:Array<string>;
- // distributed
- distributed:Array<string>;
-}
-
-export interface IItemMenu {
-
-}
-
-export interface IMenuItemProperties {
- text:string;
- group:string;
- state:string;
- dist:string;
- groupname:string;
- states:Array<any>;
-}
-
-export interface IQueryFilterParams {
- 'filter.term': string;
- 'filter.distributed': string;
- 'filter.status': string
-}
-
-
-export class DashboardFilter {
- searchTerm: string;
- checkboxes: ICheckboxesFilter;
-
- constructor(params = {}) {
- this.searchTerm = params['filter.term'] || "";
- this.checkboxes = {
- selectedStatuses : params['filter.status']? params['filter.status'].split(',') : [],
- distributed : params['filter.distributed']? params['filter.distributed'].split(',') : []
- };
- }
-
- public toParam = ():IQueryFilterParams => {
- return {
- 'filter.term': this.searchTerm,
- 'filter.distributed': this.checkboxes && this.checkboxes.distributed.join(',') || null,
- 'filter.status': this.checkboxes && this.checkboxes.selectedStatuses.join(',') || null
- };
- }
-
-}
-
-export class FoldersMenu {
-
- private _folders:Array<FoldersItemsMenu> = [];
-
- constructor(folders:Array<IMenuItemProperties>) {
- let self = this;
- folders.forEach(function (folder:IMenuItemProperties) {
- if (folder.groupname) {
- self._folders.push(new FoldersItemsMenuGroup(folder));
- } else {
- self._folders.push(new FoldersItemsMenu(folder));
- }
- });
- self._folders[0].setSelected(true);
- }
-
- public getFolders = ():Array<FoldersItemsMenu> => {
- return this._folders;
- };
-
- public getCurrentFolder = ():FoldersItemsMenu => {
- let menuItem:FoldersItemsMenu = undefined;
- this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
- if (tmpFolder.isSelected()) {
- menuItem = tmpFolder;
- }
- });
- return menuItem;
- };
-
- public setSelected = (folder:FoldersItemsMenu):void => {
- this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
- tmpFolder.setSelected(false);
- });
- folder.setSelected(true);
- }
-
-}
-
-export class FoldersItemsMenu implements IItemMenu {
-
- public text:string;
- public group:string;
- public state:string;
- public dist:string;
- public states:Array<any>;
-
- private selected:boolean = false;
-
- constructor(menuProperties:IMenuItemProperties) {
- this.text = menuProperties.text;
- this.group = menuProperties.group;
- this.state = menuProperties.state;
- this.states = menuProperties.states;
- this.dist = menuProperties.dist;
- }
-
- public isSelected = ():boolean => {
- return this.selected;
- };
-
- public setSelected = (value:boolean):void => {
- this.selected = value;
- };
-
- public isGroup = ():boolean => {
- return false;
- }
-
-}
-
-export class FoldersItemsMenuGroup extends FoldersItemsMenu {
-
- public groupname:string;
-
- constructor(menuProperties:IMenuItemProperties) {
- super(menuProperties);
- this.groupname = menuProperties.groupname;
- }
-
- public isGroup = ():boolean => {
- return true;
- }
-
-}
-
-export class DashboardViewModel {
- static '$inject' = [
- '$scope',
- '$filter',
- 'Sdc.Services.EntityService',
- '$http',
- 'sdcConfig',
- 'sdcMenu',
- '$state',
- '$stateParams',
- 'UserServiceNg2',
- 'Sdc.Services.SharingService',
- 'Sdc.Services.CacheService',
- '$q',
- 'ComponentFactory',
- 'ChangeLifecycleStateHandler',
- 'ModalsHandler',
- 'MenuHandler'
- ];
-
- private components:Array<Component>;
-
- constructor(private $scope:IDashboardViewModelScope,
- private $filter:ng.IFilterService,
- private entityService:EntityService,
- private $http:ng.IHttpService,
- private sdcConfig:IAppConfigurtaion,
- private sdcMenu:IAppMenu,
- private $state:ng.ui.IStateService,
- private $stateParams:any,
- private userService:UserService,
- private sharingService:SharingService,
- private cacheService:CacheService,
- private $q:ng.IQService,
- private ComponentFactory:ComponentFactory,
- private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
- private ModalsHandler:ModalsHandler,
- private MenuHandler:MenuHandler) {
- this.initScope();
- this.initFolders();
- this.initEntities();
-
- if (this.$stateParams) {
-
- if (this.$state.params.folder) {
- let self = this;
- let folderName = this.$state.params.folder.replaceAll("_", " ");
-
- this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
- if (tmpFolder.text === folderName) {
- self.$scope.setSelectedFolder(tmpFolder);
- }
- });
- }
-
- // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script>
- // This is called from the welcome page.
- else if (this.$stateParams.show === 'tutorial') {
- this.$scope.showTutorial = true;
- this.$scope.isFirstTime = true;
- }
- }
- }
-
- private initFolders = ():void => {
- if (this.$scope.user) {
- this.$scope.folders = new FoldersMenu(this.$scope.roles[this.$scope.user.role].folder);
- }
- };
-
- private initScope = ():void => {
- let self = this;
-
- this.$scope.version = this.cacheService.get('version');
- this.$scope.sharingService = this.sharingService;
- this.$scope.numberOfItemToDisplay = 0;
- this.$scope.isLoading = false;
- this.$scope.sdcConfig = this.sdcConfig;
- this.$scope.sdcMenu = this.sdcMenu;
- this.$scope.user = this.userService.getLoggedinUser();
- this.$scope.roles = this.sdcMenu.roles;
- this.$scope.showTutorial = false;
- this.$scope.isFirstTime = false;
- this.$scope.vfcmtType = ResourceType.VFCMT;
- this.$scope.filterParams = new DashboardFilter(this.$state.params);
-
- // Open onboarding modal
- this.$scope.notificationIconCallback = ():void => {
- this.ModalsHandler.openOnboadrdingModal('Import').then((result)=> {
- //OK
- if(!result.previousComponent || result.previousComponent.csarVersion != result.componentCsar.csarVersion) {
- this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, result.componentCsar.csarVersion);
- }
-
- this.$state.go('workspace.general', {
- id: result.previousComponent && result.previousComponent.uniqueId,
- componentCsar: result.componentCsar,
- type: result.type
- });
- }, ()=> {
- // ERROR
- });
- };
-
- this.$scope.onImportVf = (file:any):void => {
- if (file && file.filename) {
- // Check that the file has valid extension.
- let fileExtension:string = file.filename.split(".").pop();
- if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
- this.$state.go('workspace.general', {
- type: ComponentType.RESOURCE.toLowerCase(),
- importedFile: file,
- resourceType: ResourceType.VF
- });
- } else {
- let data:IClientMessageModalModel = {
- title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE"),
- message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS", "{'extensions': '" + this.sdcConfig.csarFileExtension + "'}"),
- severity: SEVERITY.ERROR
- };
- this.ModalsHandler.openClientMessageModal(data);
- }
- }
- };
-
- this.$scope.onImportVfc = (file:any):void => {
- if (file && file.filename) {
- // Check that the file has valid extension.
- let fileExtension:string = file.filename.split(".").pop();
- if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
- this.$state.go('workspace.general', {
- type: ComponentType.RESOURCE.toLowerCase(),
- importedFile: file,
- resourceType: ResourceType.VFC
- });
- } else {
- let data:IClientMessageModalModel = {
- title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE"),
- message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS", "{'extensions': '" + this.sdcConfig.toscaFileExtension + "'}"),
- severity: SEVERITY.ERROR
- };
- this.ModalsHandler.openClientMessageModal(data);
- }
- }
- };
-
- this.$scope.openCreateModal = (componentType:string, importedFile:any):void => {
- if (importedFile) {
- this.initEntities(true); // Return from import
- } else {
- this.$state.go('workspace.general', {type: componentType.toLowerCase()});
- }
-
- };
-
- this.$scope.createPNF = ():void => {
- this.$state.go('workspace.general', {
- type: ComponentType.RESOURCE.toLowerCase(),
- resourceType: ResourceType.PNF
- });
- };
-
- this.$scope.createCR = ():void => {
- this.$state.go('workspace.general', {
- type: ComponentType.RESOURCE.toLowerCase(),
- resourceType: ResourceType.CR
- });
- };
-
- this.$scope.entitiesCount = (folderItem:FoldersItemsMenu):any => {
- let self = this;
- let total:number = 0;
- if (folderItem.isGroup()) {
- this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
- if (tmpFolder.group && tmpFolder.group === (<FoldersItemsMenuGroup>folderItem).groupname) {
- total = total + self._getTotalCounts(tmpFolder, self);
- }
- });
- } else {
- total = total + self._getTotalCounts(folderItem, self);
- }
- return total;
- };
-
- this.$scope.getCurrentFolderDistributed = ():Array<any> => {
- let self = this;
- let states = [];
- if (this.$scope.folders) {
- let folderItem:FoldersItemsMenu = this.$scope.folders.getCurrentFolder();
- if (folderItem.isGroup()) {
- this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
- if (tmpFolder.group && tmpFolder.group === (<FoldersItemsMenuGroup>folderItem).groupname) {
- self._setStates(tmpFolder, states);
- }
- });
- } else {
- self._setStates(folderItem, states);
- }
- }
- return states;
- };
-
- this.$scope.setSelectedFolder = (folderItem:FoldersItemsMenu):void => {
- this.$scope.folders.setSelected(folderItem);
- };
-
- this.$scope.goToComponent = (component:Component):void => {
- this.$scope.isLoading = true;
- this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()});
- };
-
- this.$scope.raiseNumberOfElementToDisplay = ():void => {
- this.$scope.numberOfItemToDisplay = this.$scope.numberOfItemToDisplay + 35;
- if (this.$scope.components) {
- this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
- }
- };
-
- this.$scope.updateSearchTerm = (newTerm: string):void => {
- this.$scope.filterParams.searchTerm = newTerm;
- };
-
- this.$scope.changeFilterParams = ():void => {
- this.$state.go('.', this.$scope.filterParams.toParam(), {location: 'replace', notify: false});
- };
- };
-
- private _getTotalCounts(tmpFolder, self):number {
- let total:number = 0;
- if (tmpFolder.dist !== undefined) {
- let distributions = tmpFolder.dist.split(',');
- distributions.forEach((item:any) => {
- total = total + self.getEntitiesByStateDist(tmpFolder.state, item).length;
- });
- }
- else {
- total = total + self.getEntitiesByStateDist(tmpFolder.state, tmpFolder.dist).length;
- }
- return total;
- }
-
- private _setStates(tmpFolder, states) {
- if (tmpFolder.states !== undefined) {
- tmpFolder.states.forEach(function (item:any) {
- states.push({"state": item.state, "dist": item.dist});
- });
- } else {
- states.push({"state": tmpFolder.state, "dist": tmpFolder.dist});
- }
- }
-
- private initEntities = (forceReload?:boolean):void => {
-
- if(forceReload || this.componentShouldReload()){
- this.$scope.isLoading = true;
- this.entityService.getAllComponents(true).then(
- (components:Array<Component>) => {
- this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); //dashboard
- this.cacheService.set('breadcrumbsComponents', components);
- this.components = components;
- this.$scope.components = components;
- this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
- this.$scope.isLoading = false;
- });
- } else {
- this.components = this.cacheService.get('breadcrumbsComponents');
- this.$scope.components = this.components;
- this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
-
- }
-
- };
-
- private isDefaultFilter = (): boolean => {
- let defaultFilter = new DashboardFilter();
- return angular.equals(defaultFilter, this.$scope.filterParams);
- }
-
- private componentShouldReload = ():boolean => {
- let breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
- return !breadcrumbsValid || this.isDefaultFilter();
- }
-
- private getEntitiesByStateDist = (state:string, dist:string):Array<Component> => {
- let gObj:Array<Component>;
- if (this.components && (state || dist)) {
- gObj = this.components.filter(function (obj:Component) {
- if (dist !== undefined && obj.distributionStatus === dist && obj.lifecycleState === state) {
- return true;
- } else if (dist === undefined && obj.lifecycleState === state) {
- return true;
- }
- return false;
- });
- } else {
- gObj = [];
- }
- return gObj;
- }
-}
diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html
deleted file mode 100644
index 240a74d..0000000
--- a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html
+++ /dev/null
@@ -1,109 +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="sdc-catalog-container">
- <loader data-display="isLoading"></loader>
- <!-- HEADER -->
-<!--
- <ecomp-header menu-data="menuItems" version="{{version}}"></ecomp-header>
--->
-
- <div class="w-sdc-main-container">
-
- <perfect-scrollbar id="dashboard-main-scroll" include-padding="true" class="w-sdc-main-right-container">
-
- <div infinite-scroll-disabled='isAllItemDisplay' infinite-scroll="raiseNumberOfElementToDisplay()" infinite-scroll-container="'#dashboard-main-scroll'" infinite-scroll-distance="'0.2'" infinite-scroll-parent>
-
- <div class='w-sdc-row-flex-items'>
-
- <!-- ADD Component -->
- <div ng-if="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new"
- data-ng-mouseleave="displayActions = false"
- data-ng-mouseover="displayActions = true"
- data-ng-init="displayActions = false">
- <div class="w-sdc-dashboard-card-new-content" data-tests-id="AddButtonsArea">
- <div class="w-sdc-dashboard-card-new-content-plus" data-ng-show="!displayActions"></div>
- <div class="sdc-dashboard-create-element-container" data-ng-show="displayActions">
- <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createResourceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('RESOURCE')">Add VF</button>
- <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createCRButton" class="tlv-btn outline blue" data-ng-click="createCR()">Add CR</button>
- <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createPNFButton" class="tlv-btn outline blue" data-ng-click="createPNF()">Add PNF</button>
- <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createServiceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('SERVICE')">Add Service</button>
- </div>
- </div>
- </div>
-
- <!-- Import Component -->
- <div ng-if="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new"
- data-ng-mouseleave="displayActions = false"
- data-ng-mouseover="displayActions = true"
- data-ng-init="displayActions = false">
- <div class="w-sdc-dashboard-card-new-content" data-tests-id="importButtonsArea" >
- <div class="w-sdc-dashboard-card-import-content-plus" data-ng-show="!displayActions"></div>
- <div class="sdc-dashboard-import-element-container" data-ng-show="displayActions">
- <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue">Import VFC
- <file-opener on-file-upload="onImportVfc(file)" data-tests-id="importVFCbutton" extensions="{{sdcConfig.toscaFileExtension}}" data-ng-click="displayActions=false"></file-opener>
- </div>
- <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue" data-ng-click="notificationIconCallback()">Import VSP</div>
- <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue import-dcae">Import DCAE asset
- <file-opener on-file-upload="onImportVf(file)" data-tests-id="importVFbutton" extensions="{{sdcConfig.csarFileExtension}}" data-ng-click="displayActions=false"></file-opener>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Tile new -->
- <ng2-ui-tile data-ng-repeat="component in components | filter:{resourceType:('!'+vfcmtType)} | entityFilter:filterParams.checkboxes | filter:filterParams.searchTerm | limitTo:numberOfItemToDisplay"
- [component]="component" (on-tile-click)="goToComponent(component)"></ng2-ui-tile>
- <!-- Tile new -->
-
- </div>
-
- </div>
-
- </perfect-scrollbar>
-
- <div class="w-sdc-left-sidebar">
- <div class="i-sdc-left-sidebar-item "
- data-ng-repeat="folder in folders.getFolders()"
- data-ng-class="{'category-title': folder.isGroup(), 'selectedLink': folder.isSelected()}"
- >
- <span data-ng-if="folder.isGroup()">{{folder.text}}</span>
-
- <ng1-checkbox data-ng-if="!folder.isGroup() && !folder.dist"
- elem-id="checkbox-{{folder.text | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="filterParams.checkboxes.selectedStatuses"
- sdc-checklist-value="folder.state"
- sdc-checklist-change="changeFilterParams()"
- text="{{folder.text}}"></ng1-checkbox>
-
- <ng1-checkbox data-ng-if="!folder.isGroup() && folder.dist"
- elem-id="checkbox-{{folder.text | lowercase | clearWhiteSpaces}}"
- sdc-checklist-model="filterParams.checkboxes.distributed"
- sdc-checklist-value="folder.dist"
- sdc-checklist-change="changeFilterParams()"
- text="{{folder.text}}"></ng1-checkbox>
- <span class="i-sdc-left-sidebar-item-state-count">{{entitiesCount(folder)}}</span>
- </div>
- </div>
-
- </div>
-
- <top-nav [top-lvl-selected-index]="0" [version]="version" [search-term]="filterParams.searchTerm" (search-term-change)="updateSearchTerm($event);changeFilterParams()" [notification-icon-callback]="notificationIconCallback"></top-nav>
-
-</div>
-<div data-ui-view=""></div>
-
-
diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard.less b/catalog-ui/src/app/view-models/dashboard/dashboard.less
deleted file mode 100644
index 02280cd..0000000
--- a/catalog-ui/src/app/view-models/dashboard/dashboard.less
+++ /dev/null
@@ -1,413 +0,0 @@
-.sdc-dashboard-container {
- .tlv-loader {
- top: -110px;
- left: 80px;
- }
- .sdc-hide-popover {
- .popover {
- display: none !important;
- }
- }
-}
-
-.w-sdc-left-sidebar-nav {
- margin-top: 46px;
-}
-
-.w-sdc-main-right-container-element {
- float: left;
- height: 217px;
- width: 217px;
- margin: 10px;
- position: relative;
-}
-
-.w-sdc-main-right-container-element-details-container {
- position: absolute;
- top: 165px;
- left: 50px;
-}
-
-.w-sdc-main-right-container-element-name {
- font-weight: bold;
-}
-
-.w-sdc-main-right-container-element-owner {
-
-}
-
-//////////////////////////////Cards////////////////////
-.w-sdc-dashboard-card-new {
- border: 2px dashed @color_m;
- .border-radius(2px);
- cursor: pointer;
- display: inline-block;
- height: 198px;
- margin: 11px;
- position: relative;
- vertical-align: middle;
- width: 202px;
-}
-
-.w-sdc-dashboard-card-new-content {
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
- height: 100%;
-}
-
-.w-sdc-dashboard-card-new-content-plus {
- .sprite-new;
- .add-icon;
- position: relative;
- margin-bottom: 20px;
-
- &:after {
- .n_14_m;
- content: 'ADD';
- position: absolute;
- top: 25px;
- left: -3px;
- vertical-align: -50%;
- }
-}
-
-.w-sdc-dashboard-card-import-content-plus {
- .sprite-new;
- .import-icon;
- position: relative;
- margin-bottom: 20px;
-
- &:after {
- .n_14_m;
- content: 'IMPORT';
- position: absolute;
- top: 25px;
- left: -16px;
- vertical-align: -50%;
- }
-}
-
-.sdc-dashboard-create-element-container,
-.sdc-dashboard-import-element-container {
-
- width: 140px;
-
- .tlv-btn.import-dcae {
- padding: 0;
- }
-
- .tlv-btn {
- position: relative;
- width: 100%;
- margin-bottom: 10px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
-
- input[type="file"] {
- cursor: inherit;
- filter: alpha(opacity=0);
- opacity: 0;
- position: absolute;
- top: 0;
- left: 0;
- width: 138px;
- height: 30px;
- }
-}
-
-.w-sdc-dashboard-card {
- width: 204px;
- height: 200px;
- background-color: @main_color_p;
- .border-radius(2px);
- .box-shadow(0px 2px 2px 0px rgba(24, 24, 25, 0.05));
- display: inline-block;
- margin: 10px;
- position: relative;
- vertical-align: middle;
- border: solid 1px @main_color_p;
-
- &:hover {
- border: solid 1px @main_color_o;
- .box-shadow(3px 3px 2px 0px rgba(24, 24, 25, 0.05));
- }
-
- &:active {
- border: solid 1px @main_color_c;
- .box-shadow(3px 3px 2px 0px rgba(24, 24, 25, 0.05));
- }
-}
-
-.w-sdc-dashboard-card-body {
- .hand;
- border-bottom: 1px solid @color_j;
- height: 155px;
- position: relative;
- text-align: center;
-}
-
-.w-sdc-dashboard-card-description {
- .c_3;
- .hand;
- background-color: rgba(57, 73, 84, 0.9);
- border-radius: 4px 4px 0 0;
- bottom: 0;
- left: 0;
- opacity: 0;
- padding: 10px;
- position: absolute;
- right: 0;
- text-align: left;
- top: 0;
- word-wrap: break-word;
- z-index: 4;
- min-height: 100px;
- overflow: hidden;
-}
-
-
-.w-sdc-dashboard-card-schema {
- margin-top: 30px;
-}
-
-.w-sdc-dashboard-card-edit {
- .hand;
- position: absolute;
- right: 13px;
- top: 15px;
- z-index: 2;
-}
-
-.w-sdc-dashboard-card-footer {
- padding: 3px 12px 10px 12px;
- position: relative;
-}
-
-.w-sdc-dashboard-card-avatar {
- .uppercase;
- border-radius: 50%;
- display: inline-block;
- position: absolute;
- left: -6px;
- text-align: center;
- top: -6px;
-
- span {
-
- background-color: @main_color_p;
- .border-radius(15px);
- color: @color_c;
- content: '';
- height: 30px;
- text-align: center;
- display: block;
- border: solid 2px #ECEFF3;
- padding: 3px 10px 2px 10px;
-
- &.VF {
- .j_14_m;
- &::before {
- content: 'VF';
- }
- }
-
- &.VFC {
- .j_14_m;
- &::before {
- content: 'VFC';
- }
- }
-
- &.CP {
- .j_14_m;
- &::before {
- content: 'CP';
- }
- }
-
- &.VL {
- .j_14_m;
- &::before {
- content: 'VL';
- }
- }
-
- &.SERVICE {
- .c_14_m;
- &::before {
- content: 'S';
- }
- }
-
- &.green {
- .d_12;
- &::before {
- content: 'R';
- }
- }
- &.red {
- .r_12;
- &::before {
- content: 'S';
- }
- }
- &.dblack {
- .s_12;
- &::before {
- content: 'P';
- }
- }
- }
-}
-
-.w-sdc-dashboard-card-info {
- display: inline-block;
- vertical-align: middle;
- max-width: 165px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.w-sdc-dashboard-card-info-name-container{
- position: absolute;
- bottom: 0;
- left: 0;
- margin: 0 0 2px 10px;
-}
-.w-sdc-dashboard-card-info-name {
- .m_14_m;
- display: inline-block;
- vertical-align: middle;
- max-width: 165px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.w-sdc-dashboard-card-info-lifecycleState {
- .m_13_m;
- display: inline-block;
- vertical-align: middle;
- max-width: 165px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.w-sdc-dashboard-card-info-user {
- .n_13_r;
- line-height: 18px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: 100%;
-}
-
-.w-sdc-dashboard-card-menu-button {
- display: inline-block;
- padding: 12px 0 0 10px;
- position: absolute;
- right: 12px;
- top: 8px;
- border-left: solid 1px @color_k;
- height: 42px;
-
- &:hover {
- .w-sdc-dashboard-card-menu {
- display: block;
- }
- }
-}
-
-.w-sdc-dashboard-card-menu {
- .bg_c;
- border-radius: 0 0 4px 4px;
- border-top: 3px solid @color_a;
- box-shadow: 0 2px 2px 0px rgba(0, 0, 0, 0.2);
- color: @color_s;
- display: none;
- min-height: 30px;
- padding: 9px 0;
- position: absolute;
- right: -27px;
- width: 208px;
- z-index: 9;
- max-height: 164px;
-
- &::before {
- //TODO: Missing image for small blue triangle.
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE1OTIzNDI1MENFQjExRTU4ODRERTI1MDM2REZCOUYzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE1OTIzNDI2MENFQjExRTU4ODRERTI1MDM2REZCOUYzIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTU5MjM0MjMwQ0VCMTFFNTg4NERFMjUwMzZERkI5RjMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTU5MjM0MjQwQ0VCMTFFNTg4NERFMjUwMzZERkI5RjMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4gBXTlAAAAOElEQVR42mK0rp7NgASMgZgFiE/CBJjQJPcA8U4gNkdXAJMUAGJ+ZEVMaJIwAFfEhEUSRRFAgAEAVtgJyiLAPWAAAAAASUVORK5CYII=');
- content: '';
- display: block;
- height: 21px;
- position: absolute;
- right: 24px;
- top: -24px;
- width: 184px;
- background-repeat: no-repeat;
- background-position: 175px 16px;
- }
-}
-
-.i-sdc-dashboard-card-menu-item {
- .hand;
- line-height: 24px;
- padding: 0 10px;
- &:hover { .a_7; }
-}
-
-.w-sdc-dashboard-card-info-lifecycleState-icon{
- position:absolute;
- bottom:18px;
- right:10px;
-}
-
-// Same for dashboard and catalog view.
-.w-sdc-dashboard-card-schema-image {
- position: absolute;
- top: 41%;
-
- //TODO: Israel - remove this after getting the services sprite.
- height: 45px;
- width: 53px;
- background-repeat: no-repeat;
-
- // Center the icon vertical and horizontal.
- margin: auto;
- left: 0;
- right: 0;
- top: -10px;
- bottom: 0;
-}
-
-/* dashboard card main icons */
-.w-sdc-dashboard-card-schema-image.service { .s-sdc-service }
-.w-sdc-dashboard-card-schema-image.resource { .s-sdc-resource }
-
-/* dashboard card statuses icons */
-.w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN; }
-.w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT; }
-.w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED; }
-.w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION; }
-.w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS; }
-.w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED; }
-
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN.green; }
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT.green; }
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED.green; }
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION.green; }
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS.green; }
-.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED.green; }
-
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN.red; }
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT.red; }
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED.red; }
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION.red; }
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS.red; }
-.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED.red; }
diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view-model.ts b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view-model.ts
index 19bc548..e6ac970 100644
--- a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view-model.ts
+++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view-model.ts
@@ -22,7 +22,7 @@
import * as _ from "lodash";
import {MenuItemGroup, MenuItem} from "app/utils";
import {BreadcrumbsPath, BreadcrumbsMenu} from "../onboard-vendor/onboard-vendor-view-model";
-import {CacheService} from "app/services";
+import {CacheService} from "app/services-ng2";
import {IUserProperties} from "app/models";
export class TestData {
diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html
index 9dbe289..a1e0841 100644
--- a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html
+++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="sdc-catalog-container">
<loader data-display="gui.isLoading"></loader>
diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less
index 71a3101..1e091e9 100644
--- a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less
+++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less
@@ -76,22 +76,6 @@
}
}
- &.READY_FOR_CERTIFICATION {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2985px;
- width: 14px;
- height: 16px;
- }
- }
-
- &.CERTIFICATION_IN_PROGRESS {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2934px;
- width: 14px;
- height: 16px;
- }
- }
-
&.DISTRIBUTED,
&.TBD {
.i-sdc-categories-list-item-icon {
diff --git a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view-model.ts b/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view-model.ts
deleted file mode 100644
index 45ebb12..0000000
--- a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view-model.ts
+++ /dev/null
@@ -1,379 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {ArtifactModel, Resource, Component} from "app/models";
-import {ArtifactsUtils, FormState, ValidationUtils, ArtifactType} from "app/utils";
-import {CacheService} from "app/services";
-
-export interface IEditArtifactModel {
- artifactResource:ArtifactModel;
- artifactTypes:Array<string>;
- artifactFile:any;
-}
-
-export interface IArtifactResourceFormViewModelScope extends ng.IScope {
- forms:any;
- $$childTail:any;
- isNew:boolean;
- isLoading:boolean;
- validationPattern:RegExp;
- urlValidationPattern:RegExp;
- labelValidationPattern:RegExp;
- integerValidationPattern:RegExp;
- commentValidationPattern:RegExp;
- artifactType:string;
- editArtifactResourceModel:IEditArtifactModel;
- defaultHeatTimeout:number;
- validExtensions:any;
- originalArtifactName:string;
- editForm:ng.IFormController;
- footerButtons:Array<any>;
- modalInstanceArtifact:ng.ui.bootstrap.IModalServiceInstance;
-
- fileExtensions():string;
- save(doNotCloseModal?:boolean):void;
- saveAndAnother():void;
- close():void;
- getOptions():Array<string>;
- isDeploymentHeat():boolean;
- onFileChange():void;
- setDefaultTimeout():void;
- openEditEnvParametersModal(artifact:ArtifactModel):void;
- getFormTitle():string;
- fileUploadRequired():string;
- isArtifactOwner():boolean;
-}
-
-export class ArtifactResourceFormViewModel {
-
- static '$inject' = [
- '$scope',
- '$uibModalInstance',
- 'artifact',
- 'Sdc.Services.CacheService',
- 'ValidationPattern',
- 'UrlValidationPattern',
- 'LabelValidationPattern',
- 'IntegerValidationPattern',
- 'CommentValidationPattern',
- 'ValidationUtils',
- '$base64',
- '$state',
- 'ArtifactsUtils',
- '$uibModal',
- 'component'
- ];
-
- private formState:FormState;
- private entityId:string;
-
- constructor(private $scope:IArtifactResourceFormViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private artifact:ArtifactModel,
- private cacheService:CacheService,
- private ValidationPattern:RegExp,
- private UrlValidationPattern:RegExp,
- private LabelValidationPattern:RegExp,
- private IntegerValidationPattern:RegExp,
- private CommentValidationPattern:RegExp,
- private ValidationUtils:ValidationUtils,
- private $base64:any,
- private $state:any,
- private artifactsUtils:ArtifactsUtils,
- private $uibModal:ng.ui.bootstrap.IModalService,
- private component:Component) {
-
-
- this.entityId = this.component.uniqueId;
- this.formState = angular.isDefined(artifact.artifactLabel) ? FormState.UPDATE : FormState.CREATE;
- this.initScope();
- }
-
- private initEntity = ():void => {
- this.$scope.editArtifactResourceModel.artifactResource = this.artifact;
- this.$scope.originalArtifactName = this.artifact.artifactName;
- };
-
-
- private initFooterButtons = ():void => {
-
- this.$scope.footerButtons = [
- {'name': 'Done', 'css': 'blue', 'callback': this.$scope.save}
- ];
- if (this.$scope.isNew) {
- this.$scope.footerButtons.push({
- 'name': 'Add Another',
- 'css': 'grey',
- 'disabled': !this.$scope.isNew && 'deployment' === this.$scope.artifactType,
- 'callback': this.$scope.saveAndAnother
- });
- }
- };
-
- private filterDeploymentArtifactTypeByResourceType = (resourceType:string):any => {
- let result = {};
- _.each(this.$scope.validExtensions, function (typeSettings:any, typeName:string) {
- if (!typeSettings.validForResourceTypes || typeSettings.validForResourceTypes.indexOf(resourceType) > -1) {
- result[typeName] = typeSettings;
- }
- });
-
- return result;
- };
-
- private initArtifactTypes = ():void => {
-
- let artifactTypes:any = this.cacheService.get('UIConfiguration');
-
- if ('deployment' === this.$scope.artifactType) {
-
-
- if ('HEAT_ENV' == this.artifact.artifactType || this.component.selectedInstance) {
- this.$scope.validExtensions = artifactTypes.artifacts.deployment.resourceInstanceDeploymentArtifacts;
- } else if (this.component.isResource()) {
- this.$scope.validExtensions = artifactTypes.artifacts.deployment.resourceDeploymentArtifacts;
- this.$scope.validExtensions = this.filterDeploymentArtifactTypeByResourceType((<Resource>this.component).resourceType);
- } else {
- this.$scope.validExtensions = artifactTypes.artifacts.deployment.serviceDeploymentArtifacts;
- }
-
- if (this.$scope.validExtensions) {
- this.$scope.editArtifactResourceModel.artifactTypes = Object.keys(this.$scope.validExtensions);
- }
- this.$scope.defaultHeatTimeout = artifactTypes.defaultHeatTimeout;
- if (this.$scope.isNew) {
- let isHeat = 'HEAT_ENV' == this.artifact.artifactType;
- _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string)=> {
- return 'HEAT' == item.substring(0, 4) || (!isHeat && item == "VF_MODULES_METADATA") ||
- _.has(ArtifactType.THIRD_PARTY_RESERVED_TYPES, item);
- });
- }
-
- }
- if (this.$scope.artifactType === 'informational') {
- this.$scope.editArtifactResourceModel.artifactTypes = artifactTypes.artifacts.other.map((element:any)=> {
- return element.name;
- });
- _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string)=> {
- return _.has(ArtifactType.THIRD_PARTY_RESERVED_TYPES, item) ||
- _.has(ArtifactType.TOSCA, item);
- })
- }
-
- if (this.component.isResource() && (<Resource>this.component).isCsarComponent()) {
- _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string) => {
- return this.artifactsUtils.isLicenseType(item);
- })
- }
-
- };
-
- private initEditArtifactResourceModel = ():void => {
- this.$scope.editArtifactResourceModel = {
- artifactResource: null,
- artifactTypes: null,
- artifactFile: {}
- };
-
- this.initEntity();
- };
-
- private initScope = ():void => {
-
- this.$scope.validationPattern = this.ValidationPattern;
- this.$scope.urlValidationPattern = this.UrlValidationPattern;
- this.$scope.labelValidationPattern = this.LabelValidationPattern;
- this.$scope.integerValidationPattern = this.IntegerValidationPattern;
- this.$scope.commentValidationPattern = this.CommentValidationPattern;
- this.$scope.isLoading = false;
- this.$scope.isNew = (this.formState === FormState.CREATE);
- this.$scope.artifactType = this.artifactsUtils.getArtifactTypeByState(this.$state.current.name);
- this.$scope.modalInstanceArtifact = this.$uibModalInstance;
-
- this.initEditArtifactResourceModel();
- this.initArtifactTypes();
-
- // In case of edit, show the file name in browse.
- if (this.artifact.artifactName !== "" && 'HEAT_ENV' !== this.artifact.artifactType) {
- this.$scope.editArtifactResourceModel.artifactFile = {};
- this.$scope.editArtifactResourceModel.artifactFile.filename = this.artifact.artifactName;
- }
-
- //scope methods
- this.$scope.isDeploymentHeat = ():boolean => {
- return !this.$scope.isNew && this.$scope.artifactType === 'deployment'
- && this.$scope.editArtifactResourceModel.artifactResource.isHEAT();
-
- };
- this.$scope.onFileChange = ():void => {
- if (this.$scope.editArtifactResourceModel.artifactFile && this.$scope.editArtifactResourceModel.artifactFile.filename) {
- this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.editArtifactResourceModel.artifactFile.filename;
- } else {
- this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.originalArtifactName;
- }
- };
- this.$scope.setDefaultTimeout = ():void => {
- if (this.$scope.isDeploymentHeat() && !this.$scope.editArtifactResourceModel.artifactResource.timeout) {
- this.$scope.editArtifactResourceModel.artifactResource.timeout = this.$scope.defaultHeatTimeout;
- }
-
- if (this.$scope.editArtifactResourceModel.artifactFile && this.$scope.editArtifactResourceModel.artifactFile.filename) {
- this.$scope.editArtifactResourceModel.artifactFile = {};
- this.$scope.forms.editForm.myArtifactFile.$setValidity('required', false);
- }
- };
-
- this.$scope.fileExtensions = ():string => {
- let type:string = this.$scope.editArtifactResourceModel.artifactResource.artifactType;
- return type && this.$scope.validExtensions && this.$scope.validExtensions[type].acceptedTypes ?
- this.$scope.validExtensions[type].acceptedTypes.join(',') : "";
- };
-
- this.$scope.save = (doNotCloseModal?:boolean):void => {
- this.$scope.isLoading = true;
- this.$scope.editArtifactResourceModel.artifactResource.description = this.ValidationUtils.stripAndSanitize(this.$scope.editArtifactResourceModel.artifactResource.description);
-
- if (!this.$scope.isDeploymentHeat()) {
- this.$scope.editArtifactResourceModel.artifactResource.timeout = null;
- }
-
- if (this.$scope.editArtifactResourceModel.artifactFile) {
- this.$scope.editArtifactResourceModel.artifactResource.payloadData = this.$scope.editArtifactResourceModel.artifactFile.base64;
- this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.editArtifactResourceModel.artifactFile.filename;
- }
-
- let onFaild = (response):void => {
- this.$scope.isLoading = false;
- console.info('onFaild', response);
- };
-
- let onSuccess = (artifactResource:ArtifactModel):void => {
- this.$scope.isLoading = false;
- this.$scope.originalArtifactName = "";
-
- if (this.$scope.isDeploymentHeat()) {
- if (artifactResource.heatParameters) {
- this.$scope.openEditEnvParametersModal(artifactResource);
- }
- }
-
- if (!doNotCloseModal) {
- this.$uibModalInstance.close();
- } else {
- this.$scope.editArtifactResourceModel.artifactFile = null;
- angular.element("input[type='file']").val(null); // for support chrome when upload the same file
- this.artifactsUtils.addAnotherAfterSave(this.$scope);
- }
-
- };
-
- if ('HEAT_ENV' == this.artifact.artifactType) {
- if (this.component.selectedInstance) {
- this.component.uploadInstanceEnvFile(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
- } else {
- this.component.addOrUpdateArtifact(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
-
- }
- } else if (this.$scope.isArtifactOwner()) {
- this.component.addOrUpdateInstanceArtifact(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
- } else {
- this.component.addOrUpdateArtifact(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
- }
- };
-
- this.$scope.isArtifactOwner = ():boolean=> {
- return this.component.isService() && !!this.component.selectedInstance;
- };
-
- this.$scope.saveAndAnother = ():void => {
- this.$scope.save(true);
- };
-
- this.$scope.close = ():void => {
- this.$uibModalInstance.close();
- };
-
- this.$scope.fileUploadRequired = ():string => {
- if (this.$scope.editArtifactResourceModel.artifactFile.filename) {
- // This is edit mode
- return 'false';
- } else {
- return 'true';
- }
- };
-
- this.$scope.getFormTitle = ():string => {
- if ('HEAT_ENV' == this.artifact.artifactType) {
- return 'Update HEAT ENV';
- }
- if (this.$scope.isDeploymentHeat()) {
- if (!this.$scope.editArtifactResourceModel.artifactResource.artifactChecksum) {
- return 'Add HEAT Template';
- }
- return 'Update HEAT Template';
- }
- if (this.$scope.isNew) {
- return 'Add Artifact';
- }
- return 'Update Artifact';
- };
-
- this.$scope.openEditEnvParametersModal = (artifactResource:ArtifactModel):void => {
-
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- templateUrl: '../env-parameters-form/env-parameters-form.html',
- controller: 'Sdc.ViewModels.EnvParametersFormViewModel',
- size: 'sdc-md',
- backdrop: 'static',
- resolve: {
- artifact: ():ArtifactModel => {
- return artifactResource;
- },
- component: ():Component => {
- return this.component;
- }
- }
- };
-
- let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
- modalInstance
- .result
- .then(():void => {
- });
- };
-
- this.$scope.forms = {};
-
- this.initFooterButtons();
-
-
- this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => {
- if(this.$scope.forms.editForm) {
- this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
- if (this.$scope.isNew) {
- this.$scope.footerButtons[1].disabled = this.$scope.forms.editForm.$invalid;
- }
- }
- });
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view.html b/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view.html
deleted file mode 100644
index 61ebcc8..0000000
--- a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form-view.html
+++ /dev/null
@@ -1,185 +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.
--->
-
-<ng1-modal modal="modalInstanceArtifact" type="classic" class="sdc-add-artifact" buttons="footerButtons" header="{{getFormTitle()}}" show-close-button="true" get-close-modal-response="close" data-tests-id="sdc-add-artifact">
-
- <loader data-display="isLoading"></loader>
-
- <div class="sdc-edit-artifact-form-container"
- data-ng-class="{'mandatory-artifact': (editArtifactResourceModel.artifactResource.mandatory && artifactType !=='deployment') || artifactType === 'api'}">
- <form novalidate class="w-sdc-form" name="forms.editForm">
-
- <!--------------------- ARTIFACT FILE START-------------------->
- <div class="i-sdc-form-item">
- <label class="required">Upload File</label>
- <file-upload id="fileUploadElement"
- form-element="forms.editForm"
- element-required="{{::fileUploadRequired()}}"
- element-name="myArtifactFile"
- file-model="editArtifactResourceModel.artifactFile"
- extensions="{{fileExtensions()}}"
- element-disabled="{{!editArtifactResourceModel.artifactResource.artifactType}}"
- data-ng-class="{'error': forms.editForm.myArtifactFile.$dirty && forms.editForm.myArtifactFile.$invalid}"></file-upload>
-
- <div class="input-error-file-upload" data-ng-show="forms.editForm.myArtifactFile.$dirty && forms.editForm.myArtifactFile.$invalid">
- <span ng-show="forms.editForm.myArtifactFile.$error.required || forms.editForm.myArtifactFile.$error.emptyFile" translate="ADD_ARTIFACT_ERROR_FILE_REQUIRED"></span>
- <span ng-show="forms.editForm.myArtifactFile.$error.maxsize" translate="VALIDATION_ERROR_MAX_FILE_SIZE"></span>
- <span ng-if="artifactType === 'deployment'" ng-show="forms.editForm.myArtifactFile.$error.filetype" translate="ADD_ARTIFACT_ERROR_VALID_EXTENSIONS" translate-values="{'extensions': '{{fileExtensions()}}' }"></span>
- <span ng-show="forms.editForm.myArtifactFile.$error.emptyFile" translate="VALIDATION_ERROR_EMPTY_FILE"></span>
- </div>
- </div>
- <!--------------------- ARTIFACT FILE END -------------------->
-
- <div class="w-sdc-form-columns-wrapper">
-
- <div class="w-sdc-form-column" data-ng-if="artifactType === 'deployment' || (!editArtifactResourceModel.artifactResource.mandatory && artifactType !== 'api')">
-
- <div class="i-sdc-form-item"
- data-ng-class="{error:(forms.editForm.artifactLabel.$dirty && forms.editForm.artifactLabel.$invalid)}"
- data-ng-if="!isDeploymentHeat()">
- <label class="i-sdc-form-label required">Artifact Label</label>
- <input class="i-sdc-form-input"
- data-ng-maxlength="25"
- data-ng-model="editArtifactResourceModel.artifactResource.artifactLabel"
- type="text"
- name="artifactLabel"
- data-required
- data-ng-model-options="{ debounce: 200 }"
- data-ng-pattern="labelValidationPattern"
- maxlength="25"
- data-ng-disabled="!isNew"
- data-tests-id="artifactLabel"
- autofocus/>
-
- <div class="input-error" data-ng-show="forms.editForm.artifactLabel.$dirty && forms.editForm.artifactLabel.$invalid">
- <span ng-show="forms.editForm.artifactLabel.$error.required" translate="ADD_ARTIFACT_ERROR_LABEL_REQUIRED"></span>
- <span ng-show="forms.editForm.artifactLabel.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span>
- <span ng-show="forms.editForm.artifactLabel.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
-
- </div>
-
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}">
- <label class="i-sdc-form-label required">Type</label>
- <select class="i-sdc-form-select"
- data-required
- name="type"
- data-ng-disabled="!isNew"
- data-ng-change="setDefaultTimeout()"
- data-ng-model="editArtifactResourceModel.artifactResource.artifactType"
- data-ng-options="type as type for type in editArtifactResourceModel.artifactTypes track by type | uppercase"
- data-tests-id="artifacttype">
- <option value="">Choose Type</option>
- </select>
-
- <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid">
- <span ng-show="forms.editForm.type.$error.required" translate="ADD_ARTIFACT_ERROR_TYPE_REQUIRED"></span>
- </div>
-
- </div>
-
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.timeout.$dirty && forms.editForm.timeout.$invalid)}" data-ng-if="isDeploymentHeat()">
- <label class="i-sdc-form-label">Deployment Timeout (minutes)</label>
- <input class="i-sdc-form-input"
- data-ng-maxlength="25"
- data-ng-model="editArtifactResourceModel.artifactResource.timeout"
- type="number"
- name="timeout"
- min="1"
- max="2147483647"
- data-ng-disabled="'HEAT_ENV'==editArtifactResourceModel.artifactResource.artifactType"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-pattern="integerValidationPattern"
- data-ng-init="setDefaultTimeout()"
- data-ng-change="setDefaultTimeout()"
- maxlength="25"
- data-tests-id="timeout" />
-
- <div class="input-error" data-ng-show="forms.editForm.timeout.$dirty && forms.editForm.timeout.$invalid">
- <span ng-show="forms.editForm.timeout.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span>
- <span ng-show="forms.editForm.timeout.$error.pattern" translate="ADD_ARTIFACT_ERROR_TIMEOUT_PATTERN"></span>
- <span ng-show="forms.editForm.timeout.$error.min" translate="ADD_ARTIFACT_ERROR_TIMEOUT_MIN"></span>
- </div>
-
- </div>
-
- </div><!-- w-sdc-form-column -->
-
- <div class="w-sdc-form-column i-sdc-form-url" data-ng-if="artifactType==='api'">
-
- <div class="i-sdc-form-item"
- data-ng-class="{error:(forms.editForm.apiUrl.$dirty && forms.editForm.apiUrl.$invalid)}">
- <label class="i-sdc-form-label required">URL</label>
- <input class="i-sdc-form-input"
- data-ng-maxlength="100"
- data-ng-model="editArtifactResourceModel.artifactResource.apiUrl"
- data-ng-model-options="{ debounce: 200 }"
- type="url"
- name="apiUrl"
- data-required
- ng-pattern="urlValidationPattern"
- maxlength="100"
- autofocus
- invalid-characters=',#?&@$<>~^`\[]{}|")(*!+=;%' />
-
- <div class="input-error" data-ng-show="forms.editForm.apiUrl.$dirty && forms.editForm.apiUrl.$invalid">
- <span ng-show="forms.editForm.apiUrl.$error.required" translate="ADD_ARTIFACT_ERROR_APIURL_REQUIRED"></span>
- <span ng-show="forms.editForm.apiUrl.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
- <span ng-show="forms.editForm.apiUrl.$error.url || forms.editForm.apiUrl.$error.pattern || forms.editForm.apiUrl.$error.invalidCharacters" translate="ADD_ARTIFACT_ERROR_APIURL_URL"></span>
- </div>
-
- </div>
-
- </div><!-- w-sdc-form-column -->
-
- <div class="w-sdc-form-column">
-
- <div class="i-sdc-form-item"
- data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}">
- <label class="i-sdc-form-label required">Description</label>
- <textarea class="i-sdc-form-textarea"
- data-ng-maxlength="256"
- maxlength="256"
- data-required
- name="description"
- data-ng-model="editArtifactResourceModel.artifactResource.description"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-pattern="commentValidationPattern"
- data-tests-id="description"></textarea>
-
- <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid">
- <span ng-show="forms.editForm.description.$error.required" translate="ADD_ARTIFACT_ERROR_DESCRIPTION_REQUIRED"></span>
- <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
- <span ng-show="forms.editForm.description.$error.pattern" translate="ADD_ARTIFACT_ERROR_DESCRIPTION_PATTERN"></span>
- </div>
-
- <div class="w-sdc-form-column artifact-info" data-ng-show="!isNew && editArtifactResourceModel.artifactResource.esId">
- UUID <span data-ng-bind="editArtifactResourceModel.artifactResource.artifactUUID"></span>
- <br />
- Version <span data-ng-bind="editArtifactResourceModel.artifactResource.artifactVersion"></span>
- </div>
- </div>
-
- </div><!-- w-sdc-form-column -->
-
- </div><!-- w-sdc-form-columns-wrapper -->
-
- <span class="w-sdc-form-note" data-ng-show="forms.editForm.$invalid && false" translate="LABEL_ALL_FIELDS_ARE_MANDATORY"></span>
-
- </form>
- </div>
-</ng1-modal>
-
diff --git a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form.less b/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form.less
deleted file mode 100644
index 1f77958..0000000
--- a/catalog-ui/src/app/view-models/forms/artifact-form/artifact-form.less
+++ /dev/null
@@ -1,44 +0,0 @@
-.sdc-edit-artifact-form-container {
-
- .w-sdc-form-note {
- .h_9;
- display: block;
- position: relative;
- top: 13px;
- }
-
- .i-sdc-form-textarea{
- min-height: 95px;
- }
-
- .i-sdc-form-url {
- padding-bottom: 0px;
- }
-
- &.mandatory-artifact {
- .w-sdc-form-column {
- width: 100%;
- padding: 0;
- min-height: initial;
- }
- }
- .w-sdc-form .i-sdc-form-item.upload input[type="file"] {
- display: none
- }
-
- .artifact-info {
- text-align: left;
- color: rgb(140, 140, 140);
- font-size: 13px;
- margin-top: -10px;
- margin-bottom: 5px;
- width: 100%;
- min-height: initial;
-
- span {
- color: #666666;
- padding-left: 4px;
- }
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/forms/attribute-form/attribute-form-view.html b/catalog-ui/src/app/view-models/forms/attribute-form/attribute-form-view.html
deleted file mode 100644
index 902d564..0000000
--- a/catalog-ui/src/app/view-models/forms/attribute-form/attribute-form-view.html
+++ /dev/null
@@ -1,168 +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.
--->
-
-<ng1-modal modal="modalInstanceAttribute" type="classic" class="sdc-edit-attribute-container" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Attribute" show-close-button="true">
-
- <div class="sdc-edit-attribute-form-container" >
- <form novalidate class="w-sdc-form two-columns" name="forms.editForm" >
-
- <div class="w-sdc-form-columns-wrapper">
-
- <div class="w-sdc-form-column">
-
- <!-- Name -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.attributeName.$dirty && forms.editForm.attributeName.$invalid)}">
- <label class="i-sdc-form-label required">Name</label>
- <input class="i-sdc-form-input"
- data-tests-id="attributeName"
- data-ng-maxlength="50"
- data-ng-disabled="!isNew"
- maxlength="50"
- data-ng-model="editAttributeModel.attribute.name"
- type="text"
- name="attributeName"
- data-ng-pattern="propertyNameValidationPattern"
- data-required
- data-ng-model-options="{ debounce: 200 }"
- data-ng-change="validateName()"
- autofocus />
- <div class="input-error" data-ng-show="forms.editForm.attributeName.$dirty && forms.editForm.attributeName.$invalid">
- <span ng-show="forms.editForm.attributeName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Attribute name' }"></span>
- <span ng-show="forms.editForm.attributeName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '128' }"></span>
- <span ng-show="forms.editForm.attributeName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- <span ng-show="forms.editForm.attributeName.$error.nameExist" translate="NEW_ATTRIBUTE_ERROR_NAME_EXISTS"></span>
- </div>
- </div>
-
- <!-- Description -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}">
- <label class="i-sdc-form-label">Description</label>
- <textarea class="i-sdc-form-textarea"
- data-ng-maxlength="256"
- data-ng-disabled="editAttributeModel.attribute.readonly"
- maxlength="256"
- data-ng-pattern="commentValidationPattern"
- name="description"
- data-ng-model="editAttributeModel.attribute.description"
- data-ng-model-options="{ debounce: 200 }"
- data-tests-id="description"></textarea>
- <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid">
- <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
- <span ng-show="forms.editForm.description.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- <span ng-show="forms.editForm.description.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Description' }"></span>
- </div>
- </div>
-
-
- </div>
-
- <div class="w-sdc-form-column">
- <!-- Type -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}">
- <label class="i-sdc-form-label required">Type</label>
- <select class="i-sdc-form-select"
- data-tests-id="type-field"
- data-required
- data-ng-disabled="editAttributeModel.attribute.readonly"
- name="type"
- data-ng-change="onTypeChange()"
- data-ng-model="editAttributeModel.attribute.type"
- data-ng-options="type for type in editAttributeModel.types">
- <option value="">Choose Type</option>
- </select>
- <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid">
- <span ng-show="forms.editForm.type.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Type' }"></span>
- </div>
- </div>
-
- <!-- schema -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.schema.$dirty && forms.editForm.schema.$invalid)}"
- data-ng-if="showSchema()">
- <label class="i-sdc-form-label required">Entry Schema</label>
- <select class="i-sdc-form-select" ng-if="isSchemaEditable()"
- data-required
- name="schema"
- data-ng-disabled="editAttributeModel.attribute.readonly"
- data-ng-change="onTypeChange(false)"
- data-ng-model="editAttributeModel.attribute.schema.property.type"
- data-ng-options="type for type in editAttributeModel.simpleTypes">
- <option value="">Choose Schema Type</option>
- </select>
- <input class="i-sdc-form-input"
- ng-if="!isSchemaEditable()"
- data-tests-id="schema"
- data-ng-disabled="true"
- data-ng-model="editAttributeModel.attribute.schema.property.type"
- type="text"
- name="schema"/>
- <div class="input-error" data-ng-show="forms.editForm.schema.$dirty && forms.editForm.schema.$invalid">
- <span ng-show="forms.editForm.schema.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Entry schema' }"></span>
- </div>
- </div>
-
- <!-- Default value -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
- <label class="i-sdc-form-label">Default Value</label>
- <input class="i-sdc-form-input"
- data-tests-id="defaultvalue"
- ng-if="!(editAttributeModel.attribute.type == 'boolean')"
- data-ng-maxlength="2500"
- data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
- maxlength="2500"
- data-ng-model="attributeValue.value"
- type="text"
- name="value"
- data-custom-validation="" data-validation-func="validateUniqueKeys"
- data-ng-pattern="validationPattern"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-change="!forms.editForm.value.$error.pattern && ('integer'==editAttributeModel.attribute.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editAttributeModel.attribute.value)) || onValueChange())"
- autofocus />
- <select class="i-sdc-form-select"
- data-tests-id="booleantype"
- ng-if="editAttributeModel.attribute.type == 'boolean'"
- data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
- name="value"
- data-ng-change="onValueChange()"
- data-ng-model="attributeValue.value">
- <option value="true">true</option>
- <option value="false">false</option>
- </select>
- <div class="input-error" data-ng-show="forms.editForm.value.$dirty && forms.editForm.value.$invalid">
- <span ng-show="forms.editForm.value.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Default value' }"></span>
- <span ng-show="forms.editForm.value.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
- <span ng-show="forms.editForm.value.$error.pattern" translate="{{getValidationTranslate()}}"></span>
- <span ng-show="forms.editForm.value.$error.customValidation" translate="ATTRIBUTE_EDIT_MAP_UNIQUE_KEYS"></span>
- </div>
- </div>
-
- <!-- hidden -->
- <div class="i-sdc-form-item" data-ng-if="isAttributeValueOwner()">
- <label class="i-sdc-form-label">Hidden</label>
- <input class="i-sdc-form-input"
- data-tests-id="hidden"
- data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
- data-ng-model="editAttributeModel.attribute.hidden"
- type="checkbox"
- name="hidden"/>
- </div>
- </div>
-
- </div>
-
- </form>
- </div>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/forms/attribute-form/attribute-from-view-model.ts b/catalog-ui/src/app/view-models/forms/attribute-form/attribute-from-view-model.ts
deleted file mode 100644
index 0e4a851..0000000
--- a/catalog-ui/src/app/view-models/forms/attribute-form/attribute-from-view-model.ts
+++ /dev/null
@@ -1,262 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {AttributeModel, Component} from "app/models";
-import {IMapRegex, ValidationUtils, FormState, PROPERTY_TYPES} from "app/utils";
-
-export interface IEditAttributeModel {
- attribute:AttributeModel;
- types:Array<string>;
- simpleTypes:Array<string>;
-}
-
-export class attributeValue {//in order to solve DE226783, we update the value on another obj
- value:string;
-}
-
-interface IAttributeFormViewModelScope extends ng.IScope {
- $$childTail:any;
- forms:any;
- editForm:ng.IFormController;
- footerButtons:Array<any>;
- isService:boolean;
- editAttributeModel:IEditAttributeModel;
- modalInstanceAttribute:ng.ui.bootstrap.IModalServiceInstance;
- isNew:boolean;
- listRegex:IMapRegex;
- mapRegex:IMapRegex;
- propertyNameValidationPattern:RegExp;
- commentValidationPattern:RegExp;
- isLoading:boolean;
- validationPattern:RegExp;
- attributeValue:attributeValue;
-
- save():void;
- close():void;
- onTypeChange():void;
- onValueChange():void;
- isAttributeValueOwner():boolean;
- validateIntRange(value:string):boolean;
- validateUniqueKeys(viewValue:string):boolean;
- getValidationTranslate():string;
- showSchema():boolean;
- isSchemaEditable():boolean;
- validateName():void;
-}
-
-export class AttributeFormViewModel {
-
- static '$inject' = [
- '$scope',
- '$uibModalInstance',
- 'attribute',
- 'ValidationUtils',
- 'CommentValidationPattern',
- 'PropertyNameValidationPattern',
- 'component'
- ];
-
- private formState:FormState;
-
-
- constructor(private $scope:IAttributeFormViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private attribute:AttributeModel,
- private ValidationUtils:ValidationUtils,
- private CommentValidationPattern:RegExp,
- private PropertyNameValidationPattern:RegExp,
- private component:Component) {
- this.formState = angular.isDefined(attribute.name) ? FormState.UPDATE : FormState.CREATE;
- this.initScope();
- }
-
- private initResource = ():void => {
- this.$scope.editAttributeModel.attribute = new AttributeModel(this.attribute);
- if (this.$scope.editAttributeModel.types.indexOf(this.attribute.type) === -1) {//attribute defaulte type is string too?
- this.attribute.type = "string";
- }
- };
-
- private initEditAttributeModel = ():void => {
- this.$scope.editAttributeModel = {
- attribute: null,
- types: ['integer', 'string', 'float', 'boolean', 'list', 'map'],
- simpleTypes: ['integer', 'string', 'float', 'boolean']
- };
-
- this.initResource();
- };
-
- private initScope = ():void => {
-
- //scope attributes
- this.$scope.forms = {};
- this.$scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
- this.$scope.commentValidationPattern = this.CommentValidationPattern;
-
- this.$scope.modalInstanceAttribute = this.$uibModalInstance;
- this.$scope.listRegex = this.ValidationUtils.getPropertyListPatterns();
- this.$scope.mapRegex = this.ValidationUtils.getPropertyMapPatterns();
-
- this.$scope.isNew = (this.formState === FormState.CREATE);
- this.$scope.isLoading = false;
- this.$scope.attributeValue = new attributeValue();
-
- this.initEditAttributeModel();
- this.setValidationPattern();
-
- //scope methods
- this.$scope.save = ():void => {
- if (!this.$scope.forms.editForm.$invalid) {
- let attribute:AttributeModel = this.$scope.editAttributeModel.attribute;
- this.$scope.editAttributeModel.attribute.description = this.ValidationUtils.stripAndSanitize(this.$scope.editAttributeModel.attribute.description);
- ////if read only - just closes the modal
- if (this.$scope.editAttributeModel.attribute.readonly && !this.$scope.isAttributeValueOwner()) {
- this.$uibModalInstance.close();
- return;
- }
- this.$scope.isLoading = true;
- let onAttributeFaild = (response):void => {
- console.info('onFaild', response);
- this.$scope.isLoading = false;
- };
-
- let onAttributeSuccess = (attributeFromBE:AttributeModel):void => {
- console.info('onAttributeResourceSuccess : ', attributeFromBE);
- this.$scope.isLoading = false;
- this.$uibModalInstance.close();
- };
-
- //in case we have uniqueId we call update method
- if (this.$scope.isAttributeValueOwner()) {
- attribute.value = this.$scope.attributeValue.value;
- this.component.updateInstanceAttribute(attribute).then(onAttributeSuccess, onAttributeFaild);
- } else {
- attribute.defaultValue = this.$scope.attributeValue.value;
- this.component.addOrUpdateAttribute(attribute).then(onAttributeSuccess, onAttributeFaild);
- }
- }
- };
-
- this.$scope.close = ():void => {
- this.$uibModalInstance.close();
- };
-
- this.$scope.validateName = ():void => {
- let existsAttr:AttributeModel = _.find(this.component.attributes, (attribute:AttributeModel) => {
- return attribute.name === this.$scope.editAttributeModel.attribute.name;
- });
- if (existsAttr) {
- this.$scope.forms.editForm["attributeName"].$setValidity('nameExist', false);
- } else {
- this.$scope.forms.editForm["attributeName"].$setValidity('nameExist', true);
- }
-
- };
-
- this.$scope.onTypeChange = ():void => {
- this.$scope.editAttributeModel.attribute.value = '';
- this.$scope.editAttributeModel.attribute.defaultValue = '';
- this.setValidationPattern();
- };
-
- this.$scope.isAttributeValueOwner = ():boolean=> {
- return this.component.isService() || !!this.component.selectedInstance;
- };
-
- this.$scope.onValueChange = ():void => {
- if (!this.$scope.editAttributeModel.attribute.value) {
- if (this.$scope.isAttributeValueOwner()) {
- this.$scope.editAttributeModel.attribute.value = this.$scope.editAttributeModel.attribute.defaultValue;
- }
- }
- };
-
-
- this.$scope.validateUniqueKeys = (viewValue:string):boolean => {
- if (this.$scope.editAttributeModel.attribute.type === 'map') {
- return this.ValidationUtils.validateUniqueKeys(viewValue);
- }
- else {
- return true; //always valid if not a map
- }
- };
-
- this.$scope.validateIntRange = (value:string):boolean => {
- return !value || this.ValidationUtils.validateIntRange(value);
- };
-
- this.$scope.isSchemaEditable = ():boolean => {
- let schemaType = this.$scope.editAttributeModel.attribute.schema.property.type;
- return this.$scope.editAttributeModel.simpleTypes.indexOf(schemaType) > -1 || !schemaType;
- };
-
- this.$scope.showSchema = ():boolean => {
- return ['list', 'map'].indexOf(this.$scope.editAttributeModel.attribute.type) > -1;
- };
-
- this.$scope.getValidationTranslate = ():string => {
- let result = "ATTRIBUTE_EDIT_PATTERN";
- if (this.$scope.showSchema()) {
-
- result = "ATTRIBUTE_EDIT_" + this.$scope.editAttributeModel.attribute.type.toUpperCase();
-
- if (this.$scope.editAttributeModel.attribute.schema.property.type === PROPERTY_TYPES.STRING) {
- result += "_STRING";
- } else if (this.$scope.editAttributeModel.attribute.schema.property.type === PROPERTY_TYPES.BOOLEAN) {
- result += "_BOOLEAN";
- } else {
- result += "_GENERIC";
- }
- }
-
- return result;
- };
-
- // Add the done button at the footer.
- this.$scope.footerButtons = [
- {'name': 'Done', 'css': 'blue', 'callback': this.$scope.save},
- {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
- ];
-
- this.$scope.$watchCollection("forms.editForm.$invalid", (newVal, oldVal) => {
- this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
- });
-
- this.$scope.attributeValue.value = this.$scope.isAttributeValueOwner() ? this.$scope.editAttributeModel.attribute.value : this.$scope.editAttributeModel.attribute.defaultValue;
- };
-
-
- private setValidationPattern = ():void => {
-
- if (this.$scope.editAttributeModel.attribute.type === 'list') {
- this.$scope.validationPattern = this.$scope.listRegex[this.$scope.editAttributeModel.attribute.schema.property.type];
- }
- else if (this.$scope.editAttributeModel.attribute.type === 'map') {
- this.$scope.validationPattern = this.$scope.mapRegex[this.$scope.editAttributeModel.attribute.schema.property.type];
- }
- else {
- this.$scope.validationPattern = this.ValidationUtils.getValidationPattern(this.$scope.editAttributeModel.attribute.type);
- }
-
- };
-}
diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html
deleted file mode 100644
index b3d6481..0000000
--- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html
+++ /dev/null
@@ -1,108 +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.
--->
-
-<ng1-modal modal="envParametersModal" type="classic" class="sdc-env-form-container" buttons="buttons" header="{{artifactResource.artifactDisplayName}}" show-close-button="true">
- <div class="w-sdc-env-form-container">
- <div class="w-sdc-env-search pull-left">
- <input type="text" class="w-sdc-env-search-input" placeholder="Search" data-ng-model="searchText" data-tests-id="search-env-param-name"/>
- <div class="search-icon-container">
- <span class="w-sdc-search-icon env-search-icon magnification-white"></span>
- </div>
- </div>
- <div class="table-container-flex">
- <div class="table">
- <div class="head flex-container">
- <div class="table-header head-row flex-item" ng-repeat="header in tableHeadersList track by $index">
- <info-tooltip class="header-info" data-ng-if="header.info" class="info-button" info-message-translate="{{header.info}}" direction="left"></info-tooltip>
- {{header.title}}
- </div>
- </div>
- <div class="body">
- <perfect-scrollbar suppress-scroll-x="true" scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <ng-form name="forms.editForm" class="w-sdc-form">
- <div data-ng-repeat="parameter in heatParameters| filter:{filterTerm:searchText} track by $index "
- class="flex-container data-row"
- data-ng-init="parameter.filterTerm=parameter.name + ' ' + parameter.currentValue + ' ' + parameter.defaultValue + ' ' +parameter.description">
- <div class="table-col-general flex-item" data-tests-id="heatParameterName_{{parameter.name}}">
- {{parameter.name}}
- <span class="sprite-new show-desc hand"
- uib-popover-template="templatePopover"
- popover-class="parameter-description-popover top"
- popover-title="Parameter Description"
- popover-placement="top-left"
- popover-is-open="selectedParameter.name == parameter.name"
- popover-trigger="'none'"
- popover-append-to-body="true"
- data-ng-click="openDescPopover(parameter)"></span>
- </div>
-
- <div class="table-col-general flex-item text">
- <span data-tests-id="default-value-of-{{parameter.name}}" tooltips tooltip-content="{{parameter.defaultValue}}">{{parameter.defaultValue}}</span>
- </div>
-
- <!--<div class="table-col-general flex-item">-->
- <!--<input type="text" value="{{parameter.currentValue}}"/>-->
- <!--</div>-->
-
- <div class="table-col-general flex-item left-column-container">
-
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm[parameter.name].$dirty && forms.editForm[parameter.name].$invalid), required: (parameter.defaultValue)}">
- <span class="required-symbol">*</span>
- <div class="input-parameter">
- <input class="i-sdc-form-input" data-ng-class="{error: (forms.editForm[parameter.name].$invalid)}"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-model="parameter.currentValue"
- value="{{parameter.currentValue}}"
- type="text"
- name="{{parameter.name}}"
- data-ng-pattern="getValidationPattern(parameter.type, 'heat')"
- data-ng-required="parameter.defaultValue"
- data-ng-change="onValueChanged(parameter)"
- data-ng-blur="(forms.editForm[parameter.name].$error.required && (parameter.currentValue=parameter.defaultValue))"
- data-tests-id="value-field-of-{{parameter.name}}"/>
-
- <div class="action-button">
- <div class="sprite-new revert-param" data-ng-if="parameter.defaultValue" data-ng-click="parameter.currentValue = parameter.defaultValue"
- data-tests-id="revert-{{parameter.name}}">
- </div>
- <div class="sprite-new delete-param"
- data-ng-if="!parameter.defaultValue"
- data-ng-disabled="!parameter.currentValue"
- data-ng-class="{disabled:!parameter.currentValue}"
- data-ng-click="parameter.currentValue = ''"
- data-tests-id="delete-{{parameter.name}}">
- </div>
- </div>
- </div>
- <div class="input-error" data-ng-show="forms.editForm[parameter.name].$invalid">
- <span ng-show="forms.editForm[parameter.name].$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Value'}"></span>
- <span ng-show="forms.editForm[parameter.name].$error.pattern && parameter.type==='string'" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- <span ng-show="forms.editForm[parameter.name].$error.pattern && !(parameter.type==='string')" translate="VALIDATION_ERROR_TYPE" translate-values="{'type': '{{parameter.type}}'}"></span>
- </div>
- </div>
-
- </div>
-
- </div>
- </ng-form>
-
- </perfect-scrollbar>
- </div>
- </div>
- </div>
- </div>
- </div>
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less
deleted file mode 100644
index d89ab37..0000000
--- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less
+++ /dev/null
@@ -1,177 +0,0 @@
-.sdc-env-form-container{
- .w-sdc-modal-body{
- padding: 20px 10px 2px 10px;
- }
- .w-sdc-modal-body-content{
- .b_6;
- display: block;
- }
-
- .env-file-generation-label{
- .p_9;
- .bold;
- margin-bottom: 20px;
- }
-}
-
-.w-sdc-env-form-container {
- height: 650px;
-
- .w-sdc-env-search {
- padding: 10px 20px 20px 0;
- white-space: nowrap;
- position: relative;
- width: 60%;
- height: 64px;
-
- .env-search-icon {
- top: 9px;
- right: 11px;
- }
-
- .magnification-white {
- .sprite-new;
- .search-white-icon;
- .hand;
- }
-
- .search-icon-container {
- width: 35px;
- height: 30px;
- background-color: @main_color_a;
- white-space: nowrap;
- float: right;
- position: relative;
- bottom: 31px;
- right: 1px;
- border-radius: 0px 4px 4px 0px;
- .hand
- }
-
- .w-sdc-env-search-input {
- border: 1px solid @color_e;
- .border-radius(4px);
- height: 32px;
- margin: 0;
- padding: 0px 28px 3px 10px;
- vertical-align: 4px;
- width: 100%;
- outline: none;
- font-style: italic;
- }
- }
-
- .table-container-flex {
- height: 570px;
-
- .table {
- height: 100%;
- .flex-item:nth-child(1) {
- flex-grow: 20;
- .show-desc{
- float: right;
- top: 10px;
- position: relative;
- }
- }
-
- .flex-item:nth-child(2) {
- flex-grow: 10;
- }
-
- .flex-item:nth-child(3) {
- flex-grow: 10;
- }
- .scrollbar-container{
- max-height: 527px;
- }
- .left-column-container{
- .required-symbol {
- .m_14_m;
- color: #f33;
- display: none;
- position: relative;
- left: -4px;
- top: 3px;
- }
-
- .i-sdc-form-item{
- border-right: none;
- margin: 0px;
-
- .input-parameter{
- border: none;
- height: 30px;
- width: 254px;
- float: right;
- input{
- .m_13_m;
- width: 100%;
- display: inline-flex;
- padding-right: 33px;
- }
- .action-button{
- border-left: solid 1px @main_color_o;
- position: relative;
- height: 20px;
- width: 25px;
- top: -25px;
- left: 228px;
- padding-left: 6px;
- background-color: @main_color_p;
- div:not(.disable){
- .hand;
- }
- }
- }
-
- &.required{
- .required-symbol {
- display: inline-flex;
- }
- .input-parameter {
- width: 250px;
- }
- .action-button{
- left: 224px;
- }
- }
- }
-
-
-
- }
- }
-
- .text{
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- white-space: nowrap;
- }
- }
-
-
- .parameter-description{
- background-color: @func_color_r;
- border-left: 4px solid @main_color_a;
- padding: 10px 30px;
- }
-}
-
-.header-info{
- float: right;
-}
-
-.parameter-description-popover{
- z-index: 1100;
- min-width: 210px;
- .arrow{
- left: 20px !important;
- border-width: 7px;
- bottom: -8px !important;
- }
- .popover-content{
- .f-type._13_m;;
- }
-}
diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts
deleted file mode 100644
index a30fd15..0000000
--- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts
+++ /dev/null
@@ -1,184 +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=========================================================
- */
-
-'use strict';
-import {ValidationUtils} from "app/utils";
-import {ArtifactModel, HeatParameterModel, Component} from "app/models";
-
-export interface IEnvParametersFormViewModelScope extends ng.IScope {
- isLoading:boolean;
- type:string;
- heatParameters:Array<HeatParameterModel>;
- forms:any;
- artifactResource:ArtifactModel;
- buttons:Array<any>;
- envParametersModal:ng.ui.bootstrap.IModalServiceInstance;
- tableHeadersList:Array<any>;
- selectedParameter:HeatParameterModel;
- templatePopover:string;
-
- getValidationPattern(type:string):RegExp;
- isInstance():boolean;
- validateJson(json:string):boolean;
- onValueChanged(parameter: HeatParameterModel):void;
- close():void;
- save():void;
- openDescPopover(selectedParam:HeatParameterModel):void;
- closeDescriptionPopover():void;
-}
-
-export class EnvParametersFormViewModel {
-
- static '$inject' = [
- '$scope',
- '$templateCache',
- '$state',
- '$uibModalInstance',
- 'artifact',
- 'ValidationUtils',
- 'component'
- ];
-
- constructor(private $scope:IEnvParametersFormViewModelScope,
- private $templateCache:ng.ITemplateCacheService,
- private $state:any,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private artifact:ArtifactModel,
- private ValidationUtils:ValidationUtils,
- private component:Component) {
-
-
- this.initScope();
- }
-
- private updateInstanceHeat = ():void => {
- let success = (responseArtifact:ArtifactModel):void => {
- this.$scope.isLoading = false;
- this.$uibModalInstance.close();
- };
-
- let error = ():void => {
- this.$scope.isLoading = false;
- console.info('Failed to load save artifact');
- };
-
- this.component.addOrUpdateInstanceArtifact(this.$scope.artifactResource).then(success, error);
- };
-
- private initScope = ():void => {
- this.$scope.forms = {};
- this.$scope.envParametersModal = this.$uibModalInstance;
- this.$scope.artifactResource = this.artifact;
- this.$scope.heatParameters = angular.copy(this.artifact.heatParameters);
- //if param does not have a value - display the default
- this.$scope.heatParameters.forEach((heatParam) => {
- heatParam.currentValue = heatParam.currentValue || heatParam.defaultValue;
- });
- this.$scope.tableHeadersList = [
- {title: "Parameter", property: "name"},
- {title: "Default Value", property: "defaultValue", info: "DEFAULT_VALUE_INFO"},
- {title: "Current Value", property: "currentValue", info: "CURRENT_VALUE_INFO"}
- ];
-
- this.$templateCache.put("env-parametr-description-popover.html", require('app/view-models/forms/env-parameters-form/env-parametr-description-popover.html'));
- this.$scope.templatePopover = "env-parametr-description-popover.html";
-
- this.$scope.getValidationPattern = (validationType:string, parameterType?:string):RegExp => {
- return this.ValidationUtils.getValidationPattern(validationType, parameterType);
- };
-
- this.$scope.validateJson = (json:string):boolean => {
- if (!json) {
- return true;
- }
- return this.ValidationUtils.validateJson(json);
- };
-
- this.$scope.isInstance = ():boolean => {
- return !!this.component.selectedInstance;
- };
-
- this.$scope.save = ():void => {
- this.$scope.buttons[0].disabled = true;//prevent double click (DE246266)
- this.$scope.isLoading = true;
- this.artifact.heatParameters = angular.copy(this.$scope.heatParameters);
- this.artifact.heatParameters.forEach((parameter:any):void => {
- if ("" === parameter.currentValue) {
- //[Bug 154465] - Update and erase current value field in Env parameters form return empty String ("") instead of null.
- parameter.currentValue = null;
- } else if (parameter.defaultValue && parameter.defaultValue == parameter.currentValue) {
- parameter.currentValue = undefined;
- }
- });
-
- if (this.$scope.isInstance()) {
- this.updateInstanceHeat();
- return;
- }
-
- let success = (responseArtifact:ArtifactModel):void => {
- this.$scope.isLoading = false;
- this.$uibModalInstance.close();
-
- };
-
- let error = ():void => {
- this.$scope.isLoading = false;
- console.info('Failed to load save artifact');
- };
-
- this.component.addOrUpdateArtifact(this.$scope.artifactResource).then(success, error);
- };
-
- this.$scope.onValueChanged = (parameter: HeatParameterModel):void => {
- parameter.filterTerm = parameter.name + ' ' + parameter.currentValue + ' ' + parameter.defaultValue + ' ' +parameter.description
- if('json'==parameter.type){
- this.$scope.forms.editForm[parameter.name].$setValidity('pattern', this.$scope.validateJson(parameter.currentValue));
- }
- }
-
- this.$scope.close = ():void => {
- //this.artifact.heatParameters.forEach((parameter:any):void => {
- // if (!parameter.currentValue && parameter.defaultValue) {
- // parameter.currentValue = parameter.defaultValue;
- // }
- //});
- this.$uibModalInstance.dismiss();
- };
-
- this.$scope.openDescPopover = (selectedParam:HeatParameterModel):void => {
- this.$scope.selectedParameter = selectedParam;
- };
-
- this.$scope.closeDescriptionPopover = ():void => {
- this.$scope.selectedParameter = null;
- };
-
- this.$scope.buttons = [
- {'name': 'Save', 'css': 'blue', 'callback': this.$scope.save},
- {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
- ];
-
- this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => {
- this.$scope.buttons[0].disabled = this.$scope.forms.editForm.$invalid;
- });
-
- };
-}
diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parametr-description-popover.html b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parametr-description-popover.html
deleted file mode 100644
index 6db354a..0000000
--- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parametr-description-popover.html
+++ /dev/null
@@ -1,20 +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>
- <span data-tests-id='popover-x-button' data-ng-click='closeDescriptionPopover()' class='tlv-sprite tlv-x-btn close-popover-btn'></span>
- {{selectedParameter.description}}
-</div>
diff --git a/catalog-ui/src/app/view-models/forms/input-form/input-form-view-modal.ts b/catalog-ui/src/app/view-models/forms/input-form/input-form-view-modal.ts
deleted file mode 100644
index 56542b9..0000000
--- a/catalog-ui/src/app/view-models/forms/input-form/input-form-view-modal.ts
+++ /dev/null
@@ -1,146 +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=========================================================
- */
-
-'use strict';
-import {FormState, PROPERTY_TYPES, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS} from "app/utils";
-import {InputModel} from "app/models";
-
-export interface IInputEditModel {
- editInput:InputModel;
-}
-
-export interface IInputFormViewModelScope extends ng.IScope {
- forms:any;
- editForm:ng.IFormController;
- footerButtons:Array<any>;
- isService:boolean;
- modalInstanceInput:ng.ui.bootstrap.IModalServiceInstance;
- isLoading:boolean;
- inputEditModel:IInputEditModel;
- myValue:any;
- maxLength:number;
-
- save():void;
- close():void;
- validateIntRange(value:string):boolean;
- validateJson(json:string):boolean;
- getValidationPattern(type:string):RegExp;
- showSchema():boolean;
-}
-
-export class InputFormViewModel {
-
- static '$inject' = [
- '$scope',
- '$uibModalInstance',
- 'ValidationUtils',
- 'input'
- ];
-
- private formState:FormState;
-
-
- constructor(private $scope:IInputFormViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private ValidationUtils:ValidationUtils,
- private input:InputModel) {
- this.initScope();
- this.initMyValue();
- }
-
- private initMyValue = ():void => {
- switch (this.$scope.inputEditModel.editInput.type) {
- case PROPERTY_TYPES.MAP:
- this.$scope.myValue = this.$scope.inputEditModel.editInput.defaultValue ? JSON.parse(this.$scope.inputEditModel.editInput.defaultValue) : {'': null};
- break;
- case PROPERTY_TYPES.LIST:
- this.$scope.myValue = this.$scope.inputEditModel.editInput.defaultValue ? JSON.parse(this.$scope.inputEditModel.editInput.defaultValue) : [];
- break;
- }
- };
-
- private initDefaultValueMaxLength = ():void => {
- switch (this.$scope.inputEditModel.editInput.type) {
- case PROPERTY_TYPES.MAP:
- case PROPERTY_TYPES.LIST:
- this.$scope.maxLength = this.$scope.inputEditModel.editInput.schema.property.type == PROPERTY_TYPES.JSON ?
- PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH :
- PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
- break;
- case PROPERTY_TYPES.JSON:
- this.$scope.maxLength = PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH;
- break;
- default:
- this.$scope.maxLength = PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
- }
- };
-
- private initScope = ():void => {
- this.$scope.forms = {};
- this.$scope.modalInstanceInput = this.$uibModalInstance;
- this.$scope.inputEditModel = {
- editInput: null
- };
- this.$scope.inputEditModel.editInput = this.input;
- this.initDefaultValueMaxLength();
-
- //scope methods
- this.$scope.save = ():void => {
- if (this.$scope.showSchema()) {
- this.$scope.inputEditModel.editInput.defaultValue = JSON.stringify(this.$scope.myValue);
- }
- };
-
- this.$scope.close = ():void => {
- this.$uibModalInstance.close();
- };
-
- this.$scope.validateIntRange = (value:string):boolean => {
- return !value || this.ValidationUtils.validateIntRange(value);
- };
-
- this.$scope.validateJson = (json:string):boolean => {
- if (!json) {
- return true;
- }
- return this.ValidationUtils.validateJson(json);
- };
-
- this.$scope.showSchema = ():boolean => {
- return ['list', 'map'].indexOf(this.$scope.inputEditModel.editInput.type) > -1;
- };
-
- this.$scope.getValidationPattern = (type:string):RegExp => {
- return this.ValidationUtils.getValidationPattern(type);
- };
-
- // Add the done button at the footer.
- this.$scope.footerButtons = [
- {'name': 'Done', 'css': 'blue', 'callback': this.$scope.save},
- {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
- ];
-
- this.$scope.$watchCollection("forms.editForm.$invalid", (newVal, oldVal) => {
- this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
- });
-
- };
-}
-
diff --git a/catalog-ui/src/app/view-models/forms/input-form/input-form-view.html b/catalog-ui/src/app/view-models/forms/input-form/input-form-view.html
deleted file mode 100644
index 446a926..0000000
--- a/catalog-ui/src/app/view-models/forms/input-form/input-form-view.html
+++ /dev/null
@@ -1,141 +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.
--->
-
-<ng1-modal modal="modalInstanceInput" type="classic" class="sdc-edit-input-container" buttons="footerButtons" header="Update Input" show-close-button="true">
-
- <div class="sdc-edit-input-form-container" >
- <form novalidate class="w-sdc-form two-columns" name="forms.editForm" >
-
- <div class="w-sdc-form-columns-wrapper">
-
- <div class="w-sdc-form-column">
-
- <!-- Name -->
- <div class="i-sdc-form-item">
- <label class="i-sdc-form-label">Name</label>
- <input class="i-sdc-form-input"
- data-tests-id="inputName"
- data-ng-maxlength="50"
- data-ng-disabled="true"
- maxlength="50"
- data-ng-model="inputEditModel.editInput.name"
- type="text"
- name="inputName"
- autofocus />
- </div>
-
- <!-- Description -->
- <div class="i-sdc-form-item">
- <label class="i-sdc-form-label">Description</label>
- <textarea class="i-sdc-form-textarea"
- data-ng-disabled="true"
- name="description"
- data-ng-model="inputEditModel.editInput.description"
- data-tests-id="description"></textarea>
- </div>
-
-
- </div>
-
- <div class="w-sdc-form-column">
- <!-- Type -->
- <div class="i-sdc-form-item">
- <label class="i-sdc-form-label">Type</label>
- <input class="i-sdc-form-input"
- data-tests-id="type"
- data-ng-disabled="true"
- data-ng-model="inputEditModel.editInput.type"
- type="text"
- name="type"/>
- </div>
- <!-- schema -->
- <div class="i-sdc-form-item"
- data-ng-if="showSchema()">
- <label class="i-sdc-form-label">Entry Schema</label>
- <input class="i-sdc-form-input"
- data-tests-id="schema"
- data-ng-disabled="true"
- data-ng-model="inputEditModel.editInput.schema.property.type"
- type="text"
- name="schema"/>
- </div>
- <!-- Default value -->
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
- <label class="i-sdc-form-label">Default Value</label>
- <div data-ng-switch="inputEditModel.editInput.type">
- <div ng-switch-when="map">
- <type-map value-obj-ref="myValue"
- schema-property="inputEditModel.editInput.schema.property"
- parent-form-obj="forms.editForm"
- fields-prefix-name="'input-value-'"
- read-only="true"
- default-value=""
- types="[]"
- max-length="maxLength"></type-map>
- </div>
- <div ng-switch-when="list">
- <type-list value-obj-ref="myValue"
- schema-property="inputEditModel.editInput.schema.property"
- parent-form-obj="forms.editForm"
- fields-prefix-name="'input-value-'"
- read-only="true"
- default-value=""
- types="[]"
- max-length="maxLength"></type-list>
- </div>
- <div ng-switch-default>
- <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
- <input class="i-sdc-form-input"
- data-tests-id="defaultvalue"
- ng-if="inputEditModel.editInput.type != 'boolean'"
- data-ng-maxlength="maxLength"
- data-ng-disabled="true"
- maxlength="{{maxLength}}"
- data-ng-model="inputEditModel.editInput.defaultValue"
- type="text"
- name="value"
- data-ng-pattern="getValidationPattern(input.type)"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-change="('json'==inputEditModel.editInput.type && forms.editForm.value.$setValidity('pattern', validateJson(inputEditModel.editInput.defaultValue)))
- ||(!forms.editForm.value.$error.pattern && ('integer'==inputEditModel.editInput.type && forms.editForm.value.$setValidity('pattern', validateIntRange(inputEditModel.editInput.defaultValue)) || onValueChange()))"
- autofocus />
- <select class="i-sdc-form-select"
- data-tests-id="booleantype"
- ng-if="inputEditModel.editInput.type == 'boolean'"
- data-ng-disabled="true"
- name="value"
- data-ng-model="inputEditModel.editInput.defaultValue">
- <option value="true">true</option>
- <option value="false">false</option>
- </select>
-
- <div class="input-error" data-ng-show="forms.editForm.value.$dirty && forms.editForm.value.$invalid">
- <span ng-show="forms.editForm.value.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '{{maxLength}}' }"></span>
- <span ng-show="forms.editForm.value.$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- </div>
-
- </div>
-
- </form>
- </div>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base-view.html b/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base-view.html
index e2594bc..ae96b66 100644
--- a/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base-view.html
+++ b/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<ng1-modal modal="modalPropertyFormBase" type="classic" class="sdc-edit-property-container" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Property" show-close-button="true" data-tests-id="sdc-edit-property-container">
<loader data-display="isLoading" relative="false" size="medium"></loader>
<div class="sdc-modal-top-bar" data-ng-if="!isNew">
diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts
index f5c057e..37b1ce7 100644
--- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts
+++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts
@@ -20,12 +20,16 @@
'use strict';
import * as _ from "lodash";
-import {
- PROPERTY_TYPES, ModalsHandler, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS, FormState, PROPERTY_DATA} from "app/utils";
-import {DataTypesService} from "app/services";
-import {PropertyModel, DataTypesMap, Component, GroupInstance, PolicyInstance, PropertyBEModel} from "app/models";
-import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
+import { PROPERTY_TYPES, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS, FormState, PROPERTY_DATA } from "app/utils";
+import { DataTypesService } from "app/services";
+import { PropertyModel, DataTypesMap, Component, GroupInstance, PolicyInstance, PropertyBEModel, ComponentMetadata } from "app/models";
+import { ComponentInstance } from "../../../../models/componentsInstances/componentInstance";
import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+import { SdcUiCommon, SdcUiServices, SdcUiComponents } from "onap-ui-angular";
+import { CompositionService } from "app/ng2/pages/composition/composition.service";
+import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service";
+import { Observable } from "rxjs";
+import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service";
export interface IEditPropertyModel {
property:PropertyModel;
@@ -44,7 +48,7 @@
propertyNameValidationPattern:RegExp;
commentValidationPattern:RegExp;
editPropertyModel:IEditPropertyModel;
- modalInstanceProperty:ng.ui.bootstrap.IModalServiceInstance;
+ modalInstanceProperty:ng.ui.bootstrap.IModalServiceInstance;
currentPropertyIndex:number;
isLastProperty:boolean;
myValue:any;
@@ -54,6 +58,7 @@
maxLength:number;
isPropertyValueOwner:boolean;
isVnfConfiguration:boolean;
+ constraints:string[];
validateJson(json:string):boolean;
save(doNotCloseModal?:boolean):void;
@@ -82,17 +87,20 @@
'PropertyNameValidationPattern',
'CommentValidationPattern',
'ValidationUtils',
- 'component',
+ // 'component',
'$filter',
- 'ModalsHandler',
+ 'ModalServiceSdcUI',
'filteredProperties',
'$timeout',
'isPropertyValueOwner',
'propertyOwnerType',
'propertyOwnerId',
- 'ComponentInstanceServiceNg2'
+ 'ComponentInstanceServiceNg2',
+ 'TopologyTemplateService',
+ 'CompositionService',
+ 'workspaceService'
];
-
+
private formState:FormState;
constructor(private $scope:IPropertyFormViewModelScope,
@@ -103,17 +111,21 @@
private PropertyNameValidationPattern:RegExp,
private CommentValidationPattern:RegExp,
private ValidationUtils:ValidationUtils,
- private component:Component,
+ // private component:Component,
private $filter:ng.IFilterService,
- private ModalsHandler:ModalsHandler,
+ private modalService:SdcUiServices.ModalService,
private filteredProperties:Array<PropertyModel>,
private $timeout:ng.ITimeoutService,
private isPropertyValueOwner:boolean,
private propertyOwnerType:string,
private propertyOwnerId:string,
- private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2) {
+ private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2,
+ private topologyTemplateService: TopologyTemplateService,
+ private compositionService: CompositionService,
+ private workspaceService: WorkspaceService) {
this.formState = angular.isDefined(property.name) ? FormState.UPDATE : FormState.CREATE;
+
this.initScope();
}
@@ -121,8 +133,10 @@
this.$scope.editPropertyModel.property = new PropertyModel(this.property);
this.$scope.editPropertyModel.property.type = this.property.type ? this.property.type : null;
this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.value || this.$scope.editPropertyModel.property.defaultValue;
+ this.$scope.constraints = this.property.constraints && this.property.constraints[0] ? this.property.constraints[0]["validValues"] : null;
+
this.setMaxLength();
- this.initAddOnLabels();
+
};
//init property add-ons labels that show up at the left side of the input.
@@ -131,23 +145,13 @@
//the server sends back the normalized name. Remove it (to prevent interference with validation) and set the addon label to the component name directly.
//Note: this cant be done in properties.ts because we dont have access to the component
if (this.$scope.editPropertyModel.property.value) {
- let splitProp = this.$scope.editPropertyModel.property.value.split(new RegExp(this.component.normalizedName + '.', "gi"));
+ let splitProp = this.$scope.editPropertyModel.property.value.split(new RegExp(this.workspaceService.metadata.normalizedName + '.', "gi"));
this.$scope.editPropertyModel.property.value = splitProp.pop();
}
- this.$scope.editPropertyModel.property.addOn = this.component.name;
+ this.$scope.editPropertyModel.property.addOn = this.workspaceService.metadata.name;
}
}
- private initEditPropertyModel = ():void => {
- this.$scope.editPropertyModel = {
- property: null,
- types: PROPERTY_DATA.TYPES,
- simpleTypes: PROPERTY_DATA.SIMPLE_TYPES
- };
-
- this.initResource();
- };
-
private initForNotSimpleType = ():void => {
let property = this.$scope.editPropertyModel.property;
this.$scope.isTypeDataType = this.DataTypesService.isDataTypeForPropertyType(this.$scope.editPropertyModel.property);
@@ -195,20 +199,25 @@
this.$scope.commentValidationPattern = this.CommentValidationPattern;
this.$scope.isLoading = false;
this.$scope.isNew = (this.formState === FormState.CREATE);
- this.$scope.isService = this.component.isService();
+ this.$scope.isService = this.workspaceService.metadata.isService();
this.$scope.modalInstanceProperty = this.$uibModalInstance;
this.$scope.currentPropertyIndex = _.findIndex(this.filteredProperties, i=> i.name == this.property.name);
this.$scope.isLastProperty = this.$scope.currentPropertyIndex == (this.filteredProperties.length - 1);
this.$scope.dataTypes = this.DataTypesService.getAllDataTypes();
this.$scope.isPropertyValueOwner = this.isPropertyValueOwner;
this.$scope.propertyOwnerType = this.propertyOwnerType;
- this.initEditPropertyModel();
+
+ this.$scope.editPropertyModel = {
+ property : new PropertyModel(this.property),
+ types : PROPERTY_DATA.TYPES,
+ simpleTypes : PROPERTY_DATA.SIMPLE_TYPES}; //All simple types
+
//check if property of VnfConfiguration
this.$scope.isVnfConfiguration = false;
- if(this.propertyOwnerType == "component" && angular.isArray(this.component.componentInstances)) {
+ if(this.propertyOwnerType == "component" && angular.isArray(this.compositionService.componentInstances)) {
- var componentPropertyOwner:ComponentInstance = this.component.componentInstances.find((ci:ComponentInstance) => {
+ var componentPropertyOwner:ComponentInstance = this.compositionService.componentInstances.find((ci:ComponentInstance) => {
return ci.uniqueId === this.property.resourceInstanceUniqueId;
});
if (componentPropertyOwner && componentPropertyOwner.componentName === 'vnfConfiguration') {
@@ -219,6 +228,7 @@
this.$scope.nonPrimitiveTypes = _.filter(Object.keys(this.$scope.dataTypes), (type:string)=> {
return this.$scope.editPropertyModel.types.indexOf(type) == -1;
});
+ this.initResource();
this.initForNotSimpleType();
@@ -263,10 +273,10 @@
//Not clean, but doing this as a temporary fix until we update the property right panel modals
if(this.propertyOwnerType == "group"){
- this.ComponentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component, this.propertyOwnerId, [property])
+ this.ComponentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.propertyOwnerId, [property])
.subscribe((propertiesFromBE) => { onPropertySuccess(<PropertyModel>propertiesFromBE[0])}, error => onPropertyFaild);
} else if(this.propertyOwnerType == "policy"){
- this.ComponentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component, this.propertyOwnerId, [property])
+ this.ComponentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.propertyOwnerId, [property])
.subscribe((propertiesFromBE) => { onPropertySuccess(<PropertyModel>propertiesFromBE[0])}, error => onPropertyFaild);
} else {
//in case we have uniqueId we call update method
@@ -275,7 +285,7 @@
let myValueString:string = JSON.stringify(this.$scope.myValue);
property.value = myValueString;
}
- this.component.updateInstanceProperties(property.resourceInstanceUniqueId, [property]).then((propertiesFromBE) => onPropertySuccess(propertiesFromBE[0]), onPropertyFaild);
+ this.updateInstanceProperties(property.resourceInstanceUniqueId, [property]).subscribe((propertiesFromBE) => onPropertySuccess(propertiesFromBE[0]), onPropertyFaild);
} else {
if (!this.$scope.editPropertyModel.property.simpleType && !this.$scope.isSimpleType(property.type)) {
let myValueString:string = JSON.stringify(this.$scope.myValue);
@@ -283,7 +293,7 @@
} else {
this.$scope.editPropertyModel.property.defaultValue = this.$scope.editPropertyModel.property.value;
}
- this.component.addOrUpdateProperty(property).then(onPropertySuccess, onPropertyFaild);
+ this.addOrUpdateProperty(property).subscribe(onPropertySuccess, onPropertyFaild);
}
}
};
@@ -362,14 +372,65 @@
};
this.$scope.delete = (property:PropertyModel):void => {
- let onOk = ():void => {
- this.component.deleteProperty(property.uniqueId).then(
+ let onOk: Function = ():void => {
+ this.deleteProperty(property.uniqueId).subscribe(
this.$scope.close
);
};
let title:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TITLE");
let message:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TEXT", "{'name': '" + property.name + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
+ const okButton = {testId: "OK", text: "OK", type: SdcUiCommon.ButtonType.info, callback: onOk, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
};
}
+
+ private updateInstanceProperties = (componentInstanceId:string, properties:PropertyModel[]):Observable<PropertyModel[]> => {
+
+ return this.ComponentInstanceServiceNg2.updateInstanceProperties(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, componentInstanceId, properties)
+ .map(newProperties => {
+ newProperties.forEach((newProperty) => {
+ if(newProperty.path[0] === newProperty.resourceInstanceUniqueId) newProperty.path.shift();
+ // find exist instance property in parent component for update the new value ( find bu uniqueId & path)
+ let existProperty: PropertyModel = <PropertyModel>_.find(this.compositionService.componentInstancesProperties[newProperty.resourceInstanceUniqueId], {
+ uniqueId: newProperty.uniqueId,
+ path: newProperty.path
+ });
+ let index = this.compositionService.componentInstancesProperties[newProperty.resourceInstanceUniqueId].indexOf(existProperty);
+ this.compositionService.componentInstancesProperties[newProperty.resourceInstanceUniqueId][index] = newProperty;
+ });
+ return newProperties;
+ });
+ };
+
+ private addOrUpdateProperty = (property:PropertyModel):Observable<PropertyModel> => {
+ if (!property.uniqueId) {
+ let onSuccess = (property:PropertyModel):PropertyModel => {
+ let newProperty = new PropertyModel(property);
+ this.filteredProperties.push(newProperty);
+ return newProperty;
+ };
+ return this.topologyTemplateService.addProperty(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, property).map(onSuccess);
+ }
+ else {
+ let onSuccess = (newProperty:PropertyModel):PropertyModel => {
+ // find exist instance property in parent component for update the new value ( find bu uniqueId )
+ let existProperty:PropertyModel = <PropertyModel>_.find(this.filteredProperties, {uniqueId: newProperty.uniqueId});
+ let propertyIndex = this.filteredProperties.indexOf(existProperty);
+ this.filteredProperties[propertyIndex] = newProperty;
+ return newProperty;
+ };
+ return this.topologyTemplateService.updateProperty(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, property).map(onSuccess);
+ }
+ };
+
+ public deleteProperty = (propertyId:string):Observable<void> => {
+ let onSuccess = ():void => {
+ console.log("Property deleted");
+ delete _.remove(this.filteredProperties, {uniqueId: propertyId})[0];
+ };
+ let onFailed = ():void => {
+ console.log("Failed to delete property");
+ };
+ return this.topologyTemplateService.deleteProperty(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, propertyId).map(onSuccess, onFailed);
+ };
}
diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html
index 1f48416..7c29d98 100644
--- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html
+++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<ng1-modal modal="modalInstanceProperty" type="classic" class="sdc-edit-property-container" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Property" show-close-button="true" data-tests-id="sdc-edit-property-container">
<loader data-display="isLoading" relative="false" size="medium"></loader>
<div class="sdc-modal-top-bar" data-ng-if="!isNew">
@@ -160,8 +159,11 @@
fields-prefix-name="currentPropertyIndex"
read-only="(editPropertyModel.property.readonly && !isPropertyValueOwner) || isVnfConfiguration"
default-value="{{getDefaultValue()}}"
- max-length="maxLength"></type-map>
+ max-length="maxLength"
+ constraints = "editPropertyModel.property.constraints && editPropertyModel.property.constraints[0].validValues">
+ </type-map>
</div>
+
<div ng-switch-when="list">
<type-list value-obj-ref="myValue"
schema-property="editPropertyModel.property.schema.property"
@@ -169,14 +171,36 @@
fields-prefix-name="currentPropertyIndex"
read-only="editPropertyModel.property.readonly && !isPropertyValueOwner"
default-value="{{getDefaultValue()}}"
- max-length="maxLength"></type-list>
+ max-length="maxLength"
+ constraints = "editPropertyModel.property.constraints && editPropertyModel.property.constraints[0].validValues"></type-list>
</div>
+
<div ng-switch-default>
<div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid), 'input-group' : editPropertyModel.property.addOn}">
<span ng-if="editPropertyModel.property.addOn" class="input-group-addon">{{editPropertyModel.property.addOn}}</span>
+ <!-- Has Constraints -->
+ <select class="i-sdc-form-select"
+ data-tests-id="constraints"
+ ng-if="(editPropertyModel.property.constraints)"
+ data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner"
+
+ data-ng-change="onValueChange()"
+ data-ng-model="editPropertyModel.property.value">
+ <!-- Get the default value in case exist -->
+ <option value = "{{editPropertyModel.property.value}}" name = "{{editPropertyModel.property.value}}" hidden selected>
+ {{editPropertyModel.property.value}}
+ </option>
+ <!-- add all constratint to Select list -->
+ <option ng-repeat='value in constraints' value="{{value}}" name="{{value}}">
+ {{value}}
+ </option>
+ </select>
+
+
+ <!-- No Constraints -->
<input class="i-sdc-form-input"
data-tests-id="defaultvalue"
- ng-if="!((editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean')"
+ ng-if="!(editPropertyModel.property.constraints) && !((editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean')"
data-ng-maxlength="maxLength"
data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner"
maxlength="{{maxLength}}"
@@ -189,6 +213,7 @@
||(!forms.editForm.value.$error.pattern && ('integer'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editPropertyModel.property.value)) || onValueChange()))"
data-ng-change=""
autofocus />
+ <!-- Boolean -->
<select class="i-sdc-form-select"
data-tests-id="booleantype"
ng-if="(editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean'"
diff --git a/catalog-ui/src/app/view-models/forms/property-forms/module-property-modal/module-property-view.html b/catalog-ui/src/app/view-models/forms/property-forms/module-property-modal/module-property-view.html
index 57e70db..7f47b3e 100644
--- a/catalog-ui/src/app/view-models/forms/property-forms/module-property-modal/module-property-view.html
+++ b/catalog-ui/src/app/view-models/forms/property-forms/module-property-modal/module-property-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="default-value-section i-sdc-form-item">
<label class="i-sdc-form-label">Default Value</label>
<div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
diff --git a/catalog-ui/src/app/view-models/forms/property-forms/select-datatype-modal/select-datatype-modal-view.html b/catalog-ui/src/app/view-models/forms/property-forms/select-datatype-modal/select-datatype-modal-view.html
index 33fef03..d22741f 100644
--- a/catalog-ui/src/app/view-models/forms/property-forms/select-datatype-modal/select-datatype-modal-view.html
+++ b/catalog-ui/src/app/view-models/forms/property-forms/select-datatype-modal/select-datatype-modal-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div data-ng-if="dataTypes" class="default-value-section i-sdc-form-item">
<label class="i-sdc-form-label">Default Value</label>
<div data-ng-if="isTypeDataType">
diff --git a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts b/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts
deleted file mode 100644
index 67d135c..0000000
--- a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts
+++ /dev/null
@@ -1,117 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {ComponentInstanceFactory} from "app/utils";
-import {ComponentInstance} from "app/models";
-import {Requirement, Component, Capability} from "app/models";
-
-interface IResourceInstanceViewModelScope extends ng.IScope {
-
- componentInstanceModel:ComponentInstance;
- validationPattern:RegExp;
- oldName:string;
- isAlreadyPressed:boolean;
- footerButtons:Array<any>;
- forms:any;
- modalInstanceName:ng.ui.bootstrap.IModalServiceInstance;
-
- save():void;
- close():void;
-}
-
-export class ResourceInstanceNameViewModel {
-
- static '$inject' = [
- '$scope',
- 'ValidationPattern',
- '$uibModalInstance',
- 'component'
- ];
-
-
- constructor(private $scope:IResourceInstanceViewModelScope,
- private ValidationPattern:RegExp,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private component:Component) {
-
- this.initScope();
- }
-
-
- private initScope = ():void => {
- this.$scope.forms = {};
- this.$scope.validationPattern = this.ValidationPattern;
- this.$scope.componentInstanceModel = ComponentInstanceFactory.createComponentInstance(this.component.selectedInstance);
- this.$scope.oldName = this.component.selectedInstance.name;
- this.$scope.modalInstanceName = this.$uibModalInstance;
-
- this.$scope.isAlreadyPressed = false;
-
-
- this.$scope.close = ():void => {
- this.$uibModalInstance.dismiss();
- };
-
- this.$scope.save = ():void => {
-
- let onFailed = () => {
- this.$scope.isAlreadyPressed = true;
- };
-
- let onSuccess = (componentInstance:ComponentInstance) => {
- this.$uibModalInstance.close();
- this.$scope.isAlreadyPressed = false;
- this.$scope.componentInstanceModel = componentInstance;
- //this.component.name = componentInstance.name;//DE219124
- this.component.selectedInstance.name = componentInstance.name;
- //update requirements and capabilities owner name
- _.forEach(this.component.selectedInstance.requirements, (requirementsArray:Array<Requirement>) => {
- _.forEach(requirementsArray, (requirement:Requirement):void => {
- requirement.ownerName = componentInstance.name;
- });
- });
-
- _.forEach(this.component.selectedInstance.capabilities, (capabilitiesArray:Array<Capability>) => {
- _.forEach(capabilitiesArray, (capability:Capability):void => {
- capability.ownerName = componentInstance.name;
- });
- });
-
- };
-
- this.$scope.isAlreadyPressed = true;
- if (this.$scope.oldName != this.$scope.componentInstanceModel.name) {
- this.component.updateComponentInstance(this.$scope.componentInstanceModel).then(onSuccess, onFailed);
- }
- };
-
- this.$scope.footerButtons = [
- {'name': 'OK', 'css': 'blue', 'callback': this.$scope.save},
- {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
- ];
-
- this.$scope.$watch("[forms.editNameForm.$invalid,componentInstanceModel.name,isAlreadyPressed]", (newVal, oldVal) => {
- //if the name is invalid or if user pressed ok and didn't try to change name again or the new name = source name
- this.$scope.footerButtons[0].disabled = this.$scope.forms.editNameForm.$invalid || (this.$scope.isAlreadyPressed && newVal[1] === oldVal[1]) || this.$scope.componentInstanceModel.name === this.$scope.oldName;
- });
- }
-}
diff --git a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-view.html b/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-view.html
deleted file mode 100644
index ec726d0..0000000
--- a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name-view.html
+++ /dev/null
@@ -1,88 +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.
--->
-
-<ng1-modal modal="modalInstanceName" type="classic" class="w-sdc-modal-resource-instance-name modal-type-confirmation" buttons="footerButtons" header="Instance Name" show-close-button="true">
-
- <form novalidate class="w-sdc-form" name="forms.editNameForm">
- <div class="i-sdc-form-item" data-ng-class="{error:(editNameForm.componentInstanceName.$dirty && editNameForm.resourceInstanceName.$invalid)}">
- <label class="i-sdc-form-label required">Instance Name</label>
- <input class="w-sdc-modal-resource-instance-input i-sdc-form-input"
- name="componentInstanceName"
- data-ng-maxlength="50"
- data-ng-model="componentInstanceModel.name"
- type="text"
- data-required
- data-ng-pattern="validationPattern"
- maxlength="50"
- autofocus
- placeholder="Enter instance name..."
- data-tests-id="instanceName"
- />
-
- <div class="input-error" data-ng-show="forms.editNameForm.componentInstanceName.$dirty && forms.editNameForm.componentInstanceName.$invalid">
- <span ng-show="forms.editNameForm.componentInstanceName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Resource name' }"></span>
- <span ng-show="forms.editNameForm.componentInstanceName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span>
- <span ng-show="forms.editNameForm.componentInstanceName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
-
- </div>
- </form>
-
-</ng1-modal>
-
-
-
-<!--
-
-<div class="w-sdc-modal w-sdc-modal-resource-instance-name">
- <header>
- <div class="w-sdc-modal-head">
- Instance Name
- </div>
- </header>
- <div>
- <form novalidate class="w-sdc-modal-body w-sdc-form" name="editNameForm">
- <div class="i-sdc-form-item" data-ng-class="{error:(editNameForm.componentInstanceName.$dirty && editNameForm.resourceInstanceName.$invalid)}">
- <label class="i-sdc-form-label required">Instance Name</label>
- <input class="w-sdc-modal-resource-instance-input i-sdc-form-input"
- name="componentInstanceName"
- data-ng-maxlength="50"
- data-ng-model="componentInstanceModel.name"
- type="text"
- data-required
- data-ng-pattern="validationPattern"
- maxlength="50"
- autofocus
- placeholder="Enter instance name..."
- data-tests-id="instanceName"
- />
-
- <div class="input-error" data-ng-show="editNameForm.componentInstanceName.$dirty && editNameForm.componentInstanceName.$invalid">
- <span ng-show="editNameForm.componentInstanceName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Resource name' }"></span>
- <span ng-show="editNameForm.componentInstanceName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span>
- <span ng-show="editNameForm.componentInstanceName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
-
- </div>
- </form>
-
- <div class="w-sdc-modal-action">
- <button class="w-sdc-btn-blue" data-ng-click="save()" type="button" data-ng-disabled="(!componentInstanceModel.name || componentInstanceModel.name === oldName) || isAlreadyPressed">Ok</button>
- <button class="w-sdc-btn-dark-gray" data-ng-click="close()" type="button">Cancel</button>
- </div>
- </div>
-</div>
--->
diff --git a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name.less b/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name.less
deleted file mode 100644
index 57698be..0000000
--- a/catalog-ui/src/app/view-models/forms/resource-instance-name-form/resource-instance-name.less
+++ /dev/null
@@ -1,29 +0,0 @@
-.w-sdc-modal-resource-instance-name {
-
- .w-sdc-modal-body {
- overflow: visible;
- }
-
- .w-sdc-modal-action {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .w-sdc-modal-resource-instance-input {
- .p_1;
- border: solid 1px @color_p;
- height: 45px;
- padding: 0 20px;
- margin: 0 auto 0 auto;
- display: block;
- }
- .w-sdc-modal-body {
- border-bottom: none;
- }
-
- .w-sdc-form .i-sdc-form-item.error::after {
- top: 13px;
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view-model.ts
deleted file mode 100644
index 7998d10..0000000
--- a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view-model.ts
+++ /dev/null
@@ -1,93 +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=========================================================
- */
-
-'use strict';
-import {ValidationUtils, ModalType} from "app/utils";
-
-export interface IConfirmationModalModel {
- title:string;
- message:string;
- showComment:boolean;
- type:ModalType;
-}
-
-interface IConfirmationModalViewModelScope {
- modalInstanceConfirmation:ng.ui.bootstrap.IModalServiceInstance;
- confirmationModalModel:IConfirmationModalModel;
- comment:any;
- commentValidationPattern:RegExp;
- editForm:ng.IFormController;
- okButtonColor:string;
- hideCancelButton:boolean;
- ok():any;
- cancel():void;
-}
-
-export class ConfirmationModalViewModel {
-
- static '$inject' = ['$scope', '$uibModalInstance', 'confirmationModalModel', 'CommentValidationPattern', 'ValidationUtils'];
-
- constructor(private $scope:IConfirmationModalViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- confirmationModalModel:IConfirmationModalModel,
- private CommentValidationPattern:RegExp,
- private ValidationUtils:ValidationUtils) {
-
- this.initScope(confirmationModalModel);
- }
-
- private initScope = (confirmationModalModel:IConfirmationModalModel):void => {
- let self = this;
- this.$scope.hideCancelButton = false;
- this.$scope.modalInstanceConfirmation = this.$uibModalInstance;
- this.$scope.confirmationModalModel = confirmationModalModel;
- this.$scope.comment = {"text": ''};
- this.$scope.commentValidationPattern = this.CommentValidationPattern;
-
- this.$scope.ok = ():any => {
- self.$uibModalInstance.close(this.ValidationUtils.stripAndSanitize(self.$scope.comment.text));
- };
-
- this.$scope.cancel = ():void => {
- console.info('Cancel pressed on: ' + this.$scope.confirmationModalModel.title);
- self.$uibModalInstance.dismiss();
- };
-
- // Set the OK button color according to modal type (standard, error, alert)
- let _okButtonColor = 'blue'; // Default
- switch (confirmationModalModel.type) {
- case ModalType.STANDARD:
- _okButtonColor = 'blue';
- break;
- case ModalType.ERROR:
- _okButtonColor = 'red';
- break;
- case ModalType.ALERT:
- this.$scope.hideCancelButton = true;
- _okButtonColor = 'grey';
- break;
- default:
- _okButtonColor = 'blue';
- break;
- }
- this.$scope.okButtonColor = _okButtonColor;
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view.html b/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view.html
deleted file mode 100644
index cb9b159..0000000
--- a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal-view.html
+++ /dev/null
@@ -1,45 +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.
--->
-
-<ng1-modal modal="modalInstanceConfirmation" type="classic" class="w-sdc-modal-confirmation modal-type-{{confirmationModalModel.type}}" header="{{confirmationModalModel.title}}" show-close-button="true">
- <form novalidate class="w-sdc-form" name="editForm">
- <label class="i-sdc-form-label required w-sdc-modal-label" data-ng-bind-html="confirmationModalModel.message"></label>
-
- <div class="i-sdc-form-item">
- <textarea class="w-sdc-modal-body-comment"
- data-tests-id="checkindialog"
- autofocus="autofocus"
- data-ng-show="confirmationModalModel.showComment===true"
- data-ng-model="comment.text"
- placeholder="Comment..."
- maxlength="256"
- data-required
- name="comment1"
- data-ng-pattern="commentValidationPattern"
- data-ng-maxlength="256"></textarea>
-
- <div class="input-error" data-ng-show="editForm.comment1.$dirty && editForm.comment1.$invalid">
- <span ng-show="editForm.comment1.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- <span ng-show="editForm.comment1.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Comment' }"></span>
- </div>
- </div>
- </form>
- <div class="w-sdc-modal-footer classic">
- <button class="tlv-btn {{okButtonColor}}" data-tests-id="OK" data-ng-click="ok()" data-ng-disabled="confirmationModalModel.showComment===true && (!comment.text || comment.text && comment.text.length===0)">OK</button>
- <button class="tlv-btn grey" data-ng-if="hideCancelButton===false" data-tests-id="Cancel" data-ng-click="cancel()" >Cancel</button>
- <!--<button class="tlv-btn blue add-property-add-another" data-ng-if="isNew" data-ng-click="saveAndAnother()" type="reset" data-ng-disabled="editForm.$invalid">Add Another</button>-->
- </div>
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal.less b/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal.less
deleted file mode 100644
index 666c41d..0000000
--- a/catalog-ui/src/app/view-models/modals/confirmation-modal/confirmation-modal.less
+++ /dev/null
@@ -1,30 +0,0 @@
-.w-sdc-modal-confirmation {
- form.w-sdc-form{
- padding: 0;
- }
-
- .w-sdc-modal-body-content {
- .b_6;
- word-break: break-word;
-
- }
- .w-sdc-modal-body {
- height: auto;
- /* padding: 47px 60px 20px 60px; */
- border-bottom: none;
- }
- .w-sdc-modal-body-content {
- padding: 0;
- }
- .w-sdc-modal-body-comment {
- width: 430px;
- height: 127px;
- border: solid 1px @color_e;
- margin: 20px 0 0 0;
- padding: 15px;
- }
- .w-sdc-modal-label {
- .m_14_r;
- text-align: left;
- }
-}
diff --git a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view-model.ts
deleted file mode 100644
index 4569656..0000000
--- a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view-model.ts
+++ /dev/null
@@ -1,49 +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=========================================================
- */
-
-'use strict';
-
-export interface IConformanceLevelModalModelScope {
- footerButtons:Array<any>;
- modalInstance:ng.ui.bootstrap.IModalServiceInstance;
-}
-
-export class ConformanceLevelModalViewModel {
-
- static '$inject' = ['$scope', '$uibModalInstance'];
-
- constructor(private $scope:IConformanceLevelModalModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance) {
-
- this.initScope();
- }
-
- private initScope = ():void => {
-
- this.$scope.modalInstance = this.$uibModalInstance;
-
- this.$scope.footerButtons = [
- {'name': 'Continue', 'css': 'grey', 'callback': this.$uibModalInstance.close},
- {'name': 'Reject', 'css': 'blue', 'callback': this.$uibModalInstance.dismiss}
- ];
-
- };
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view.html b/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view.html
deleted file mode 100644
index 5ba0425..0000000
--- a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal-view.html
+++ /dev/null
@@ -1,38 +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.
--->
-
-<ng1-modal modal="modalInstance"
- type="classic"
- class="w-sdc-modal modal-type-alert conformance-level-modal"
- header="Warning"
- buttons="footerButtons"
- show-close-button="false">
-
- <perfect-scrollbar include-padding="true">
- <div class="w-sdc-modal-body-content" data-tests-id="message">
- <p>
- You are about to distribute a service with models and artifacts created with an <b>older version of the platform</b>.
- For such service, new properties, metadata and requirements needed by ECOMP components will not be available.
- </p><p>
- It is highly recommended that you upgrade the service models and artifacts.
- </p><p>
- Click "Continue" if you need to distribute the current service version.<br />
- Click "Reject" if you need to stop the distribution and manually upgrade the service.
- </p>
- </div>
- </perfect-scrollbar>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal.less b/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal.less
deleted file mode 100644
index 7f195ad..0000000
--- a/catalog-ui/src/app/view-models/modals/conformance-level-modal/conformance-level-modal.less
+++ /dev/null
@@ -1,3 +0,0 @@
-.conformance-level-modal{
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view-model.ts
deleted file mode 100644
index 095d143..0000000
--- a/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view-model.ts
+++ /dev/null
@@ -1,116 +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=========================================================
- */
-
-'use strict';
-import {IAppConfigurtaion, Component, AsdcComment} from "app/models";
-import {ValidationUtils} from "app/utils";
-
-export interface IEmailModalModel_Email {
- to:string;
- subject:string;
- message:string;
-}
-
-export interface IEmailModalModel_Data {
- component:Component;
- stateUrl:string;
-}
-
-export interface IEmailModalModel {
- title:string;
- email:IEmailModalModel_Email;
- data:IEmailModalModel_Data;
-}
-
-interface IEmailModalViewModelScope {
- modalInstanceEmail:ng.ui.bootstrap.IModalServiceInstance;
- emailModalModel:IEmailModalModel;
- submitInProgress:boolean;
- commentValidationPattern:RegExp;
- isLoading:boolean;
- submit():any;
- cancel():void;
- validateField(field:any):boolean;
-}
-
-export class EmailModalViewModel {
-
- static '$inject' = ['$scope', '$filter', 'sdcConfig', '$uibModalInstance', 'emailModalModel', 'ValidationUtils', 'CommentValidationPattern'];
-
- constructor(private $scope:IEmailModalViewModelScope,
- private $filter:ng.IFilterService,
- private sdcConfig:IAppConfigurtaion,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private emailModalModel:IEmailModalModel,
- private ValidationUtils:ValidationUtils,
- private CommentValidationPattern:RegExp) {
-
- this.initScope(emailModalModel);
- }
-
- private initScope = (emailModalModel:IEmailModalModel):void => {
- this.$scope.emailModalModel = emailModalModel;
- this.$scope.submitInProgress = false;
- this.$scope.commentValidationPattern = this.CommentValidationPattern;
- this.$scope.modalInstanceEmail = this.$uibModalInstance;
-
- this.$scope.submit = ():any => {
-
- let onSuccess = (component:Component) => {
- this.$scope.isLoading = false;
- this.$scope.submitInProgress = false;
- // showing the outlook modal according to the config json
- if (this.sdcConfig.showOutlook) {
- let link:string = encodeURI(this.sdcConfig.api.baseUrl + "?folder=Ready_For_Testing");
- let outlook:string = this.$filter('translate')("EMAIL_OUTLOOK_MESSAGE", "{'to': '" + emailModalModel.email.to + "','subject': '" + emailModalModel.email.subject + "','message': '" + emailModalModel.email.message + "', 'entityNameAndVersion': '" + emailModalModel.email.subject + "','link': '" + link + "'}");
- window.location.href = outlook; // Open outlook with the email to send
- }
- this.$uibModalInstance.close(component); // Close the dialog
- };
-
- let onError = () => {
- this.$scope.isLoading = false;
- this.$scope.submitInProgress = false;
- this.$uibModalInstance.close(); // Close the dialog
- };
-
- // Submit to server
- // Prevent from user pressing multiple times on submit.
- if (this.$scope.submitInProgress === false) {
- this.$scope.isLoading = true;
- this.$scope.submitInProgress = true;
- let comment:AsdcComment = new AsdcComment();
- comment.userRemarks = emailModalModel.email.message;
- emailModalModel.data.component.changeLifecycleState(emailModalModel.data.stateUrl, comment).then(onSuccess, onError);
- }
- };
-
- this.$scope.cancel = ():void => {
- this.$uibModalInstance.dismiss();
- };
-
- this.$scope.validateField = (field:any):boolean => {
- if (field && field.$dirty && field.$invalid) {
- return true;
- }
- return false;
- };
- }
-}
diff --git a/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view.html b/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view.html
deleted file mode 100644
index 612fe22..0000000
--- a/catalog-ui/src/app/view-models/modals/email-modal/email-modal-view.html
+++ /dev/null
@@ -1,93 +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.
--->
-
-<ng1-modal modal="modalInstanceEmail" type="classic" class="w-sdc-modal-email modal-type-standard" header="{{emailModalModel.title}}" show-close-button="true">
- <loader data-display="isLoading"></loader>
- <form novalidate class="w-sdc-form" name="editForm">
-
- <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.to)}">
- <label class="i-sdc-form-label col-sm-2">To</label>
- <div class="col-sm-10">
- <input class="i-sdc-form-input" type="text"
- data-ng-model="emailModalModel.email.to"
- data-ng-model-options="{ debounce: 500 }"
- data-ng-maxlength="255"
- data-required
- name="to"
- id="to"
- data-ng-disabled="true"
- />
- </div>
-
- <div class="input-error" data-ng-show="validateField(editForm.to)" alignToSelector="#to">
- <span ng-show="editForm.to.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'To' }"></span>
- <span ng-show="editForm.to.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '255' }"></span>
- <span ng-show="editForm.to.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
-
- </div>
-
- <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.subject)}">
- <label class="i-sdc-form-label col-sm-2">Subject</label>
- <div class="col-sm-10">
- <input class="i-sdc-form-input" type="text"
- data-ng-model="emailModalModel.email.subject"
- data-ng-model-options="{ debounce: 500 }"
- data-ng-maxlength="255"
- data-required
- name="subject"
- data-ng-disabled="true"
- />
- </div>
-
- <div class="input-error" data-ng-show="validateField(editForm.subject)">
- <span ng-show="editForm.subject.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Subject' }"></span>
- <span ng-show="editForm.subject.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '255' }"></span>
- <span ng-show="editForm.subject.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
-
- </div>
-
- <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.message)}">
- <label class="i-sdc-form-label required col-sm-2">Message</label>
- <div class="col-sm-10">
- <textarea class="w-sdc-modal-body-email"
- data-ng-model="emailModalModel.email.message"
- placeholder="{{'EMAIL_MODAL_MESSAGE' | translate }}"
- data-required
- name="message"
- data-ng-pattern="commentValidationPattern"
- maxlength="255"
- data-tests-id="changeLifeCycleMessage"
- data-ng-maxlength="255">
- </textarea>
-
- <div class="input-error" data-ng-show="validateField(editForm.message)">
- <span ng-show="editForm.message.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Message' }"></span>
- <span ng-show="editForm.message.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '255' }"></span>
- <span ng-show="editForm.message.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
- </div>
-
- </div>
-
- </form>
-
- <div class="w-sdc-modal-footer classic">
- <button class="tlv-btn blue" data-tests-id="OK" data-ng-click="submit()" data-ng-disabled="editForm.$invalid">OK</button>
- <button class="tlv-btn grey" data-tests-id="Cancel" data-ng-click="cancel()" >Cancel</button>
- </div>
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/email-modal/email-modal.less b/catalog-ui/src/app/view-models/modals/email-modal/email-modal.less
deleted file mode 100644
index 471089f..0000000
--- a/catalog-ui/src/app/view-models/modals/email-modal/email-modal.less
+++ /dev/null
@@ -1,57 +0,0 @@
-.w-sdc-modal-email {
-
- .w-sdc-modal-body {
- border-bottom: none;
- }
-
- form.w-sdc-form{
- padding: 0;
-
- .i-sdc-form-item {
- clear: both;
- label {
- min-height: 30px;
- padding-top: 4px;
- }
-
- .col-sm-10 {
- padding-right: 0;
- }
-
- }
-
- .w-sdc-modal-body-email {
- border-style: solid;
- border-width: 1px;
- border-color: @color_e;
- box-sizing: border-box;
- width: 100%;
- height: 127px;
- margin-bottom: 20px;
- }
-
- label {.m_14_m; text-align: left;}
- input {.m_14_r;}
- textarea {.m_14_r;}
- /* I made the subject and to fields as input (for future use), but for now they look like labels: */
- input:disabled {
- .bg_c;
- border: none;
- }
- }
-
- .w-sdc-modal-action {
- background-color: @main_color_p;
- padding: 0 13px 0 0;
- height: 90px;
- line-height: 65px;
-
- button {width: 174px;}
- }
-
- .w-sdc-form .i-sdc-form-item label.required::before {
- position: absolute;
- left: -13px;
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/error-modal/error-403-view.html b/catalog-ui/src/app/view-models/modals/error-modal/error-403-view.html
index ba08b51..1cab8ad 100644
--- a/catalog-ui/src/app/view-models/modals/error-modal/error-403-view.html
+++ b/catalog-ui/src/app/view-models/modals/error-modal/error-403-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="sdc-error-403-container" >
<div class="sdc-error-403-container-title" translate="GENERAL_ERROR_403_TITLE"></div>
<div class="w-sdc-error-403-text w-sdc-form" translate="GENERAL_ERROR_403_DESCRIPTION" translate-values="{'mailto': mailto }"></div>
diff --git a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html
index 75bc82d..86c776a 100644
--- a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html
+++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<ng1-modal modal="modalIcons" type="classic" class="w-sdc-modal-icons" buttons="footerButtons" header="Choose Icon" show-close-button="true">
<div class="suggested-icons-container">
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-base-modal-model.ts b/catalog-ui/src/app/view-models/modals/message-modal/message-base-modal-model.ts
deleted file mode 100644
index b987f10..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-base-modal-model.ts
+++ /dev/null
@@ -1,63 +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=========================================================
- */
-
-'use strict';
-import {SEVERITY} from "app/utils";
-
-export interface IMessageModalModel {
- title:string;
- message:string;
- severity:SEVERITY;
-}
-
-export interface IMessageModalViewModelScope extends ng.IScope {
- footerButtons:Array<any>;
- messageModalModel:IMessageModalModel;
- modalInstanceError:ng.ui.bootstrap.IModalServiceInstance;
- ok():void;
-}
-
-export class MessageModalViewModel {
-
- constructor(private $baseScope:IMessageModalViewModelScope,
- private $baseModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private baseMessageModalModel:IMessageModalModel) {
-
- this.initScope(baseMessageModalModel);
- }
-
- private initScope = (messageModalViewModel:IMessageModalModel):void => {
-
- this.$baseScope.messageModalModel = messageModalViewModel;
- this.$baseScope.modalInstanceError = this.$baseModalInstance;
-
- this.$baseScope.ok = ():void => {
- this.$baseModalInstance.close();
- };
-
- this.$baseScope.footerButtons = [
- {
- 'name': 'OK',
- 'css': 'grey',
- 'callback': this.$baseScope.ok
- }
- ];
- }
-}
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view-model.ts
deleted file mode 100644
index f2b2217..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view-model.ts
+++ /dev/null
@@ -1,42 +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=========================================================
- */
-
-'use strict';
-import {IMessageModalModel, MessageModalViewModel, IMessageModalViewModelScope} from "../message-base-modal-model";
-
-export interface IClientMessageModalModel extends IMessageModalModel {
-}
-
-export interface IClientMessageModalViewModelScope extends IMessageModalViewModelScope {
- clientMessageModalModel:IClientMessageModalModel;
-}
-
-export class ClientMessageModalViewModel extends MessageModalViewModel {
-
- static '$inject' = ['$scope', '$uibModalInstance', 'clientMessageModalModel'];
-
- constructor(private $scope:IClientMessageModalViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private clientMessageModalModel:IClientMessageModalModel) {
-
- super($scope, $uibModalInstance, clientMessageModalModel);
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view.html b/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view.html
deleted file mode 100644
index f0a4f9a..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal-view.html
+++ /dev/null
@@ -1,32 +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.
--->
-
-<ng1-modal modal="modalInstanceError"
- type="classic"
- class="w-sdc-modal modal-type-alert"
- header="{{messageModalModel.title}}"
- buttons="footerButtons"
- show-close-button="true">
-
- <perfect-scrollbar include-padding="true">
- <div class="w-sdc-modal-icon w-sdc-modal-icon-{{messageModalModel.severity}}"></div>
- <div class="w-sdc-modal-caption">
- <div ng-bind-html="messageModalModel.message" data-tests-id="message"></div>
- </div>
- <!--<div class="w-sdc-modal-body-content" data-ng-bind-html="messageModalModel.message"></div>-->
- </perfect-scrollbar>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal.less b/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal.less
deleted file mode 100644
index e69de29..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-client-modal/client-message-modal.less
+++ /dev/null
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view-model.ts
deleted file mode 100644
index b92069f..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view-model.ts
+++ /dev/null
@@ -1,46 +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=========================================================
- */
-
-'use strict';
-import {IMessageModalModel, IMessageModalViewModelScope, MessageModalViewModel} from "../message-base-modal-model";
-
-export interface IServerMessageModalModel extends IMessageModalModel {
- status:string;
- messageId:string;
-
-
-}
-
-export interface IServerMessageModalViewModelScope extends IMessageModalViewModelScope {
- serverMessageModalModel:IServerMessageModalModel;
-}
-
-export class ServerMessageModalViewModel extends MessageModalViewModel {
-
- static '$inject' = ['$scope', '$uibModalInstance', 'serverMessageModalModel'];
-
- constructor(private $scope:IServerMessageModalViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private serverMessageModalModel:IServerMessageModalModel) {
-
- super($scope, $uibModalInstance, serverMessageModalModel);
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view.html b/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view.html
deleted file mode 100644
index 7d3204c..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal-view.html
+++ /dev/null
@@ -1,33 +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.
--->
-
-<ng1-modal modal="modalInstanceError"
- type="classic"
- class="w-sdc-modal modal-type-error"
- header="{{messageModalModel.title}}"
- buttons="footerButtons"
- show-close-button="true">
-
- <perfect-scrollbar include-padding="true">
- <div class="w-sdc-modal-icon w-sdc-modal-icon-{{messageModalModel.severity}}"></div>
- <div class="w-sdc-modal-caption">
- <div>Error code: {{messageModalModel.messageId}}</div>
- <div>Status code: {{messageModalModel.status}}</div>
- </div>
- <div class="w-sdc-modal-body-content" data-ng-bind-html="messageModalModel.message" data-tests-id="message"></div>
- </perfect-scrollbar>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal.less b/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal.less
deleted file mode 100644
index e69de29..0000000
--- a/catalog-ui/src/app/view-models/modals/message-modal/message-server-modal/server-message-modal.less
+++ /dev/null
diff --git a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts
deleted file mode 100644
index 01394a3..0000000
--- a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts
+++ /dev/null
@@ -1,272 +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=========================================================
- */
-
-'use strict';
-import {ComponentType, SEVERITY, FileUtils, ModalsHandler, ComponentFactory} from "app/utils";
-import {OnboardingService, CacheService} from "app/services";
-import {Component, IComponent, IUser, IAppConfigurtaion, Resource} from "app/models";
-import {IServerMessageModalModel} from "../message-modal/message-server-modal/server-message-modal-view-model";
-import {Dictionary} from "app/utils";
-import * as _ from 'underscore';
-
-interface IOnboardingModalViewModelScope {
- modalOnboarding:ng.ui.bootstrap.IModalServiceInstance;
- componentsList:Array<IComponent>;
- tableHeadersList:Array<any>;
- selectedComponent:Component;
- componentFromServer:Component;
- reverse:boolean;
- sortBy:string;
- searchBind:string;
- okButtonText:string;
- isCsarComponentExists:boolean;
- user:IUser;
- isLoading:boolean;
-
- //this is for UI paging
- numberOfItemsToDisplay:number;
- allItemsDisplayed:boolean;
-
- doSelectComponent(component:Component):void;
- doUpdateCsar():void;
- doImportCsar():void;
- sort(sortBy:string):void;
- downloadCsar(packageId:string):void;
- increaseNumItemsToDisplay():void;
-}
-
-export class OnboardingModalViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- '$state',
- 'sdcConfig',
- '$uibModalInstance',
- 'Sdc.Services.OnboardingService',
- 'okButtonText',
- 'currentCsarUUID',
- 'currentCsarVersion',
- 'Sdc.Services.CacheService',
- 'FileUtils',
- 'ComponentFactory',
- 'ModalsHandler'
- ];
-
- constructor(private $scope:IOnboardingModalViewModelScope,
- private $filter:ng.IFilterService,
- private $state:any,
- private sdcConfig:IAppConfigurtaion,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private onBoardingService:OnboardingService,
- private okButtonText:string,
- private currentCsarUUID:string,
- private currentCsarVersion:string,
- private cacheService:CacheService,
- private fileUtils:FileUtils,
- private componentFactory:ComponentFactory,
- private modalsHandler:ModalsHandler) {
-
- this.init();
- }
-
- /**
- * Called from controller constructor, this will call onboarding service to get list
- * of "mini" components (empty components created from CSAR).
- * The list is inserted to componentsList on $scope.
- * And then call initScope method.
- */
- private init = ():void => {
- this.initOnboardingComponentsList();
- };
-
- private initScope = ():void => {
-
- this.initSortedTableScope();
- this.initModalScope();
- this.$scope.sortBy = "name"; // Default sort by
- this.$scope.user = this.cacheService.get('user');
- this.$scope.okButtonText = this.okButtonText;
- this.$scope.numberOfItemsToDisplay = 0;
- this.$scope.allItemsDisplayed = false;
-
- // Dismiss the modal and pass the "mini" component to workspace general page
- this.$scope.doImportCsar = ():void => {
-
- this.$uibModalInstance.close({
- componentCsar: this.$scope.selectedComponent,
- type: ComponentType.RESOURCE.toLowerCase()
- });
- };
-
- this.$scope.doUpdateCsar = ():void => {
-
- // Change the component version to the CSAR version we want to update.
- if(!this.currentCsarVersion || this.currentCsarVersion != (<Resource>this.$scope.selectedComponent).csarVersion) {
- this.$uibModalInstance.close({
- componentCsar: this.$scope.selectedComponent,
- previousComponent: this.$scope.componentFromServer,
- type: this.$scope.componentFromServer.componentType.toLowerCase()
-
- });
-
- } else {
- this.$uibModalInstance.close();
- }
- };
-
- this.$scope.downloadCsar = (packageId:string):void => {
- this.$scope.isLoading = true;
- this.onBoardingService.downloadOnboardingCsar(packageId).then(
- (file:any):void => {
- this.$scope.isLoading = false;
- if (file) {
- this.fileUtils.downloadFile(file, packageId + '.csar');
- }
- }, ():void => {
- this.$scope.isLoading = false;
- var data:IServerMessageModalModel = {
- title: 'Download error',
- message: "Error downloading file",
- severity: SEVERITY.ERROR,
- messageId: "",
- status: ""
- };
- this.modalsHandler.openServerMessageModal(data);
- }
- );
- };
-
- this.$scope.increaseNumItemsToDisplay = ():void => {
- this.$scope.numberOfItemsToDisplay = this.$scope.numberOfItemsToDisplay + 40;
- if (this.$scope.componentsList) {
- this.$scope.allItemsDisplayed = this.$scope.numberOfItemsToDisplay >= this.$scope.componentsList.length;
- }
- };
-
- // When the user select a row, set the component as selectedComponent
- this.$scope.doSelectComponent = (component:Component):void => {
-
- if (this.$scope.selectedComponent === component) {
- // Collapse the item
- this.$scope.selectedComponent = undefined;
- return;
- }
-
- this.$scope.isLoading = true;
- this.$scope.componentFromServer = undefined;
- this.$scope.selectedComponent = component;
-
- let onSuccess = (componentFromServer:Component):void => {
- this.$scope.isLoading = false;
- if (componentFromServer) {
- this.$scope.componentFromServer = componentFromServer;
- this.$scope.isCsarComponentExists = true;
- } else {
- this.$scope.componentFromServer = component;
- this.$scope.isCsarComponentExists = false;
- }
- };
-
- let onError = ():void => {
- this.$scope.isLoading = false;
- this.$scope.componentFromServer = component;
- this.$scope.isCsarComponentExists = false;
- };
-
- this.onBoardingService.getComponentFromCsarUuid((<Resource>component).csarUUID).then(onSuccess, onError);
- };
-
- };
-
- private initSortedTableScope = ():void => {
- this.$scope.tableHeadersList = [
- {title: 'Name', property: 'name'},
- {title: 'Vendor', property: 'vendorName'},
- {title: 'Category', property: 'categories'},
- {title: 'Version', property: 'csarVersion'},
- {title: 'Type', property: 'resourceType'},
- {title: '#', property: 'importAndUpdate'}
- //{title: 'Date', property: 'componentDate'}
- ];
-
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
- };
-
- private initModalScope = ():void => {
- // Enable the modal directive to close
- this.$scope.modalOnboarding = this.$uibModalInstance;
- };
-
- private initOnboardingComponentsList = ():void => {
- let onSuccess = (onboardingResponse:Array<IComponent>):void => {
- initMaxVersionOfItemsInList(onboardingResponse);
-
- if (this.currentCsarUUID) {
- //this.$scope.componentsList = this.$filter('filter')(this.$scope.componentsList, {csarUUID: this.currentCsarUUID});
- this.$scope.componentsList = this.$filter('filter')(this.$scope.componentsList,
- (input):boolean => {
- return input.csarUUID === this.currentCsarUUID;
- }
- );
- }
- this.initScope();
- };
-
- let onError = ():void => {
- console.log("Error getting onboarding list");
- this.initScope();
- };
-
- let initMaxVersionOfItemsInList = (onboardingResponse:Array<IComponent>):void => {
- // Get only the latest version of each item
- this.$scope.componentsList = [];
-
- // Get all unique items from the list
- let uniqueItems:Array<any> = _.uniq(onboardingResponse, false, (item:any):void=>{
- return item.packageId;
- });
-
- // Loop on all the items with unique packageId
- _.each(uniqueItems, (item:any):void=> {
- // Find all the items that has same packageId
- let ItemsFound:Array<IComponent> = _.filter(onboardingResponse, (inListItem:any):any => {
- return inListItem.packageId === item.packageId;
- });
-
- // Loop on all the items with same packageId and find the max version.
- let maxItem:any;
- _.each(ItemsFound, (ItemFound:any):void=> {
- if (!maxItem) {
- maxItem = ItemFound;
- } else if (maxItem && parseInt(maxItem.csarVersion) < parseInt(ItemFound.csarVersion)) {
- maxItem = ItemFound;
- }
- });
- this.$scope.componentsList.push(maxItem);
- });
- };
-
- this.onBoardingService.getOnboardingComponents().then(onSuccess, onError);
- };
-}
diff --git a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view.html b/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view.html
deleted file mode 100644
index 7f19389..0000000
--- a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view.html
+++ /dev/null
@@ -1,165 +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.
--->
-
-<ng1-modal modal="modalOnboarding" class="w-sdc-modal-onboarding w-sdc-classic-top-line-modal" buttons="footerButtons" header="Import VSP" show-close-button="true">
- <info-tooltip class="general-info-button" info-message-translate="ON_BOARDING_GENERAL_INFO "></info-tooltip>
- <div class="title-wrapper">
- <div>
- <p class="sub-title">Select one of the software product component below:</p>
- </div>
-
- <div class="top-search">
- <input type="text"
- class="search-text"
- placeholder="Search"
- data-ng-model="search.filterTerm"
- data-tests-id="onboarding-search"
- ng-model-options="{ debounce: 300 }" />
- <span class="w-sdc-search-icon magnification"></span>
- </div>
- </div>
-
- <div class="table-container-flex">
- <div class="table" data-ng-class="{'view-mode': isViewMode()}">
-
- <!-- Table headers -->
- <div class="head flex-container">
- <div class="table-header head-row hand flex-item" ng-repeat="header in tableHeadersList track by $index" data-ng-click="sort(header.property)" data-tests-id="{{header.title}}">{{header.title}}
- <span data-ng-show="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- </div>
-
- <!-- Table body -->
- <div class="body">
- <perfect-scrollbar suppress-scroll-x="true" scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container" id="onboarding-modal-scrollbar-container">
-
- <!-- In case the component list is empty -->
- <div data-ng-if="!componentsList || componentsList.length===0" class="no-row-text">
- There are no software product component to display
- </div>
-
- <div infinite-scroll-disabled='allItemsDisplayed' infinite-scroll="increaseNumItemsToDisplay()" infinite-scroll-container="'#onboarding-modal-scrollbar-container'">
-
- <!-- Loop on components list -->
- <div data-ng-repeat-start="component in componentsList | filter: search | orderBy:sortBy:reverse | limitTo:numberOfItemsToDisplay track by $index"
- class="flex-container data-row"
- data-ng-class="{'selected': component.packageId === selectedComponent.packageId}"
- data-ng-click="doSelectComponent(component);"
- data-tests-id="csar-row"
- >
-
- <!-- Name -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- <span class="sprite table-arrow" data-ng-class="{'opened': component.packageId === selectedComponent.packageId}" data-tests-id="{{component.name}}"></span>
- {{component.name}}
- </div>
-
- <!-- Vendor -->
- <div class="table-col-general flex-item" data-tests-id="{{component.vendorName}}" sdc-smart-tooltip>
- {{component.vendorName}}
- </div>
-
- <!-- Category -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{component.categories[0].name}} {{component.categories[0].subcategories[0].name}}
- </div>
-
- <!-- Version -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{component.csarVersion}}
- </div>
-
- <!-- Type -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{component.resourceType}}
- </div>
-
- <!-- Import And Update -->
- <div class="table-col-general flex-item" sdc-smart-tooltip></div>
-
- </div>
-
- <div data-ng-repeat-end="" data-ng-if="component.packageId === selectedComponent.packageId" class="item-opened">
-
- <div class="item-opened-description">
- <div class="item-opened-description-title">VSP Description:</div>
- {{component.description}}
- </div>
-
- <div class="item-opened-metadata1">
- <div data-ng-if="isCsarComponentExists===true">
- <div class="item-opened-metadata-title">VF'S Meta Data:</div>
- <div><span class="th">Name:</span> {{componentFromServer.name}}</div>
- <div><span class="th">Lifecycle:</span> {{componentFromServer.lifecycleState}}</div>
- <div><span class="th">Creator:</span> {{componentFromServer.creatorFullName}}</div>
- </div>
- </div>
-
- <div class="item-opened-metadata2">
- <div data-ng-if="isCsarComponentExists===true">
- <div class="item-opened-metadata-title"> </div>
- <div><span class="th">UUID:</span> {{componentFromServer.uuid}}</div>
- <div><span class="th">Version:</span> {{componentFromServer.version}}</div>
- <div><span class="th">Modifier:</span> {{componentFromServer.lastUpdaterFullName}}</div>
- <div data-ng-if="componentFromServer.lifecycleState==='NOT_CERTIFIED_CHECKOUT' && componentFromServer.lastUpdaterUserId !== user.userId">
- <span class="note">Designers cannot update a VSP if the VF is checked out by another user.</span>
- </div>
- <div data-ng-if="componentFromServer.lifecycleState==='READY_FOR_CERTIFICATION'">
- <span class="note">Designers cannot update a VSP if the VF is in Ready for testing state.</span>
- </div>
- </div>
- </div>
-
- <div class="item-opened-metadata3">
- <info-tooltip class="info-button" info-message-translate="{{isCsarComponentExists?'ON_BOARDING_UPDATE_INFO':'ON_BOARDING_IMPORT_INFO'}}" direction="left"></info-tooltip>
- </div>
-
- <div class="item-opened-icon">
- <span data-ng-if="isCsarComponentExists!==true"
- class="sprite-new import-file-btn"
- data-ng-click="doImportCsar()"
- uib-tooltip="Import VSP"
- tooltip-class="uib-custom-tooltip"
- tooltip-placement="bottom"
- data-tests-id="import-csar"></span>
-
- <span data-ng-if="isCsarComponentExists===true"
- class="sprite-new refresh-file-btn"
- uib-tooltip="Update VSP"
- tooltip-class="uib-custom-tooltip"
- tooltip-placement="bottom"
- data-ng-class="{'disabled': (componentFromServer.lifecycleState==='NOT_CERTIFIED_CHECKOUT' && componentFromServer.lastUpdaterUserId!==user.userId) || componentFromServer.lifecycleState==='READY_FOR_CERTIFICATION'}"
- data-ng-click="doUpdateCsar()"
- data-tests-id="update-csar"></span>
-
- <span data-ng-click="downloadCsar(component.packageId)"
- class="sprite-new download-file-btn hand"
- uib-tooltip="Download VSP"
- tooltip-class="uib-custom-tooltip"
- tooltip-placement="bottom"
- data-tests-id="download-csar"></span>
- </div>
- <loader data-display="isLoading" relative="true" size="small"></loader>
- </div>
- </div>
-
- </perfect-scrollbar>
- </div><!-- End table body -->
- </div><!-- End table -->
- </div><!-- End table-container-flex -->
- <div class="w-sdc-modal-footer classic"></div>
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal.less b/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal.less
deleted file mode 100644
index ccf4fb0..0000000
--- a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal.less
+++ /dev/null
@@ -1,149 +0,0 @@
-.w-sdc-modal-onboarding {
-
- width: 100%;
- display: inline-block;
-
- .general-info-button{
- position: relative;
- top: -40px;
- left: 95px;
- float: left;
- }
-
- .title-wrapper {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
-
- .sub-title {
- .m_14_r;
- float:left;
- }
- }
-
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
- .table{
- height: 472px;
- margin-bottom: 0;
- }
-
- .table-container-flex {
- margin-top: 10px;
-
- .table {
- .body {
- .data-row + div.item-opened {
- word-wrap: break-word;
- display: flex;
- justify-content: space-between;
- padding: 10px 0;
-
- .item-opened-description-title,
- .item-opened-metadata-title {
- .m_14_m;
- }
-
- .item-opened-description,
- .item-opened-metadata1,
- .item-opened-metadata2,
- .item-opened-metadata3 {
- .th { .m_14_m; }
- flex-basis: 0;
- overflow: hidden;
- padding: 5px 15px;
- }
-
- .item-opened-description,
- .item-opened-metadata3 {
- border-right: 1px solid @main_color_o;
- }
-
- .item-opened-metadata2 {
- word-break: break-word;
- .note {
- color: @func_color_q;
- }
- }
-
- .item-opened-icon {
- flex-basis: 0;
- overflow: hidden;
- padding: 5px 15px;
- align-self: center;
- }
-
- .item-opened-description {flex-grow: 25.3;}
- .item-opened-metadata1 {flex-grow: 25;}
- .item-opened-metadata2 {flex-grow: 45;}
- .item-opened-metadata3 {
- flex-grow: 10;
- .info-button{
- float: right;
- }
- }
- .item-opened-icon {flex-grow: 10.1;}
- }
- }
- }
-
- .flex-item:nth-child(1) {
- flex-grow: 25;
- .hand;
- span.table-arrow {
- margin-right: 7px;
- }
- }
-
- .flex-item:nth-child(2) {flex-grow: 25;}
- .flex-item:nth-child(3) {flex-grow: 30;}
- .flex-item:nth-child(4) {flex-grow: 10; text-align: center; }
- .flex-item:nth-child(5) {flex-grow: 10; text-align: center; }
- .flex-item:nth-child(6) {flex-grow: 10; }
-
- }
-
- .download-file-btn {
- cursor: pointer;
- margin-left: 4px;
- }
-
- .refresh-file-btn,
- .import-file-btn {
- cursor: pointer;
- margin-left: 20px;
- }
-
- .top-search {
- float: right;
- position: relative;
-
- input.search-text {
- .border-radius(2px);
- width: 245px;
- height: 32px;
- line-height: 32px;
- border: 1px solid @main_color_o;
- margin: 0;
- outline: none;
- text-indent: 10px;
-
- &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */
- &:-moz-placeholder { font-style: italic; } /* Firefox 18- */
- &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */
- &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */
- &:-ms-input-placeholder { font-style: italic; } /* Edge */
- }
-
- .magnification {
- position: absolute;
- top: 10px;
- right: 10px;
- }
-
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view-model.ts b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view-model.ts
index 10f41f6..fc3672c 100644
--- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view-model.ts
+++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view-model.ts
@@ -22,7 +22,7 @@
import * as _ from "underscore";
import {IUserProperties} from "app/models";
import {MenuItemGroup, MenuItem} from "app/utils";
-import {CacheService} from "app/services";
+import {CacheService} from "app/services-ng2";
declare var PunchOutRegistry;
export class BreadcrumbsMenuItem {
diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html
index fc1140e..2d8010b 100644
--- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html
+++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="sdc-catalog-container">
<loader data-display="isLoading"></loader>
diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less
index 71a3101..1e091e9 100644
--- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less
+++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less
@@ -76,22 +76,6 @@
}
}
- &.READY_FOR_CERTIFICATION {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2985px;
- width: 14px;
- height: 16px;
- }
- }
-
- &.CERTIFICATION_IN_PROGRESS {
- .i-sdc-categories-list-item-icon {
- background: url('/assets/styles/images/sprites/sprite-global-old.png') no-repeat -53px -2934px;
- width: 14px;
- height: 16px;
- }
- }
-
&.DISTRIBUTED,
&.TBD {
.i-sdc-categories-list-item-icon {
diff --git a/catalog-ui/src/app/view-models/plugins/plugins-tab-view-model.ts b/catalog-ui/src/app/view-models/plugins/plugins-tab-view-model.ts
deleted file mode 100644
index d25cd19..0000000
--- a/catalog-ui/src/app/view-models/plugins/plugins-tab-view-model.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-
-* Copyright (c) 2018 AT&T Intellectual Property.
-
-*
-
-* 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.
-
-*/
-
-import {IUserProperties, Plugin} from "app/models";
-import {CacheService} from "app/services";
-import {PluginsService} from "../../ng2/services/plugins.service";
-
-
-interface IPluginsTabViewModelScope extends ng.IScope {
- plugin: Plugin
- user: IUserProperties;
- version: string;
- queryParams: Object;
- isLoading: boolean;
-
- onLoadingDone(plugin: Plugin): void;
-}
-
-export class PluginsTabViewModel {
- static '$inject' = [
- '$scope',
- '$stateParams',
- 'Sdc.Services.CacheService',
- 'PluginsService'
- ];
-
- constructor(private $scope: IPluginsTabViewModelScope,
- private $stateParams: any,
- private cacheService: CacheService,
- private pluginsService: PluginsService) {
-
- this.initScope();
- }
-
- private initScope = (): void => {
- this.$scope.plugin = this.pluginsService.getPluginByStateUrl(this.$stateParams.path);
- this.$scope.version = this.cacheService.get('version');
- this.$scope.user = this.cacheService.get('user');
-
- this.$scope.isLoading = true;
-
- this.$scope.queryParams = {
- userId: this.$scope.user.userId,
- userRole: this.$scope.user.role,
- displayType: "tab",
- parentUrl: window.location.origin,
- eventsClientId: this.$scope.plugin.pluginId
- };
-
- this.$scope.onLoadingDone = (plugin: Plugin) => {
- if (plugin.pluginId == this.$scope.plugin.pluginId) {
- this.$scope.isLoading = false;
- }
- };
- }
-}
diff --git a/catalog-ui/src/app/view-models/preloading/preloading-view.html b/catalog-ui/src/app/view-models/preloading/preloading-view.html
deleted file mode 100644
index e894587..0000000
--- a/catalog-ui/src/app/view-models/preloading/preloading-view.html
+++ /dev/null
@@ -1,25 +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="sdc-loading-page">
- <h1 class="caption1" translate="SIGN_IN_CAPTION"></h1>
- <p class="caption2" translate="SIGN_IN_DESCRIPTION"></p>
-
- <div class="load-container-wrapper">
- <div class="load-container load2 animated fadeIn"><div class="loader">Loading...</div></div>
- </div>
-
-</div>
diff --git a/catalog-ui/src/app/view-models/preloading/preloading-view.ts b/catalog-ui/src/app/view-models/preloading/preloading-view.ts
deleted file mode 100644
index d629d29..0000000
--- a/catalog-ui/src/app/view-models/preloading/preloading-view.ts
+++ /dev/null
@@ -1,47 +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=========================================================
- */
-
-'use strict';
-
-interface IPreLoadingViewScope {
- startZoomIn:boolean;
-}
-
-export class PreLoadingViewModel {
-
- static '$inject' = ['$scope'];
-
- constructor(private $scope:IPreLoadingViewScope) {
- this.init($scope);
- }
-
- private init = ($scope:IPreLoadingViewScope):void => {
- this.animate($('.caption1'), 'fadeInUp', 400);
- this.animate($('.caption2'), 'fadeInUp', 800);
- };
-
- private animate = (element:any, animation:string, when:number):void => {
- window.setTimeout(()=> {
- element.addClass("animated " + animation);
- element[0].style = "visibility: visible;";
- }, when);
- };
-
-}
diff --git a/catalog-ui/src/app/view-models/shared/notification-custom-template.html b/catalog-ui/src/app/view-models/shared/notification-custom-template.html
index 869c49b..9456b87 100644
--- a/catalog-ui/src/app/view-models/shared/notification-custom-template.html
+++ b/catalog-ui/src/app/view-models/shared/notification-custom-template.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="ui-notification">
<div class="notification-container">
<div class="icon-container">
diff --git a/catalog-ui/src/app/view-models/shared/notification-template.less b/catalog-ui/src/app/view-models/shared/notification-template.less
new file mode 100644
index 0000000..5baf10d
--- /dev/null
+++ b/catalog-ui/src/app/view-models/shared/notification-template.less
@@ -0,0 +1,53 @@
+.notification-container{
+ display: flex;
+ padding: 15px 11px;
+ float: left;
+ .icon-container{
+ flex-grow: 1;
+ margin-right: 20px;
+ .icon-circle{
+ background-color: black;
+ height: 40px;
+ width: 40px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ margin-right: 0;
+ background-color: rgba(255, 255, 255, 0.3);
+ .icon{
+ margin: 0 auto;
+ display: block;
+ }
+ }
+ }
+ .msg-content{
+ flex-grow: 3;
+ h3{
+ border-bottom: none;
+ font-weight: 400;
+ .f-type._18_m;
+ }
+ .message{
+ font-weight: 300;
+ .f-type._14_m;
+ }
+ }
+}
+.ui-notification.success{
+ background-color: @main_color_d;
+ .icon{
+ .notification-success-icon;
+ }
+}
+.ui-notification.error{
+ background-color: @func_color_q;
+ .icon{
+ .notification-error-icon;
+ }
+}
+.ui-notification.info{
+ background-color: @main_color_a;
+ .icon{
+ .notification-process-icon;
+ }
+}
diff --git a/catalog-ui/src/app/view-models/support/support-view-model.ts b/catalog-ui/src/app/view-models/support/support-view-model.ts
deleted file mode 100644
index 5703a74..0000000
--- a/catalog-ui/src/app/view-models/support/support-view-model.ts
+++ /dev/null
@@ -1,36 +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=========================================================
- */
-
-'use strict';
-import {CacheService} from "app/services";
-
-interface ISupportViewModelScope {
- version:string;
-}
-
-export class SupportViewModel {
-
- static '$inject' = ['$scope', 'Sdc.Services.CacheService'];
-
- constructor(private $scope:ISupportViewModelScope,
- private cacheService:CacheService) {
- this.$scope.version = this.cacheService.get('version');
- }
-}
diff --git a/catalog-ui/src/app/view-models/support/support-view.html b/catalog-ui/src/app/view-models/support/support-view.html
deleted file mode 100644
index e85373b..0000000
--- a/catalog-ui/src/app/view-models/support/support-view.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
--->
-
-<div class="full-height" >
- <loader data-display="isLoading"></loader>
- <div class="w-sdc-header">
- <div class="w-sdc-header-logo">
- <div class="w-sdc-header-logo-icon sprite logo"></div>
- <a class="w-sdc-header-logo-link" data-ui-sref="dashboard" translate="PROJECT_TITLE"></a>
- <div class="w-sdc-header-version"> v.{{version}}</div>
- </div>
- <div class="i-sdc-header-caption">Support</div>
- <user-header-details ></user-header-details>
- </div>
- <div class="w-sdc-main-container">
- <div class="w-sdc-left-sidebar">
- <div class="w-sdc-left-sidebar-in-progress" >
- <div class="i-sdc-left-sidebar-item category-title" data-ng-class="{'selectedLink':selectedLeftBarGroupLink === inProgressEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroup(inProgressEnumVal)" >In Design ({{numOfCheckOutEntities+numOfCheckInEntities}})</div>
- <div class="i-sdc-left-sidebar-item" data-ng-class="{'selectedLink':selectedLeftBarStateLink===notCertifiedCheckOutEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroupAndEntityState(inProgressEnumVal, notCertifiedCheckOutEnumVal)" >Checked Out ({{numOfCheckOutEntities}})</div>
- <div class="i-sdc-left-sidebar-item" data-ng-class="{'selectedLink':selectedLeftBarStateLink===notCertifiedCheckInEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroupAndEntityState(inProgressEnumVal, notCertifiedCheckInEnumVal)" >Checked In ({{numOfCheckInEntities}})</div>
- </div>
- <div class="w-sdc-left-sidebar-following" >
- <div class="i-sdc-left-sidebar-item category-title" data-ng-class="{'selectedLink':selectedLeftBarGroupLink===followingEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroup(followingEnumVal)" >Completed Design ({{numOfReadyForCertificationEntities+numOfCertificationInProgressEntities+numOfCertifiedEntities}})</div>
- <div class="i-sdc-left-sidebar-item" data-ng-class="{'selectedLink':selectedLeftBarStateLink===readyForCertificationEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroupAndEntityState(followingEnumVal, readyForCertificationEnumVal)" >Ready For Certification ({{numOfReadyForCertificationEntities}})</div>
- <div class="i-sdc-left-sidebar-item" data-ng-class="{'selectedLink':selectedLeftBarStateLink===certificationInProgressEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroupAndEntityState(followingEnumVal, certificationInProgressEnumVal)" >Certification In Progress ({{numOfCertificationInProgressEntities}})</div>
- <div class="i-sdc-left-sidebar-item" data-ng-class="{'selectedLink':selectedLeftBarStateLink===certifiedEnumVal}" data-ng-click="setSelectedEntitiesByEntityGroupAndEntityState(followingEnumVal, certifiedEnumVal)" >Certified ({{numOfCertifiedEntities}})</div>
- </div>
- <div class="w-sdc-left-sidebar-nav">
- <div class="i-sdc-left-sidebar-nav-item catalog" data-ui-sref="catalog">Catalog</div>
- <div class="i-sdc-left-sidebar-nav-item support" data-ui-sref="support">Support</div>
- </div>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/support/support.less b/catalog-ui/src/app/view-models/support/support.less
deleted file mode 100644
index 8159e38..0000000
--- a/catalog-ui/src/app/view-models/support/support.less
+++ /dev/null
@@ -1,8 +0,0 @@
-.w-sdc-left-sidebar-in-progress,
-.w-sdc-left-sidebar-following {
- .b_7;
-}
-
-.w-sdc-left-sidebar-following {
- padding: 13px 0;
-}
diff --git a/catalog-ui/src/app/view-models/tabs/general-tab.less b/catalog-ui/src/app/view-models/tabs/general-tab.less
deleted file mode 100644
index 936b3e3..0000000
--- a/catalog-ui/src/app/view-models/tabs/general-tab.less
+++ /dev/null
@@ -1,122 +0,0 @@
-.sdc-general-tab {
-
- display: flex;
- min-height: 100%;
- flex-flow: column;
-
- .sdc-edit-icon {
- .sprite;
- .e-sdc-small-icon-pencil;
- }
- .sdc-general-tab-title {
-
- .f-color.a;
- .f-type._14_m;
- padding: 0px 0px 15px 20px;
- border-bottom: 1px solid @main_color_o;
- }
-
- .sdc-general-tab-sub-title {
-
- .f-color.a;
- .f-type._14_m;
- padding: 15px 20px 15px 20px;
-
- }
-
- //scrollbar
- .general-tab-scrollbar-container {
-
- .perfect-scrollbar;
- width: 100%;
- }
-
- //plus minus expand collapse
- .general-tab-expand-collapse {
-
- &.expanded {
- .expand-collapse-title {
- .expand-collapse-title-icon {
- .expand-collapse-minus-icon;
- }
- }
- }
-
- .expand-collapse-title {
-
- padding: 8px 20px 4px 20px;
- cursor: pointer;
- &:hover {
- background-color: @main_color_o;
- }
-
- .expand-collapse-title-icon {
- .hand;
- .sprite-new;
- .expand-collapse-plus-icon;
- }
- .expand-collapse-title-text {
- max-width: 225px;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding-left: 10px;
- line-height: 15px;
- }
- }
- .selected {
- background-color: @main_color_a;
- .f-color.p;
- }
-
- }
-
- .expand-collapse-sub-title {
- max-width: 190px;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding: 10px 0 0 43px;
-
- }
-
- //resizable view
- .resizable-container {
-
- flex: 1 1 auto;
- display: flex;
- flex-direction: column;
- height: 90%;
-
- .resizable-section {
- min-height: 50px;
- flex: 1;
- display: flex;
- flex-flow: column;
- &.resizable {
- flex: 0 0 300px;
- }
- }
-
- //this is the resizable icon custom design for the angular resizable directive
- .rg-top {
- span {
- margin-top: -5px;
- &:before {
- border-top: 1px dotted @main_color_m;
- content: '';
- display: inline-block;
- width: 39px;
- height: 6px;
- }
-
- border-top: 1px dotted @main_color_m;
- border-bottom: 1px dotted @main_color_m;
- width: 39px;
- height: 4px;
- }
- }
- }
-}
diff --git a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view-model.ts b/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view-model.ts
deleted file mode 100644
index f752e3d..0000000
--- a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view-model.ts
+++ /dev/null
@@ -1,134 +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=========================================================
- */
-
-'use strict';
-import {ModalsHandler} from "app/utils";
-import {PropertyModel, DisplayModule, Component, ComponentInstance, Tab, Module} from "app/models";
-import {ExpandCollapseListData} from "app/directives/utils/expand-collapse-list-header/expand-collapse-list-header";
-
-interface IComponentInstancesMap {
- [key:string]: ComponentInstance
-}
-
-export interface IHierarchyScope extends ng.IScope {
- component:Component;
- selectedIndex:number;
- selectedModule:DisplayModule;
- singleTab:Tab;
- isLoading:boolean;
- expandCollapseArtifactsList:ExpandCollapseListData;
- expandCollapsePropertiesList:ExpandCollapseListData;
- selectedInstanceId:string;
- componentInstancesMap:IComponentInstancesMap;
-
- onModuleSelected(module:Module, selectedIndex:number, componentInstanceId?:string):void;
- onModuleNameChanged(module:DisplayModule):void;
- updateHeatName():void;
- loadInstanceModules(instance:ComponentInstance):ng.IPromise<boolean>;
- openEditPropertyModal(property:PropertyModel, filteredProperties:Array<PropertyModel>):void;
-}
-
-export class HierarchyViewModel {
-
- static '$inject' = [
- '$scope',
- '$q',
- 'ModalsHandler'
- ];
-
- constructor(private $scope:IHierarchyScope, private $q:ng.IQService, private ModalsHandler:ModalsHandler) {
- this.$scope.component = this.$scope.singleTab.data;
- this.$scope.isLoading = false;
- this.$scope.expandCollapseArtifactsList = new ExpandCollapseListData();
- this.$scope.expandCollapsePropertiesList = new ExpandCollapseListData();
- this.$scope.componentInstancesMap = <IComponentInstancesMap>{};
- this.initScopeMethods();
- }
-
- private initScopeMethods():void {
-
- let collapseModuleData = ():void => {
- this.$scope.expandCollapseArtifactsList.expandCollapse = false;
- this.$scope.expandCollapsePropertiesList.expandCollapse = false;
- this.$scope.expandCollapseArtifactsList.orderByField = "artifactName";
- this.$scope.expandCollapsePropertiesList.orderByField = "name";
- };
-
- this.$scope.onModuleSelected = (module:Module, selectedIndex:number, componentInstanceId?:string):void => {
-
- let onSuccess = (module:DisplayModule) => {
- console.log("Module Loaded: ", module);
- this.$scope.selectedModule = module;
- this.$scope.isLoading = false;
- collapseModuleData();
- };
-
- let onFailed = () => {
- this.$scope.isLoading = false;
- };
-
- this.$scope.selectedIndex = selectedIndex;
- if (!this.$scope.selectedModule || (this.$scope.selectedModule && this.$scope.selectedModule.uniqueId != module.uniqueId)) {
- this.$scope.isLoading = true;
- if (this.$scope.component.isService()) {
- this.$scope.selectedInstanceId = componentInstanceId;
- this.$scope.component.getModuleInstanceForDisplay(componentInstanceId, module.uniqueId).then(onSuccess, onFailed);
- } else {
- this.$scope.component.getModuleForDisplay(module.uniqueId).then(onSuccess, onFailed);
- }
- }
-
- const componentInstances: Array<ComponentInstance> = this.$scope.component.componentInstances || [];
- (<string[]>_.values(module.members)).forEach((memberId) => {
- if (!(memberId in this.$scope.componentInstancesMap)) {
- const compInstance = componentInstances.find((c) => c.uniqueId === memberId);
- if (compInstance) {
- this.$scope.componentInstancesMap[compInstance.uniqueId] = compInstance;
- }
- }
- });
- };
-
- this.$scope.updateHeatName = () => {
- this.$scope.isLoading = true;
-
- let originalName:string = this.$scope.selectedModule.name;
-
- let onSuccess = (module:Module) => {
- console.log("Module name updated:", module.name);
- this.$scope.selectedModule.name = module.name;
- this.$scope.isLoading = false;
- };
-
- let onFailed = () => {
- this.$scope.isLoading = false;
- this.$scope.selectedModule.name = originalName;
- };
-
- this.$scope.selectedModule.updateName();
- this.$scope.component.updateGroupMetadata(new DisplayModule(this.$scope.selectedModule)).then(onSuccess, onFailed);
- };
-
- this.$scope.openEditPropertyModal = (property:PropertyModel, filteredProperties:Array<PropertyModel>):void => {
- this.ModalsHandler.openEditModulePropertyModal(property, this.$scope.component, this.$scope.selectedModule, filteredProperties).then(() => {
- });
- }
- }
-}
diff --git a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view.html b/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view.html
deleted file mode 100644
index 423cbcd..0000000
--- a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy-view.html
+++ /dev/null
@@ -1,123 +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="sdc-general-tab hierarchy-tab" ng-class="">
- <loader data-display="isLoading" relative="true" size="medium"></loader>
- <div class="sdc-general-tab-title" data-tests-id="tab-header" translate="DEPLOYMENT_TAB_TITLE"></div>
-
- <div class="resizable-container">
- <div data-ng-if="!component.isService()"class="resizable-section">
-
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true"
- class="general-tab-scrollbar-container">
- <div class="sdc-general-tab-sub-title" data-tests-id="tab-sub-header">{{component.name}}</div>
- <expand-collapse expanded-selector=".hierarchy-module-member-list.{{$index}}"
- class="general-tab-expand-collapse" is-close-on-init="true"
- data-tests-id="hierarchy-module-{{$index}}"
- data-ng-repeat-start="module in component.modules">
- <div class="expand-collapse-title first-level" data-tests-id="hierarchy-module-{{$index}}-title" ng-class="{'selected': selectedIndex === $index}" data-ng-click="onModuleSelected(module, $index)">
- <div class="expand-collapse-title-icon"></div>
- <span class="expand-collapse-title-text" data-ng-bind="module.name" tooltips
- tooltip-content="{{module.name}}"></span>
-
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="hierarchy-module-member-list {{$index}}">
- <div ng-repeat="memberId in ::module.members track by $index">
- <div class="expand-collapse-sub-title" tooltips tooltip-content="{{componentInstancesMap[memberId].name}}">{{componentInstancesMap[memberId].name}}</div>
- </div>
- </div>
- </perfect-scrollbar>
- </div>
- <div data-ng-if="component.isService()"class="resizable-section">
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true"
- class="general-tab-scrollbar-container">
- <expand-collapse expanded-selector=".hierarchy-modules-list.{{$index}}"
- class="general-tab-expand-collapse" is-close-on-init="true"
- data-tests-id="hierarchy-instance-{{$index}}"
-
- data-ng-repeat-start="instance in component.componentInstances">
- <div class="expand-collapse-title first-level" data-tests-id="hierarchy-instance-{{$index}}-title">
- <div class="expand-collapse-title-icon"></div>
- <span class="expand-collapse-title-text" data-ng-bind="instance.name" tooltips
- tooltip-content="{{instance.name}}"></span>
-
- </div>
- </expand-collapse>
- <!--TODO: Rachel : -->
- <div data-ng-repeat-end="" class="hierarchy-modules-list {{$index}}">
- <expand-collapse expanded-selector=".outer-index-{{$parent.$index}}.hierarchy-module-member-list.{{$index}}"
- class="general-tab-expand-collapse" is-close-on-init="true"
- data-tests-id="hierarchy-module-{{$index}}"
- data-ng-repeat-start="module in instance.groupInstances">
- <div class="expand-collapse-title second-level" data-tests-id="hierarchy-module-{{$index}}-title" ng-class="{'selected': selectedIndex === $index && selectedInstanceId === instance.uniqueId}" data-ng-click="onModuleSelected(module, $index, instance.uniqueId)">
- <div class="expand-collapse-title-icon"></div>
- <span class="expand-collapse-title-text" data-ng-bind="module.name" tooltips tooltip-content="{{module.name}}"></span>
-
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="outer-index-{{$parent.$index}} hierarchy-module-member-list {{$index}}">
- <div ng-repeat="memberId in ::module.members track by $index">
- <div class="expand-collapse-sub-title" tooltips tooltip-content="{{componentInstancesMap[memberId].name}}">{{componentInstancesMap[memberId].name}}</div>
- </div>
- </div>
- </div>
- </perfect-scrollbar>
- </div>
-
- <div resizable r-directions="['top']" r-flex="true" ng-if="selectedModule" class="resizable-section module-data-container" data-tests-id="selected-module-data">
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true"
- class="general-tab-scrollbar-container">
- <div class="module-data">
- <div>
- <div class="module-name module-text-overflow" data-tests-id="selected-module-name" tooltips tooltip-content="{{selectedModule.name}}">{{selectedModule.name}}</div>
- <div class="edit-name-container" data-ng-if="!component.isService()">
- <edit-name-popover header="Edit Module Name" direction="auto top" module="selectedModule" on-save="updateHeatName()" ng-class="{'disabled': isViewOnly}" class="sdc-edit-icon" data-tests-id="edit-name-popover-icon"></edit-name-popover>
- </div>
- </div>
- <div class="" data-tests-id="selected-module-group-uuid" tooltips tooltip-content="{{selectedModule.groupUUID}}"><span class="bold">Module ID:</span><br><span class="small-font">{{selectedModule.groupUUID}}</span></div>
- <div class="" data-tests-id="selected-module-group-customization-uuid" data-ng-if="component.isService() && isViewOnly" tooltips tooltip-content="{{selectedModule.customizationUUID}}"><span class="bold">Customization ID:</span ><br><span class="small-font">{{selectedModule.customizationUUID}}</span></div>
- <div class="" data-tests-id="selected-module-group-invariant-uuid" tooltips tooltip-content="{{selectedModule.invariantUUID}}"><span class="bold">Invariant UUID:</span><span class="small-font">{{selectedModule.invariantUUID}}</span></div>
- <div data-tests-id="selected-module-version"><span class="bold">Version:</span> {{selectedModule.version}}</div>
- <div data-tests-id="selected-module-is-base"><span class="bold">IsBase:</span> {{selectedModule.isBase}}</div>
-
- </div>
- <expand-collapse-list-header title="Properties" expand-collapse-list-data="expandCollapsePropertiesList"></expand-collapse-list-header>
- <div ng-repeat="property in filteredProperties=(selectedModule.properties | filter: expandCollapsePropertiesList.filter | orderBy:expandCollapsePropertiesList.orderByField) track by $index" data-ng-if="expandCollapsePropertiesList.expandCollapse">
- <div class="list-item property-data" data-ng-class="{'last':$last}">
- <div class="property-name module-text-overflow" data-tests-id="selected-module-property-name">
- <span tooltips tooltip-content="{{property.name}}"
- data-ng-class="{'hand': !isViewOnly}"
- data-ng-click="!isViewOnly && openEditPropertyModal(property, filteredProperties)">{{property.name}}</span>
- </div>
- <div class="module-text-overflow property-info" data-tests-id="selected-module-property-type"> Type: {{property.type}}</div>
- <div class="module-text-overflow property-info" data-tests-id="selected-module-property-schema-type">Value: {{property.value}}</div>
- </div>
- </div>
- <expand-collapse-list-header title="Artifacts" expand-collapse-list-data="expandCollapseArtifactsList"></expand-collapse-list-header>
- <div ng-repeat="artifact in selectedModule.artifacts| filter: expandCollapseArtifactsList.filter | orderBy:expandCollapseArtifactsList.orderByField track by $index" data-ng-if="expandCollapseArtifactsList.expandCollapse">
- <div class="list-item artifact-data" data-ng-class="{'last':$last}">
- <div class="artifact-name module-text-overflow" data-tests-id="selected-module-artifact-name" tooltips tooltip-content="{{artifact.artifactName}}">{{artifact.artifactName}}</div>
- <div class="module-text-overflow" tooltips data-tests-id="selected-module-artifact-uuid" tooltip-content="{{artifact.artifactUUID}}">UUID: {{artifact.artifactUUID}}</div>
- <div data-tests-id="selected-module-artifact-version">Version: {{artifact.artifactVersion}}</div>
- </div>
- </div>
- </perfect-scrollbar>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy.less b/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy.less
deleted file mode 100644
index dee0eeb..0000000
--- a/catalog-ui/src/app/view-models/tabs/hierarchy/hierarchy.less
+++ /dev/null
@@ -1,101 +0,0 @@
-.hierarchy-tab{
- width: 100%;
- .hierarchy-module-list-container{
- padding: 0px 20px 0px 20px;
- }
- .module-data-container{
-
- width: 100%;
- height: 100%;
- background-color: #e6f6fb;
- border: 1px solid #009fdb;
- border-top: 4px solid #009fdb;
- box-shadow: 0.3px 1px 2px rgba(24, 24, 25, 0.32);
-
- .module-data {
-
- .selectable;
- .module-name {
- .f-type._14_m;
- width: 87%;
- }
- .f-type._14_r;
- .f-color.a;
- padding: 10px 0px 10px 0px;
- margin: 0px 20px 0px 20px;
- //border-bottom: 1px solid rgba(0, 159, 219, 0.6);
-
- .small-font{
- font-size: 12px;
- }
- }
-
- .list-item{
- padding: 10px 0px 10px 0px;
- margin: 0px 20px 0px 20px;
- &:not(.last){
- border-bottom: 1px solid rgba(0, 159, 219, 0.6);
- }
- }
-
- .artifact-data{
- .selectable;
- .f-type._12_r;
- .f-color.m;
- .artifact-name {
- .f-type._14_r;
- font-weight: bold;
- }
- }
-
- .property-data{
- .property-name{
- width: 100%;
- .f-type._14_m;
- font-weight: 400;
- color: @main_color_a;
- }
- .property-info{
- color: @func_color_s;
- .f-type._14_r;
- width: 100%;
- }
- }
-
- .module-text-overflow {
- max-width: 240px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- //display: inline-block;
- }
- }
-
- .hierarchy-modules-list{
- .expand-collapse-title{
- .expand-collapse-title-text{
- max-width: 202px;
- }
- }
- }
-
- .hierarchy-module-member-list {
- overflow: hidden;
- background-color: @main_color_p;
- }
-
- .edit-name-container {
- float: right;
- border-left: 1px solid #5cc1e7;
- height: 20px;
- width: 12%;
-
- .sdc-edit-icon {
- float: right;
- cursor: pointer;
- position: relative;
- top: 4px;
- right: 5px;
- }
- }
-}
diff --git a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.html b/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.html
deleted file mode 100644
index 3dffbb9..0000000
--- a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.html
+++ /dev/null
@@ -1,26 +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="sdc-tutorial-end-page">
- <perfect-scrollbar include-padding="true" class="sdc-tutorial-end-page-main">
- <h2 translate="TUTORIAL_LAST_PAGE_TITLE"></h2>
- <p class="sdc-tutorial-end-page-description1" translate="TUTORIAL_LAST_PAGE_TEXT"></p>
- <div>
- <button class="w-sdc-btn-blue" data-ui-sref="dashboard" type="button" translate="TUTORIAL_LAST_PAGE_BTN_ACTION_MY_DASHBOARD"></button>
- <button class="w-sdc-btn-blue" data-ui-sref="catalog" type="button" translate="WELCOME_BTN_ACTION_CATALOG"></button>
- </div>
- </perfect-scrollbar>
-</div>
diff --git a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.less b/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.less
deleted file mode 100644
index 30fa4f7..0000000
--- a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.less
+++ /dev/null
@@ -1,41 +0,0 @@
-.sdc-tutorial-end-page {
-
- .bg_s;
- width: 100%;
- height: 100%;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 999;
- .opacity(0.8);
- display: flex;
- align-items: center;
-
- background-image: url('/assets/styles/images/welcome.png');
- background-repeat: no-repeat;
- background-position: bottom left;
-
- .sdc-tutorial-end-page-main {
- width: 600px;
- height: 400px;
- margin: 100px auto 100px auto;
- padding: 80px;
- }
-
- h2 {
- .t_15;
- margin: 0;
- }
-
- .sdc-tutorial-end-page-description1 {
- .c_2;
- .opacity(0.8);
- margin-top: 10px;
- line-height: 22px;
- }
-
- .w-sdc-btn-blue {
- margin: 40px 10px 0 0;
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.ts b/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.ts
deleted file mode 100644
index 5c4c499..0000000
--- a/catalog-ui/src/app/view-models/tutorial-end/tutorial-end.ts
+++ /dev/null
@@ -1,40 +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=========================================================
- */
-
-'use strict';
-
-interface ITutorialEndViewModelScope extends ng.IScope {
-}
-
-export class TutorialEndViewModel {
-
- static '$inject' = [
- '$scope'
- ];
-
- constructor(private $scope:ITutorialEndViewModelScope) {
- this.init();
- }
-
- private init = ():void => {
-
- }
-
-}
diff --git a/catalog-ui/src/app/view-models/welcome/welcome-view.html b/catalog-ui/src/app/view-models/welcome/welcome-view.html
deleted file mode 100644
index c342741..0000000
--- a/catalog-ui/src/app/view-models/welcome/welcome-view.html
+++ /dev/null
@@ -1,25 +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="sdc-welcome-new-page">
- <div data-ng-click="onCloseButtonClick()" class="sdc-welcome-close"></div>
- <div class="sdc-welcome-wrapper">
- <div class="sdc-welcome-cover"></div>
- <div class="sdc-welcome-main">
- <h1>Welcome to SDC</h1>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/welcome/welcome-view.ts b/catalog-ui/src/app/view-models/welcome/welcome-view.ts
deleted file mode 100644
index 5ed7159..0000000
--- a/catalog-ui/src/app/view-models/welcome/welcome-view.ts
+++ /dev/null
@@ -1,81 +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=========================================================
- */
-
-'use strict';
-
-export interface IWelcomeViewMode {
- onCloseButtonClick():void;
-}
-
-export class WelcomeViewModel {
-
- firstLoad:boolean = true;
- alreadyAnimated:Array<number> = [];
-
- static '$inject' = [
- '$scope',
- '$state'
- ];
-
- constructor(private $scope:IWelcomeViewMode,
- private $state:ng.ui.IStateService
- ) {
- this.init();
- this.initScope();
- window.setTimeout(():void => {
- this.loadImages(():void=> {
- window.setTimeout(():void =>{
- $(".sdc-welcome-new-page").addClass("animated fadeIn");
- },1000);
- });
- },0);
- }
-
- private initScope = ():void => {
- let timeout = window.setTimeout(():void => {
- this.$state.go("dashboard", {});
- }, 4000);
- this.$scope.onCloseButtonClick = ():void => {
- window.clearTimeout(timeout);
- this.$state.go("dashboard", {});
- }
- };
-
- private init = ():void => {
- let viewModelsHtmlBasePath:string = 'src/app/view-models/';
- $('body').keyup((e):void=> {
- if (e.keyCode == 27) { // escape key maps to keycode `27`
- this.$state.go('dashboard');
- }
- });
- };
-
- private loadImages = (callback:Function):void => {
- let src = $('.sdc-welcome-wrapper').css('background-image');
- let url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');
-
- let img = new Image();
- img.onload = function() {
- callback();
- };
- img.src = url;
- };
-
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.html b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.html
deleted file mode 100644
index c5ab3cc..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.html
+++ /dev/null
@@ -1,101 +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="activity-log">
-
- <div class="title-wrapper">
- <div class="top-search">
- <input type="text"
- class="search-text"
- placeholder="Search"
- data-ng-model="searchBind"
- data-tests-id="main-menu-input-search"
- ng-model-options="{ debounce: 500 }" />
- <span class="w-sdc-search-icon magnification"></span>
- </div>
- </div>
-
- <div class="table-container-flex">
- <div class="table" data-ng-class="{'view-mode': isViewMode()}">
-
- <!-- Table headers -->
- <div class="head flex-container">
- <div class="table-header head-row hand flex-item" ng-repeat="header in tableHeadersList track by $index" data-ng-click="sort(header.property)">{{header.title}}
- <span data-ng-show="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- </div>
-
- <!-- Table body -->
- <div class="body">
- <perfect-scrollbar suppress-scroll-x="true" scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
-
- <!-- In case the logs are empty -->
- <div data-ng-if="!activityLog || activityLog.length===0" class="no-row-text">
- There are no logs to display
- </div>
-
- <!-- Loop on logs list -->
- <div data-ng-repeat="item in activityLog | filter: searchBind | orderBy:sortBy:reverse track by $index"
- data-ng-init="item.dateFormat = ( item.TIMESTAMP.replace(' UTC', '') | stringToDateFilter | date: 'MM/dd/yyyy':'UTC')+' | '+(item.TIMESTAMP.replace(' UTC', '') | stringToDateFilter | date: 'shortTime':'UTC' )"
- class="flex-container data-row"
- data-ng-class="{'selected': component === selectedComponent}"
- data-ng-click="doSelectComponent(component);"
- >
-
- <!-- Date -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{item.dateFormat}}
- </div>
-
- <!-- Action -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{item.ACTION}}
- </div>
-
- <!-- Comment -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{item.COMMENT}}
- </div>
-
- <!-- Username -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{item.MODIFIER}}
- </div>
-
- <!-- Status -->
- <div class="table-col-general flex-item" sdc-smart-tooltip>
- {{item.STATUS}}
- <span data-ng-class="{'success': item.STATUS>='200' && item.STATUS<='204','error': item.STATUS<'200' || item.STATUS>='300'}"></span>
- </div>
-
- </div>
-
- </perfect-scrollbar>
- </div><!-- End table body -->
- </div><!-- End table -->
- </div><!-- End table-container-flex -->
-
-</div>
-
-
-
-<!--<div ng-repeat="activityDate in activityDateArray " class="w-sdc-component-viewer-right-activity-log" >
- <div class="w-sdc-component-viewer-right-activity-log-date" >{{activityDate | date: 'longDate'}}</div>
- <div ng-repeat="activity in activityLog[activityDate] | orderBy: '-TIMESTAMP'">
- <div class="w-sdc-component-viewer-right-activity-log-time">{{activity.TIMESTAMP.replace(" UTC", '') | stringToDateFilter | date: 'mediumTime':'UTC'}}</div>
- <div class="w-sdc-component-viewer-right-activity-log-content">{{"Action: " + parseAction(activity.ACTION) + " Performed by: " + activity.MODIFIER + " Status: " + activity.STATUS}}</div>
- </div>
-</div>-->
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less
deleted file mode 100644
index 24f83ec..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less
+++ /dev/null
@@ -1,80 +0,0 @@
-.activity-log {
- .title-wrapper {
- display: flex;
- justify-content: flex-end;
- }
-
- .table-container-flex .table .body .scrollbar-container {
- max-height: 448px;
- }
-
- .view-mode {
- background-color: @main_color_p;
- }
-
- .table{
- height: 490px;
- margin-bottom: 0;
- }
-
- .table-container-flex {
- margin-top: 10px;
-
- .flex-item:nth-child(1) { width: 200px; }
- .flex-item:nth-child(2) { flex-grow: 20; }
- .flex-item:nth-child(3) { flex-grow: 30; }
- .flex-item:nth-child(4) { flex-grow: 20; }
- .flex-item:nth-child(5) { width: 80px; }
-
- .success {
- position: absolute;
- top: 11px;
- right: 20px;
- .sprite-new;
- .sdc-success;
- }
-
- .error {
- position: absolute;
- top: 11px;
- right: 20px;
- .sprite-new;
- .sdc-error;
- }
-
- }
-
- .data-row {
- position: relative;
- }
-
- .top-search {
- float: right;
- position: relative;
-
- input.search-text {
- .border-radius(2px);
- width: 245px;
- height: 32px;
- line-height: 32px;
- border: 1px solid @main_color_o;
- margin: 0;
- outline: none;
- text-indent: 10px;
-
- &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */
- &:-moz-placeholder { font-style: italic; } /* Firefox 18- */
- &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */
- &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */
- &:-ms-input-placeholder { font-style: italic; } /* Edge */
- }
-
- .magnification {
- position: absolute;
- top: 10px;
- right: 10px;
- }
-
- }
-
-}
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
deleted file mode 100644
index 452224a..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.ts
+++ /dev/null
@@ -1,123 +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=========================================================
- */
-
-'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";
-
-export interface IActivityLogViewModelScope extends IWorkspaceViewModelScope {
- activityDateArray:Array<any>; //this is in order to sort the dates
- activityLog:Array<Activity>;
- preVersion:string;
-
- tableHeadersList:Array<any>;
- reverse:boolean;
- sortBy:string;
- searchBind:string;
-
- getActivityLog(uniqueId:string):void;
- onVersionChanged(version:any):void;
- parseAction(action:string):string;
- sort(sortBy:string):void;
-}
-
-export class ActivityLogViewModel {
-
- static '$inject' = [
- '$scope',
- '$state',
- 'Sdc.Services.ActivityLogService'
- ];
-
- constructor(private $scope:IActivityLogViewModelScope,
- private $state:ng.ui.IStateService,
- private activityLogService:ActivityLogService) {
-
- this.initScope();
- this.$scope.setValidState(true);
- this.initSortedTableScope();
-
- // Set default sorting
- this.$scope.sortBy = 'logDate';
- }
-
- private initScope():void {
-
- this.$scope.preVersion = this.$scope.component.version;
-
- this.$scope.onVersionChanged = (version:any):void => {
- if (version.versionNumber != this.$scope.component.version) {
- this.$scope.isLoading = true;
- this.$scope.getActivityLog(version.versionId);
- }
- };
-
- this.$scope.getActivityLog = (uniqueId:any):void => {
-
- let onError = (response) => {
- this.$scope.isLoading = false;
- console.info('onFaild', response);
-
- };
-
- let onSuccess = (response:Array<Activity>) => {
- this.$scope.activityLog = _.sortBy(response, function (o) {
- return o.TIMESTAMP;
- }); //response; //
- this.$scope.isLoading = false;
- };
-
- this.$scope.isLoading = true;
- if (this.$scope.component.isResource()) {
- this.activityLogService.getActivityLogService('resources', uniqueId).then(onSuccess, onError);
- }
- if (this.$scope.component.isService()) {
- this.activityLogService.getActivityLogService('services', uniqueId).then(onSuccess, onError);
- }
-
- };
-
- if (!this.$scope.activityLog || this.$scope.preVersion != this.$scope.component.version) {
- this.$scope.getActivityLog(this.$scope.component.uniqueId);
- }
-
- this.$scope.parseAction = (action:string) => {
- return action ? action.split(/(?=[A-Z])/).join(' ') : '';
- };
-
- }
-
- private initSortedTableScope = ():void => {
- this.$scope.tableHeadersList = [
- {title: 'Date', property: 'dateFormat'},
- {title: 'Action', property: 'ACTION'},
- {title: 'Comment', property: 'COMMENT'},
- {title: 'Username', property: 'MODIFIER'},
- {title: 'Status', property: 'STATUS'}
- ];
-
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
- };
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view-model.ts
deleted file mode 100644
index 312a663..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view-model.ts
+++ /dev/null
@@ -1,99 +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=========================================================
- */
-
-'use strict';
-import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
-import {Component, AttributeModel} from "app/models";
-import {ModalsHandler} from "app/utils";
-import {ComponentServiceNg2} from "../../../../ng2/services/component-services/component.service";
-import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response";
-
-interface IAttributesViewModelScope extends IWorkspaceViewModelScope {
- tableHeadersList:Array<any>;
- reverse:boolean;
- sortBy:string;
-
- addOrUpdateAttribute(attribute?:AttributeModel):void;
- delete(attribute:AttributeModel):void;
- sort(sortBy:string):void;
-}
-
-export class AttributesViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- '$uibModal',
- 'ModalsHandler',
- 'ComponentServiceNg2'
- ];
-
-
- constructor(private $scope:IAttributesViewModelScope,
- private $filter:ng.IFilterService,
- private $uibModal:ng.ui.bootstrap.IModalService,
- private ModalsHandler:ModalsHandler,
- private ComponentServiceNg2: ComponentServiceNg2) {
-
- this.initComponentAttributes();
- }
-
- private initComponentAttributes = () => {
- if(this.$scope.component.attributes) {
- this.initScope();
- } else {
- this.ComponentServiceNg2.getComponentAttributes(this.$scope.component).subscribe((response:ComponentGenericResponse) => {
- this.$scope.component.attributes = response.attributes;
- this.initScope();
- });
- }
- }
-
-
- private initScope = ():void => {
-
- this.$scope.sortBy = 'name';
- this.$scope.reverse = false;
- this.$scope.setValidState(true);
- this.$scope.tableHeadersList = [
- {title: 'Name', property: 'name'},
- {title: 'Type', property: 'type'},
- {title: 'Default Value', property: 'defaultValue'}
- ];
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
-
- this.$scope.addOrUpdateAttribute = (attribute?:AttributeModel):void => {
- this.ModalsHandler.openEditAttributeModal(attribute ? attribute : new AttributeModel(), this.$scope.component);
- };
-
- this.$scope.delete = (attribute:AttributeModel):void => {
-
- let onOk = ():void => {
- this.$scope.component.deleteAttribute(attribute.uniqueId);
- };
- let title:string = this.$filter('translate')("ATTRIBUTE_VIEW_DELETE_MODAL_TITLE");
- let message:string = this.$filter('translate')("ATTRIBUTE_VIEW_DELETE_MODAL_TEXT", "{'name': '" + attribute.name + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view.html b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view.html
deleted file mode 100644
index 675ae0c..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes-view.html
+++ /dev/null
@@ -1,68 +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-attributes">
- <div class="add-btn" data-tests-id="add-attribute-button" ng-if="!isViewMode()"
- data-ng-class="{'disabled': isDisableMode()}" data-ng-click="addOrUpdateAttribute()" data-tests-id="add-attribute-button">Add</div>
- <div class="table-container-flex">
- <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 tableHeadersList track by $index" data-ng-click="sort(header.property)">{{header.title}}
- <span data-ng-if="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- <div class="table-no-text-header head-row flex-item" ng-if="!isViewMode()"></div>
- <!--div class="table-no-text-header head-row flex-item"></div-->
- </div>
-
- <div class="body">
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <div data-ng-if="component.attributes.length === 0" class="no-row-text" data-ng-class="{'disabled': isDisableMode()}">
- There are no attributes to display <br>
- <span ng-if="!isViewMode()"> click <a data-ng-click="addOrUpdateAttribute()">here</a> to add one </span>
-
- </div>
- <div data-ng-repeat-start="attribute in component.attributes | orderBy:sortBy:reverse track by $index"
- class="flex-container data-row" data-ng-class="{'selected': attribute.selected}"
- data-ng-click="attribute.selected = !attribute.selected" data-tests-id="attributes-table-row">
-
- <div class="table-col-general flex-item text">
- <span class="sprite table-arrow" data-ng-class="{'opened': attribute.selected}"></span>
- <span data-tests-id="{{attribute.name}}" tooltips tooltip-content="{{attribute.name}}">{{attribute.name}}</span>
-
- </div>
-
- <div class="table-col-general flex-item text" data-tests-id="{{attribute.type}}" data-ng-bind="attribute.type"></div>
-
- <div class="table-col-general flex-item text">
- <span tooltips tooltip-content="{{attribute.defaultValue}}" data-tests-id="{{attribute.defaultValue}}" data-ng-bind="attribute.defaultValue"></span>
- </div>
-
- <div class="table-btn-col flex-item" ng-if="!isViewMode()">
- <button class="table-edit-btn" data-tests-id="edit_{{attribute.name}}" data-ng-show="attribute.parentUniqueId==component.uniqueId"
- data-ng-click="addOrUpdateAttribute(attribute); $event.stopPropagation();" data-ng-class="{'disabled': isViewMode()}"> </button>
- <button class="table-delete-btn" data-tests-id="delete_{{attribute.name}}" data-ng-show="attribute.parentUniqueId==component.uniqueId"
- data-ng-click="delete(attribute); $event.stopPropagation();" data-ng-class="{'disabled': isViewMode()}"> </button>
- </div>
- </div>
- <div data-ng-repeat-end="" data-ng-if="attribute.selected && attribute.description" class="item-opened" data-ng-bind="attribute.description">
- </div>
- </perfect-scrollbar>
- </div>
-
- </div>
- </div>
-
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less
deleted file mode 100644
index 932daa1..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less
+++ /dev/null
@@ -1,54 +0,0 @@
-.workspace-attributes {
-
- width: 93%;
- display: inline-block;
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
- .table{
- height:490px;
- margin-bottom: 0;
- }
-
- .table-container-flex {
- margin-top: 0;
-
- .text{
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- white-space: nowrap;
- }
-
- .flex-item:nth-child(1) {
- flex-grow: 15;
-
- .hand;
- span.table-arrow {
- margin-right: 7px;
- }
- }
-
- .flex-item:nth-child(2) {
- flex-grow: 6;
- }
-
- .flex-item:nth-child(3) {
- flex-grow: 9;
- }
-
- .flex-item:nth-child(4) {
- flex-grow: 3;
- padding-top: 10px;
- }
-
- .flex-item:nth-child(5) {
- flex-grow: 1;
-
- }
-
- }
-
-}
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
deleted file mode 100644
index 2270a7b..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts
+++ /dev/null
@@ -1,501 +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=========================================================
- */
-'use strict';
-import * as _ from "lodash";
-import { Component, ComponentInstance, IAppMenu, Requirement, Capability, ButtonModel } from "app/models";
-import { SharingService, CacheService, EventListenerService, LeftPaletteLoaderService } from "app/services";
-import { ModalsHandler, GRAPH_EVENTS, ComponentFactory, ChangeLifecycleStateHandler, MenuHandler, EVENTS, ComponentInstanceFactory } from "app/utils";
-import { IWorkspaceViewModelScope } from "../../workspace-view-model";
-import { ComponentGenericResponse } from "app/ng2/services/responses/component-generic-response";
-import { Resource } from "app/models/components/resource";
-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";
-import { ZoneInstance } from "app/models/graph/zones/zone-instance";
-import { ComponentServiceNg2 } from "app/ng2/services/component-services/component.service";
-import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"
-import { IModalConfig, IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config";
-import { ValueEditComponent } from "app/ng2/components/ui/forms/value-edit/value-edit.component";
-import { UnsavedChangesComponent } from "../../../../ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
-import { ModalButtonComponent } from "sdc-ui/lib/angular/components";
-
-
-
-export interface ICompositionViewModelScope extends IWorkspaceViewModelScope {
-
- currentComponent:Component;
-
- //Added for now, in the future need to remove and use only id and type to pass to tabs.
- selectedComponent: Component;
- selectedZoneInstance: ZoneInstance;
-
- componentInstanceNames: Array<string>;
- isLoading:boolean;
- graphApi:any;
- sharingService:SharingService;
- sdcMenu:IAppMenu;
- version:string;
- isViewOnly:boolean;
- isCanvasTagging:boolean;
- isLoadingRightPanel:boolean;
- disabledTabs:boolean;
- openVersionChangeModal(pathsToDelete:string[]):ng.IPromise<any>;
- onComponentInstanceVersionChange(component:Component);
- isComponentInstanceSelected():boolean;
- updateSelectedComponent():void;
- openUpdateModal();
- deleteSelectedComponentInstance():void;
- onBackgroundClick():void;
- setSelectedInstance(componentInstance:ComponentInstance):void;
- setSelectedZoneInstance(zoneInstance: ZoneInstance):void;
- changeZoneInstanceName(newName:string):void;
- printScreen():void;
- isPNF():boolean;
- isConfiguration():boolean;
- preventMoveTab(state: boolean):void;
- registerCreateInstanceEvent(callback: Function):void;
- unregisterCreateInstanceEvent():void;
- registerChangeComponentInstanceNameEvent(callback: Function):void;
- unregisterChangeComponentInstanceNameEvent():void;
-
- ComponentServiceNg2:ComponentServiceNg2,
- cacheComponentsInstancesFullData:Component;
-}
-
-export class CompositionViewModel {
-
- static '$inject' = [
- '$scope',
- '$log',
- 'sdcMenu',
- 'MenuHandler',
- '$uibModal',
- '$state',
- 'Sdc.Services.SharingService',
- '$filter',
- 'Sdc.Services.CacheService',
- 'ComponentFactory',
- 'ChangeLifecycleStateHandler',
- 'LeftPaletteLoaderService',
- 'ModalsHandler',
- 'ModalServiceSdcUI',
- 'EventListenerService',
- 'ComponentServiceFactoryNg2',
- 'ComponentServiceNg2',
- 'Notification'
- ];
-
- constructor(private $scope:ICompositionViewModelScope,
- private $log:ng.ILogService,
- private sdcMenu:IAppMenu,
- private MenuHandler:MenuHandler,
- private $uibModal:ng.ui.bootstrap.IModalService,
- private $state:ng.ui.IStateService,
- private sharingService:SharingService,
- private $filter:ng.IFilterService,
- private cacheService:CacheService,
- private ComponentFactory:ComponentFactory,
- private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
- private LeftPaletteLoaderService:LeftPaletteLoaderService,
- private ModalsHandler:ModalsHandler,
- private ModalServiceSdcUI: ModalServiceSdcUI,
- private eventListenerService:EventListenerService,
- private ComponentServiceFactoryNg2: ComponentServiceFactoryNg2,
- private ComponentServiceNg2:ComponentServiceNg2,
- private Notification:any
- ) {
-
- this.$scope.setValidState(true);
- this.initScope();
- this.initGraphData();
- this.registerGraphEvents(this.$scope);
- }
-
-
- private initGraphData = ():void => {
- if(!this.hasCompositionGraphData(this.$scope.component)) {
- this.$scope.isLoading = true;
- 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.component.groupInstances = response.groupInstances || [];
- this.$scope.isLoading = false;
- this.initComponent();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED);
- });
- } else {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED);
- }
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED);
- };
-
- private hasCompositionGraphData = (component:Component):boolean => {
- return !!(component.componentInstances && component.componentInstancesRelations && component.policies && component.groupInstances);
- };
-
- private cacheComponentsInstancesFullData:Array<Component>;
-
- private initComponent = ():void => {
- this.$scope.currentComponent = this.$scope.component;
- this.$scope.selectedComponent = this.$scope.currentComponent;
- this.$scope.selectedZoneInstance = null;
- this.updateUuidMap();
- this.$scope.isViewOnly = this.$scope.isViewMode();
- };
-
- private registerGraphEvents = (scope:ICompositionViewModelScope):void => {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, scope.setSelectedInstance);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, scope.setSelectedZoneInstance);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, scope.onBackgroundClick);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CANVAS_TAG_START, () => {
- scope.isCanvasTagging = true;
- this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, true, this.showUnsavedChangesAlert);
- });
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CANVAS_TAG_END, () => {
- scope.isCanvasTagging = false;
- this.resetUnsavedChanges();
- });
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ZONE_INSTANCE_NAME_CHANGED, scope.changeZoneInstanceName);
- this.eventListenerService.registerObserverCallback(EVENTS.UPDATE_PANEL, this.removeSelectedZoneInstance);
- };
-
- private showUnsavedChangesAlert = (afterSave?:Function):Promise<any> => {
- let deferred = new Promise<any>((resolve, reject)=> {
- const modal = this.ModalServiceSdcUI.openCustomModal(
- {
- title: "Unsaved Changes",
- size: 'sm',
- type: 'custom',
-
- buttons: [
- {id: 'cancelButton', text: 'Cancel', type: 'secondary', size: 'xsm', closeModal: true, callback: () => reject()},
- {id: 'discardButton', text: 'Discard', type: 'secondary', size: 'xsm', closeModal: true, callback: () => { this.resetUnsavedChanges(); resolve()}},
- {id: 'saveButton', text: 'Save', type: 'primary', size: 'xsm', closeModal: true, callback: () => { reject(); this.saveUnsavedChanges(afterSave); }}
- ] as IModalButtonComponent[]
- }, UnsavedChangesComponent, { isValidChangedData: true});
- });
-
- return deferred;
- }
-
- private unRegisterGraphEvents = (scope: ICompositionViewModelScope):void => {
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_NODE_SELECTED, scope.setSelectedInstance);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, scope.setSelectedZoneInstance);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, scope.onBackgroundClick);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CANVAS_TAG_START);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CANVAS_TAG_END);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_ZONE_INSTANCE_NAME_CHANGED, scope.changeZoneInstanceName);
- this.eventListenerService.unRegisterObserver(EVENTS.UPDATE_PANEL, this.removeSelectedZoneInstance);
-
- };
-
- private resetUnsavedChanges = () => {
- this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
- }
-
- private saveUnsavedChanges = (afterSaveFunction?:Function):void => {
- this.$scope.selectedZoneInstance.forceSave.next(afterSaveFunction);
- this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
- }
-
- private openUpdateComponentInstanceNameModal = ():void => {
-
- let modalConfig:IModalConfig = {
- title: "Edit Name",
- size: "sm",
- type: "custom",
- testId: "renameInstanceModal",
- buttons: [
- {id: 'saveButton', text: 'OK', size: 'xsm', callback: this.saveInstanceName, closeModal: false},
- {id: 'cancelButton', text: 'Cancel', size: 'sm', closeModal: true}
- ]
- };
-
- this.ModalServiceSdcUI.openCustomModal(modalConfig, ValueEditComponent, {name: this.$scope.currentComponent.selectedInstance.name, validityChangedCallback: this.enableOrDisableSaveButton});
-
- };
-
-
- private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
- let saveButton: ModalButtonComponent = this.ModalServiceSdcUI.getCurrentInstance().getButtonById('saveButton');
- saveButton.disabled = !shouldEnable;
- }
-
- private saveInstanceName = () => {
- let currentModal = this.ModalServiceSdcUI.getCurrentInstance();
- let nameFromModal:string = currentModal.innerModalContent.instance.name;
-
- if(nameFromModal != this.$scope.currentComponent.selectedInstance.name){
- currentModal.buttons[0].disabled = true;
- let componentInstanceModel:ComponentInstance = ComponentInstanceFactory.createComponentInstance(this.$scope.currentComponent.selectedInstance);
- componentInstanceModel.name = nameFromModal;
-
- let onFailed = (error) => {
- currentModal.buttons[0].disabled = false;
- };
- let onSuccess = (componentInstance:ComponentInstance) => {
-
- this.$scope.currentComponent.selectedInstance.name = componentInstance.name;
- //update requirements and capabilities owner name
- _.forEach(this.$scope.currentComponent.selectedInstance.requirements, (requirementsArray:Array<Requirement>) => {
- _.forEach(requirementsArray, (requirement:Requirement):void => {
- requirement.ownerName = componentInstance.name;
- });
- });
-
- _.forEach(this.$scope.currentComponent.selectedInstance.capabilities, (capabilitiesArray:Array<Capability>) => {
- _.forEach(capabilitiesArray, (capability:Capability):void => {
- capability.ownerName = componentInstance.name;
- });
- });
- this.ModalServiceSdcUI.closeModal();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, this.$scope.currentComponent.selectedInstance);
- };
-
- this.$scope.currentComponent.updateComponentInstance(componentInstanceModel).then(onSuccess, onFailed);
- } else {
- this.ModalServiceSdcUI.closeModal();
- }
-
- };
-
- private removeSelectedComponentInstance = ():void => {
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.$scope.currentComponent.selectedInstance)
- this.$scope.currentComponent.selectedInstance = null;
- this.$scope.selectedComponent = this.$scope.currentComponent;
- };
-
- private removeSelectedZoneInstance = ():void => {
- this.$scope.currentComponent.selectedInstance = null;
- this.$scope.selectedZoneInstance = null;
- this.$scope.selectedComponent = this.$scope.currentComponent;
- }
-
- private updateUuidMap = ():void => {
- /**
- * In case user press F5, the page is refreshed and this.sharingService.currentEntity will be undefined,
- * but after loadService or loadResource this.sharingService.currentEntity will be defined.
- * Need to update the uuidMap with the new resource or service.
- */
- this.sharingService.addUuidValue(this.$scope.currentComponent.uniqueId, this.$scope.currentComponent.uuid);
- };
-
- private initScope = ():void => {
- this.$scope.sharingService = this.sharingService;
- this.$scope.sdcMenu = this.sdcMenu;
- this.$scope.isLoading = false;
- this.$scope.isLoadingRightPanel = false;
- this.$scope.isCanvasTagging = false;
- this.$scope.graphApi = {};
- this.$scope.version = this.cacheService.get('version');
- this.initComponent();
-
- this.cacheComponentsInstancesFullData = new Array<Component>();
-
- this.$scope.isComponentInstanceSelected = ():boolean => {
- return this.$scope.currentComponent && this.$scope.currentComponent.selectedInstance != undefined && this.$scope.currentComponent.selectedInstance != null;
- };
-
- this.$scope.$on('$destroy', () => {
- this.unRegisterGraphEvents(this.$scope);
- })
-
- this.$scope.restoreComponent = ():void => {
- this.ComponentServiceNg2.restoreComponent(this.$scope.selectedComponent.componentType, this.$scope.selectedComponent.uniqueId).subscribe(() => {
- this.Notification.success({
- message: '<' + this.$scope.component.name + '> ' + this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
- });
- this.$scope.selectedComponent.archived = false;
- }
- )
- };
-
- this.$scope.updateSelectedComponent = ():void => {
- if (this.$scope.currentComponent.selectedInstance) {
- let parentComponentUid = this.$scope.currentComponent.selectedInstance.componentUid
- if(this.$scope.currentComponent.selectedInstance.originType === ComponentType.SERVICE_PROXY){
- parentComponentUid = this.$scope.currentComponent.selectedInstance.sourceModelUid;
- }
- let componentParent = _.find(this.cacheComponentsInstancesFullData, (component) => {
- return component.uniqueId === parentComponentUid;
- });
- if (componentParent) {
- this.$scope.selectedComponent = componentParent;
- }
- else {
- try {
- let onSuccess = (component:Component) => {
- this.$scope.isLoadingRightPanel = false;
- this.$scope.selectedComponent = component;
- this.cacheComponentsInstancesFullData.push(component);
- };
- let onError = (component:Component) => {
- console.log("Error updating selected component");
- this.$scope.isLoadingRightPanel = false;
- };
- this.ComponentFactory.getComponentFromServer(this.$scope.currentComponent.selectedInstance.originType, parentComponentUid).then(onSuccess, onError);
- } catch (e) {
- console.log("Error updating selected component", e);
- this.$scope.isLoadingRightPanel = false;
- }
- }
- }
- else {
-
- this.$scope.selectedComponent = this.$scope.currentComponent;
- }
- };
-
- this.$scope.setSelectedInstance = (selectedComponent:ComponentInstance):void => {
-
- this.$log.debug('composition-view-model::onNodeSelected:: with id: ' + selectedComponent.uniqueId);
- this.$scope.currentComponent.setSelectedInstance(selectedComponent);
- this.$scope.selectedZoneInstance = null;
- this.$scope.updateSelectedComponent();
-
- if (this.$state.current.name === 'workspace.composition.api') {
- this.$state.go('workspace.composition.details');
- }
- if(!selectedComponent.isServiceProxy() && (this.$state.current.name === 'workspace.composition.consumption' || this.$state.current.name === 'workspace.composition.dependencies')) {
- this.$state.go('workspace.composition.details');
- }
- };
-
- this.$scope.setSelectedZoneInstance = (zoneInstance: ZoneInstance): void => {
- this.$scope.currentComponent.selectedInstance = null;
- this.$scope.selectedZoneInstance = zoneInstance;
- };
-
- this.$scope.onBackgroundClick = ():void => {
- this.$scope.currentComponent.selectedInstance = null;
- this.$scope.selectedZoneInstance = null;
- this.$scope.selectedComponent = this.$scope.currentComponent;
-
- if (this.$state.current.name === 'workspace.composition.api' || this.$state.current.name === 'workspace.composition.consumption' || this.$state.current.name === 'workspace.composition.dependencies') {
- this.$state.go('workspace.composition.details');
- }
-
- if(this.$scope.selectedComponent.isService() && this.$state.current.name === 'workspace.composition.relations'){
- this.$state.go('workspace.composition.api');
- }
- };
-
- this.$scope.openUpdateModal = ():void => {
- this.openUpdateComponentInstanceNameModal();
- };
-
- this.$scope.changeZoneInstanceName = (newName:string):void => {
- this.$scope.selectedZoneInstance.instanceData.name = newName;
- };
-
- this.$scope.deleteSelectedComponentInstance = ():void => {
- 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.ModalServiceSdcUI.openAlertModal(title, modalText, "OK", this.removeSelectedComponentInstance, "deleteInstanceModal");
- };
-
- 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 => {
- 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 => {
- return this.$scope.selectedComponent.isResource() && (<Resource>this.$scope.selectedComponent).resourceType === ResourceType.PNF;
- };
-
- this.$scope.isConfiguration = (): boolean => {
- 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_LIFECYCLE_CHANGE, this.$scope.reload);
-
- this.$scope.registerCreateInstanceEvent = (callback: Function): void => {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, callback);
- };
-
- this.$scope.unregisterCreateInstanceEvent = (): void => {
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE);
- };
-
- this.$scope.registerChangeComponentInstanceNameEvent = (callback: Function): void => {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, callback);
- };
-
- this.$scope.unregisterChangeComponentInstanceNameEvent = (): void => {
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED);
- };
- }
-}
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
deleted file mode 100644
index c2d6007..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-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-composition">
- <loader data-display="isLoading"></loader>
- <div class="w-sdc-designer-canvas" data-ng-class="{sidebaractive: displayDesignerRightSidebar}">
- <palette current-component="currentComponent"
- is-view-only="isViewOnly || isCanvasTagging"
- 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>
-
- <div class="w-sdc-designer-sidebar-toggle" data-ng-class="{'active': displayDesignerRightSidebar}"
- data-ng-init="displayDesignerRightSidebar = true"
- data-ng-click="displayDesignerRightSidebar = !displayDesignerRightSidebar">
- <div class="w-sdc-designer-sidebar-toggle-icon sprite-new pointer menu-open-left"></div>
- </div>
-
- <div class="w-sdc-designer-sidebar" data-ng-class="{'view-mode':isViewOnly}">
-
- <div ng-if="!selectedZoneInstance">
-
- <div class="w-sdc-designer-sidebar-head" data-tests-id="w-sdc-designer-sidebar-head">
- <div class="w-sdc-designer-sidebar-logo-ph">
- <div class=" large {{selectedComponent.iconSprite}} {{selectedComponent.icon}}"
- ng-class="{'archive-component':selectedComponent.archived}">
- <div ng-if="isComponentInstanceSelected()"
- data-ng-class="{'non-certified':'CERTIFIED' !== selectedComponent.lifecycleState}"
- tooltips tooltip-side="top" tooltip-content="Not certified"></div>
- </div>
- </div>
-
- <div class="w-sdc-designer-sidebar-logo">
- <span class="w-sdc-designer-sidebar-logo-title" data-tests-id="selectedCompTitle" tooltips
- tooltip-class="tooltip-custom break-word-tooltip"
- tooltip-content="​{{isComponentInstanceSelected() ? currentComponent.selectedInstance.name : currentComponent.name | resourceName}}"
- data-ng-bind="isComponentInstanceSelected() ? currentComponent.selectedInstance.name : currentComponent.name | resourceName"></span>
- </div>
- <div class="sprite e-sdc-small-icon-pencil w-sdc-designer-update-resource-icon"
- data-tests-id="renameInstance"
- data-ng-if="!isViewOnly && isComponentInstanceSelected() && !selectedComponent.archived"
- data-ng-click="openUpdateModal()" id="editPencil"></div>
-
- <div class="sprite e-sdc-small-icon-delete w-sdc-designer-delete-resource-icon"
- data-tests-id="deleteInstance"
- data-ng-if="!isViewOnly && isComponentInstanceSelected() && !selectedComponent.archived"
- data-ng-click="!isLoading && deleteSelectedComponentInstance()" title="Delete Resource Instance"></div>
- </div>
-
- <div class="w-sdc-designer-sidebar-tabs">
- <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-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"-->
- <!--ui-sref="workspace.composition.structure"-->
- <!--tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Composition">-->
- <!--<div class="i-sdc-designer-sidebar-tab-icon sprite-new structure"></div>-->
- <!--</button>-->
- <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active"
- 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="!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-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"
- 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 {{currentComponent.selectedInstance.isServiceProxy() ? '' : 'tooltip-rightside'}}"
- 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"
- data-ng-class="{'disabled': disabledTabs}">
- <div class="i-sdc-designer-sidebar-tab-icon sprite-new api"></div>
- </button>
- <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active"
- data-ui-sref="workspace.composition.consumption"
- tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Operation Consumption"
- data-tests-id="service-consumption-tab"
- data-ng-if="(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())"
- data-ng-class="{'disabled': disabledTabs}">
- <div class="i-sdc-designer-sidebar-tab-icon sprite-new import-icon"></div>
- </button>
- <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active"
- data-ui-sref="workspace.composition.dependencies"
- tooltips tooltip-class="tooltip-custom tab-tooltip " tooltip-content="Service Dependencies"
- data-tests-id="service-dependency-tab"
- data-ng-if="(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())"
- data-ng-class="{'disabled': disabledTabs}">
- <div class="i-sdc-designer-sidebar-tab-icon sprite-new dependencies-icon"></div>
- </button>
-
- </div>
- <div data-ui-view="" class="w-sdc-designer-sidebar-tab-content-view"></div>
-
- </div>
-
- <!-- Solution for now to support policies and groups working with Angular 2 components -->
- <!-- isCertified not relevant for group or policy -->
- <!-- (selectedZoneInstanceType === ZoneInstanceType.GROUP || selectedZoneInstanceType === ZoneInstanceType.POLICY) -->
- <div ng-if="selectedZoneInstance">
-
- <ng2-composition-panel
- [is-loading]="isLoading"
- [is-view-only]="isViewOnly || isCanvasTagging"
- [selected-zone-instance-name]="selectedZoneInstance.instanceData.name"
- [selected-zone-instance-id]="selectedZoneInstance.instanceData.uniqueId"
- [selected-zone-instance-type]="selectedZoneInstance.type"
- [topology-template]="currentComponent"
- >
- </ng2-composition-panel>
- </div>
-
- <loader data-display="isLoadingRightPanel" relative="true" size="medium"></loader>
-
- </div>
-</div>
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
deleted file mode 100644
index f37a492..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less
+++ /dev/null
@@ -1,955 +0,0 @@
- .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{
- .w-sdc-main-container{
- .w-sdc-main-right-container{
- left:0;
- //overflow-y: scroll;
- .sdc-workspace-top-bar {
- padding-left: 295px;
- .not-latest{
- left: 270px;
- }
- }
- .w-sdc-main-container-body-content{
- padding: 0 0 0 247px;
- }
-
- > div:first-child{
- padding: 0;
- }
- }
- }
- }
-
- .custom-modal {
- /* Hack solution to hide canvas tooltips under modals */
- z-index: 20000 !important;
- }
-}
-
-.workspace-composition {
- height:100%;
- display: block;
- text-align: left;
- align-items: left;
- padding: 0;
-
-
-
- // ---------------------------------------------------------------------------------------------------
- // Sidebar
- // ---------------------------------------------------------------------------------------------------
-
-
-
- .w-sdc-designer-sidebar-toggle {
- background-color: @main_color_p;
- border-left: 1px solid @main_color_o;
- border-bottom: 1px solid @main_color_o;
- height: 21px;
- position: absolute;
- right: 0;
- top: 53px;
- width: 17px;
- transition: right 0.2s;
- z-index: 10;
- .box-shadow(-1px 1px 3px 0 @main_color_n);
-
- &.active {
- right: 302px;
- .w-sdc-designer-sidebar-toggle-icon{
- transform: rotate(180deg);
- }
- }
-
- }
-
- .w-sdc-designer-sidebar-toggle-icon {
- margin-left: 6px;
- margin-top: 6px;
- }
-
- .w-sdc-designer-sidebar {
- background-color:@main_color_p ;
- .noselect;
- bottom: 0;
- position: fixed;
- right: -302px;
- width: 302px;
- top: 103px;
- transition: right 0.2s;
- z-index: 9;
- .box-shadow(-7px -3px 6px -8px @main_color_n);
-
- }
-
- .w-sdc-designer-sidebar-toggle.active + .w-sdc-designer-sidebar {
- right: 0;
-
- }
-
- .w-sdc-designer-sidebar-head {
- padding: 36px 30px 30px 30px;
- height: 120px;
- }
-
- .w-sdc-designer-sidebar-logo-ph {
- display: inline-block;
- vertical-align: middle;
- line-height: 60px;
- height: 60px;
- }
-
- .w-sdc-designer-sidebar-logo {
- .g_6;
- display: inline-block;
- margin-left: 10px;
- font-weight: 500;
- }
-
- .w-sdc-designer-sidebar-logo-title {
- .s_16_r;
- .selectable;
- vertical-align: middle;
- text-overflow: ellipsis;
- max-width: 167px;
- display: inline-block;
- white-space: nowrap;
- overflow: hidden;
- }
-
- .w-sdc-designer-update-resource-icon {
- .hand;
- position: absolute;
- right: 20px;
- top: 10px;
- }
-
- .w-sdc-designer-delete-resource-icon {
- .hand;
- position: absolute;
- right: 40px;
- top: 10px;
- }
-
- .w-sdc-designer-restore-button {
- .hand;
- position:absolute;
- right: 20px;
- top:10px;
- width:65px;
- }
- .w-sdc-designer-sidebar-tabs {
- .bg_c;
- }
-
- .w-sdc-designer-sidebar-tabs::after {
- clear: both;
- content: '';
- display: table;
- }
-
- .i-sdc-designer-sidebar-tab {
- background-color: @main_color_p;
- border: 1px solid @tlv_color_u;;
- border-left: none;
- display: inline-block;
- float: left;
- height: 36px;
- padding-top: 9px;
- text-align: center;
- width: 60px;
- .hand;
-
- &:focus {
- outline: none;
- }
- &.tab-disabled {
- /* .disabled; */
- }
- &.active, &:hover:enabled {
- background-color: @tlv_color_u;
- .i-sdc-designer-sidebar-tab-icon {
- opacity: 1;
-
-
- }
-
- }
-
- div& {
- padding-top: 0;
- }
- /*for tooltip on disabled buttons*/
- }
-
- .i-sdc-designer-sidebar-tab-icon {
- margin-top: 5px ;
- &.import-icon {
- transform: rotate(270deg);
- }
- // opacity: .4;
- }
-
- .w-sdc-designer-sidebar-tab-content {
- .perfect-scrollbar;
- height: 100%;
- }
-
- .w-sdc-designer-sidebar-tab-content-view {
- position: absolute;
- top: 156px;
- bottom: 0;
- width: 100%;
- padding-bottom: 10px;
-
- }
-
- .w-sdc-designer-sidebar-section {
- }
-
- .w-sdc-designer-sidebar-section-title {
- .m_14_m;
- background-color: @tlv_color_u;
- .hand;
- clear: both;
- height: 32px;
- line-height: 32px;
- margin-top: 1px;
- padding: 0 10px 0 20px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- position: relative;
- width: 100%;
- display: block;
-
- &.expanded {
- .w-sdc-designer-sidebar-section-title-icon {
- transform: rotate(180deg);
- }
- }
- }
-
- .w-sdc-designer-sidebar-section-title-text {
- max-width: 240px;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- position: relative;
- }
-
- .w-sdc-designer-sidebar-section-title-icon {
- .hand;
- .sprite-new;
- .arrow-up;
- right: 16px;
- top: 13px;
- transition: .3s all;
- position: absolute;
- }
-
- .w-sdc-designer-sidebar-section-content {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .w-sdc-designer-sidebar-section-title {
- text-transform: uppercase;
- }
-
- .w-sdc-designer-sidebar-section-title + .w-sdc-designer-sidebar-section-content {
- margin: 0 auto;
- }
-
- .w-sdc-designer-sidebar-section-title.expanded + .w-sdc-designer-sidebar-section-content {
- margin: 0 auto 1px;
-
- }
-
- .i-sdc-designer-sidebar-section-content-item {
- .b_7;
- font-size: 13px;
- margin-bottom: 5px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- //max-width: 250px;
-
- &.description {
- margin-top: 28px;
- white-space: normal;
- word-wrap: break-word;
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-tag {
- .g_7;
- .bg_c;
- border-radius: 4px;
- //fix long name for firefox:
- display: block;
- float: left;
- line-height: 25px;
- margin: 0 4px 6px 0;
- min-width: 50px;
- padding: 0 9px;
- text-align: center;
- max-width: 280px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .w-sdc-designer-sidebar-section-footer {
- margin-top: 10px;
- text-align: center;
- width: 100%;
- }
-
-
-
- .w-sdc-designer-sidebar-section-footer-action {
- width: 180px;
- margin-top: 10px;
- }
-
- //////////////////////Relationship
- .w-sdc-designer-sidebar-section-requirements {
- border-bottom: 1px solid @color_e;
- margin: 0 13px 20px 13px;
- padding: 15px 0 0;
- }
-
- .w-sdc-designer-sidebar-section-requirements-item {
- margin-bottom: 20px;
- }
-
- .w-sdc-designer-sidebar-section-requirements-label {
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- vertical-align: middle;
- white-space: nowrap;
- width: 102px;
- }
-
- .w-sdc-designer-sidebar-section-requirements-select {
- border: 1px solid @color_e;
- min-height: 30px;
- padding: 4px 13px;
- width: 168px;
- }
-
- //////////////////////Properties
- .i-sdc-designer-sidebar-section-content-item-property-and-attribute {
- .b_7;
- border-bottom: 1px solid @color_e;
- min-height: 72px;
- padding: 15px 10px 10px 18px;
- position: relative;
-
- &:first-child {
- //margin-top: -18px;
- }
-
- &:hover {
- // .bg_c_hover;
- .bg_c;
- transition: all .3s;
-
- .i-sdc-designer-sidebar-section-content-item-button {
- display: block;
- }
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-property-and-attribute-label {
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 200px;
- white-space: nowrap;
- display: inline-block;
- &:hover {
- .a_7;
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-property-value {
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 200px;
- display: inline-block;
- white-space: nowrap;
-
- }
-
- .i-sdc-designer-sidebar-section-content-item-property-label-value {
- }
-
- .i-sdc-designer-sidebar-section-content-item-button {
- display: none;
- position: absolute;
- top: 25px;
-
- &.update {
- background-color: transparent;
- border: 0;
- right: 60px;
- }
-
- &.delete {
- background-color: transparent;
- border: 0;
- right: 13px;
- }
-
- &.download {
- background-color: transparent;
- border: 0;
- right: 35px;
- }
-
- &.download-env {
- background-color: transparent;
- border: 0;
- right: 35px;
- margin-top: 65px;
- }
-
- &.update-env {
- background-color: transparent;
- border: 0;
- right: 15px;
- margin-top: 65px;
- }
-
- &.attach {
- background-color: transparent;
- border: 0;
- right: 15px;
- }
- }
-
- // ---------------------------------------------------------------------------------------------------
- // Canvas
- // ---------------------------------------------------------------------------------------------------
- .w-sdc-designer-canvas {
- height:100%;
- .noselect;
- .bg_c;
- bottom: 0;
- // position: fixed;
- //right: 0;
- //left: 240px;
- //top: 94px;
- .view-mode{
- background-color: #f8f8f8;
- border:0;
- }
- }
-
- .w-sdc-designer-canvas.sidebaractive {
- //right: 300px;
- }
-
- .w-sdc-designer-element {
- .hand;
- width: 200px;
- height: 100px;
- position: absolute;
- text-align: center;
- top: 50%;
- margin-top: -200px;
- left: 50%;
- margin-left: -50px;
- }
-
- .w-sdc-designer-resource-label {
- .q_7;
- }
-
- .w-sdc-designer-resource-label-indicator {
- .bg_q;
- border-radius: 50%;
- display: inline-block;
- height: 10px;
- margin-right: 6px;
- vertical-align: middle;
- width: 10px;
-
- &.valid {
- .bg_l;
- }
-
- &.invalid {
- .bg_h;
- }
- }
-
- // ---------------------------------------------------------------------------------------------------
- // Leftbar
- // ---------------------------------------------------------------------------------------------------
- .w-sdc-designer-leftbar {
- background-color: @main_color_p;
- bottom: 0;
- left: 0;
- overflow-y: scroll;
- overflow-x: hidden;
- position: absolute;
- top: 0;
- width: 244px;
- .box-shadow(7px -3px 6px -8px @main_color_n);
-
- }
-
- .w-sdc-designer-leftbar-title {
-
- .p_16_m;
- background-color: @main_color_n;
- line-height: 40px;
- padding: 0 17px;
- }
-
- .w-sdc-designer-leftbar-title-count {
- float: right;
- }
-
- .w-scd-diagram-container {
- // left: 240px;
- //right: 300px;
- }
-
- .w-sdc-designer-leftbar-search {
- background-color: @tlv_color_u;
- padding: 10px;
- white-space: nowrap;
- position: relative;
- }
-
- .w-sdc-designer-leftbar-search-input {
- border: 1px solid @color_e;
- .border-radius(4px);
- height: 30px;
- margin: 0;
- padding: 0px 28px 3px 10px;
- vertical-align: 4px;
- width: 100%;
- outline: none;
- font-style: italic;
- }
-
- .w-sdc-designer-leftbar-search-filter {
-
- }
-
- .i-sdc-designer-leftbar-section {
- .hand;
- }
-
- .i-sdc-designer-leftbar-section-title {
- .m_14_m;
- background-color: @tlv_color_u;
- .hand;
- clear: both;
- height: 40px;
- line-height: 40px;
- margin-top: 1px;
- padding: 0 10px;
- position: relative;
- text-transform: uppercase;
- font-weight: bold;
- }
-
- .i-sdc-designer-leftbar-section-title-icon {
- .hand;
- .sprite-new;
- .arrow-up;
- width: 15px;
- height: 9px;
- position: absolute;
- right: 13px;
- top: 18px;
- transition: .3s all;
- }
-
- .i-sdc-designer-leftbar-section.expanded .i-sdc-designer-leftbar-section-title-icon {
- transform: rotate(180deg);
- margin-right: 2px;
- }
-
- .i-sdc-designer-leftbar-section-content {
- background-color: @main_color_o;
- }
-
- .i-sdc-designer-leftbar-section-content-item {
- background-color: @main_color_p;
- overflow: hidden;
-
- &:hover {
- background-color: @main_color_p;
- }
-
- .cp{
- margin: 6px;
- }
-
- .vl{
- margin: 6px;
- }
- }
-
- .i-sdc-designer-leftbar-section-content-subcat {
- .m_14_m;
- background-color: @tlv_color_t;
- line-height: 35px;
- padding: 0 10px;
- cursor: default;
-
-
- &:hover {
- background-color: @func_color_r;
- }
-
-
- }
-
- .i-sdc-designer-leftbar-section .i-sdc-designer-leftbar-section-content .i-sdc-designer-leftbar-section-content-item {
- max-height: 0px;
- margin: 0 auto;
- transition: all .3s;
- }
-
- .i-sdc-designer-leftbar-section.expanded .i-sdc-designer-leftbar-section-content .i-sdc-designer-leftbar-section-content-item {
- max-height: 64px;
- margin: 0 auto 1px auto;
- // padding: 4px 13px;
- }
-
- .i-sdc-designer-leftbar-section.expanded .i-sdc-designer-leftbar-section-content .i-sdc-designer-leftbar-section-content-subcat {
- margin: 0;
- }
-
- .i-sdc-designer-leftbar-section-content-item-icon-ph {
- display: inline-block;
- margin: 12px 0 12px 10px;
- pointer-events: auto;
- height: 45px;
- width: 40px;
- float: left;
- display: flex;
- align-items: center;
- .non-certified {
- position: relative;
- left: -4px;
- top: -4px;
- .sprite;
- .s-sdc-state-non-certified;
- display: block;
-
- &.smaller-icon {
- bottom: 6px;
- left: 13px;
- }
- }
-
-
-
- }
-
- .non-certified {
- position: relative;
- left: 0px;
- top: 0px;
- .sprite;
- .s-sdc-state-non-certified;
- display: block;
-
- &.smaller-icon {
- left: 35px;
- bottom: -14px;
- }
- }
- /*
- .i-sdc-composition-leftbar-section-content-item-icon {
- background-image: url('../../../styles/images/resource-icons/default.png');
- // position: absolute;
- right: 20px;
- top: 10px;
- height: 40px;
- width: 40px;
- background-size: 40px;
- }
- */
-
- .i-sdc-designer-leftbar-section-content-item-info {
- display: inline-block;
- // margin-left: 10px;
- //overflow: hidden;
- // vertical-align: middle;
- width: 160px;
- padding: 0 0 0 10px;
- }
-
- .i-sdc-designer-leftbar-section-content-item-info-title {
- .m_13_m;
- line-height: 14px;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 120px;
- display: inline-block;
- white-space: nowrap;
- vertical-align: bottom;
- }
-
- .i-sdc-designer-leftbar-section-content-item-info-text {
- .m_13_r;
- line-height: 15px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .i-sdc-designer-leftbar-section-content-item-info-text-link {
- color: @color_s;
- text-decoration: underline;
- float: right;
- position: absolute;
- right: 17px;
- // bottom: 5px;
- }
-
- // ---------------------------------------------------------------------------------------------------
- // Form actions
- // ---------------------------------------------------------------------------------------------------
- .w-sdc-form-actions-container.add-property {
- text-align: center;
- width: 100%;
- margin-top: 2px;
- margin-bottom: 12px;
-
- .w-sdc-form-action {
- width: 245px;
- }
- .w-sdc-form-action.add-property-add-another {
- .bg_a;
- margin-left: 35px;
- }
- .w-sdc-form-action.add-property-done {
- margin-left: 312px;
- }
- .w-sdc-form-action.save {
- margin-left: 327px;
- margin-bottom: 30px;
- }
-
- }
-
- // ---------------------------------------------------------------------------------------------------
- // Top menu
- // ---------------------------------------------------------------------------------------------------
- .w-sdc-header-menu {
- padding: 25px 0;
- text-align: center;
- white-space: nowrap;
- }
-
- .i-sdc-header-menu-item {
- cursor: pointer;
- display: inline-block;
- height: 43px;
- min-width: 93px;
- padding: 0 38px;
- position: relative;
- vertical-align: middle;
-
- &::after {
- border-right: 1px solid @color_m;
- content: '';
- display: block;
- height: 43px;
- right: 0;
- position: absolute;
- top: 0;
- width: 2px;
- }
-
- &:first-child {
- &::before {
- border-right: 1px solid @color_m;
- content: '';
- display: block;
- height: 43px;
- left: 0;
- position: absolute;
- top: 0;
- width: 2px;
- }
- }
- }
-
- .i-sdc-header-menu-item-icon {
- display: inline-block;
- height: 20px;
- width: 28px;
- }
-
- .i-sdc-header-menu-item-label {
- .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;
- right: 18px;
- top:53px;
- transition: right 0.2s;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- margin-right:10px;
- pointer-events: none;
-
- & > * {
- pointer-events: all;
- }
-
- &.with-sidebar {
- right:320px;
- }
-
- .search-with-autocomplete-container.composition-search {
- margin-top: 12px;
-
- .search-bar-input {
- width: 250px;
- padding:2px 50px 2px 10px;
- transition:all 0.4s;
- }
- .search-bar-container {
- position:relative;
- }
-
- &:not(:hover):not(.autocomplete-visible):not(.active){
- border-radius: 0;
- box-shadow:none;
-
- .search-bar-input:not(:focus){
- width: 0px;
- padding:0;
- border:none;
- }
- .clear-search-x {
- display:none;
- }
- .search-bar-input:not(:focus) ~ .search-bar-button {
- border-radius: 2px;
- border:solid 1px #fff;
- }
- }
- }
-
- .zoom-icons {
- border:solid 1px #fff;
- border-radius: 2px;
- box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
- background-color: rgba(234, 234, 234, 0.88);
- background-repeat: no-repeat;
- margin-top: 10px;
-
- &:hover {
- cursor:pointer;
- }
-
- &:active {
- border:none;
- background-color: rgba(31, 171, 223, 0.88);
- }
- }
- }
-
- // ---------------------------------------------------------------------------------------------------
- // Canvas inline menu
- // ---------------------------------------------------------------------------------------------------
- .w-sdc-canvas-menu-list {
- .w-sdc-canvas-menu-item-view {
- &::before {
- content: '';
- display: inline-block;
-
- .sprite-new;
- .view-icon;
- vertical-align: top;
- margin: 2px 6px 2px 4px;
- }
- }
-
- .w-sdc-canvas-menu-item-delete {
- &::before {
- content: '';
- display: inline-block;
-
- .sprite-new;
- .delete-icon;
- vertical-align: bottom;
- margin: 1px 10px 0 7px;
- }
- }
- }
-}
-/*.right-tab-loader {
- border: 16px solid #f3f3f3; !* Light grey *!
- border-top: 16px solid #3498db; !* Blue *!
- border-radius: 50%;
- width: 120px;
- height: 120px;
- animation: spin 2s linear infinite;
-}*/
-
-@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
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
deleted file mode 100644
index 2af341b..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts
+++ /dev/null
@@ -1,352 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {
- ArtifactModel,
- Service,
- IAppConfigurtaion,
- Resource,
- Component,
- ComponentInstance,
- ArtifactGroupModel,
- IFileDownload
-} from "app/models";
-import {ICompositionViewModelScope} from "../../composition-view-model";
-import {ArtifactsUtils, ModalsHandler, ArtifactGroupType} from "app/utils";
-import {GRAPH_EVENTS} from "app/utils/constants";
-import {EventListenerService} from "app/services/event-listener-service";
-import {Dictionary} from "../../../../../../utils/dictionary/dictionary";
-
-export interface IArtifactsViewModelScope extends ICompositionViewModelScope {
- artifacts:Array<ArtifactModel>;
- artifactType:string;
- downloadFile:IFileDownload;
- isLoading:boolean;
- allowDeleteAndUpdateArtifactMap:Dictionary<string, boolean>;
- getTitle():string;
- addOrUpdate(artifact:ArtifactModel):void;
- delete(artifact:ArtifactModel):void;
- download(artifact:ArtifactModel):void;
- openEditEnvParametersModal(artifact:ArtifactModel):void;
- getEnvArtifact(heatArtifact:ArtifactModel):any;
- getEnvArtifactName(artifact:ArtifactModel):string;
- isLicenseArtifact(artifact:ArtifactModel):boolean;
- isVfOrPnf():boolean;
- //isVFiArtifact(artifact:ArtifactModel):boolean;
-}
-
-export class ResourceArtifactsViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- '$state',
- 'sdcConfig',
- 'ArtifactsUtils',
- 'ModalsHandler',
- '$q',
- 'EventListenerService'
- ];
-
- constructor(private $scope:IArtifactsViewModelScope,
- private $filter:ng.IFilterService,
- private $state:any,
- private sdcConfig:IAppConfigurtaion,
- private artifactsUtils:ArtifactsUtils,
- private ModalsHandler:ModalsHandler,
- private $q:ng.IQService,
- private eventListenerService: EventListenerService) {
-
- this.initScope();
- }
-
-
- private initArtifactArr = (artifactType:string):void => {
- let artifacts:Array<ArtifactModel> = [];
-
- if (this.$scope.selectedComponent) {
- if ('interface' == artifactType) {
- let interfaces = this.$scope.currentComponent.interfaces;
- if (interfaces && interfaces.standard && interfaces.standard.operations) {
-
- angular.forEach(interfaces.standard.operations, (operation:any, interfaceName:string):void => {
- let item:ArtifactModel = <ArtifactModel>{};
- if (operation.implementation) {
- item = <ArtifactModel> operation.implementation;
- }
- item.artifactDisplayName = interfaceName;
- item.artifactLabel = interfaceName;
- item.mandatory = false;
- artifacts.push(item);
- });
- }
- } else {
- //init normal artifacts, deployment or api artifacts
- let artifactsObj:ArtifactGroupModel;
- switch (artifactType) {
- case "api":
- artifactsObj = (<Service>this.$scope.currentComponent).serviceApiArtifacts;
- break;
- case "deployment":
- if (!this.$scope.isComponentInstanceSelected()) {
- artifactsObj = this.$scope.currentComponent.deploymentArtifacts;
- } else {
- artifactsObj = this.$scope.currentComponent.selectedInstance.deploymentArtifacts;
- }
- break;
- default:
- //artifactsObj = this.$scope.selectedComponent.artifacts;
- if (!this.$scope.isComponentInstanceSelected()) {
- artifactsObj = this.$scope.currentComponent.artifacts;
- } else {
- artifactsObj = this.$scope.currentComponent.selectedInstance.artifacts;
- }
- break;
- }
- _.forEach(artifactsObj, (artifact:ArtifactModel, key) => {
- artifacts.push(artifact);
- });
- }
- }
- this.$scope.artifacts = artifacts;
- this.$scope.allowDeleteAndUpdateArtifactMap = new Dictionary<string, boolean>();
- _.forEach(this.$scope.artifacts, (artifact:ArtifactModel)=>{
- this.$scope.allowDeleteAndUpdateArtifactMap[artifact.artifactLabel] = this.allowDeleteAndUpdateArtifact(artifact);
- });
- this.$scope.isLoading = false;
- this.$scope.preventMoveTab(false);
- };
-
-
- private convertToArtifactUrl = (artifactType:string):string => {
-
- switch (artifactType) {
- case 'deployment':
- return 'DEPLOYMENT';
- case 'api':
- return 'SERVICE_API';
- default:
- return 'INFORMATIONAL';
- }
-
- }
-
- private loadComponentArtifactIfNeeded = (forceLoad?: boolean) => {
-
- let onGetComponentArtifactsSuccess = (artifacts:ArtifactGroupModel)=> {
- switch (this.$scope.artifactType) {
- case 'deployment':
- this.$scope.currentComponent.deploymentArtifacts = artifacts;
- break;
- case 'api':
- (<Service>this.$scope.currentComponent).serviceApiArtifacts = artifacts;
- break;
- default:
- this.$scope.currentComponent.artifacts = artifacts;
- break;
- }
- this.$scope.isLoading = false;
- this.initArtifactArr(this.$scope.artifactType);
- }
-
- let onError = ()=> {
- this.$scope.isLoading = false;
- };
-
- switch (this.$scope.artifactType) {
- case 'deployment':
- if(forceLoad || !this.$scope.currentComponent.deploymentArtifacts) {
- this.$scope.component.getArtifactByGroupType(this.convertToArtifactUrl(this.$scope.artifactType)).then(onGetComponentArtifactsSuccess, onError);
- } else {
- this.initArtifactArr(this.$scope.artifactType);
- }
-
- break;
- case 'api':
- if(!(<Service>this.$scope.currentComponent).serviceApiArtifacts) {
- this.$scope.component.getArtifactByGroupType(this.convertToArtifactUrl(this.$scope.artifactType)).then(onGetComponentArtifactsSuccess, onError);
- } else {
- this.initArtifactArr(this.$scope.artifactType);
- }
- break;
- default:
- if(!this.$scope.currentComponent.artifacts) {
- this.$scope.component.getArtifactByGroupType(this.convertToArtifactUrl(this.$scope.artifactType)).then(onGetComponentArtifactsSuccess, onError);
- } else {
- this.initArtifactArr(this.$scope.artifactType);
- }
- break;
- }
- }
- private loadArtifacts = (forceLoad?: boolean):void => {
-
- let onGetInstanceArtifactsSuccess = (artifacts:ArtifactGroupModel)=> {
- switch (this.$scope.artifactType) {
- case 'deployment':
- this.$scope.currentComponent.selectedInstance.deploymentArtifacts = artifacts;
- break;
- default:
- this.$scope.currentComponent.selectedInstance.artifacts = artifacts;
- break;
- }
- this.initArtifactArr(this.$scope.artifactType);
- };
-
- let onError = ()=> {
- this.$scope.isLoading = false;
- };
-
- 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 {
- this.loadComponentArtifactIfNeeded(forceLoad);
- }
- }
-
- private updateArtifactsIfNeeded = ():void => {
- if (this.$scope.artifactType === "deployment") {
- this.loadArtifacts(true);
- } else {
- this.initArtifactArr(this.$scope.artifactType);
- }
- };
-
- private openEditArtifactModal = (artifact:ArtifactModel):void => {
- this.ModalsHandler.openArtifactModal(artifact, this.$scope.currentComponent).then(():void => {
- this.updateArtifactsIfNeeded();
- });
- };
-
- private allowDeleteAndUpdateArtifact = (artifact:ArtifactModel):boolean => {
- if(!this.$scope.isViewMode()){
- if(this.$scope.isComponentInstanceSelected()){//is artifact of instance
- return !this.$scope.selectedComponent.deploymentArtifacts || !this.$scope.selectedComponent.deploymentArtifacts[artifact.artifactLabel];//if the artifact is not from instance parent
- }else{//is artifact of main component
- return (!artifact.isHEAT() && !artifact.isThirdParty() && !this.$scope.isLicenseArtifact(artifact));
- }
- }
- return false;
-};
-
- private initScope = ():void => {
-
- this.$scope.isLoading = false;
- this.$scope.artifactType = this.artifactsUtils.getArtifactTypeByState(this.$state.current.name);
- this.$scope.getTitle = ():string => {
- return this.artifactsUtils.getTitle(this.$scope.artifactType, this.$scope.currentComponent);
- };
-
- // Bug 310499 - user should be unable to delete RI artifact. (also talked to David and agreed this function isn't necessary)
- // this.$scope.isVFiArtifact = (artifact:ArtifactModel):boolean=> {
- // if (artifact.artifactGroupType === ArtifactGroupType.INFORMATION) {//fix DE256847
- // return this.$scope.currentComponent.artifacts && (!this.$scope.currentComponent.artifacts[artifact.artifactLabel] || !this.$scope.currentComponent.artifacts[artifact.artifactLabel].artifactName);
- // }
- // return this.$scope.currentComponent.selectedInstance && this.$scope.currentComponent.selectedInstance.deploymentArtifacts && this.$scope.currentComponent.selectedInstance.deploymentArtifacts[artifact.artifactLabel];
- // };
-
- this.$scope.addOrUpdate = (artifact:ArtifactModel):void => {
- this.artifactsUtils.setArtifactType(artifact, this.$scope.artifactType);
- let artifactCopy = new ArtifactModel(artifact);
- this.openEditArtifactModal(artifactCopy);
- };
-
-
- this.$scope.delete = (artifact:ArtifactModel):void => {
-
- let onOk = ():void => {
- this.$scope.isLoading = true;
- this.artifactsUtils.removeArtifact(artifact, this.$scope.artifacts);
-
- let success = (responseArtifact:ArtifactModel):void => {
- this.initArtifactArr(this.$scope.artifactType);
- this.$scope.isLoading = false;
- };
-
- let error = (error:any):void => {
- console.log('Delete artifact returned error:', error);
- this.initArtifactArr(this.$scope.artifactType);
- this.$scope.isLoading = false;
- };
- if (this.$scope.isComponentInstanceSelected()) {
- this.$scope.currentComponent.deleteInstanceArtifact(artifact.uniqueId, artifact.artifactLabel).then(success, error);
- } else {
- this.$scope.currentComponent.deleteArtifact(artifact.uniqueId, artifact.artifactLabel).then(success, error);//TODO simulate error (make sure error returns)
- }
- };
- let title:string = this.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TITLE");
- let message:string = this.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TEXT", "{'name': '" + artifact.artifactDisplayName + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
-
-
- this.$scope.getEnvArtifact = (heatArtifact:ArtifactModel):any=> {
- return _.find(this.$scope.artifacts, (item:ArtifactModel)=> {
- return item.generatedFromId === heatArtifact.uniqueId;
- });
- };
-
- this.$scope.getEnvArtifactName = (artifact:ArtifactModel):string => {
- let envArtifact = this.$scope.getEnvArtifact(artifact);
- if (envArtifact) {
- return envArtifact.artifactDisplayName;
- }
- };
-
- this.$scope.isLicenseArtifact = (artifact:ArtifactModel):boolean => {
- let isLicense:boolean = false;
- if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
- isLicense = this.artifactsUtils.isLicenseType(artifact.artifactType);
- }
-
- return isLicense;
- };
-
- this.$scope.openEditEnvParametersModal = (artifact:ArtifactModel):void => {
- this.ModalsHandler.openEditEnvParametersModal(artifact, this.$scope.currentComponent).then(()=> {
- this.updateArtifactsIfNeeded();
- }, ()=> {
- // ERROR
- });
- };
-
- this.$scope.isVfOrPnf = ():boolean => {
- if (this.$scope.selectedComponent.isResource()) {
- let selectedResourceType = (<Resource>this.$scope.selectedComponent).resourceType;
- return selectedResourceType == 'VF' || selectedResourceType == 'PNF';
- }
- return false;
- }
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, this.loadArtifacts);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.loadArtifacts);
-
- this.$scope.$on('$destroy', () => {
-
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_NODE_SELECTED, this.loadArtifacts);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.loadArtifacts);
- });
-
- this.loadArtifacts();
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html
deleted file mode 100644
index ec81ed8..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html
+++ /dev/null
@@ -1,84 +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.
--->
-
-<perfect-scrollbar class="w-sdc-designer-sidebar-tab-content artifacts">
- <div class="w-sdc-designer-sidebar-section">
- <loader data-display="isLoading"></loader>
- <expand-collapse
- expanded-selector=".w-sdc-designer-sidebar-section-content" class="w-sdc-designer-sidebar-section-title">
- <span class="w-sdc-designer-sidebar-section-title-text" data-ng-bind="getTitle()" tooltips tooltip-content="{{getTitle()}}"></span>
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <div class="i-sdc-designer-sidebar-section-content-item-artifact"
- data-ng-repeat="artifact in artifacts | orderBy: ['-mandatory', 'artifactDisplayName'] track by $index"
- data-ng-if="(!isComponentInstanceSelected() || artifact.esId) && 'HEAT_ENV' !== artifact.artifactType"
- data-tests-id="artifact-item-{{artifact.artifactDisplayName}}">
- <span data-ng-if="artifact.heatParameters.length" class="i-sdc-designer-sidebar-section-content-item-file-link"></span>
- <div class="i-sdc-designer-sidebar-section-content-item-artifact-details" data-ng-class="{'heat':artifact.isHEAT() && artifact.heatParameters.length}">
- <div class="i-sdc-designer-sidebar-section-content-item-artifact-filename" data-tests-id="artifactName-{{artifact.artifactDisplayName}}"
- data-ng-bind="artifact.artifactName" tooltips tooltip-content="{{artifact.artifactName}}"
- data-ng-if="artifact.artifactName"></div>
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-name" data-tests-id="artifact_Display_Name-{{artifact.artifactDisplayName}}"
- data-ng-class="{'hand enabled': allowDeleteAndUpdateArtifactMap[artifact.artifactLabel]}"
- data-ng-bind="artifact.artifactDisplayName" data-ng-click="!isLoading && allowDeleteAndUpdateArtifactMap[artifact.artifactLabel] && addOrUpdate(artifact)"
- tooltips tooltip-content="{{artifact.artifactDisplayName}}"></span>
- <div class="i-sdc-designer-sidebar-section-content-item-artifact-heat-env" ng-if="artifact.heatParameters.length">
- <span data-ng-bind="getEnvArtifactName(artifact)"data-tests-id="heat_env_{{artifact.artifactDisplayName}}"></span>
- <button class="i-sdc-designer-sidebar-section-content-item-button update-env sprite e-sdc-small-icon-pencil" data-tests-id="edit_{{artifact.artifactDisplayName}}"
- data-ng-if="!isViewMode()" data-ng-click="addOrUpdate(getEnvArtifact(artifact))"></button>
- <download-artifact class="i-sdc-designer-sidebar-section-content-item-button download-env sprite e-sdc-small-download hand" artifact="getEnvArtifact(artifact)"
- component="currentComponent" instance="isComponentInstanceSelected()"
- data-tests-id="download_env_{{artifact.artifactDisplayName}}"></download-artifact>
- </div>
- </div>
-
- <div class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc">
- <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label" data-ng-show="artifact.description">Description:</span>{{artifact.description}}
- </div>
- </div>
- <button ng-if="artifact.esId && allowDeleteAndUpdateArtifactMap[artifact.artifactLabel]" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete"
- data-tests-id="delete_{{artifact.artifactDisplayName}}" data-ng-click="delete(artifact)" type="button"></button>
- <button ng-if="!isViewMode() && artifact.isHEAT() && isComponentInstanceSelected() && artifact.heatParameters.length"
- class="i-sdc-designer-sidebar-section-content-item-button attach sprite e-sdc-small-icon-pad"
- data-ng-click="openEditEnvParametersModal(getEnvArtifact(artifact))" type="button"
- data-tests-id="edit-parameters-of-{{artifact.artifactDisplayName}}"></button>
- <!--need to remove this button -->
- <button ng-if="!isViewMode() && artifact.isHEAT() && !isComponentInstanceSelected() && artifact.heatParameters.length"
- class="i-sdc-designer-sidebar-section-content-item-button attach sprite e-sdc-small-icon-pad"
- data-ng-click="openEditEnvParametersModal(artifact)" type="button"
- data-tests-id="edit-parameters-of-{{artifact.artifactDisplayName}}"></button>
-
- <download-artifact ng-if="artifact.esId && 'deployment' != artifactType" class="i-sdc-designer-sidebar-section-content-item-button download sprite e-sdc-small-download hand"
- artifact="artifact" component="currentComponent" data-tests-id="download_{{artifact.artifactDisplayName}}" instance="isComponentInstanceSelected()"></download-artifact>
- <download-artifact ng-if="artifact.esId && 'deployment' == artifactType" class="i-sdc-designer-sidebar-section-content-item-button download sprite e-sdc-small-download hand"
- artifact="artifact" component="currentComponent" instance="isComponentInstanceSelected()" data-tests-id="download_{{artifact.artifactDisplayName}}"
- show-loader="artifact.isHEAT()"
- download-icon-class="i-sdc-designer-sidebar-section-content-item-button download sprite e-sdc-small-download hand"></download-artifact>
- <button ng-if="!isViewMode() && !artifact.esId && artifactType==='deployment' && !isComponentInstanceSelected() && !artifact.isThirdParty()" class="i-sdc-designer-sidebar-section-content-item-button attach sprite e-sdc-small-icon-upload"
- data-ng-click="addOrUpdate(artifact)" type="button" data-tests-id="add_Artifact"></button>
- </div>
- </div>
-
- </div>
- <div class="w-sdc-designer-sidebar-section-footer" data-ng-if="!isViewMode() && artifactType!=='api' && (!isComponentInstanceSelected()||isVfOrPnf()) && ('deployment' != artifactType || selectedComponent.isComplex())">
- <button class="w-sdc-designer-sidebar-section-footer-action tlv-btn blue" data-tests-id="add_Artifact_Button" data-ng-click="addOrUpdate({})" type="button">Add Artifact</button>
- </div>
- </div>
-</perfect-scrollbar>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts.less
deleted file mode 100644
index 5256542..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts.less
+++ /dev/null
@@ -1,173 +0,0 @@
-.w-sdc-designer-sidebar-tab-content.artifacts {
-
- .i-sdc-designer-sidebar-section-content-item-artifact.hand {
- .hand;
- }
-
- .w-sdc-designer-sidebar-section-content {
- padding: 0;
- }
- .w-sdc-designer-sidebar-section-title {
- &.expanded {
- margin-bottom: 0;
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-details {
- display: inline-block;
- margin-left: 5px;
- vertical-align: middle;
- width: 180px;
- &.heat {
- line-height: 18px;
- width: 250px;
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-details-name {
- .s_14_r;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width:220px;
- display: inline-block;
- //text-transform: capitalize;
- &.enabled {
- &:hover {
- .a_7;
- font-family: @font-opensans-regular
- }
- }
-
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-heat-env {
- .g_7;
- margin-top: 6px;
- line-height: 42px;
- padding-top: 10px;
- border-top:1px solid #c8cdd1;
- .enabled {
- &:hover {
- .hand;
- .a_7;
- }
- }
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-filename {
- .g_7;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 225px;
- display: inline-block;
- .bold;
- &.enabled {
- &:hover {
- .a_7;
- }
- }
- }
-
-
- .i-sdc-designer-sidebar-section-content-item-file-link{
- border-left: 1px #848586 solid;
- height: 58px;
- margin-left: -11px;
- margin-top: 11px;
- border-top: 1px #848586 solid;
- border-bottom: 1px #848586 solid;
- width: 12px;
- float: left;
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-details-desc {
- display: none;
- line-height: 16px;
- word-wrap: break-word;
- white-space: normal;
- }
-
- .i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label {
- .b_3;
- }
-
-
- .i-sdc-designer-sidebar-section-content-item-artifact {
- border-bottom: 1px solid #c8cdd1;
- padding: 5px 10px 5px 18px;
- position: relative;
- // line-height: 36px;
- min-height: 61px;
- //cursor: default;
- display: flex;
- align-items: center;
-
-
- .i-sdc-designer-sidebar-section-content-item-button {
- top: 20px;
- line-height: 10px;
- }
-
- &:hover {
- //background-color: @color_c;
- .bg_c;
- transition: all .3s;
-
- .i-sdc-designer-sidebar-section-content-item-button {
- display: block;
-
- }
-
- }
- }
-
-}
-
-///////////////////Lifecycle Management
-.i-sdc-designer-sidebar-section-content-item-lm {
- .b_7;
- border-bottom: 1px solid @color_e;
- cursor: pointer;
- height: 65px;
- padding: 22px 0;
- position: relative;
-
- &:hover {
- .bg_c_hover;
- margin-left: -10px;
- margin-right: -10px;
- padding: 22px 10px;
-
- .i-sdc-designer-sidebar-section-content-item-lm-icon {
- right: 16px;
- }
- }
-}
-
-.i-sdc-designer-sidebar-section-content-item-lm:first-child {
- margin-top: -18px;
-}
-
-.i-sdc-designer-sidebar-section-content-item-lm-icon {
- position: absolute;
- right: 6px;
-
- //TODO: Replace the icons.
- &.icon-view {
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAJCAYAAAACTR1pAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjdGMDNBRUJDMDkxNjExRTVCMjRBOEI5QzMxQTlBQjY4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjdGMDNBRUJEMDkxNjExRTVCMjRBOEI5QzMxQTlBQjY4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6N0YwM0FFQkEwOTE2MTFFNUIyNEE4QjlDMzFBOUFCNjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6N0YwM0FFQkIwOTE2MTFFNUIyNEE4QjlDMzFBOUFCNjgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4U2decAAABRUlEQVR42pyRPUvDUBSG39t2UyyaBgvWQZMqKoFq4lBH0U0UqXSxKPaPieCoWPAPKIgdjG1ohaghOrSR1iaLKMXpmnMhQVfPcLmc8zxwPhjnHFE4rx3eMO/w4rr4+vwQuZHRMcwqClaMVeRnplnEskg8O7/g96YJSZLgBz5+R0bKIAgC6IaBvdKukBP0HJ+cctu2cVCtQsrIUFUVlcp+LE6EItWIIVaIV9c3/PnRRqlcxkJeYV2vi+/hEO/9QSx6b56oEUMsOal6/TacQcXinCpaGE+n0QnljufFIuUoiAlZTk6iWFyD6zpoWi3RwvrmBlLJZCzRn3IUxBBLjlgO9e06T9ja3sGyrqPX66NtWQLWCgVks5Owmg1c1mpQ8vM4OqywP1s1w1PkpnJY0jTIsizy/sDHQ7sFmt0ITxJtlf33jj8CDADhB52tEX6ifAAAAABJRU5ErkJggg==');
- height: 9px;
- top: 29px;
- width: 14px;
- }
-
- //TODO: Replace the icons.
- &.icon-alert {
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAANCAYAAAB2HjRBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjhBM0YxQTBCMDkyMDExRTVBNzlCQUYxNEYwMDUwOTQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjhBM0YxQTBDMDkyMDExRTVBNzlCQUYxNEYwMDUwOTQ5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OEEzRjFBMDkwOTIwMTFFNUE3OUJBRjE0RjAwNTA5NDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OEEzRjFBMEEwOTIwMTFFNUE3OUJBRjE0RjAwNTA5NDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7exgceAAAB5klEQVR42oySy2tTQRTGfzN3cpvbpFTaUlzUjeCuVFyJf4DuCl34wL/CrbpUunLnwpUuFFy48IFiwYWhpYuW+gCLrbWKBQumaRIba5ub3MccJ5WECCV44MDMme873/lmBhGhnZulcn/3/sfrO7J/45R017pT0xUS2bC93vy2LAOLt5DfCeUn14RD4h/ysbHRDii/8pyo7DmFiP7VZ4Rbu9KT3I7i+qJklp7ibQt2J6HeNOhXV/gv8tDcbaLtXYLJKeTcZfxqSPPzvGu6ID3J1Q8z0ny/hIkM5swF8qenUFUfwixHCtd7Kwez04jOgEmc+hq6tuZ8N9E6xG5U+Pn2kRxKLs7eE7tRc0XlToRM2sD+2sGmDiY+kWsSFG528Kr1Xgfjfn0n5uElvFrrzVqVDHqkiTKjxCsV9LBx08QkgcY/eZH+89Oqo+x9eumkwQaQaoPEKWpsHHN8ArItgLt5UdiG6736mFLxixyQt+bviik8QPuaNFRIkjqQRZ2YJDo6QWydjTRtOcGPPdJKgnlxFfN9fVmGNhecR4U3mLrL6nPTRTQHXZO5+4jyyI4Iqs99GJvgBiKjcySlj3897y6/kbreI4w0QS7ASxrsa4/cXkxkIzK5PKmNqRMw7NfdeczA+Fn1R4ABAPnMAeCjkgf5AAAAAElFTkSuQmCC');
- height: 13px;
- top: 27px;
- width: 15px;
- }
-
-}
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
deleted file mode 100644
index 36ceabf..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts
+++ /dev/null
@@ -1,201 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {Component, ModalModel, ButtonModel} 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";
-import {ModalService} from 'app/ng2/services/modal.service';
-
-export interface IEditResourceVersion {
- allVersions:any;
- changeVersion:string;
-}
-
-interface IDetailsViewModelScope extends ICompositionViewModelScope {
- isLoading:boolean;
- $parent:ICompositionViewModelScope;
- expandedSection:Array<string>;
- editForm:ng.IFormController;
- editResourceVersion:IEditResourceVersion;
-
- onChangeResourceVersion():void;
- alertBeforeChangeResourceVersion():void;
- changeVersion():void;
- cancelChangeResourceVersion():void;
-}
-
-export class DetailsViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- 'LeftPaletteLoaderService',
- 'EventListenerService',
- 'ComponentServiceFactoryNg2',
- 'ServiceServiceNg2',
- 'ModalServiceNg2'
- ];
-
- constructor(private $scope:IDetailsViewModelScope,
- private $filter:ng.IFilterService,
- private LeftPaletteLoaderService:LeftPaletteLoaderService,
- private eventListenerService:EventListenerService,
- private ComponentServiceFactoryNg2: ComponentServiceFactoryNg2,
- private serviceService: ServiceServiceNg2,
- private ModalServiceNg2: ModalService) {
- this.initScope();
- }
-
- private clearSelectedVersion = ():void => {
- this.$scope.editResourceVersion = {
- allVersions: {},
- changeVersion: null
- };
- };
-
- private versioning:Function = (versionNumber:string):string => {
- let version:Array<string> = versionNumber.split('.');
- return '00000000'.slice(version[0].length) + version[0] + '.' + '00000000'.slice(version[1].length) + version[1];
- };
-
- private initEditResourceVersion = ():void => {
- this.clearSelectedVersion();
- this.$scope.editResourceVersion.allVersions[this.$scope.currentComponent.selectedInstance.componentVersion] = this.$scope.currentComponent.selectedInstance.componentUid;
- _.merge(this.$scope.editResourceVersion.allVersions, angular.copy(this.$scope.selectedComponent.allVersions));
- let sorted:any = _.sortBy(_.toPairs(this.$scope.editResourceVersion.allVersions), (item)=> {
- return this.versioning(item[0]);
- });
- this.clearSelectedVersion();
- _.forEach(sorted, (item)=> {
- this.$scope.editResourceVersion.allVersions[item[0]] = item[1];
- });
-
- let highestVersion = _.last(Object.keys(this.$scope.selectedComponent.allVersions));
-
- if (parseFloat(highestVersion) % 1) { //if highest is minor, make sure it is the latest checked in -
- let latestVersionComponent:LeftPaletteComponent = _.maxBy(_.filter(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(this.$scope.currentComponent), (component:LeftPaletteComponent) => { //latest checked in
- return (component.systemName === this.$scope.selectedComponent.systemName
- || component.uuid === this.$scope.selectedComponent.uuid);
- }),(component)=>{return component.version});
-
- let latestVersion:string = latestVersionComponent ? latestVersionComponent.version : highestVersion;
-
- if (highestVersion != latestVersion) { //highest is checked out - remove from options
- this.$scope.editResourceVersion.allVersions = _.omit(this.$scope.editResourceVersion.allVersions, highestVersion);
- }
- }
- this.$scope.editResourceVersion.changeVersion = this.$scope.currentComponent.selectedInstance.componentVersion;
- };
-
- private initScope = ():void => {
- this.$scope.isLoading = false;
- this.$scope.$parent.isLoading = false;
- this.$scope.expandedSection = ['general', 'tags'];
- //this.clearSelectedVersion();
-
- this.$scope.$watch('selectedComponent', (component:Component) => {
- if (this.$scope.isComponentInstanceSelected()) {
- this.initEditResourceVersion();
- }
- });
-
- this.$scope.onChangeResourceVersion = ():void => {
- if(this.$scope.isComponentInstanceSelected() && this.$scope.currentComponent.selectedInstance.isServiceProxy()) {
- this.$scope.alertBeforeChangeResourceVersion();
- }
- else {
- this.$scope.changeVersion();
- }
- };
-
- this.$scope.alertBeforeChangeResourceVersion = ():void => {
- let modalApproveTxt:string = this.$filter('translate')("MODAL_APPROVE");
- let modalCancelTxt:string = this.$filter('translate')("MODAL_CANCEL");
- let changeVersionModalTitle:string = this.$filter('translate')("DETAILS_TAB_CHANGE_VERSION_MODAL_TITLE");
- let changeVersionModalMsg:string = this.$filter('translate')("DETAILS_TAB_CHANGE_VERSION_MODAL_MSG");
-
- let actionButton: ButtonModel = new ButtonModel(modalApproveTxt, 'blue', this.$scope.changeVersion);
- let cancelButton: ButtonModel = new ButtonModel(modalCancelTxt, 'grey', this.$scope.cancelChangeResourceVersion);
- let modalModel: ModalModel = new ModalModel('sm', changeVersionModalTitle, changeVersionModalMsg, [actionButton, cancelButton]);
- let customModal = this.ModalServiceNg2.createCustomModal(modalModel);
- customModal.instance.open();
- };
-
- this.$scope.cancelChangeResourceVersion = () => {
- this.ModalServiceNg2.closeCurrentModal();
- this.$scope.editResourceVersion.changeVersion = this.$scope.currentComponent.selectedInstance.componentVersion;
- };
-
- this.$scope.changeVersion = ():void => {
- this.ModalServiceNg2.closeCurrentModal();
- this.$scope.isLoading = true;
- this.$scope.$parent.isLoading = true;
-
- 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.editResourceVersion.changeVersion = this.$scope.currentComponent.selectedInstance.componentVersion;
-
- if (error) {
- 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);
- };
-
- if (this.$scope.currentComponent.isService()) {
- 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);
- } else {
- onUpdate();
- }
- };
- }
-}
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
deleted file mode 100644
index db5322a..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html
+++ /dev/null
@@ -1,181 +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.
--->
-
-<perfect-scrollbar include-padding="true" class="w-sdc-designer-sidebar-tab-content details">
-
- <div class="w-sdc-designer-sidebar-section">
- <loader data-display="isLoading"></loader>
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.general" class="w-sdc-designer-sidebar-section-title">
-
- General Info
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content general">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Type:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-tests-id="rightTab_componentType" data-ng-bind="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy() ? 'Service Proxy' : selectedComponent.componentType"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isResource()">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Resource Type:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-if="selectedComponent.isResource()" data-ng-bind="selectedComponent.resourceType"
- tooltips tooltip-content="​{{selectedComponent.resourceType | resourceTypeName}}"
- data-tests-id="rightTab_resourceType"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item">
-
- <span class="i-sdc-designer-sidebar-section-content-item-label">Version:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value"
- 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 || selectedComponent.uniqueId != editResourceVersion.allVersions[editResourceVersion.changeVersion] || selectedComponent.archived"
- class="i-sdc-designer-sidebar-section-content-item-value i-sdc-form-select"
- data-ng-class="{'minor': (editResourceVersion.changeVersion)%1, 'disabled':selectedComponent.archived}"
- data-ng-change="onChangeResourceVersion()">
- <option class="select-instance-version" data-ng-class="{'minor': key%1}"
- ng-repeat="(key, value) in editResourceVersion.allVersions">{{key}}</option>
- </select></ng-form>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.categories && selectedComponent.categories[0]">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Category:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.categories[0].name"
- tooltips tooltip-content="​{{selectedComponent.categories[0].name}}"
- data-tests-id="rightTab_category"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.categories && selectedComponent.categories[0] && selectedComponent.categories[0].subcategories">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Sub Category:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.categories[0].subcategories[0].name"
- tooltips tooltip-content="​{{selectedComponent.categories[0].subcategories[0].name}}"
- data-tests-id="rightTab_subCategory"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Creation Date:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.creationDate | date: 'MM/dd/yyyy'"
- data-tests-id="rightTab_creationDate"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Author:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.creatorFullName"
- tooltips tooltip-content="​{{selectedComponent.creatorFullName}}"
- data-tests-id="rightTab_author">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isService()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_PROJECT_CODE"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value"
- data-tests-id="rightTab_projectCode" data-ng-bind="selectedComponent.projectCode"></span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isResource()">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Vendor Name:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.vendorName"
- tooltips tooltip-content="​{{selectedComponent.vendorName}}"
- data-tests-id="rightTab_vendorName">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isResource()">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Vendor Release:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.vendorRelease"
- tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.vendorRelease}}"
- data-tests-id="rightTab_vendorRelease">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isResource()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_RESOURCE_MODEL_NUMBER"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value vendor-model-number" data-ng-bind="selectedComponent.resourceVendorModelNumber"
- tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.resourceVendorModelNumber}}"
- data-tests-id="rightTab_resourceVendorModelNumber">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isService()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SERVICE_TYPE"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.serviceType"
- tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.serviceType}}"
- data-tests-id="rightTab_serviceType">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isService()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SERVICE_ROLE"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.serviceRole"
- tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.serviceRole}}"
- data-tests-id="rightTab_serviceRole">
- </span>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_CONTACT_ID"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.contactId"
- data-tests-id="rightTab_contactId"></span>
- </div>
-
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SOURCE_SERVICE_NAME"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="currentComponent.selectedInstance.sourceModelName" tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{currentComponent.selectedInstance.sourceModelName}}"
- data-tests-id="rightTab_sourceModelName"></span>
- </div>
-
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="isViewMode() && currentComponent.isService() && selectedComponent.isResource()">
- <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_RESOURCE_CUSTOMIZATION_UUID"></span><br>
- <span class="customization-uuid selectable" data-ng-bind="currentComponent.selectedInstance.customizationUUID"
- data-tests-id="rightTab_customizationModuleUUID"></span><br>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item description">
- <span class="i-sdc-designer-sidebar-section-content-item-label">Description:
-
- <span class="i-sdc-designer-sidebar-section-content-description-item-value" ellipsis="selectedComponent.description" max-chars="55"
- data-tests-id="rightTab_description"></span>
- </span>
- </div>
-
- </div>
- </div>
-
- <div class="w-sdc-designer-sidebar-section additionalInformation">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.additionalInformation" class="w-sdc-designer-sidebar-section-title">
- Additional Information
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content additionalInformation">
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-repeat="additionalInformation in selectedComponent.getAdditionalInformation() track by $index">
- <span class="i-sdc-designer-sidebar-section-content-item-label additional-information" data-ng-bind="additionalInformation.key" tooltips tooltip-content="{{additionalInformation.key}}"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-label">:</span>
- <span class="i-sdc-designer-sidebar-section-content-item-value additional-information" data-ng-bind="additionalInformation.value"
- tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="{{additionalInformation.value}}"></span>
- </div>
- </div>
- </div>
-
-
- <div class="w-sdc-designer-sidebar-section tags">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.tags" class="w-sdc-designer-sidebar-section-title">
- Tags
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content tags">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <span class="i-sdc-designer-sidebar-section-content-item-tag" data-ng-if="selectedComponent.tags.indexOf(selectedComponent.name)===-1" data-ng-bind="selectedComponent.name"
- data-tests-id="rightTab_tag" tooltips tooltip-content="{{selectedComponent.name}}"></span>
- <span class="i-sdc-designer-sidebar-section-content-item-tag" data-ng-repeat="tag in selectedComponent.tags track by $index" data-ng-bind="tag"
- data-tests-id="rightTab_tag" tooltips tooltip-content="{{tag}}"></span>
- </div>
- </div>
- </div>
- </div>
-
-</perfect-scrollbar>
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less
deleted file mode 100644
index 90bb565..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less
+++ /dev/null
@@ -1,81 +0,0 @@
-.w-sdc-designer-sidebar-tab-content.details {
-
- .w-sdc-designer-sidebar-section-title + .w-sdc-designer-sidebar-section-content {
- padding: 0 10px 0 18px;
- }
-
- .w-sdc-designer-sidebar-section-title.expanded + .w-sdc-designer-sidebar-section-content {
- padding: 10px 10px 10px 18px;
- }
-
- .i-sdc-designer-sidebar-section-content-item-label {
- font-family: @font-opensans-medium;
- color: #191919;
- font-size: 13px;
- &.additional-information{
- max-width:100px;
- display: inline-block;
- text-overflow: ellipsis;
- overflow: hidden;
- vertical-align: bottom;
- }
-
- }
-
-
-
- .i-sdc-designer-sidebar-section-content-item-value {
- // .hyphenate;
- font-family: @font-opensans-regular;
- color: #191919;
- font-size: 13px;
- padding-left: 10px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- //display: inline-block; fix long name for firefox
- max-width: 160px;
- vertical-align:bottom;
- font-weight: normal;
- &.vendor-model-number{
- max-width: 110px;
- }
- &.additional-information{
- max-width:160px;
- display: inline-block;
- }
- &.i-sdc-form-select {
- .b_1;
- border: 1px solid @border_color_f;
- width: 210px;
- max-width: 210px;
- padding-left: 4px;
-
- .select-instance-version {
- .b_1;
- &.minor {
- .h_1;
- }
- }
- }
- &.minor {
- .h_1;
- }
- }
- .i-sdc-designer-sidebar-section-content-description-item-value{
- max-width: none;
- font-weight: normal;
- font-family: @font-opensans-regular;
- }
-
- .customization-uuid{
- .f-type._12_m;
- }
-
- .w-sdc-designer-sidebar-section.tags {
- .i-sdc-designer-sidebar-section-content-item {
- white-space: normal;
- }
- }
-
-}
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
deleted file mode 100644
index e3ddecd..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view-model.ts
+++ /dev/null
@@ -1,244 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {
- AttributeModel,
- AttributesGroup,
- Component,
- ComponentInstance,
- PropertyModel,
- PropertiesGroup
-} from "app/models";
-import {ICompositionViewModelScope} from "../../composition-view-model";
-import {ModalsHandler} from "app/utils";
-import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service";
-import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response";
-
-interface IResourcePropertiesAndAttributesViewModelScope extends ICompositionViewModelScope {
- properties:PropertiesGroup;
- attributes:AttributesGroup;
- propertiesMessage:string;
- groupPropertiesByInstance:boolean;
- showGroupsOfInstanceProperties:Array<boolean>;
- addProperty():void;
- updateProperty(property:PropertyModel):void;
- deleteProperty(property:PropertyModel):void;
- viewAttribute(attribute:AttributeModel):void;
- groupNameByKey(key:string):string;
- isPropertyOwner():boolean;
- getComponentInstanceNameFromInstanceByKey(key:string):string;
-}
-
-export class ResourcePropertiesViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- '$uibModal',
- 'ModalsHandler',
- 'ComponentServiceNg2'
-
- ];
-
-
- constructor(private $scope:IResourcePropertiesAndAttributesViewModelScope,
- private $filter:ng.IFilterService,
- private $uibModal:ng.ui.bootstrap.IModalService,
- private ModalsHandler:ModalsHandler,
- private ComponentServiceNg2:ComponentServiceNg2) {
-
- this.getComponentInstancesPropertiesAndAttributes();
- }
-
- private initComponentProperties = ():void => {
- let result:PropertiesGroup = {};
-
- if (this.$scope.selectedComponent) {
- this.$scope.propertiesMessage = undefined;
- this.$scope.groupPropertiesByInstance = false;
- if (this.$scope.isComponentInstanceSelected()) {
- if (this.$scope.currentComponent.selectedInstance.originType === 'VF') {
- this.$scope.groupPropertiesByInstance = true;
- }
- result[this.$scope.currentComponent.selectedInstance.uniqueId] = this.$scope.currentComponent.componentInstancesProperties[this.$scope.currentComponent.selectedInstance.uniqueId];
- } else if (this.$scope.currentComponent.isService()) {
- // Temporally fix to hide properties for service (UI stack when there are many properties)
- result = this.$scope.currentComponent.componentInstancesProperties;
- this.$scope.propertiesMessage = "Note: properties for service are disabled";
- } else {
- let key = this.$scope.selectedComponent.uniqueId;
- result[key] = Array<PropertyModel>();
- let derived = Array<PropertyModel>();
- _.forEach(this.$scope.selectedComponent.properties, (property:PropertyModel) => {
- if (key == property.parentUniqueId) {
- result[key].push(property);
- } else {
- property.readonly = true;
- derived.push(property);
- }
- });
- if (derived.length) {
- result['derived'] = derived;
- }
- }
- this.$scope.properties = result;
- }
- };
-
-
- private initComponentAttributes = ():void => {
- let result:AttributesGroup = {};
-
- if (this.$scope.selectedComponent) {
- if (this.$scope.isComponentInstanceSelected()) {
- result[this.$scope.currentComponent.selectedInstance.uniqueId] = this.$scope.currentComponent.componentInstancesAttributes[this.$scope.currentComponent.selectedInstance.uniqueId];
- } else if (this.$scope.currentComponent.isService()) {
- result = this.$scope.currentComponent.componentInstancesAttributes;
- }
- this.$scope.attributes = result;
- }
- };
-
- /**
- * This function is checking if the component is the value owner of the current property
- * in order to notify the edit property modal which fields to disable
- */
- private isPropertyValueOwner = ():boolean => {
- return this.$scope.currentComponent.isService() || !!this.$scope.currentComponent.selectedInstance;
- };
-
- /**
- * The function opens the edit property modal.
- * It checks if the property is from the VF or from one of it's resource instances and sends the needed property list.
- * For create property reasons an empty array is transferd
- *
- * @param property the wanted property to edit/create
- */
- private openEditPropertyModal = (property:PropertyModel):void => {
- this.ModalsHandler.openEditPropertyModal(property,
- this.$scope.component,
- (this.$scope.isPropertyOwner() ?
- this.$scope.properties[property.parentUniqueId] :
- this.$scope.properties[property.resourceInstanceUniqueId]) || [],
- this.isPropertyValueOwner(), "component", property.resourceInstanceUniqueId).then((updatedProperty:PropertyModel) => {
- if(updatedProperty){
- let oldProp = _.find(this.$scope.properties[updatedProperty.resourceInstanceUniqueId], (prop:PropertyModel) => {return prop.uniqueId == updatedProperty.uniqueId;});
- oldProp.value = updatedProperty.value;
- }
- });
- };
-
- private openAttributeModal = (atrribute:AttributeModel):void => {
-
- let modalOptions:ng.ui.bootstrap.IModalSettings = {
- template: 'app/view-models/forms/attribute-form/attribute-form-view.html',
- controller: 'Sdc.ViewModels.AttributeFormViewModel',
- size: 'sdc-md',
- backdrop: 'static',
- keyboard: false,
- resolve: {
- attribute: ():AttributeModel => {
- return atrribute;
- },
- component: ():Component => {
- return this.$scope.currentComponent;
- }
- }
- };
- this.$uibModal.open(modalOptions);
- };
-
- private getComponentInstancesPropertiesAndAttributes = () => {
-
- this.ComponentServiceNg2.getComponentInstanceAttributesAndProperties(this.$scope.currentComponent).subscribe((genericResponse:ComponentGenericResponse) => {
- this.$scope.currentComponent.componentInstancesAttributes = genericResponse.componentInstancesAttributes;
- this.$scope.currentComponent.componentInstancesProperties = genericResponse.componentInstancesProperties;
- this.initScope();
- });
- };
-
- private initScope = ():void => {
-
-
- this.initComponentProperties();
- this.initComponentAttributes();
-
- this.$scope.$watchCollection('currentComponent.properties', (newData:any):void => {
- this.initComponentProperties();
- });
-
- this.$scope.$watch('currentComponent.selectedInstance', (newInstance:ComponentInstance):void => {
- if (angular.isDefined(newInstance)) {
- this.initComponentProperties();
- this.initComponentAttributes();
-
- }
- });
-
- this.$scope.isPropertyOwner = ():boolean => {
- return this.$scope.currentComponent && this.$scope.currentComponent.isResource() && !this.$scope.isComponentInstanceSelected();
- };
-
- this.$scope.updateProperty = (property:PropertyModel):void => {
- this.openEditPropertyModal(property);
- };
-
- this.$scope.deleteProperty = (property:PropertyModel):void => {
-
- let onOk = ():void => {
- this.$scope.currentComponent.deleteProperty(property.uniqueId);
- };
-
- let title:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TITLE");
- let message:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TEXT", "{'name': '" + property.name + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
-
- this.$scope.viewAttribute = (attribute:AttributeModel):void => {
- this.openAttributeModal(attribute);
- };
-
- this.$scope.groupNameByKey = (key:string):string => {
- switch (key) {
- case 'derived':
- return "Derived";
-
- case this.$scope.currentComponent.uniqueId:
- return this.$filter("resourceName")(this.$scope.currentComponent.name);
-
- default:
- let componentInstance = _.find(this.$scope.currentComponent.componentInstances, {uniqueId: key});
- if(componentInstance)
- return this.$filter("resourceName")(componentInstance.name);
- }
- };
-
- this.$scope.getComponentInstanceNameFromInstanceByKey = (key:string):string => {
- let instanceName:string = "";
- if (key !== undefined && this.$scope.selectedComponent.uniqueId == this.$scope.currentComponent.selectedInstance.componentUid) {
- instanceName = this.$filter("resourceName")((_.find(this.$scope.selectedComponent.componentInstances, {uniqueId: key})).name);
- }
- return instanceName;
- };
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view.html
deleted file mode 100644
index cdd6968..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties-view.html
+++ /dev/null
@@ -1,133 +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.
--->
-
-<perfect-scrollbar class="w-sdc-designer-sidebar-tab-content properties" id="main-scroll">
-
- <div class="w-sdc-designer-sidebar-section">
-
- <!--expand-collapse data-ng-if="isPropertyOwner() && !currentComponent.properties.length" expanded-selector=".w-sdc-composition-sidebar-section-content.{{currentComponent.name}}"
- class="w-sdc-composition-sidebar-section-title">
- <span class="w-sdc-composition-sidebar-section-title-text" tooltips tooltip-content="{{currentComponent.name | resourceName}} Properties"
- data-ng-bind="(currentComponent.name | resourceName)+ ' Properties'"></span>
- <div class="w-sdc-composition-sidebar-section-title-icon"></div>
- </expand-collapse-->
- <!--properties-->
- <expand-collapse data-ng-repeat-start="(key, group) in properties"
- expanded-selector=".w-sdc-designer-sidebar-section-content.properties.{{$index}}">
- <div class="first-level">
- <div class="expand-collapse-title-icon"></div>
- <span class="w-sdc-designer-sidebar-section-title-text" data-ng-bind="groupNameByKey(key) + ' Properties'"
- tooltips tooltip-content="{{groupNameByKey(key)}} Properties"
- data-tests-id="vfi-properties"></span>
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="w-sdc-designer-sidebar-section-content properties {{$index}}"> <!--data-ng-show="isShowDetailsSection" -->
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="!groupPropertiesByInstance">
- <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow"
- data-ng-repeat="property in group | orderBy: 'name' track by $index">
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
- data-ng-class="{'hand enabled': !$parent.isViewOnly}"
- tooltips tooltip-content="{{property.name}}"
- data-ng-click="!$parent.isViewOnly && updateProperty(property)"
- data-tests-id="{{property.name}}">{{property.name}}</span>
- </div>
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-value" data-ng-if="isPropertyOwner()"
- tooltips tooltip-content="{{property.defaultValue}}">{{property.defaultValue}}</span>
- <span class="i-sdc-designer-sidebar-section-content-item-property-value" data-ng-if="!isPropertyOwner()"
- tooltips tooltip-content="{{property.value}}"
- data-tests-id="value_{{property.name}}">{{property.value}}</span>
- </div>
- <button class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete"
- data-ng-if="!$parent.isViewOnly&&(isPropertyOwner() && !property.readonly)"
- data-ng-click="deleteProperty(property)" type="button"></button>
- </div>
- </div>
- <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="groupPropertiesByInstance">
- <div data-ng-repeat-start="(instancesIds , InstanceProperties) in (group | groupBy:'path')"
- class="vfci-properties-group"
- data-ng-click="showGroupsOfInstanceProperties[$index]=!showGroupsOfInstanceProperties[$index]"
- data-ng-class="{'expanded':showGroupsOfInstanceProperties[$index]}">
- <div class="second-level">
- <div class="expand-collapse-title-icon"></div>
- <span class="w-sdc-designer-sidebar-section-title-text" data-ng-bind="getComponentInstanceNameFromInstanceByKey(InstanceProperties[0].path[1]) + ' Properties'"
- tooltips tooltip-content="{{getComponentInstanceNameFromInstanceByKey(InstanceProperties[0].path[1])}} Properties"
- data-tests-id="vfci-properties"></span>
- </div>
- </div>
- <div data-ng-repeat-end="" class="w-sdc-designer-sidebar-section-content instance-properties {{$index}}" data-ng-if="showGroupsOfInstanceProperties[$index]">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute" data-tests-id="propertyRow"
- data-ng-repeat="instanceProperty in InstanceProperties | orderBy: 'name'">
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
- data-ng-class="{'hand enabled': !$parent.isViewOnly}"
- tooltips tooltip-content="{{instanceProperty.name}}"
- data-tests-id="vfci-property">{{instanceProperty.name}}</span>
- </div>
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-value"
- tooltips tooltip-content="{{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}">
- {{instanceProperty.value === undefined ? instanceProperty.defaultValue : instanceProperty.value}}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!--<div class="w-sdc-designer-sidebar-section-footer" data-ng-if="(!$parent.isViewOnly && isPropertyOwner()) || showAddPropertyButton">-->
- <!--<button class="w-sdc-designer-sidebar-section-footer-action tlv-btn blue" data-tests-id="addGrey" data-ng-click="addProperty()" type="button">-->
- <!--Add Property-->
- <!--</button>-->
- <!--</div>-->
- </div>
-
-
- <!--attributes-->
- <expand-collapse data-ng-repeat-start="(key, group) in attributes"
- expanded-selector=".w-sdc-designer-sidebar-section-content.attributes.{{$index}}">
- <div class="first-level">
- <div class="expand-collapse-title-icon"></div>
- <span class="w-sdc-designer-sidebar-section-title-text" data-ng-bind="groupNameByKey(key) + ' Attributes'"
- tooltips tooltip-content="{{groupNameByKey(key)}} Attributes"></span>
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="w-sdc-designer-sidebar-section-content attributes {{$index}}"> <!--data-ng-show="isShowDetailsSection" -->
- <div class="i-sdc-designer-sidebar-section-content-item">
- <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute"
- data-ng-repeat="attribute in group | orderBy: 'name' track by $index">
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
- data-ng-class="{'hand enabled': !$parent.isViewOnly}"
- tooltips tooltip-content="{{attribute.name}}"
- data-ng-click="!$parent.isViewOnly && viewAttribute(attribute)"
- data-tests-id="{{attribute.name}}-attr">{{attribute.name}}</span>
- </div>
- <div>
- <span class="i-sdc-designer-sidebar-section-content-item-property-value" data-ng-if="isPropertyOwner()"
- tooltips tooltip-content="{{attribute.defaultValue}}">{{attribute.defaultValue}}</span>
- <span class="i-sdc-designer-sidebar-section-content-item-property-value" data-ng-if="!isPropertyOwner()"
- tooltips tooltip-content="{{attribute.value}}" data-tests-id="value-of-{{attribute.name}}">{{attribute.value}}</span>
- </div>
- </div>
- </div>
-
- </div>
-
- </div>
-</perfect-scrollbar>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties.less
deleted file mode 100644
index ce5acc8..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/properties-and-attributes/properties.less
+++ /dev/null
@@ -1,39 +0,0 @@
-.w-sdc-designer-sidebar-tab-content.properties {
- .i-sdc-designer-sidebar-section-content-item-property-and-attribute-label{
- display:block;
- font-weight: bold;
- }
- .i-sdc-designer-sidebar-section-content-item-button.update{
- right: 17px;
- }
- .i-sdc-designer-sidebar-section-content-item-button.delete{
- right: 35px;
- }
-
- .w-sdc-designer-sidebar-properties-disabled {
- .s_14_m;
- padding: 20px 20px;
- }
-
- .vfci-properties-group{
- background-color: @func_color_r;
- }
-
- .expand-collapse-title-icon{
- .hand;
- .sprite-new;
- .expand-collapse-plus-icon;
- vertical-align: middle;
- margin: 0 6px;
- }
-
- .expanded {
- .expand-collapse-title-icon {
- .expand-collapse-minus-icon;
- }
- }
-
- .w-sdc-designer-sidebar-section-title-text{
- vertical-align: middle;
- }
-}
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
deleted file mode 100644
index ce44aaf..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view-model.ts
+++ /dev/null
@@ -1,177 +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=========================================================
- */
-
-'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";
-import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response";
-import {GRAPH_EVENTS} from "app/utils";
-import {EventListenerService} from "app/services";
-import {ComponentInstance, Capability} from "app/models";
-
-interface IRelationsViewModelScope extends ICompositionViewModelScope {
- isLoading:boolean;
- $parent:ICompositionViewModelScope;
- getRelation(requirement:any):any;
- capabilities:Array<Capability>;
- requirements:Array<Requirement>;
-
- //for complex components
- capabilitiesInstancesMap:InstanceCapabilitiesMap;
- requirementsInstancesMap:InstanceRequirementsMap;
-}
-export class InstanceCapabilitiesMap {
- [key:string]:Array<Capability>;
-}
-
-export class InstanceRequirementsMap {
- [key:string]:Array<Requirement>;
-}
-
-export class RelationsViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- 'ComponentServiceNg2',
- 'EventListenerService'
- ];
-
- constructor(private $scope:IRelationsViewModelScope,
- private $filter:ng.IFilterService,
- private ComponentServiceNg2:ComponentServiceNg2,
- private eventListenerService:EventListenerService) {
- this.initScope();
- }
-
- private loadComplexComponentData = () => {
- this.$scope.isLoading = true;
- this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.$scope.currentComponent.componentType, this.$scope.currentComponent.uniqueId).subscribe((response:ComponentGenericResponse) => {
- this.$scope.currentComponent.capabilities = response.capabilities;
- this.$scope.currentComponent.requirements = response.requirements;
- this.setScopeCapabilitiesRequirements(this.$scope.currentComponent.capabilities, this.$scope.currentComponent.requirements);
- this.initInstancesMap();
- this.$scope.isLoading = false;
- });
- }
-
-
- private extractValuesFromMap = (map:CapabilitiesGroup | RequirementsGroup):Array<any> => {
- let values = [];
- _.forEach(map, (capabilitiesOrRequirements:Array<Capability> | Array<Requirement>, key) => {
- values = values.concat(capabilitiesOrRequirements)
- }
- );
- return values;
- }
-
- private setScopeCapabilitiesRequirements = (capabilities:CapabilitiesGroup, requirements:RequirementsGroup) => {
- this.$scope.capabilities = this.extractValuesFromMap(capabilities);
- this.$scope.requirements = this.extractValuesFromMap(requirements);
- }
-
-
- private initInstancesMap = ():void => {
-
- this.$scope.capabilitiesInstancesMap = new InstanceCapabilitiesMap();
- _.forEach(this.$scope.capabilities, (capability:Capability) => {
- if (this.$scope.capabilitiesInstancesMap[capability.ownerName]) {
- this.$scope.capabilitiesInstancesMap[capability.ownerName] = this.$scope.capabilitiesInstancesMap[capability.ownerName].concat(capability);
- } else {
- this.$scope.capabilitiesInstancesMap[capability.ownerName] = new Array<Capability>(capability);
- }
- });
-
- this.$scope.requirementsInstancesMap = new InstanceRequirementsMap();
- _.forEach(this.$scope.requirements, (requirement:Requirement) => {
- if (this.$scope.requirementsInstancesMap[requirement.ownerName]) {
- this.$scope.requirementsInstancesMap[requirement.ownerName] = this.$scope.requirementsInstancesMap[requirement.ownerName].concat(requirement);
- } else {
- this.$scope.requirementsInstancesMap[requirement.ownerName] = new Array<Requirement>(requirement);
- }
- });
- }
-
- private initRequirementsAndCapabilities = (needUpdate?: boolean) => {
-
- // if instance selected, we take the requirement and capabilities of the instance - always exist because we load them with the graph
- if (this.$scope.isComponentInstanceSelected()) {
- this.$scope.isLoading = false;
- this.setScopeCapabilitiesRequirements(this.$scope.currentComponent.selectedInstance.capabilities, this.$scope.currentComponent.selectedInstance.requirements);
- if (this.$scope.currentComponent.selectedInstance.originType === 'VF') {
- this.initInstancesMap();
- }
- } else {
- // if instance not selected, we take the requirement and capabilities of the VF/SERVICE, if not exist we call api
- if (needUpdate || !this.$scope.currentComponent.capabilities || !this.$scope.currentComponent.requirements) {
- this.loadComplexComponentData();
-
- } else {
- this.$scope.isLoading = false;
- this.setScopeCapabilitiesRequirements(this.$scope.currentComponent.capabilities, this.$scope.currentComponent.requirements);
- this.initInstancesMap();
- }
- }
- }
-
- private updateRequirementCapabilities = () => {
- if (!this.$scope.isComponentInstanceSelected()) {
- this.loadComplexComponentData();
- }
- }
-
- private initEvents = ():void => {
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
- }
-
- private initScope = ():void => {
-
- this.$scope.requirements = [];
- this.$scope.capabilities = [];
-
- this.initEvents();
- this.initRequirementsAndCapabilities();
-
- this.$scope.isCurrentDisplayComponentIsComplex = ():boolean => {
- if (this.$scope.isComponentInstanceSelected()) {
- if (this.$scope.currentComponent.selectedInstance.originType === 'VF') {
- return true;
- }
- return false;
- } else {
- return this.$scope.currentComponent.isComplex();
- }
- }
-
- this.$scope.$on('$destroy', () => {
-
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_NODE_SELECTED, this.initRequirementsAndCapabilities);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED, this.updateRequirementCapabilities);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
- this.eventListenerService.unRegisterObserver(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE, this.updateRequirementCapabilities);
- });
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view.html
deleted file mode 100644
index 889f129..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations-view.html
+++ /dev/null
@@ -1,77 +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.
--->
-
-<perfect-scrollbar class="w-sdc-designer-sidebar-tab-content sdc-general-tab relations">
- <div ng-if="!isCurrentDisplayComponentIsComplex()">
- <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.capabilities" class="w-sdc-designer-sidebar-section-title"> Capabilities
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
- <div class="w-sdc-designer-sidebar-section-content capabilities">
- <capabilities-list capabilities="capabilities"></capabilities-list>
- </div>
- </div>
- <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.requirements" class="w-sdc-designer-sidebar-section-title"> Requirements
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content requirements">
- <requirements-list component='currentComponent' requirements="requirements"></requirements-list>
- </div>
- </div>
- </div>
-
- <div ng-if="isCurrentDisplayComponentIsComplex()">
- <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.capabilities" class="w-sdc-designer-sidebar-section-title"> Capabilities
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
- </div>
- <div class="w-sdc-designer-sidebar-section-content capabilities">
- <expand-collapse expanded-selector=".capabilities-component-instances.{{$index}}" is-close-on-init="true" class="general-tab-expand-collapse"
- data-ng-repeat-start="(key, instanceCapabilities) in capabilitiesInstancesMap track by $index">
- <div class="expand-collapse-title second-level">
- <div class="expand-collapse-title-icon"></div>
- <span class="expand-collapse-title-text" data-ng-bind="key"></span>
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="capabilities-component-instances {{$index}}">
- <capabilities-list capabilities="instanceCapabilities"></capabilities-list>
- </div>
- </div>
-
- <div class="w-sdc-designer-sidebar-section w-sdc-designer-sidebar-section-relations">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content.requirements" class="w-sdc-designer-sidebar-section-title"> Requirements
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
- </div>
- <div class="w-sdc-designer-sidebar-section-content requirements">
- <expand-collapse expanded-selector=".requirements-component-instances.{{$index}}" is-close-on-init="true" class="general-tab-expand-collapse"
- data-ng-repeat-start="(key, instanceRequirements) in requirementsInstancesMap track by $index">
- <div class="expand-collapse-title second-level">
- <div class="expand-collapse-title-icon"></div>
- <span class="expand-collapse-title-text" data-ng-bind="key"></span>
- </div>
- </expand-collapse>
-
- <div data-ng-repeat-end="" class="requirements-component-instances {{$index}}">
- <requirements-list component='currentComponent' requirements="instanceRequirements"></requirements-list>
- </div>
- </div>
- </div>
-</perfect-scrollbar>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations.less
deleted file mode 100644
index c3b224d..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/relations/relations.less
+++ /dev/null
@@ -1,14 +0,0 @@
-.w-sdc-designer-sidebar-tab-content.relations {
-
- .w-sdc-designer-sidebar-section-content {
- padding: 0;
- }
-
- .w-sdc-designer-sidebar-section-title {
- &.expanded {
- margin-bottom: 0;
- }
- }
-}
-
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts
deleted file mode 100644
index 7370023..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts
+++ /dev/null
@@ -1,101 +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.
-*/
-
-
-import {ICompositionViewModelScope} from "../../composition-view-model";
-import {
- Service,
- PropertiesGroup,
- InputsGroup,
- ServiceInstanceObject,
- InterfaceModel,
- InputBEModel,
- CapabilitiesGroup,
- Capability,
- ComponentInstance
-} from 'app/models';
-import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response";
-import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
-
-interface IServiceConsumptionViewModelScope extends ICompositionViewModelScope {
- service: Service;
- instancesMappedList: Array<ServiceInstanceObject>;
- componentInstancesProperties: PropertiesGroup;
- componentInstancesInputs: InputsGroup;
- componentInstancesInterfaces: Map<string, Array<InterfaceModel>>;
- componentInputs: Array<InputBEModel>;
- componentCapabilities: Array<Capability>;
- instancesCapabilitiesMap: Map<string, Array<Capability>>;
-}
-
-
-export class ServiceConsumptionViewModel {
-
- static '$inject' = [
- '$scope',
- 'ServiceServiceNg2'
- ];
-
- constructor(private $scope:IServiceConsumptionViewModelScope, private ServiceServiceNg2:ServiceServiceNg2) {
- this.$scope.service = <Service>this.$scope.currentComponent;
- this.initInstances();
- this.initScope();
- }
-
- private initInstances = ():void => {
- this.ServiceServiceNg2.getServiceConsumptionData(this.$scope.service).subscribe((genericResponse:ComponentGenericResponse) => {
- this.$scope.componentInstancesProperties = genericResponse.componentInstancesProperties;
- this.$scope.componentInstancesInputs = genericResponse.componentInstancesInputs;
- this.$scope.componentInstancesInterfaces = genericResponse.componentInstancesInterfaces;
- this.$scope.componentInputs = genericResponse.inputs;
- this.buildInstancesCapabilitiesMap(genericResponse.componentInstances);
- this.updateInstanceAttributes();
- });
- }
-
- buildInstancesCapabilitiesMap = (componentInstances: Array<ComponentInstance>): void => {
- this.$scope.instancesCapabilitiesMap = new Map();
- let flattenCapabilities = [];
- _.forEach(componentInstances, componentInstance => {
- flattenCapabilities = CapabilitiesGroup.getFlattenedCapabilities(componentInstance.capabilities);
- this.$scope.instancesCapabilitiesMap[componentInstance.uniqueId] = _.filter(flattenCapabilities, cap => cap.properties && cap.ownerId === componentInstance.uniqueId);
- });
- }
-
- private updateInstanceAttributes = ():void => {
- if (this.$scope.isComponentInstanceSelected() && this.$scope.componentInstancesProperties) {
- this.$scope.instancesMappedList = this.$scope.service.componentInstances.map(coInstance => new ServiceInstanceObject({
- id: coInstance.uniqueId,
- name: coInstance.name,
- properties: this.$scope.componentInstancesProperties[coInstance.uniqueId] || [],
- inputs: this.$scope.componentInstancesInputs[coInstance.uniqueId] || [],
- interfaces: this.$scope.componentInstancesInterfaces[coInstance.uniqueId] || []
- }));
- }
- }
-
- private initScope = ():void => {
- this.$scope.$watch('currentComponent.selectedInstance', ():void => {
- this.updateInstanceAttributes();
- });
-
- this.$scope.registerCreateInstanceEvent(() => {
- this.initInstances();
- });
-
- this.$scope.$on('$destroy', this.$scope.unregisterCreateInstanceEvent);
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html
deleted file mode 100644
index 8404a7f..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<perfect-scrollbar class="w-sdc-designer-sidebar-tab-content service-consumption">
- <div class="w-sdc-designer-sidebar-section">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content"
- class="w-sdc-designer-sidebar-section-title">
- <span class="w-sdc-designer-sidebar-section-title-text" tooltips tooltip-content="Operation Consumption">Operation Consumption</span>
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <ng2-service-consumption
- [parent-service]="service"
- [selected-service]="selectedComponent"
- [selected-service-instance-id]="currentComponent.selectedInstance.uniqueId"
- [instances-mapped-list]="instancesMappedList"
- [parent-service-inputs]="componentInputs"
- [instances-capabilities-map]="instancesCapabilitiesMap"
- [readonly]="isViewMode() || !isDesigner()">
- </ng2-service-consumption>
- </div>
- </div>
- </div>
-</perfect-scrollbar>
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view-model.ts
deleted file mode 100644
index b634e60..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view-model.ts
+++ /dev/null
@@ -1,125 +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.
- */
-
-
-import {ICompositionViewModelScope} from "../../composition-view-model";
-import {Service, ComponentInstance, PropertiesGroup, ServiceInstanceObject, PropertyBEModel} from 'app/models';
-import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service";
-import {ConstraintObject} from "app/ng2/components/logic/service-dependencies/service-dependencies.component";
-import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response';
-import {DEPENDENCY_EVENTS} from "app/utils/constants";
-import {EventListenerService} from 'app/services';
-
-interface IServiceDependenciesViewModelScope extends ICompositionViewModelScope {
- service: Service;
- selectedInstanceSiblings: Array<ServiceInstanceObject>;
- componentInstancesConstraints: Array<any>;
- selectedInstanceConstraints: Array<ConstraintObject>;
- selectedInstanceProperties: Array<PropertyBEModel>;
- updateSelectedInstanceConstraints(constraintsList:Array<ConstraintObject>): void;
- loadConstraints(): void;
- componentInstanceProperties: PropertiesGroup;
- notifyDependencyEventsObserver: Function;
-}
-
-
-
-export class ServiceDependenciesViewModel {
-
- static '$inject' = [
- '$scope',
- 'ComponentServiceNg2',
- 'EventListenerService'
- ];
-
- constructor(private $scope:IServiceDependenciesViewModelScope, private ComponentServiceNg2:ComponentServiceNg2, private eventListenerService: EventListenerService) {
- this.$scope.service = <Service>this.$scope.currentComponent;
- this.$scope.notifyDependencyEventsObserver = this.notifyDependencyEventsObserver;
- this.initInstancesWithProperties();
- this.loadConstraints();
-
- this.initScope();
- }
-
- private initInstancesWithProperties = ():void => {
- this.ComponentServiceNg2.getComponentInstanceProperties(this.$scope.currentComponent).subscribe((genericResponse:ComponentGenericResponse) => {
- this.$scope.componentInstanceProperties = genericResponse.componentInstancesProperties;
- this.updateInstanceAttributes();
- });
- }
-
- private updateInstanceAttributes = ():void => {
- if (this.$scope.isComponentInstanceSelected() && this.$scope.componentInstanceProperties) {
- let instancesMappedList = this.$scope.service.componentInstances.map(coInstance => new ServiceInstanceObject({
- id: coInstance.uniqueId,
- name: coInstance.name,
- properties: this.$scope.componentInstanceProperties[coInstance.uniqueId] || []
- }));
- this.$scope.selectedInstanceProperties = this.$scope.componentInstanceProperties[this.$scope.currentComponent.selectedInstance.uniqueId];
- this.$scope.selectedInstanceSiblings = instancesMappedList.filter(coInstance => coInstance.id !== this.$scope.currentComponent.selectedInstance.uniqueId);
- }
- }
-
- private initScope = ():void => {
- this.$scope.$watch('currentComponent.selectedInstance', (newInstance:ComponentInstance):void => {
- if (angular.isDefined(newInstance) && this.$scope.componentInstancesConstraints) {
- this.updateInstanceAttributes();
- this.$scope.selectedInstanceConstraints = this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId] ?
- this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId].properties :
- [];
- }
- });
- this.$scope.$watch('componentInstancesConstraints', (constraints: Array<any>):void => {
- if (angular.isDefined(constraints)) {
- if(this.$scope.isComponentInstanceSelected()) {
- this.$scope.selectedInstanceConstraints = this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId] ?
- this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId].properties || [] :
- [];
- }
- }
- });
-
- this.$scope.updateSelectedInstanceConstraints = (constraintsList:Array<ConstraintObject>):void => {
- this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId].properties = constraintsList;
- this.$scope.selectedInstanceConstraints = this.$scope.componentInstancesConstraints[this.$scope.currentComponent.selectedInstance.uniqueId].properties;
- }
-
- this.$scope.loadConstraints = ():void => {
- this.loadConstraints();
- }
-
- this.$scope.registerCreateInstanceEvent(() => {
- this.initInstancesWithProperties();
- });
-
- this.$scope.registerChangeComponentInstanceNameEvent((updatedComponentInstance) => {
- this.$scope.currentComponent.selectedInstance = updatedComponentInstance;
- });
-
- this.$scope.$on('$destroy', this.$scope.unregisterCreateInstanceEvent);
- this.$scope.$on('$destroy', this.$scope.unregisterChangeComponentInstanceNameEvent);
- }
-
- private loadConstraints = ():void => {
- this.ComponentServiceNg2.getServiceFilterConstraints(this.$scope.service).subscribe((response) => {
- this.$scope.componentInstancesConstraints = response.nodeFilterData;
- });
- }
-
- public notifyDependencyEventsObserver = (isChecked: boolean):void => {
- this.eventListenerService.notifyObservers(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, isChecked);
- }
-}
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view.html
deleted file mode 100644
index ba50994..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-dependencies/service-dependencies-view.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-<perfect-scrollbar class="w-sdc-designer-sidebar-tab-content service-dependencies">
- <div class="w-sdc-designer-sidebar-section">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content"
- class="w-sdc-designer-sidebar-section-title">
- <span class="w-sdc-designer-sidebar-section-title-text" tooltips tooltip-content="Service Dependencies">Service Dependencies</span>
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
- <div class="w-sdc-designer-sidebar-section-content" data-ng-if="isComponentInstanceSelected()">
- <div class="i-sdc-designer-sidebar-section-content-item">
- <ng2-service-dependencies
- [composite-service]="service"
- [current-service-instance]="currentComponent.selectedInstance"
- [selected-instance-properties]="selectedInstanceProperties"
- [selected-instance-siblings]="selectedInstanceSiblings"
- [selected-instance-constraints]="selectedInstanceConstraints"
- [readonly]="isViewMode() || !isDesigner()"
- (dependency-status)="notifyDependencyEventsObserver($event)"
- (update-rules-list-event)="updateSelectedInstanceConstraints($event)"
- (load-rules-list-event)="loadConstraints()">
- </ng2-service-dependencies>
- </div>
- </div>
- </div>
-</perfect-scrollbar>
\ No newline at end of file
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.html
deleted file mode 100644
index 4d89625..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/structure/structure-view.html
+++ /dev/null
@@ -1,29 +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.
--->
-
-<perfect-scrollbar include-padding="true" class="w-sdc-designer-sidebar-tab-content">
-
- <div class="w-sdc-designer-sidebar-section">
- <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content" class="w-sdc-designer-sidebar-section-title">
- Composition
- <div class="w-sdc-designer-sidebar-section-title-icon"></div>
- </expand-collapse>
-
- <div class="w-sdc-designer-sidebar-section-content" ng-show="selectedComponent.isComplex()">
- <structure-tree component="selectedComponent"></structure-tree>
- </div>
- </div>
-</perfect-scrollbar>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-description-popover.html b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-description-popover.html
deleted file mode 100644
index 94c28a0..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-description-popover.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
--->
-
-<!-- Description Popover -->
-<div >
- <span data-tests-id='popover-x-button' data-ng-click='closeDescriptionPopover()' class='tlv-sprite tlv-x-btn close-popover-btn'></span>
- <div class="w-sdc-form-item" ng-form="descriptionForm" data-ng-class="{error:(descriptionForm.$dirty && descriptionForm.$invalid)}">
- <textarea class="i-sdc-form-textarea {{$index}}" data-ng-class="{'view-mode': isViewMode()}"
- data-ng-maxlength="256"
- maxlength="256"
- data-ng-required="true"
- name="description"
- data-ng-model="artifact.description"
- data-ng-model-options="{ debounce: 200 }"
- data-ng-pattern="getValidationPattern('string')"
- ng-readonly="isViewMode()"
- data-tests-id="description">
- </textarea>
-
- <div class="input-error" data-ng-show="descriptionForm.$dirty && descriptionForm.$invalid">
- <span ng-show="descriptionForm.$error.required" translate="ADD_ARTIFACT_ERROR_DESCRIPTION_REQUIRED"></span>
- <span ng-show="descriptionForm.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
- <span ng-show="descriptionForm.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
- </div>
- </div>
-</div>
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
deleted file mode 100644
index fc3de6e..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model.ts
+++ /dev/null
@@ -1,352 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Nokia. 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=========================================================
- */
-
-//@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";
-import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service";
-import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response";
-import {GenericArtifactBrowserComponent} from "../../../../ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component";
-import {PathsAndNamesDefinition} from "../../../../models/paths-and-names";
-import {ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service";
-import {IModalConfig} from "sdc-ui/lib/angular/modals/models/modal-config";
-import {CacheService} from "../../../../services/cache-service";
-import {GabConfig} from "../../../../models/gab-config";
-
-interface IDeploymentArtifactsViewModelScope extends IWorkspaceViewModelScope {
- tableHeadersList:Array<any>;
- reverse:boolean;
- sortBy:string;
- artifacts:Array<ArtifactModel>;
- editForm:ng.IFormController;
- isLoading:boolean;
- artifactDescriptions:any;
- selectedArtifactId:string;
- popoverTemplate:string;
-
- addOrUpdate(artifact:ArtifactModel):void;
- updateSelectedArtifact():void;
- delete(artifact:ArtifactModel):void;
- sort(sortBy:string):void;
- noArtifactsToShow():boolean;
- getValidationPattern(validationType:string, parameterType?:string):RegExp;
- validateJson(json:string):boolean;
- resetValue(parameter:any):void;
- viewModeOrCsarComponent():boolean;
- isLicenseArtifact(artifact:ArtifactModel):void;
- getEnvArtifact(heatArtifact:ArtifactModel):ArtifactModel;
- getEnvArtifactName(artifact:ArtifactModel):string;
- openEditEnvParametersModal(artifact:ArtifactModel):void;
- openDescriptionPopover(artifactId:string):void;
- closeDescriptionPopover():void;
-}
-
-export class DeploymentArtifactsViewModel {
-
- static '$inject' = [
- '$scope',
- '$templateCache',
- '$filter',
- 'Sdc.Services.CacheService',
- 'ValidationUtils',
- 'ArtifactsUtils',
- 'ModalsHandler',
- 'ComponentServiceNg2',
- 'ModalServiceSdcUI'
- ];
-
- constructor(private $scope:IDeploymentArtifactsViewModelScope,
- private $templateCache:ng.ITemplateCacheService,
- private $filter:ng.IFilterService,
- private cacheService:CacheService,
- private validationUtils:ValidationUtils,
- private artifactsUtils:ArtifactsUtils,
- private ModalsHandler:ModalsHandler,
- private ComponentServiceNg2: ComponentServiceNg2,
- private ModalServiceSdcUI: ModalServiceSdcUI) {
- this.initScope();
- }
-
- private initDescriptions = ():void => {
- this.$scope.artifactDescriptions = {};
- _.forEach(this.$scope.component.deploymentArtifacts, (artifact:ArtifactModel):void => {
- this.$scope.artifactDescriptions[artifact.artifactLabel] = artifact.description;
- });
- };
-
- private setArtifact = (artifact:ArtifactModel):void => {
- if (!artifact.description || !this.$scope.getValidationPattern('string').test(artifact.description)) {
- artifact.description = this.$scope.artifactDescriptions[artifact.artifactLabel];
- }
- };
-
- private initScopeArtifacts = ()=> {
- this.$scope.artifacts = <ArtifactModel[]>_.values(this.$scope.component.deploymentArtifacts);
- _.forEach(this.$scope.artifacts, (artifact:ArtifactModel):void => {
- artifact.envArtifact = this.getEnvArtifact(artifact);
- });
- };
-
- private initArtifacts = (loadFromServer:boolean):void => {
- if (loadFromServer) {
- this.$scope.isLoading = true;
- this.ComponentServiceNg2.getComponentDeploymentArtifacts(this.$scope.component).subscribe((response:ComponentGenericResponse) => {
- this.$scope.component.deploymentArtifacts = response.deploymentArtifacts;
- this.initScopeArtifacts();
- this.$scope.isLoading = false;
- });
- } else {
- this.initScopeArtifacts();
- }
-
- };
-
- private getEnvArtifact = (heatArtifact:ArtifactModel):ArtifactModel=> {
- return _.find(this.$scope.artifacts, (item:ArtifactModel)=> {
- return item.generatedFromId === heatArtifact.uniqueId;
- });
- };
-
- private getCurrentArtifact = ():ArtifactModel => {
- if (!this.$scope.selectedArtifactId) {
- return null;
- }
- let artifact:ArtifactModel = this.$scope.artifacts.filter((art) => {
- return art.uniqueId == this.$scope.selectedArtifactId;
- })[0];
- return artifact;
- }
-
- private initScope = ():void => {
- let self = this;
- this.$scope.isLoading = false;
- this.$scope.selectedArtifactId = null;
- this.initDescriptions();
- if(this.$scope.component.deploymentArtifacts) {
- this.initArtifacts(false);
- } else {
- this.initArtifacts(true);
- }
- this.$scope.setValidState(true);
-
- this.$scope.tableHeadersList = [
- {title: 'Name', property: 'artifactDisplayName'},
- {title: 'Type', property: 'artifactType'},
- {title: 'Deployment timeout', property: 'timeout'},
- {title: 'Version', property: 'artifactVersion'},
- {title: 'UUID', property: 'artifactUUID'}
- ];
-
- this.$templateCache.put("deployment-artifacts-description-popover.html", require('app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-description-popover.html'));
- this.$scope.popoverTemplate = "deployment-artifacts-description-popover.html";
-
- this.$scope.isLicenseArtifact = (artifact:ArtifactModel):boolean => {
- let isLicense:boolean = false;
- if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
-
- isLicense = this.artifactsUtils.isLicenseType(artifact.artifactType);
- }
-
- return isLicense;
- };
-
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
-
- this.$scope.getValidationPattern = (validationType:string, parameterType?:string):RegExp => {
- return this.validationUtils.getValidationPattern(validationType, parameterType);
- };
-
- this.$scope.validateJson = (json:string):boolean => {
- if (!json) {
- return true;
- }
- return this.validationUtils.validateJson(json);
- };
-
- this.$scope.viewModeOrCsarComponent = ():boolean => {
- return this.$scope.isViewMode() || (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent());
- };
-
- this.$scope.addOrUpdate = (artifact:ArtifactModel):void => {
- artifact.artifactGroupType = 'DEPLOYMENT';
- let artifactCopy = new ArtifactModel(artifact);
-
- let success = (response:any):void => {
- this.$scope.artifactDescriptions[artifactCopy.artifactLabel] = artifactCopy.description;
- this.initArtifacts(true);
- // this.$scope.artifacts = _.values(this.$scope.component.deploymentArtifacts);
- };
-
- let error = (err:any):void => {
- console.log(err);
- this.initArtifacts(true);
- // self.$scope.artifacts = _.values(self.$scope.component.deploymentArtifacts);
- };
-
- this.ModalsHandler.openArtifactModal(artifactCopy, this.$scope.component).then(success, error);
- };
-
- this.$scope.noArtifactsToShow = ():boolean => {
- return !_.some(this.$scope.artifacts, 'esId');
- };
-
- this.$scope.resetValue = (parameter:any):void => {
- if (!parameter.currentValue && parameter.defaultValue) {
- parameter.currentValue = parameter.defaultValue;
- }
- else if ('boolean' == parameter.type) {
- parameter.currentValue = parameter.currentValue.toUpperCase();
- }
- };
-
- this.$scope.$watch('editForm.$valid', ():void => {
- if (this.$scope.editForm) {
- // this.$scope.setValidState(this.$scope.editForm.$valid);
- }
- });
-
- this.$scope.updateSelectedArtifact = ():void => {
- if (!this.$scope.isViewMode() && !this.$scope.isLoading) {
- let artifact:ArtifactModel = this.getCurrentArtifact();
- this.setArtifact(artifact); //resets artifact description to original value if invalid.
- if (artifact && artifact.originalDescription != artifact.description) {
- this.$scope.isLoading = true;
- let onSuccess = (responseArtifact:ArtifactModel):void => {
- this.$scope.artifactDescriptions[responseArtifact.artifactLabel] = responseArtifact.description;
- // this.$scope.artifacts = _.values(this.$scope.component.deploymentArtifacts);
- this.initArtifacts(true);
- this.$scope.isLoading = false;
- };
-
- let onFailed = (error:any):void => {
- console.log('Delete artifact returned error:', error);
- this.$scope.isLoading = false;
- };
-
- this.$scope.component.addOrUpdateArtifact(artifact).then(onSuccess, onFailed);
- }
- }
- };
-
- this.$scope.delete = (artifact:ArtifactModel):void => {
- let onOk = ():void => {
- this.$scope.isLoading = true;
- let onSuccess = ():void => {
- this.$scope.isLoading = false;
- this.initArtifacts(true);
- //this.$scope.artifacts = _.values(this.$scope.component.deploymentArtifacts);
- };
-
- let onFailed = (error:any):void => {
- this.$scope.isLoading = false;
- console.log('Delete artifact returned error:', error);
- };
-
- this.$scope.component.deleteArtifact(artifact.uniqueId, artifact.artifactLabel).then(onSuccess, onFailed);
- };
-
- let title:string = self.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TITLE");
- let message:string = self.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TEXT", "{'name': '" + artifact.artifactDisplayName + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
-
- this.$scope.getEnvArtifactName = (artifact:ArtifactModel):string => {
- let envArtifact = this.$scope.getEnvArtifact(artifact);
- if (envArtifact) {
- return envArtifact.artifactDisplayName;
- }
- };
-
- this.$scope.openGenericArtifactBrowserModal = (artifact:ArtifactModel):void => {
- let self = this;
- const title = 'Generic Artifact Browser';
- let modalConfig: IModalConfig = {
- size: 'xl',
- title: title,
- type: 'custom',
- buttons: [{
- id: 'closeGABButton',
- text: 'Close',
- size: "'x-small'",
- closeModal: true
- }]
- };
-
- const uiConfiguration: any = this.cacheService.get('UIConfiguration');
- let noConfig: boolean = false;
- let pathsandnames: PathsAndNamesDefinition[] = [];
-
- if(typeof uiConfiguration.gab === 'undefined') {
- noConfig = true;
- } else {
- const gabConfig: GabConfig = uiConfiguration.gab
- .find(config => config.artifactType === artifact.artifactType);
- if(typeof gabConfig === 'undefined') {
- noConfig = true;
- } else {
- pathsandnames = gabConfig.pathsAndNamesDefinitions;
- }
- }
-
- if(noConfig) {
- const msg = self.$filter('translate')("DEPLOYMENT_ARTIFACT_GAB_NO_CONFIG");
- this.ModalServiceSdcUI.openAlertModal(title, msg);
- }
-
- const modalInputs = {
- pathsandnames: pathsandnames,
- artifactid: artifact.esId,
- resourceid: this.$scope.component.uniqueId
- };
-
- this.ModalServiceSdcUI.openCustomModal(modalConfig, GenericArtifactBrowserComponent, modalInputs);
- };
-
- this.$scope.openEditEnvParametersModal = (artifact:ArtifactModel):void => {
- this.ModalsHandler.openEditEnvParametersModal(artifact, this.$scope.component).then(()=> {
- this.initArtifacts(true);
- }, ()=> {
- this.initArtifacts(true);
- });
- };
-
- this.$scope.openDescriptionPopover = (artifactId:string):void => {
- if (this.$scope.selectedArtifactId && this.$scope.selectedArtifactId != artifactId) {
- this.$scope.updateSelectedArtifact();
- }
- this.$scope.selectedArtifactId = artifactId;
-
- };
-
- this.$scope.closeDescriptionPopover = ():void => {
- if (this.$scope.selectedArtifactId) {
- this.$scope.updateSelectedArtifact();
- this.$scope.selectedArtifactId = null;
- }
- };
- };
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view.html
deleted file mode 100644
index a26bcde..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!--
- ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- ~ Modifications Copyright (C) 2019 Nokia. 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-deployment-artifact">
-
- <div data-tests-id="add-deployment-artifact-button" ng-if="!isViewMode()" data-ng-class="{'disabled': isDisableMode()}" data-tests-id="add-property-button" class="add-btn" data-ng-click="addOrUpdate({})">Add</div>
-
- <div class="table-container-flex">
-
- <div class="table" data-ng-class="{'view-mode': isViewMode()}">
- <loader data-display="isLoading"></loader>
- <div class="head flex-container">
- <div class="table-header head-row hand flex-item" data-ng-repeat="header in tableHeadersList track by $index" data-ng-click="sort(header.property)">{{header.title}}
- <span data-ng-if="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- <div class="table-no-text-header head-row flex-item"></div>
- </div>
-
- <form class="body" name="editForm">
-
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
-
- <!-- Artifact row -->
- <div ng-if="noArtifactsToShow()" data-ng-class="{'disabled': isDisableMode()}" class="no-row-text" translate="DEPLOYMENT_ARTIFACT_NO_ARTIFACTS_TO_DISPLAY"></div>
- <div data-ng-repeat-start="artifact in artifacts | orderBy:sortBy:reverse track by $index"
- class="flex-container data-row"
- data-ng-class="{'selected': selectedArtifactId == artifact.uniqueId }"
- data-ng-if="artifact.esId && 'HEAT_ENV' !== artifact.artifactType"
- data-tests-id="artifact-item-{{artifact.artifactDisplayName}}">
- <div class="table-col-general flex-item" >
- <div class="heat-env-connect-container" ng-class="{'heat-env-connect-container-view-mode': isViewMode()}" data-ng-if="artifact.envArtifact">
- <span class="heat-env-connect"></span>
- </div>
- <span data-tests-id="artifactDisplayName_{{artifact.artifactDisplayName}}" class="artifact-name text" tooltips tooltip-content="{{artifact.artifactDisplayName}}">{{artifact.artifactDisplayName}}</span>
-
- <span class="sprite-new show-desc hand description-popover-icon"
- uib-popover-template="popoverTemplate"
- popover-class="parameter-description-popover deployment-artifact-view top"
- popover-title="Description"
- popover-placement="auto top-left"
- popover-is-open="selectedArtifactId == artifact.uniqueId && !isLoading"
- popover-trigger="'none'"
- popover-append-to-body="false"
- data-ng-click="openDescriptionPopover(artifact.uniqueId)"
- data-tests-id="descriptionIcon_{{artifact.artifactDisplayName}}"></span>
- </div>
-
- <div class="table-col-general flex-item text" data-tests-id="artifactType_{{artifact.artifactDisplayName}}" tooltips tooltip-content="{{artifact.artifactType}}">
- {{artifact.artifactType}}
- </div>
- <div class="table-col-general flex-item" data-tests-id="timeout_{{artifact.artifactDisplayName}}">
- {{artifact.timeout? artifact.timeout:''}}
- </div>
- <div class="table-col-general flex-item" data-tests-id="artifactVersion_{{artifact.artifactDisplayName}}">
- {{artifact.artifactVersion}}
- </div>
- <div class="table-col-general flex-item text" data-tests-id="artifactUUID_{{artifact.artifactDisplayName}}" tooltips tooltip-content="{{artifact.artifactUUID}}">
- <span>{{artifact.artifactUUID}}</span>
- </div>
-
- <div class="table-btn-col flex-item">
- <button class="table-edit-btn" data-tests-id="edit_{{artifact.artifactDisplayName}}"
- data-ng-if="!isViewMode() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact)" data-ng-click="addOrUpdate(artifact)"></button>
- <button class="table-delete-btn" data-tests-id="delete_{{artifact.artifactDisplayName}}"
- data-ng-if="!isViewMode() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact)" data-ng-click="delete(artifact)"> </button>
- <button class="table-download-btn" download-artifact data-tests-id="download_{{artifact.artifactDisplayName}}"
- data-ng-if="artifact.artifactDisplayName" component="component" artifact="artifact"></button>
- <button ng-if="artifact.isGenericBrowseable()"
- class="table-magnifier-btn"
- data-ng-click="openGenericArtifactBrowserModal(artifact)" component="component" artifact="artifact"
- data-tests-id="gab-{{artifact.artifactDisplayName}}"></button>
- <button ng-if="!isViewMode() && artifact.isHEAT()"
- class="sprite e-sdc-small-icon-pad edit-paramtes-button"
- data-ng-click="openEditEnvParametersModal(artifact)" type="button"
- data-tests-id="edit-parameters-of-{{artifact.artifactDisplayName}}"></button>
- </div>
- </div>
- <div data-ng-repeat-end="" class="flex-container data-row" data-ng-if="artifact.envArtifact">
-
- <div class="table-col-general flex-item" zzdata-ng-click="!isViewMode() && addOrUpdate(artifact.envArtifact)">
- <span>{{artifact.envArtifact.artifactDisplayName}}</span>
- </div>
-
- <div class="table-col-general flex-item" data-tests-id="{{artifact.envArtifact.artifactType}}">
- {{artifact.envArtifact.artifactType}}
- </div>
- <div class="table-col-general flex-item" data-tests-id="{{artifact.envArtifact.timeout}}">
- {{artifact.envArtifact.timeout? artifact.envArtifact.timeout:''}}
- </div>
- <div class="table-col-general flex-item" data-tests-id="artifactEnvVersion_{{artifact.artifactDisplayName}}">
- {{artifact.envArtifact.artifactVersion}}
- </div>
- <div class="table-col-general flex-item text" data-tests-id="{{artifact.envArtifact.artifactUUID}}" tooltips tooltip-content="{{artifact.envArtifact.artifactUUID}}">
- <span>{{artifact.envArtifact.artifactUUID}}</span>
- </div>
-
-
- <div class="table-btn-col flex-item" >
- <button class="table-edit-btn" data-tests-id="edit_{{artifact.artifactLabel}}env"
- data-ng-if="!isViewMode()" data-ng-click="addOrUpdate(artifact.envArtifact)"></button>
- <button class="table-download-btn" data-tests-id="download_env_{{artifact.artifactDisplayName}}" download-artifact
- data-ng-if="artifact.artifactName" component="component" artifact="artifact.envArtifact"></button>
-
- </div>
- </div>
-
- <!--<div class="i-sdc-designer-sidebar-section-content-item-artifact-heat-env" ng-if="artifact.heatParameters.length">-->
- <!--<span class="enabled" data-ng-bind="getEnvArtifactName(artifact)" data-ng-click="!isViewMode() && addOrUpdate(getEnvArtifact(artifact))"></span>-->
- <!--<download-artifact class="i-sdc-designer-sidebar-section-content-item-button download-env sprite e-sdc-small-download hand" artifact="getEnvArtifact(artifact)"-->
- <!--component="currentComponent" instance="true"-->
- <!--data-tests-id="download"></download-artifact>-->
- <!--</div>-->
-
-
-
- <!-- Add artifacts buttons -->
- <!--<button class="add-button" data-ng-repeat="artifact in artifacts track by $index"-->
- <!--type="button"-->
- <!--data-ng-show="!artifact.esId"-->
- <!--data-ng-if="!viewModeOrCsarComponent()"-->
- <!--data-ng-class="{'disabled': isDisableMode() || component.isCsarComponent()}"-->
- <!--data-tests-id="{{artifact.artifactDisplayName}} deployment_artifact"-->
- <!--translate="DEPLOYMENT_ARTIFACT_BUTTON_ADD_HEAT"-->
- <!--translate-values="{'name': '{{artifact.artifactDisplayName}}'}"-->
- <!--data-ng-click="addOrUpdate(artifact)"></button>-->
-
- <!-- Top add button -->
- <button class="add-button" type="button" data-ng-if="!isViewMode()" data-ng-class="{'disabled': isDisableMode()}" translate="DEPLOYMENT_ARTIFACT_BUTTON_ADD_OTHER" data-ng-click="addOrUpdate({})"></button>
- </perfect-scrollbar>
- </form>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less
deleted file mode 100644
index f67d088..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less
+++ /dev/null
@@ -1,201 +0,0 @@
-.workspace-deployment-artifact {
- width: 93%;
- display: inline-block;
- .table-container-flex .table .body .data-row + div.item-opened {
- align-items: center;
- padding: 10px 40px 10px 30px;
- }
-
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
-
- .heat-env-connect-container{
- background-color: white;
- position: absolute;
- height: 70px;
- width:20px;
- left: 0;
- top:0;
- }
- .heat-env-connect-container-view-mode{
- background-color: @tlv_color_t;
- }
- .heat-env-connect{
- border-left: 1px #848586 solid;
- height: 50px;
- margin-left: 10px;
- margin-top: 10px;
- border-top: 1px #848586 solid;
- border-bottom: 1px #848586 solid;
- width: 11px;
- float: left;
-
- }
-
- .artifact-name{
- width:85%;
- }
-
- .table-container-flex .table .body .data-row div .heat-env-connect-container{
- border-right: none;
- }
-
- .i-sdc-designer-sidebar-section-content-item-file-link::before{
- content:"";
- background-color: white;
- width: 12px;
-
- }
-
-
-
- .table {
- height:490px;
- margin-bottom: 0;
- }
-
- .parameter-description {
- .circle(18px, @color_p);
- content: '?';
- line-height: 18px;
- vertical-align: middle;
- margin-left: 5px;
- cursor: default;
- display: inline-block;
- position: absolute;
- top: 16px;
- }
-
- .table-container-flex {
-
- margin-top: 0;
-
- .text{
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- white-space: nowrap;
- }
-
- .flex-item:nth-child(1) {
- flex-grow: 15;
- .hand;
- padding-left: 30px;
- position: relative;
- span.table-arrow {
- margin-right: 7px;
- }
- .description-popover-icon{
- float:right;
- margin-top:6px;
- }
- }
-
- .flex-item:nth-child(2) {
- flex-grow: 6;
- }
-
- .flex-item:nth-child(3) {
- flex-grow: 9;
- }
-
- .flex-item:nth-child(4) {
- flex-grow: 3;
- }
-
- .flex-item:nth-child(5) {
- flex-grow: 20;
- }
-
- .flex-item:nth-child(6) {
- flex-grow: 5;
-
- &.table-btn-col {
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- button {
- flex: 0 1 auto;
- background-color: transparent;
- border: 0;
- margin: 0;
- }
- .edit-paramtes-button {
- order: -1;
- }
- }
- }
- }
- .w-sdc-form{
- text-align: left;
-
- .w-sdc-env-params{
- border-top: 1px solid #cdcdcd;
- margin: 25px 0 10px 0;
- }
-
- .i-sdc-form-textarea {
- border: 1px solid @color_e;
- min-height: 60px;
- padding: 10px 13px;
- width: 100%;
- resize: none;
-
- }
-
- .w-sdc-form-item {
- &.error {
- .i-sdc-form-input,
- .i-sdc-form-select,
- .i-sdc-form-textarea {
- border-color: @color_h;
- outline: none;
- box-sizing: border-box;
- }
- }
- }
-
- .i-sdc-env-form-label{
- font-family: @font-opensans-medium;
- color: @main_color_m;
- overflow: hidden;
- max-width: 450px;
- text-overflow: ellipsis;
- display: inline-block;
- white-space: nowrap;
- margin-top: 14px;
-
- &.required::before {
- color: #f33;
- content: '*';
- margin-right: 4px;
- }
- }
- }
-}
-
-.table-container-flex .table .body .scrollbar-container {
- overflow-x:auto !important; //need to override the overflow-hidden for the table so that the popover auto positioning works
- min-height: 400px;
-}
-
-.parameter-description-popover.deployment-artifact-view {
- margin-left: -22px;
- z-index: 1040;
- min-width: 300px;
- .input-error {
- .q_12_m;
- }
- .error textarea{
- border-color: @main_color_g;
- color: @color_h;
- outline: none;
- }
- .popover-content textarea {
- width:100%;
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view-model.ts
deleted file mode 100644
index 9df377c..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view-model.ts
+++ /dev/null
@@ -1,146 +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=========================================================
- */
-
-'use strict';
-import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
-import {ComponentFactory, MenuHandler, ChangeLifecycleStateHandler, ModalsHandler} from "app/utils";
-import {LeftPaletteLoaderService, CacheService, SharingService} from "app/services";
-import {Component, IAppMenu, Tab, ComponentInstance} from "app/models";
-import {GRAPH_EVENTS} from "../../../../utils/constants";
-import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response";
-import {EventListenerService} from "../../../../services/event-listener-service";
-import {ComponentServiceNg2} from "../../../../ng2/services/component-services/component.service";
-
-export interface IDeploymentViewModelScope extends IWorkspaceViewModelScope {
-
- currentComponent:Component;
- selectedComponent:Component;
- isLoading:boolean;
- sharingService:SharingService;
- sdcMenu:IAppMenu;
- version:string;
- isViewOnly:boolean;
- tabs:Array<Tab>;
- selectedTab: Tab;
- isComponentInstanceSelected():boolean;
- updateSelectedComponent():void
- openUpdateModal();
- deleteSelectedComponentInstance():void;
- onBackgroundClick():void;
- setSelectedInstance(componentInstance:ComponentInstance):void;
- printScreen():void;
-
-}
-
-export class DeploymentViewModel {
-
- static '$inject' = [
- '$scope',
- '$templateCache',
- 'sdcMenu',
- 'MenuHandler',
- '$state',
- 'Sdc.Services.SharingService',
- '$filter',
- 'Sdc.Services.CacheService',
- 'ComponentFactory',
- 'ChangeLifecycleStateHandler',
- 'LeftPaletteLoaderService',
- 'ModalsHandler',
- 'EventListenerService',
- 'ComponentServiceNg2'
- ];
-
- constructor(private $scope:IDeploymentViewModelScope,
- private $templateCache:ng.ITemplateCacheService,
- private sdcMenu:IAppMenu,
- private MenuHandler:MenuHandler,
- private $state:ng.ui.IStateService,
- private sharingService:SharingService,
- private $filter:ng.IFilterService,
- private cacheService:CacheService,
- private ComponentFactory:ComponentFactory,
- private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
- private LeftPaletteLoaderService:LeftPaletteLoaderService,
- private ModalsHandler:ModalsHandler,
- private eventListenerService: EventListenerService,
- private ComponentServiceNg2: ComponentServiceNg2) {
-
- this.$scope.setValidState(true);
- this.initScope();
- this.initGraphData();
- }
-
-
- private initComponent = ():void => {
-
- this.$scope.currentComponent = this.$scope.component;
- this.$scope.selectedComponent = this.$scope.currentComponent;
- this.updateUuidMap();
- this.$scope.isViewOnly = this.$scope.isViewMode();
- };
-
-
- private updateUuidMap = ():void => {
- /**
- * In case user press F5, the page is refreshed and this.sharingService.currentEntity will be undefined,
- * but after loadService or loadResource this.sharingService.currentEntity will be defined.
- * Need to update the uuidMap with the new resource or service.
- */
- this.sharingService.addUuidValue(this.$scope.currentComponent.uniqueId, this.$scope.currentComponent.uuid);
- };
-
- private initRightTabs = ()=> {
- if (this.$scope.currentComponent.modules) {
- this.$templateCache.put("hierarchy-view.html", require('app/view-models/tabs/hierarchy/hierarchy-view.html'));
- let hierarchyTab = new Tab("hierarchy-view.html", 'Sdc.ViewModels.HierarchyViewModel', 'hierarchy', this.$scope.isViewMode(), this.$scope.currentComponent, 'hierarchy');
- this.$scope.tabs.push(hierarchyTab)
- }
- }
-
- private initGraphData = ():void => {
- if(!this.$scope.component.componentInstances || !this.$scope.component.componentInstancesRelations || !this.$scope.component.modules) {
- this.ComponentServiceNg2.getDeploymentGraphData(this.$scope.component).subscribe((response:ComponentGenericResponse) => {
- this.$scope.component.componentInstances = response.componentInstances;
- this.$scope.component.componentInstancesRelations = response.componentInstancesRelations;
- this.$scope.component.modules = response.modules;
- this.$scope.isLoading = false;
- this.initComponent();
- this.initRightTabs();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED);
- this.$scope.selectedTab = this.$scope.tabs[0];
- });
- } else {
- this.$scope.isLoading = false;
- this.initRightTabs();
- this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED);
-
- }
- };
-
- private initScope = ():void => {
- this.$scope.isLoading = true;
- this.$scope.sharingService = this.sharingService;
- this.$scope.sdcMenu = this.sdcMenu;
- this.$scope.version = this.cacheService.get('version');
- this.initComponent();
- this.$scope.tabs = Array<Tab>();
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view.html b/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view.html
deleted file mode 100644
index aae0313..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment-view.html
+++ /dev/null
@@ -1,26 +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="deployment-view">
- <loader display="isLoading"></loader>
- <div class="w-sdc-deployment-canvas" data-ng-class="{sidebaractive: displayDesignerRightSidebar}">
- <deployment-graph component="currentComponent" is-view-only="isViewOnly"></deployment-graph>
- </div>
-
- <div class="w-sdc-deployment-right-bar">
- <ng1-tabs tabs="tabs" is-view-only="isViewOnly" selected-tab="selectedTab"></ng1-tabs>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment.less b/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment.less
deleted file mode 100644
index f51ff62..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/deployment/deployment.less
+++ /dev/null
@@ -1,34 +0,0 @@
-.deployment-view {
-
- display: inline-block;
- text-align: left;
- align-items: left;
- padding: 0;
- width: 100%;
- height: 100%;
-
- .w-sdc-deployment-canvas {
- .noselect;
- .bg_c;
- position: relative;
- bottom: 0;
- width: 100%;
- height: 100%;
- z-index: 0;
-
- .view-mode{
- background-color: #f8f8f8;
- border:0;
- }
- }
-
- .w-sdc-deployment-right-bar {
-
- .noselect;
- bottom: 0;
- position: absolute;
- right: 0px;
- transition: right 0.2s;
- top: @action_nav_height;
- }
-}
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
deleted file mode 100644
index eab06f2..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model.ts
+++ /dev/null
@@ -1,104 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {Distribution, DistributionComponent, ExportExcel} from "app/models";
-
-interface IDistributionStatusModalViewModelScope {
- distribution:Distribution;
- status:string;
- getStatusCount(distributionComponent:Array<DistributionComponent>):any;
- getUrlName(url:string):string;
- modalDitributionStatus:ng.ui.bootstrap.IModalServiceInstance;
- footerButtons:Array<any>;
- //exportExcelData:ExportExcel;
- close():void;
- initDataForExportExcel():ExportExcel;
-}
-
-export class DistributionStatusModalViewModel {
-
- static '$inject' = ['$scope', '$uibModalInstance', 'data', '$filter'];
-
- constructor(private $scope:IDistributionStatusModalViewModelScope,
- private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
- private data:any,
- private $filter:ng.IFilterService) {
- this.initScope();
- }
-
- private generateMetaDataForExportExcel = ():Array<string>=> {
- let metaData = [];
- metaData[0] = 'Name:' + this.data.component.name + '| UUID:' + this.data.component.uuid + '| Invariant UUID:' + this.data.component.invariantUUID;
- metaData[1] = 'Distribution ID:' + this.$scope.distribution.distributionID +
- '| USER ID:' + this.$scope.distribution.userId +
- '| Time[UTC]:' + this.$filter('date')(this.$scope.distribution.timestamp, 'MM/dd/yyyy h:mma', 'UTC') +
- '| Status:' + this.$scope.distribution.deployementStatus;
- return metaData;
- };
-
- private generateDataObjectForExportExcel = ():any=> {
- let correctFormatDataObj = [];
- _.each(this.$scope.distribution.distributionComponents, (dComponent:DistributionComponent) => {
- if (dComponent.status == this.$scope.status) {
- correctFormatDataObj.push({
- 'omfComponentID': dComponent.omfComponentID,
- 'artiFactName': this.$scope.getUrlName(dComponent.url),
- 'url': dComponent.url,
- 'timestamp': this.$filter('date')(dComponent.timestamp, 'MM/dd/yyyy h:mma', 'UTC'),
- 'status': dComponent.status
- });
- }
- });
- return correctFormatDataObj;
- };
-
- private initScope = ():void => {
- this.$scope.distribution = this.data.distribution;
- this.$scope.status = this.data.status;
- this.$scope.modalDitributionStatus = this.$uibModalInstance;
-
-
- this.$scope.getUrlName = (url:string):string => {
- let urlName:string = _.last(url.split('/'));
- return urlName;
- };
-
- this.$scope.initDataForExportExcel = ():ExportExcel => {
- let exportExcelData = new ExportExcel();
- exportExcelData.fileName = this.$scope.status;
- exportExcelData.groupByField = "omfComponentID";
- exportExcelData.tableHeaders = ["Component ID", "Artifact Name", "URL", "Time(UTC)", "Status"];
- exportExcelData.metaData = this.generateMetaDataForExportExcel();
- exportExcelData.dataObj = this.generateDataObjectForExportExcel();
- return exportExcelData;
- };
-
- this.$scope.close = ():void => {
- this.$uibModalInstance.close();
- };
-
- this.$scope.footerButtons = [
- {'name': 'Close', 'css': 'blue', 'callback': this.$scope.close}
- ];
-
- };
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view.html b/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view.html
deleted file mode 100644
index 0e58959..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view.html
+++ /dev/null
@@ -1,146 +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.
--->
-
-<ng1-modal modal="modalDitributionStatus" type="classic" class="w-sdc-classic-top-line-modal" buttons="footerButtons" header="Distribution by Status" show-close-button="true">
-
- <div class="w-sdc-distribution-view">
- <div class="w-sdc-distribution-view-header">
-
- </div>
-
- <div class="actions-buttons">
- <json-export-excel init-export-excel-data="initDataForExportExcel()">
- </json-export-excel>
- </div>
-
- <perfect-scrollbar include-padding="true" class="w-sdc-distribution-view-content">
- <div class="w-sdc-distribution-view-content-section w-sdc-distribute-parent-block">
- <ul>
- <li class="w-sdc-distribute-parent-block" >
- <div class="w-sdc-distribute-row w-sdc-distribute-row-extends extends">
-
- <div class="w-sdc-distribute-row-content">
- <div class="w-sdc-distribute-content">
- <div class="title-section item-1">
- <div class="title">Distribution ID</div>
- <div data-ng-bind="distribution.distributionID"></div>
- </div>
- <div class="title-section item-2">
- <div class="title" translate="DISTRIBUTION_VIEW_TITLE_USER_ID"></div>
- <div data-ng-bind="distribution.userId"></div>
- </div>
- <div class="title-section item-3">
- <div class="title">Time[UTC]:</div>
- <div
- data-ng-bind="distribution.timestamp | stringToDateFilter | date: 'MM/dd/yyyy h:mma':'UTC'"></div>
- </div>
- <div class="title-section item-4">
- <span class="sprite-new status-icon" data-ng-class="distribution.deployementStatus"></span>
- <span class="sprite-new" data-ng-bind="distribution.deployementStatus"></span>
- </div>
- </div>
- <div class="w-sdc-distribute-status-block" data-ng-show="distribution.statusCount">
- <div class="status-item-1">Status: {{status}} <span data-ng-bind="(distribution.distributionComponents | filter:status:true).length"
- class="blue-font"></span></div>
-
- </div>
- </div>
- </div>
-
- <ul class="w-sdc-distribute-components-block disable-hover">
- <li data-ng-repeat="(omfComponentID,omfComponentList) in distribution.distributionComponents | orderBy: '-timestamp' | filter:status:true | groupBy:'omfComponentID'"
- class="disable-hover">
- <div class="w-sdc-distribute-row omf-component-row w-sdc-distribute-row-extends "
- data-ng-class="{'extends': omfComponentListExtends}">
- <div class="w-sdc-distribution-arrow-btn" data-ng-click="omfComponentListExtends=!omfComponentListExtends"
- ng-class="{'extends': omfComponentListExtends}"
- data-ng-init="omfComponentListExtends=false"
- ></div>
- <div class="w-sdc-distribute-status-block">
- <div class="status-item-1">{{omfComponentID}} <span class="blue-font">{{omfComponentList.length}}</span>
- </div>
- </div>
- </div>
- <div data-ng-show="omfComponentListExtends"
- class="w-sdc-distribute-omfComponent-block disable-hover">
- <div class="w-sdc-distribute-row-extends disable-hover">
- <div class="disable-hover">
- <div class="w-sdc-distribute-row omfComponent-table-head">
- <div class="title item-1">Component ID</div>
- <div class="title item-2">Artifact Name</div>
- <div class="title item-3">URL</div>
- <div class="title item-4">Time(UTC)</div>
- <div class="title item-5">Status</div>
- </div>
-
- <div class="w-sdc-distribute-row omfComponent-table-row"
- data-ng-repeat-start="(url,urlList) in omfComponentList | orderBy: '-timestamp' | groupBy:'url'"
- data-ng-class="urlListExtends?'extends row-{{$index}}':'row-{{$index}}'" >
- <div class="w-sdc-distribute-cell item-1">
- <div class="w-sdc-distribution-arrow-btn" data-ng-click="urlListExtends=!urlListExtends"
- data-ng-class="{'extends': urlListExtends}"
- data-ng-init="urlListListExtends=false"
- ></div>
- {{urlList[0].omfComponentID}}
- </div>
- <div class="w-sdc-distribute-cell item-2" sdc-smart-tooltip>
- {{getUrlName(urlList[0].url)}}
- </div>
- <div class="w-sdc-distribute-cell item-3 disable-hover">
- <div sdc-smart-tooltip class="distribution-url">{{urlList[0].url}}</div>
- <div sdc-smart-tooltip title="Copy url" clipboard text="urlList[0].url"
- class="sprite-new link-btn copy-link disable-hover"></div>
- </div>
- <div class="w-sdc-distribute-cell item-4"><span
- data-ng-bind="urlList[0].timestamp | date: 'MM/dd/yyyy h:mma':'UTC'"></span>
- </div>
- <div class="w-sdc-distribute-cell item-5">{{urlList[0].status}}</div>
- </div>
-
-
- <div data-ng-repeat-end data-ng-show="urlListExtends" class="disable-hover">
- <div class="w-sdc-distribute-row extends disable-hover">
- <ul data-ng-show="urlListExtends"
- class="w-sdc-distribute-url-block disable-hover">
- <li data-ng-repeat="distributionComponent in urlList | orderBy: '-timestamp'"
- class="disable-hover">
- <span
- data-ng-bind="distributionComponent.timestamp | date: 'MM/dd/yyyy h:mma':'UTC'"
- class="disable-hover"></span>
- <span
- class="disable-hover">{{distributionComponent.status}}</span>
- <span
- class="disable-hover reason" data-ng-show="distributionComponent.status == 'NOT_NOTIFIED'">Reason: Component has determined artifact is not needed.</span>
- <span
- class="disable-hover reason" data-ng-show="distributionComponent.errorReason">Reason: {{distributionComponent.errorReason}}</span>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- </div>
- </li>
- </ul>
- </li>
- </ul>
- </div>
-
- </perfect-scrollbar>
- </div>
-
-
-</ng1-modal>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal.less b/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal.less
deleted file mode 100644
index d167083..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal.less
+++ /dev/null
@@ -1,40 +0,0 @@
-.w-sdc-classic-top-line-modal {
-
- .w-sdc-modal-head {
- // border-bottom: none;
- }
- .w-sdc-distribution-view {
- .actions-buttons {
- height: 29px;
- padding: 0 25px 0 0px;
- span{
- float: right;
- }
- }
-
- .w-sdc-distribution-view-content {
- height: 500px;
- }
-
- .w-sdc-distribution-view-content-section {
-
- .w-sdc-distribute-parent-block {
- .w-sdc-distribute-components-block {
-
- .omf-component-row {
- .w-sdc-distribute-status-block {
- margin-left: 0;
- }
-
- }
- div {
- padding-left: 0;
- }
- }
-
- }
-
- }
- }
-}
-
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
deleted file mode 100644
index 47ec1fd..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view-model.ts
+++ /dev/null
@@ -1,131 +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=========================================================
- */
-
-'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";
-
-interface IDistributionViewModel extends IWorkspaceViewModelScope {
- modalDistribution:ng.ui.bootstrap.IModalServiceInstance;
- service:Service;
- distributions:Array<Distribution>;
- showComponents(distribution:Distribution):void;
- markAsDeployed(distribution:Distribution):void;
- getStatusCount(distributionComponent:Array<DistributionComponent>):any;
- initDistributions():void;
- getUrlName(url:string):string;
- close():void;
- openDisributionStatusModal:Function;
-}
-
-export class DistributionViewModel {
-
- static '$inject' = [
- '$scope',
- 'ModalsHandler'
-
- ];
-
- constructor(private $scope:IDistributionViewModel,
- private ModalsHandler:ModalsHandler) {
- this.initScope();
- this.$scope.setValidState(true);
- }
-
- private initScope = ():void => {
- this.$scope.service = <Service>this.$scope.component;
-
-
- // Open Distribution status modal
- this.$scope.openDisributionStatusModal = (distribution:Distribution, status:string):void => {
- this.ModalsHandler.openDistributionStatusModal(distribution, status, this.$scope.component).then(()=> {
- // OK
- }, ()=> {
- // ERROR
- });
- };
-
-
- this.$scope.showComponents = (distribution:Distribution):void => {
- let onError = (response) => {
- console.info('onError showComponents', response);
- };
- let onSuccess = (distributionComponents:Array<DistributionComponent>) => {
- distribution.distributionComponents = distributionComponents;
- distribution.statusCount = this.$scope.getStatusCount(distribution.distributionComponents);
- // distribution.components = this.aggregateDistributionComponent(distributionComponents);;
- };
- this.$scope.service.getDistributionsComponent(distribution.distributionID).then(onSuccess, onError);
- };
-
- this.$scope.getStatusCount = (distributionComponent:Array<DistributionComponent>):any => {
- return _.countBy(distributionComponent, 'status')
- };
-
- this.$scope.getUrlName = (url:string):string => {
- let urlName:string = _.last(url.split('/'));
- return urlName;
- };
-
- this.$scope.markAsDeployed = (distribution:Distribution):void => {
- let onError = (response) => {
- console.info('onError markAsDeployed', response);
- };
- let onSuccess = (result:any) => {
- distribution.deployementStatus = 'Deployed';
- };
- this.$scope.service.markAsDeployed(distribution.distributionID).then(onSuccess, onError);
-
- };
-
- this.$scope.initDistributions = ():void => {
- let onError = (response) => {
- console.info('onError initDistributions', response);
- };
- let onSuccess = (distributions:Array<Distribution>) => {
- this.$scope.distributions = distributions;
- };
- this.$scope.service.getDistributionsList().then(onSuccess, onError);
- };
-
- this.$scope.initDistributions();
-
- };
-
-
- private aggregateDistributionComponent = (distributionComponents:Array<DistributionComponent>):any => {
- let aggregateDistributions:Dictionary<string,Dictionary<string,Array<DistributionComponent>>> = new Dictionary<string,Dictionary<string,Array<DistributionComponent>>>();
- let tempAggregateDistributions:any = _.groupBy(distributionComponents, 'omfComponentID');
- let aa = new Dictionary<string,Array<DistributionComponent>>();
-
- let tempAggregate:any;
- _.forEach(tempAggregateDistributions, (distributionComponents:Array<DistributionComponent>, omfComponentID:string)=> {
-
- let urls:any = _.groupBy(distributionComponents, 'url');
- aggregateDistributions.setValue(omfComponentID, urls);
- // aggregateDistributions[omfComponentID] = ;
-
- });
- console.log(aggregateDistributions);
- return aggregateDistributions;
- };
-}
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
deleted file mode 100644
index babe5c2..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution-view.html
+++ /dev/null
@@ -1,198 +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="w-sdc-distribution-view">
- <div class="w-sdc-distribution-view-header">
- <div class="w-sdc-distribution-view-title">DISTRIBUTION <span data-ng-bind="'[' + distributions.length +']'"
- class="blue-font"></span></div>
- <div class="header-spacer"></div>
- <div class="top-search">
- <input type="text"
- style="width: auto;"
- class="search-text"
- data-tests-id="searchTextbox"
- placeholder="Search"
- data-ng-model="searchBind"
- data-tests-id="main-menu-input-search"
- ng-model-options="{ debounce: 500 }"/>
- <span class="w-sdc-search-icon magnification"></span>
- </div>
- <div class="sprite-new refresh-btn" data-tests-id="refreshButton" data-ng-click="initDistributions()" sdc-smart-tooltip=""
- title="Refresh"></div>
- </div>
-
-
- <perfect-scrollbar include-padding="true" class="w-sdc-distribution-view-content">
- <div class="w-sdc-distribution-view-content-section" data-tests-id="ditributionTable">
- <ul>
- <li data-ng-repeat="item in distributions | orderBy: '-timestamp' | filter:searchBind"
- data-ng-init="item.dateFormat = ( item.timestamp | stringToDateFilter | date: 'MM/dd/yyyy h:mma':'UTC' )"
- class="w-sdc-distribute-parent-block" data-tests-id="record_{{$index}}" data-ng-class="{'extends': item.showDetails}">
- <div class="w-sdc-distribute-row w-sdc-distribute-row-extends"
- data-ng-class="{'extends': item.showDetails && item.distributionComponents.length}">
- <div class="w-sdc-distribution-arrow-btn" data-tests-id="ShowRecordButton_{{$index}}" data-ng-click="showComponents(item); item.showDetails=!item.showDetails"
- data-ng-class="{'extends': item.showDetails}"
- ></div>
- <div class="w-sdc-distribute-row-content">
- <div class="w-sdc-distribute-content">
- <div class="title-section item-1">
- <div class="title">Distribution ID</div>
- <div data-ng-bind="item.distributionID"></div>
- </div>
- <div class="title-section item-2">
- <div class="title" translate="DISTRIBUTION_VIEW_TITLE_USER_ID"></div>
- <div data-ng-bind="item.userId"></div>
- </div>
- <div class="title-section item-3">
- <div class="title">Time[UTC]:</div>
- <div
- data-ng-bind="item.dateFormat"></div>
- </div>
- <div class="title-section item-4">
- <span class="sprite-new status-icon" data-ng-class="item.deployementStatus"></span>
- <span class="sprite-new" data-ng-bind="item.deployementStatus"></span>
- </div>
- <div>
- <div class="sprite-new distribution-bth item-5"
- data-ng-class="{'disable':item.deployementStatus==='Deployed'}"
- data-ng-click="(item.deployementStatus==='Deployed') || markAsDeployed(item)"></div>
- </div>
- </div>
- <div class="w-sdc-distribute-status-block" data-ng-if="item.statusCount">
- <div class="status-item-1">Total Artifacts:<span data-ng-bind="(item.statusCount.NOT_NOTIFIED || 0) + (item.statusCount.NOTIFIED || 0) "
- class="blue-font" data-tests-id="totalArtifacts_{{$index}}"></span></div>
- <div class="status-item-2 " ><sapn class="link" data-ng-click="openDisributionStatusModal(item,'NOTIFIED')">Notified:</sapn><span
- data-ng-bind="item.statusCount.NOTIFIED || 0" class="blue-font" data-tests-id="notified_{{$index}}"></span></div>
-
- <div class="status-item-3 link" ><sapn class="link" data-ng-click="openDisributionStatusModal(item,'DOWNLOAD_OK')">Downloaded:</sapn><span
- data-ng-bind="item.statusCount.DOWNLOAD_OK || 0" class="blue-font" data-tests-id="downloaded_{{$index}}"></span></div>
-
- <div class="status-item-4 link"><sapn class="link" data-ng-click="openDisributionStatusModal(item,'DEPLOY_OK')">Deployed:</sapn><span
- data-ng-bind="item.statusCount.DEPLOY_OK || 0" class="blue-font" data-tests-id="deployed_{{$index}}" ></span><span
- data-ng-class="{'deployed':(item.statusCount.DEPLOY_OK > 0)}"></span></div>
- <div class="status-item-5 link" ><sapn class="link" data-ng-click="openDisributionStatusModal(item,'NOT_NOTIFIED')">Not Notified:</sapn><span
- data-ng-bind="item.statusCount.NOT_NOTIFIED || 0" class="blue-font" data-tests-id="NotNotified_{{$index}}"></span></div>
- <div class="status-item-6"><sapn class="link" data-ng-click="openDisributionStatusModal(item,'DEPLOY_ERROR')" >Deploy Errors:</sapn><span
- data-ng-bind="item.statusCount.DEPLOY_ERROR || 0" class="red-font "></span><span
- data-ng-class="{'error':(item.statusCount.DEPLOY_ERROR > 0)}" data-tests-id="errors_{{$index}}"></span></div>
- <div class="status-item-7"><sapn class="link" data-ng-click="openDisributionStatusModal(item,'DOWNLOAD_ERROR')" >Download Errors:</sapn><span
- data-ng-bind="item.statusCount.DOWNLOAD_ERROR || 0" class="red-font "></span><span
- data-ng-class="{'error':(item.statusCount.DOWNLOAD_ERROR > 0)}" data-tests-id="errors_{{$index}}"></span></div>
- </div>
- </div>
- </div>
-
- <ul data-ng-if="item.showDetails && item.distributionComponents.length"
- class="w-sdc-distribute-components-block disable-hover">
-
- <li data-ng-repeat="(omfComponentID,omfComponentList) in ::item.distributionComponents | orderBy: '-timestamp' | filter:searchBind | groupBy:'omfComponentID' "
- class="disable-hover"
- data-ng-init="statusCount = getStatusCount(omfComponentList);">
- <div class="w-sdc-distribute-row omf-component-row w-sdc-distribute-row-extends"
- data-ng-class="{'extends': omfComponentListExtends}">
- <div class="w-sdc-distribution-arrow-btn" data-ng-click="omfComponentListExtends=!omfComponentListExtends"
- ng-class="{'extends': omfComponentListExtends}"
- data-ng-init="omfComponentListExtends=false"
- ></div>
- <div class="w-sdc-distribute-status-block">
- <div class="status-item-1">{{omfComponentID}} <span class="blue-font">{{(statusCount.NOT_NOTIFIED || 0) + (statusCount.NOTIFIED || 0) }}</span>
- </div>
- <div class="status-item-2">Notified:<span data-ng-bind="statusCount.NOTIFIED || 0"
- class="blue-font"></span></div>
- <div class="status-item-3">Downloaded:<span
- data-ng-bind="statusCount.DOWNLOAD_OK || 0" class="blue-font"></span></div>
- <div class="status-item-4">Deployed:<span data-ng-bind="statusCount.DEPLOY_OK || 0"
- class="blue-font"></span><span
- data-ng-class="{'deployed':(statusCount.DEPLOY_OK > 0)}"></span></div>
- <div class="status-item-5">Not Notified:<span
- data-ng-bind="statusCount.NOT_NOTIFIED || 0" class="blue-font"></span></div>
- <div class="status-item-6">Deploy Errors:<span
- data-ng-bind="statusCount.DEPLOY_ERROR || 0" class="red-font"></span><span
- data-ng-class="{'error':(statusCount.DEPLOY_ERROR > 0)}"></span></div>
- <div class="status-item-7">Download Errors:<span
- data-ng-bind="statusCount.DOWNLOAD_ERROR || 0" class="red-font"></span><span
- data-ng-class="{'error':(statusCount.DOWNLOAD_ERROR > 0)}"></span></div>
- </div>
- </div>
- <div data-ng-if="omfComponentListExtends"
- class="w-sdc-distribute-omfComponent-block disable-hover">
- <div class="w-sdc-distribute-row-extends disable-hover">
- <div class="disable-hover">
- <div class="w-sdc-distribute-row omfComponent-table-head">
- <div class="title item-1">Component ID</div>
- <div class="title item-2">Artifact Name</div>
- <div class="title item-3">URL</div>
- <div class="title item-4">Time(UTC)</div>
- <div class="title item-5">Status</div>
- </div>
-
- <div class="w-sdc-distribute-row omfComponent-table-row"
- data-ng-repeat-start="(url,urlList) in ::omfComponentList | orderBy: '-timestamp' | groupBy:'url'"
- data-ng-class="urlListExtends?'extends row-{{$index}}':'row-{{$index}}'">
- <div class="w-sdc-distribute-cell item-1" sdc-smart-tooltip>
- <div class="w-sdc-distribution-arrow-btn" data-ng-click="urlListExtends=!urlListExtends"
- data-ng-class="{'extends': urlListExtends}"
- data-ng-init="urlListListExtends=false;urlList[0].displayUrl=getUrlName(urlList[0].url)"
- ></div>
- {{urlList[0].omfComponentID}}
- </div>
- <div class="w-sdc-distribute-cell item-2" sdc-smart-tooltip>
- {{urlList[0].displayUrl}}
- </div>
- <div class="w-sdc-distribute-cell item-3 disable-hover">
- <div sdc-smart-tooltip class="distribution-url">{{urlList[0].url}}</div>
- <div sdc-smart-tooltip title="Copy url" clipboard text="urlList[0].url"
- class="sprite-new link-btn copy-link disable-hover"></div>
- </div>
- <div class="w-sdc-distribute-cell item-4"><span
- data-ng-bind="urlList[0].timestamp | date: 'MM/dd/yyyy h:mma':'UTC'"></span>
- </div>
- <div class="w-sdc-distribute-cell item-5" sdc-smart-tooltip>
- {{urlList[0].status}}
- </div>
- </div>
-
-
- <div data-ng-repeat-end data-ng-if="urlListExtends" class="disable-hover" >
- <div class="w-sdc-distribute-row extends disable-hover">
- <ul data-ng-if="urlListExtends"
- class="w-sdc-distribute-url-block disable-hover">
- <li data-ng-repeat="distributionComponent in ::urlList | orderBy: '-timestamp'"
- class="disable-hover">
- <span
- data-ng-bind="distributionComponent.timestamp | date: 'MM/dd/yyyy h:mma':'UTC'"
- class="disable-hover"></span>
- <span
- class="disable-hover">{{distributionComponent.status}}</span>
- <span
- class="disable-hover reason" data-ng-if="distributionComponent.status == 'NOT_NOTIFIED'">Reason: Component has determined artifact is not needed.</span>
- <span
- class="disable-hover reason" data-ng-if="distributionComponent.errorReason">Reason: {{distributionComponent.errorReason}}</span>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- </div>
- </li>
- </ul>
- </li>
- </ul>
- </div>
-
- </perfect-scrollbar>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution.less b/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution.less
deleted file mode 100644
index ee1f7ed..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/distribution/distribution.less
+++ /dev/null
@@ -1,362 +0,0 @@
-
-.w-sdc-distribution-view {
- text-align: left;
-
- .g_1;
- min-height: 500px;
-
- .w-sdc-distribution-view-distributed-green-text {
- .l_9;
- .bold;
- }
- .w-sdc-distribution-view-distributed-error-red-text {
- .h_9;
- .bold;
- }
-
- .bg_c;
- vertical-align: top;
- padding: 30px 10px;
- width: 100%;
-
- .w-sdc-distribution-view-header {
- display: flex;
- -webkit-justify-content: space-between;
- margin: 0 25px 5px 40px;
-
- .header-spacer {
- flex-grow: 5;
- }
- }
-
- .top-search {
- position: relative;
- input {
- &.search-text {
- height: 26px;
- line-height: 26px;
- margin: 0 18px 4px 20px;
- padding-right: 25px;
- }
-
- }
- .magnification {
- top: 8px;
- right: 25px;
- }
- }
-
- .w-sdc-distribution-view-content {
- .perfect-scrollbar;
- padding: 0 25px 0 0px;
- margin-bottom: 25px;
- height: 700px;
- overflow: hidden;
- position: relative;
-
- }
-
- .w-sdc-distribution-view-title {
- .s_14_r;
-
- line-height: 30px;
-
- span {
- padding-left: 5px;
- }
- }
-
- .blue-font {
- .a_14_m;
-
- }
-
- .red-font {
- .q_14_m;
- }
-
- .w-sdc-distribution-view-block {
- div {
- display: inline-block;
- }
- }
-
- .w-sdc-distribution-view-content-section {
- ul {
- list-style-type: none;
- }
-
- .distribution-bth {
- .hand;
- &.disabled {
- cursor: none;
- }
- }
-
- .copy-link {
- padding-right: 19px;
- margin-left: 8px;
- cursor: pointer;
-
- }
-
- .w-sdc-distribute-row-extends {
- border-Left: solid 4px transparent;
- &.extends {
- border-left: solid 4px @main_color_c;
- border-bottom: 1px solid @border_color_f;
- margin-bottom: 10px;
- }
- }
- .w-sdc-distribute-parent-block {
- border: 1px solid @main_color_o;;
- width: 100%;
- margin-bottom: 6px;
-
- .status-icon {
- vertical-align: middle;
- margin-bottom: 4px;
- }
-
- &.extends {
- background-color: @tlv_color_t;
- }
-
- :not(.disable-hover):hover {
- background-color: @tlv_color_u;
- }
-
- .title-section {
- display: inline-block;
- margin-right: 10px;
- flex-basis: 0;
- }
-
- .title {
- .l_12_m;
- font-weight: bold;
- }
- .w-sdc-distribute-content {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-left: 10px;
- }
-
- .w-sdc-distribution-arrow-btn {
- .sprite-new;
- .arrow-up-small;
- margin: 0 6px;
- display: inline-table;
- }
- .extends.w-sdc-distribution-arrow-btn {
- -webkit-transform: rotate(180deg);
- -ms-transform: rotate(180deg);
- transform: rotate(180deg);
- }
-
- .w-sdc-distribute-row {
- display: flex;
- align-items: center;
- justify-content: space-between;
-
- .w-sdc-distribute-row-content {
- margin: 15px 31px 10px 0;
- width: 100%;
- .w-sdc-distribute-status-block {
- border-top: solid 1px @main_color_o;
- }
- .item-1 {
- flex-grow: 2;
- }
- .item-2 {
- flex-grow: 1;
- }
- .item-3 {
- flex-grow: 1;
- }
- .item-4 {
- flex-grow: 1;
- }
- .item-5 {
- flex-grow: 1;
- }
- }
- }
-
- .w-sdc-distribute-status-block {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin: 10px 5px 0 5px;
- padding: 5px 5px 0 5px;;
- width: 100%;
- div {
- border-left: 1px solid @main_color_o;
- padding: 0 12px;
- }
-
- .link {
- .a_14_m;
- cursor: pointer;
- &:hover{
- text-decoration: underline;
- .b_14_m;
- }
- }
-
- span {
- padding: 2px;
- }
-
- .deployed {
- margin-left: 10px;
- .sprite-new;
- .success-circle-small;
- }
-
- .error {
- .q_14_m;
- margin-left: 10px;
- .sprite-new;
- .error-icon;
- }
-
- .status-item-1 {
- border-left: 0;
- }
-
- .status-item-6 {
- flex-grow: 1;
- border-left: none;
- text-align: right;
- }
- }
-
- .w-sdc-distribute-components-block {
- padding: 0;
- padding-bottom: 5px;
- list-style-type: none;
-
- li {
- margin: 5px 2px;
- }
-
- .omf-component-row {
- border: 1px solid @border_color_f;
- padding-left: 3px;
- background-color: white;
- margin: 0 30px;
- &.extends {
- padding-left: 0;
- border-Left: solid 4px @main_color_c;
-
- }
-
- .w-sdc-distribute-status-block {
- margin: 5px;
- padding: 5px;
- }
-
- .blue-font {
- .a_16_m;
-
- }
-
- &:hover {
- background-color: @tlv_color_u;
- }
-
- }
-
- }
-
- .w-sdc-distribute-omfComponent-block {
- background-color: white;
- margin: 0 30px;
- padding: 8px 10px;
- border: 1px solid @border_color_f;
-
- .omfComponent-table-head {
- margin-bottom: 5px;
- background-color: @tlv_color_u;
- .title {
- padding: 6px 10px;
- border-left: 1px solid @border_color_f;
- &:first-child {
- border: none;
- }
- }
- }
-
- .omfComponent-table-row {
- border-bottom: 1px solid @border_color_f;
- &.row-0 {
- border-top: 1px solid @border_color_f;
- }
- .w-sdc-distribute-cell {
- padding: 10px;
- border-left: 1px solid @border_color_f;
- &:last-child {
- border-right: 1px solid @border_color_f;
- }
- &.item-5 {
- .m_14_m;
- }
- }
- }
-
- .distribution-url {
-
- }
-
- .w-sdc-distribute-row.extends {
- border-Left: solid 4px @main_color_c;
- .item-1 {
- border: none;
- }
-
- }
-
- .item-1 {
- width: 20%;
- }
- .item-2 {
- width: 20%;
- }
-
- .item-3 {
- width: 24%;
- display: flex;
- }
-
- .item-4 {
- width: 18%;
- }
-
- .item-5 {
- width: 18%;
- }
- }
-
- .w-sdc-distribute-url-block {
-
- padding: 10px 15px;
- border: none;
- border-right: 1px solid @border_color_f;
- border-bottom: 1px solid @border_color_f;
- width: 100%;
- li {
- border: none;
- span {
- padding-right: 30px;
- .m_12_r;
- }
- }
-
- }
- }
-
- }
-}
-
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 b452970..e270928 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
@@ -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,11 +22,13 @@
import * as _ from "lodash";
import {ModalsHandler, ValidationUtils, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, DEFAULT_ICON,
ResourceType, ComponentState, instantiationType, ComponentFactory} from "app/utils";
-import {CacheService, EventListenerService, ProgressService, OnboardingService} from "app/services";
+import { EventListenerService, ProgressService} from "app/services";
+import {CacheService, OnboardingService, ImportVSPService} from "app/services-ng2";
import {IAppConfigurtaion, IValidate, IMainCategory, Resource, ISubCategory,Service, ICsarComponent, Component} from "app/models";
import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
import {Dictionary} from "lodash";
import { PREVIOUS_CSAR_COMPONENT } from "../../../../utils/constants";
+import { Observable, Subject } from "rxjs";
export class Validation {
@@ -37,7 +39,6 @@
VendorNameValidationPattern:RegExp;
VendorModelNumberValidationPattern:RegExp;
commentValidationPattern:RegExp;
- projectCodeValidationPattern:RegExp;
}
export class componentCategories {//categories field bind to this obj in order to solve this bug: DE242059
@@ -61,7 +62,7 @@
isShowFileBrowse:boolean;
isShowOnboardingSelectionBrowse:boolean;
importedToscaBrowseFileText:string;
- importCsarProgressKey:string;
+ importCsarProProgressKey:string;
browseFileLabel:string;
componentCategories:componentCategories;
instantiationTypes:Array<instantiationType>;
@@ -86,6 +87,7 @@
possibleToUpdateIcon():boolean;
}
+// tslint:disable-next-line:max-classes-per-file
export class GeneralViewModel {
static '$inject' = [
@@ -100,7 +102,6 @@
'CommentValidationPattern',
'ValidationUtils',
'sdcConfig',
- 'ProjectCodeValidationPattern',
'$state',
'ModalsHandler',
'EventListenerService',
@@ -109,8 +110,10 @@
'$interval',
'$filter',
'$timeout',
- 'Sdc.Services.OnboardingService',
- 'ComponentFactory'
+ 'OnboardingService',
+ 'ComponentFactory',
+ 'ImportVSPService',
+ '$stateParams'
];
constructor(private $scope:IGeneralScope,
@@ -124,7 +127,6 @@
private CommentValidationPattern:RegExp,
private ValidationUtils:ValidationUtils,
private sdcConfig:IAppConfigurtaion,
- private ProjectCodeValidationPattern:RegExp,
private $state:ng.ui.IStateService,
private ModalsHandler:ModalsHandler,
private EventListenerService:EventListenerService,
@@ -133,8 +135,10 @@
protected $interval:any,
private $filter:ng.IFilterService,
private $timeout:ng.ITimeoutService,
- private onBoardingService:OnboardingService,
- private ComponentFactory:ComponentFactory) {
+ private onBoardingService: OnboardingService,
+ private ComponentFactory:ComponentFactory,
+ private importVSPService: ImportVSPService,
+ private $stateParams: any) {
this.initScopeValidation();
this.initScopeMethods();
@@ -153,13 +157,11 @@
this.$scope.validation.VendorNameValidationPattern = this.VendorNameValidationPattern;
this.$scope.validation.VendorModelNumberValidationPattern = this.VendorModelNumberValidationPattern;
this.$scope.validation.commentValidationPattern = this.CommentValidationPattern;
- this.$scope.validation.projectCodeValidationPattern = this.ProjectCodeValidationPattern;
};
- private loadOnboardingFileCache = ():ng.IPromise<Dictionary<any>> =>{
-
+ private loadOnboardingFileCache = (): Observable<Dictionary<Dictionary<string>>> => {
let onboardCsarFilesMap:Dictionary<Dictionary<string>>;
- let onSuccess = (vsps:Array<ICsarComponent>) =>{
+ let onSuccess = (vsps:Array<ICsarComponent>) => {
onboardCsarFilesMap = {};
_.each(vsps, (vsp:ICsarComponent)=>{
onboardCsarFilesMap[vsp.packageId] = onboardCsarFilesMap[vsp.packageId] || {};
@@ -170,8 +172,8 @@
};
let onError = (): void =>{
console.log("Error getting onboarding list");
- };
- return this.onBoardingService.getOnboardingVSPs().then(onSuccess, onError);
+ };
+ return this.onBoardingService.getOnboardingVSPs().map(onSuccess, onError);
};
private setImportedFileText = ():void => {
@@ -179,7 +181,7 @@
if(!this.$scope.isShowOnboardingSelectionBrowse) return;
//these variables makes it easier to read this logic
- let csarUUID:string = (<Resource>this.$scope.component).csarUUID;
+ let csarUUID:string = (<Resource>this.$scope.component).csarUUID;
let csarVersion:string = (<Resource>this.$scope.component).csarVersion;
let onboardCsarFilesMap:Dictionary<Dictionary<string>> = this.cacheService.get('onboardCsarFilesMap');
@@ -187,21 +189,25 @@
if(this.$scope.component.vspArchived){
this.$scope.importedToscaBrowseFileText = 'VSP is archived';
} else {
- this.$scope.importedToscaBrowseFileText = onboardCsarFilesMap[csarUUID][csarVersion];
+ if(this.$stateParams.componentCsar && this.$scope.component.lifecycleState === 'NOT_CERTIFIED_CHECKIN' && !this.$scope.isCreateMode()) {
+ this.$scope.importedToscaBrowseFileText = this.$scope.originComponent.name + ' (' + (this.$scope.originComponent as Resource).csarVersion + ')';
+ } else {
+ this.$scope.importedToscaBrowseFileText = onboardCsarFilesMap[csarUUID][csarVersion];
+ }
}
}
-
+
if(this.$scope.component.vspArchived || (onboardCsarFilesMap && onboardCsarFilesMap[csarUUID] && onboardCsarFilesMap[csarUUID][csarVersion])){ //check that the file name is already in cache
assignFileName();
} else {
- this.loadOnboardingFileCache().then((onboardingFiles) => {
+ this.loadOnboardingFileCache().subscribe((onboardingFiles) => {
onboardCsarFilesMap = onboardingFiles;
this.cacheService.set('onboardCsarFilesMap', onboardingFiles);
assignFileName();
}, ()=> {});
}
-
+
}
isCreateModeAvailable(verifyObj:string): boolean {
@@ -211,10 +217,9 @@
private initScope = ():void => {
-
this.$scope.importCsarProgressKey = "importCsarProgressKey";
- this.$scope.browseFileLabel = this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType === ResourceType.VF ? "Upload file" : "Upload VFC";
+ this.$scope.browseFileLabel = this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType === ResourceType.VF ? 'VSP' : 'Upload VFC';
this.$scope.progressService = this.progressService;
this.$scope.componentCategories = new componentCategories();
this.$scope.componentCategories.selectedCategory = this.$scope.component.selectedCategory;
@@ -236,7 +241,7 @@
if (resource.importedFile) { // Component has imported file.
this.$scope.isShowFileBrowse = true;
}
- if (this.$scope.isEditMode() && resource.resourceType == ResourceType.VF && !resource.csarUUID) {
+ if (resource.resourceType === ResourceType.VF && !resource.csarUUID) {
this.$scope.isShowFileBrowse = true;
}
} else if(this.$scope.component.isService()){
@@ -244,30 +249,35 @@
this.$scope.initInstantiationTypes();
}
- // Work around to change the csar version
- if (this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
- //(<Resource>this.$scope.component).csarVersion = this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
- this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
- this.$scope.updateUnsavedFileFlag(true);
+ if (this.cacheService.get(PREVIOUS_CSAR_COMPONENT)) { //keep the old component in the cache until checkout, so we dont need to pass it around
+ this.$scope.setOriginComponent(this.cacheService.get(PREVIOUS_CSAR_COMPONENT));
+ this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
+ }
- if (!this.$scope.isViewMode() && this.cacheService.get(PREVIOUS_CSAR_COMPONENT)) { //keep the old component in the cache until checkout, so we dont need to pass it around
- this.$scope.setOriginComponent(this.cacheService.get(PREVIOUS_CSAR_COMPONENT));
- this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
+ if (this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
+ this.$scope.updateUnsavedFileFlag(true);
+ // We are coming from update VSP modal we need to automatically checkout (if needed) and save the VF
+ if (this.$scope.component.lifecycleState !== ComponentState.NOT_CERTIFIED_CHECKOUT) {
+ // Checkout is needed after that a save will be invoked in workspace-view.handleLifeCycleStateChange
+ this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, 'checkOut');
+ // if(this.$scope.component.lifecycleState !== 'NOT_CERTIFIED_CHECKIN') {
+ // (<Resource>this.$scope.component).csarVersion = this.$stateParams.componentCsar.csarVersion;
+ // }
+ } else {
+ this.$scope.save();
}
}
- // Init the decision if to show onboarding
- if (this.$scope.component.isResource() && this.$scope.isEditMode() &&
- ((<Resource>this.$scope.component).resourceType == ResourceType.VF ||
- (<Resource>this.$scope.component).resourceType == ResourceType.PNF)
- && (<Resource>this.$scope.component).csarUUID) {
+ if (this.$scope.component.isResource() &&
+ (this.$scope.component as Resource).resourceType === ResourceType.VF ||
+ (this.$scope.component as Resource).resourceType === ResourceType.PNF && (this.$scope.component as Resource).csarUUID) {
this.$scope.isShowOnboardingSelectionBrowse = true;
this.setImportedFileText();
} else {
this.$scope.isShowOnboardingSelectionBrowse = false;
}
-
+
//init file extensions based on the file that was imported.
if (this.$scope.component.isResource() && (<Resource>this.$scope.component).importedFile) {
@@ -304,7 +314,7 @@
this.$scope.originComponent.contactId = this.$scope.component.contactId;
}
-
+
this.$scope.$on('$destroy', () => {
this.EventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE);
this.EventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
@@ -313,7 +323,7 @@
};
// Convert category string MainCategory_#_SubCategory to Array with one item (like the server except)
- private convertCategoryStringToOneArray = ():Array<IMainCategory> => {
+ private convertCategoryStringToOneArray = ():IMainCategory[] => {
let tmp = this.$scope.component.selectedCategory.split("_#_");
let mainCategory = tmp[0];
let subCategory = tmp[1];
@@ -333,14 +343,14 @@
}
let tmpSelected = <IMainCategory> mainCategoryClone;
- let result:Array<IMainCategory> = [];
+ let result:IMainCategory[] = [];
result.push(tmpSelected);
return result;
};
private updateComponentNameInBreadcrumbs = ():void => {
- //update breadcrum after changing name
+ // update breadcrum after changing name
this.$scope.breadcrumbsModel[1].updateSelectedMenuItemText(this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name);
this.$scope.updateMenuComponentName(this.$scope.component.name);
};
@@ -436,24 +446,20 @@
if(this.$scope.component.vspArchived) return;
let csarUUID = (<Resource>this.$scope.component).csarUUID;
let csarVersion = (<Resource>this.$scope.component).csarVersion;
- this.ModalsHandler.openOnboadrdingModal('Update', csarUUID, csarVersion).then((result)=> {
-
- if(result){
- this.ComponentFactory.getComponentWithMetadataFromServer(result.type.toUpperCase(), result.previousComponent.uniqueId).then(
- (component:Component)=> {
- if (result.componentCsar && component.isResource()){
- this.cacheService.set(PREVIOUS_CSAR_COMPONENT, angular.copy(component));
- component = this.ComponentFactory.updateComponentFromCsar(result.componentCsar, <Resource>component);
- }
-
- this.$scope.setComponent(component);
- this.$scope.updateUnsavedFileFlag(true);
- this.setImportedFileText();
- }, ()=> {
- // ERROR
- });
- }
- }, () => {});
+ this.importVSPService.openOnboardingModal(csarUUID, csarVersion).subscribe((result) => {
+ this.ComponentFactory.getComponentWithMetadataFromServer(result.type.toUpperCase(), result.previousComponent.uniqueId).then(
+ (component:Component)=> {
+ if (result.componentCsar && component.isResource()){
+ this.cacheService.set(PREVIOUS_CSAR_COMPONENT, angular.copy(component));
+ component = this.ComponentFactory.updateComponentFromCsar(result.componentCsar, <Resource>component);
+ }
+ this.$scope.setComponent(component);
+ this.$scope.save();
+ this.setImportedFileText();
+ }, ()=> {
+ // ERROR
+ });
+ })
};
this.$scope.updateIcon = ():void => {
@@ -491,17 +497,17 @@
return;
}
- let subtype:string = ComponentType.RESOURCE == this.$scope.componentType ? this.$scope.component.getComponentSubType() : undefined;
+ const subtype:string = ComponentType.RESOURCE == this.$scope.componentType ? this.$scope.component.getComponentSubType() : undefined;
- let onFailed = (response) => {
- //console.info('onFaild', response);
- //this.$scope.isLoading = false;
+ const onFailed = (response) => {
+ // console.info('onFaild', response);
+ // this.$scope.isLoading = false;
};
- let onSuccess = (validation:IValidate) => {
- this.$scope.editForm["componentName"].$setValidity('nameExist', validation.isValid);
+ const onSuccess = (validation:IValidate) => {
+ this.$scope.editForm['componentName'].$setValidity('nameExist', validation.isValid);
if (validation.isValid) {
- //update breadcrumb after changing name
+ // update breadcrumb after changing name
this.updateComponentNameInBreadcrumbs();
}
};
@@ -522,48 +528,57 @@
&& !this.$scope.editForm["componentName"].$error.pattern
&& (!this.$scope.originComponent.name || this.$scope.component.name.toUpperCase() !== this.$scope.originComponent.name.toUpperCase())
) {
- if (!(this.$scope.componentType === ComponentType.RESOURCE && (<Resource>this.$scope.component).csarUUID !== undefined)
+ if (!(this.$scope.componentType === ComponentType.RESOURCE && (this.$scope.component as Resource).csarUUID !== undefined)
) {
this.$scope.component.validateName(name, subtype).then(onSuccess, onFailed);
}
- } else if (this.$scope.originComponent.name && this.$scope.component.name.toUpperCase() === this.$scope.originComponent.name.toUpperCase()) {
+ } else if (this.$scope.editForm && this.$scope.originComponent.name && this.$scope.component.name.toUpperCase() === this.$scope.originComponent.name.toUpperCase()) {
// Clear the error
- this.$scope.editForm["componentName"].$setValidity('nameExist', true);
+ this.$scope.editForm['componentName'].$setValidity('nameExist', true);
}
}
};
this.EventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, (nextState) => {
- if (this.$state.current.data.unsavedChanges && this.$scope.isValidForm){
+ if (this.$state.current.data.unsavedChanges && this.$scope.isValidForm) {
this.$scope.save().then(() => {
this.$scope.handleChangeLifecycleState(nextState);
}, () => {
- console.error("Save failed, unable to change lifecycle state to " + nextState);
+ console.error('Save failed, unable to change lifecycle state to ' + nextState);
});
} else if(!this.$scope.isValidForm){
- console.error("Form is not valid");
+ console.error('Form is not valid');
} else {
let newCsarVersion:string;
- if(this.$scope.unsavedFile){
- newCsarVersion = (<Resource>this.$scope.component).csarVersion;
+ if(this.$scope.unsavedFile) {
+ newCsarVersion = (this.$scope.component as Resource).csarVersion;
}
- this.$scope.handleChangeLifecycleState(nextState, newCsarVersion);
+ if(this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
+ const onError = (): void => {
+ if (this.$scope.component.lifecycleState === 'NOT_CERTIFIED_CHECKIN') {
+ this.$scope.revert();
+ }
+ };
+ this.$scope.handleChangeLifecycleState(nextState, newCsarVersion, onError);
+
+ } else {
+ this.$scope.handleChangeLifecycleState(nextState, newCsarVersion);
+ }
}
});
-
this.$scope.revert = ():void => {
- //in state of import file leave the file in place
+ // in state of import file leave the file in place
this.$scope.setComponent(this.ComponentFactory.createComponent(this.$scope.originComponent));
if (this.$scope.component.isResource() && this.$scope.restoreFile) {
- (<Resource>this.$scope.component).importedFile = angular.copy(this.$scope.restoreFile);
- }
-
- this.setImportedFileText();
- this.$scope.updateBreadcrumbs(this.$scope.component); //update on workspace
+ (this.$scope.component as Resource).importedFile = angular.copy(this.$scope.restoreFile);
+ }
+
+ this.setImportedFileText();
+ this.$scope.updateBreadcrumbs(this.$scope.component); // update on workspace
this.$scope.componentCategories.selectedCategory = this.$scope.originComponent.selectedCategory;
this.setUnsavedChanges(false);
@@ -573,8 +588,8 @@
this.$scope.onImportFileChange = () => {
- if( !this.$scope.restoreFile && this.$scope.editForm.fileElement.value && this.$scope.editForm.fileElement.value.filename || //if file started empty but we have added a new one
- this.$scope.restoreFile && !angular.equals(this.$scope.restoreFile, this.$scope.editForm.fileElement.value)){ //or file was swapped for a new one
+ if( !this.$scope.restoreFile && this.$scope.editForm.fileElement.value && this.$scope.editForm.fileElement.value.filename || // if file started empty but we have added a new one
+ this.$scope.restoreFile && !angular.equals(this.$scope.restoreFile, this.$scope.editForm.fileElement.value)){ // or file was swapped for a new one
this.$scope.updateUnsavedFileFlag(true);
} else {
this.$scope.updateUnsavedFileFlag(false);
@@ -582,46 +597,46 @@
}
};
- this.$scope.$watchCollection('component.name', (newData:any):void => {
+ this.$scope.$watchCollection('component.name', (newData: any): void => {
this.$scope.validateName(false);
});
// Notify the parent if this step valid or not.
- this.$scope.$watch("editForm.$valid", (newVal, oldVal) => {
+ this.$scope.$watch('editForm.$valid', (newVal, oldVal) => {
this.$scope.setValidState(newVal);
});
- this.$scope.$watch("editForm.$dirty", (newVal, oldVal) => {
+ this.$scope.$watch('editForm.$dirty', (newVal, oldVal) => {
if (newVal && !this.$scope.isCreateMode()) {
this.setUnsavedChanges(true);
}
});
- this.$scope.onCategoryChange = ():void => {
+ this.$scope.onCategoryChange = (): void => {
this.$scope.component.selectedCategory = this.$scope.componentCategories.selectedCategory;
this.$scope.component.categories = this.convertCategoryStringToOneArray();
this.$scope.component.icon = DEFAULT_ICON;
};
- this.$scope.onEcompGeneratedNamingChange = ():void =>{
- if(!(<Service>this.$scope.component).ecompGeneratedNaming){
- (<Service>this.$scope.component).namingPolicy = '';
+ this.$scope.onEcompGeneratedNamingChange = (): void => {
+ if (!(this.$scope.component as Service).ecompGeneratedNaming) {
+ (this.$scope.component as Service).namingPolicy = '';
}
};
- this.$scope.onVendorNameChange = (oldVendorName:string):void => {
+ this.$scope.onVendorNameChange = (oldVendorName: string): void => {
if (this.$scope.component.icon === oldVendorName) {
this.$scope.component.icon = DEFAULT_ICON;
}
};
this.EventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.$scope.reload);
- };
+ }
- private setUnsavedChanges = (hasChanges:boolean):void => {
+ private setUnsavedChanges = (hasChanges: boolean): void => {
this.$state.current.data.unsavedChanges = hasChanges;
- };
+ }
}
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 07f1e4d..86f1feb 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
@@ -13,13 +13,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div include-padding="true" class="sdc-workspace-general-step">
<div class="w-sdc-main-container-body-content-action-buttons">
- <div data-ng-if="unsavedFile && !isCreateMode() && !isViewMode()" class="unsaved-file-warning">
+ <div data-ng-if="unsavedFile && !isCreateMode() && !isViewMode()" data-tests-id="save-warning" class="unsaved-file-warning">
<span class="sprite-new sdc-warning"></span> Click save to update to the new VSP
</div>
- <button class="tlv-btn blue" data-ng-if="isDesigner()" data-ng-show="isGeneralView()" data-ng-class="{'disabled' : !isValidForm || isDisableMode() || isViewMode() || isCreateMode()}"
+ <button class="tlv-btn blue" data-ng-if="isDesigner()" data-ng-show="isGeneralView()" data-ng-class="{'disabled' : !isValidForm || isDisableMode() || isViewMode() || isCreateMode()}"
data-ng-click="save()" data-tests-id="create/save" tooltips tooltip-content="Save">Save</button>
<span data-ng-if="isDesigner()" data-ng-class="{'disabled' :isDisableMode() || isViewMode() || isCreateMode()}" ng-click="revert()" class="sprite-new revert-btn" data-tests-id="revert"
data-ng-show="isGeneralView()" tooltips tooltip-content="Revert"></span>
@@ -160,7 +159,7 @@
<div class="w-sdc-form-column">
<!--------------------- IMPORT TOSCA FILE USING BROWSE (ALSO VFC) -------------------->
<div class="i-sdc-form-item" ng-if="isShowFileBrowse">
-
+
<!-- // element-disabled="{{!isCreateMode()&&!(isEditMode()&&component.resourceType=='VF')&&component.vspArchived}} || {{isViewMode()}}" -->
<label class="i-sdc-form-label" data-ng-class="{'required':isCreateMode()}">{{browseFileLabel}}</label>
@@ -173,17 +172,17 @@
on-file-changed-in-directive="onImportFileChange"
extensions="{{importedFileExtension}}"
default-text="'Browse to select file'"
- data-ng-class="{'error':!(isEditMode()&&component.resourceType=='VF') && (!editForm.fileElement.$valid || !component.importedFile.filename)}"></file-upload>
+ ></file-upload>
</div>
<!--------------------- IMPORT TOSCA FILE USING ONBOARDING -------------------->
<div class="i-sdc-form-item" ng-if="isShowOnboardingSelectionBrowse">
- <label class="i-sdc-form-label required">Select VSP</label>
+ <label class="i-sdc-form-label required">VSP</label>
<div class="i-sdc-form-file-upload i-sdc-form-input">
<span class="i-sdc-form-file-name" data-ng-disabled="component.vspArchived" data-tests-id="filename">{{(fileModel && fileModel.filename) || importedToscaBrowseFileText }}</span>
<div class="i-sdc-form-file-upload-x-btn" ng-click="cancel()" data-ng-show="fileModel.filename && fileModel.filename!=='' && elementDisabled!=='true'"></div>
- <input type="button" data-ng-disabled="component.vspArchived" name="fileElement" />
- <div class="file-upload-browse-btn" data-ng-click="openOnBoardingModal()" data-ng-disabled="!component.vspArchived" data-tests-id="browseButton">Browse</div>
+ <input type="button" data-ng-class="{'disabled': !isEditMode() && component.vspArchived}" data-ng-disabled="component.vspArchived" name="fileElement" />
+ <div class="file-upload-browse-btn" data-ng-class="{'disabled': !isEditMode() && !component.vspArchived}" data-ng-click="openOnBoardingModal()" data-ng-disabled="!component.vspArchived" data-tests-id="browseButton">Browse</div>
</div>
</div>
@@ -218,28 +217,6 @@
</div>
<!--------------------- USER ID -------------------->
- <!--------------------- PROJECT CODE -------------------->
- <div class="i-sdc-form-item" data-ng-if="!component.isResource()"
- data-ng-class="{'error': validateField(editForm.projectCode)}">
- <label class="i-sdc-form-label required" translate="GENERAL_LABEL_PROJECT_CODE"></label>
- <input class="i-sdc-form-input" type="text"
- data-ng-model="component.projectCode"
- data-ng-class="{'view-mode': isViewMode()}"
- data-ng-model-options="{ debounce: 500 }"
- data-ng-maxlength="50"
- data-required
- name="projectCode"
- data-ng-pattern="validation.projectCodeValidationPattern"
- data-tests-id="projectCode"
- />
-
- <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>
- </div>
-
<!--------------------- VENDOR NAME -------------------->
<div ng-if="component.isResource()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.vendorName)}">
<label class="i-sdc-form-label required">Vendor</label>
@@ -401,6 +378,27 @@
</div>
<!--------------------- Service Role -------------------->
+ <!--------------------- Service Function -------------------->
+ <div ng-if="component.isService()"
+ class="i-sdc-form-item"
+ data-ng-class="{'error': validateField(editForm.serviceFunction)}">
+ <label class="i-sdc-form-label" translate="GENERAL_TAB_LABEL_SERVICE_FUNCTION"></label>
+ <input class="i-sdc-form-input" type="text"
+ data-ng-class="{'view-mode': isViewMode()}"
+ data-ng-model="component.serviceFunction"
+ data-ng-model-options="{ debounce: 500 }"
+ name="serviceFunction"
+ data-tests-id="serviceFunction"
+ data-ng-maxlength="256"
+ data-ng-pattern="validation.ServiceTypeAndRoleValidationPattern"
+ />
+ <div class="input-error" data-ng-show="validateField(editForm.serviceFunction)">
+ <span ng-show="editForm.serviceFunction.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
+ <span ng-show="editForm.serviceFunction.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ </div>
+ </div>
+ <!--------------------- Service Function -------------------->
+
<!-------------------- ENVIRONMENT CONTEXT ----------------->
<div ng-if="component.isService()" class="i-sdc-form-item">
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less
index b60e4b8..8b2cc01 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less
+++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less
@@ -27,6 +27,7 @@
.file-upload-browse-btn {
.noselect;
.bg_n;
+ color:#191919;
padding: 4px 6px;
cursor: pointer;
z-index: 999;
@@ -35,10 +36,6 @@
text-align: center;
border-left: solid 1px #cfcfcf;
- &.disabled {
- cursor: default;
- }
-
&:hover:not(.disabled) {
background-color: #dbdee2;
}
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
deleted file mode 100644
index 47a96fb..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view-model.ts
+++ /dev/null
@@ -1,158 +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=========================================================
- */
-
-'use strict';
-import * as _ from "lodash";
-import {ModalsHandler} from "app/utils";
-import {SharingService} from "app/services";
-import {IAppConfigurtaion, ArtifactModel, IFileDownload} from "app/models";
-import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
-import {ComponentServiceNg2} from "../../../../ng2/services/component-services/component.service";
-import {ArtifactGroupModel} from "../../../../models/artifacts";
-import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response";
-
-export interface IInformationArtifactsScope extends IWorkspaceViewModelScope {
- artifacts:Array<ArtifactModel>;
- tableHeadersList:Array<any>;
- artifactType:string;
- isResourceInstance:boolean;
- downloadFile:IFileDownload;
- isLoading:boolean;
- sortBy:string;
- reverse:boolean;
-
- getTitle():string;
- addOrUpdate(artifact:ArtifactModel):void;
- delete(artifact:ArtifactModel):void;
- download(artifact:ArtifactModel):void;
- clickArtifactName(artifact:any):void;
- openEditEnvParametersModal(artifactResource:ArtifactModel):void;
- sort(sortBy:string):void;
- showNoArtifactMessage():boolean;
-}
-
-export class InformationArtifactsViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- '$state',
- 'sdcConfig',
- 'ModalsHandler',
- 'ComponentServiceNg2'
- ];
-
- constructor(private $scope:IInformationArtifactsScope,
- private $filter:ng.IFilterService,
- private $state:any,
- private sdcConfig:IAppConfigurtaion,
- private ModalsHandler:ModalsHandler,
- private ComponentServiceNg2: ComponentServiceNg2) {
- this.initInformationalArtifacts();
- }
-
- private initInformationalArtifacts = ():void => {
- if(!this.$scope.component.artifacts) {
- this.$scope.isLoading = true;
- this.ComponentServiceNg2.getComponentInformationalArtifacts(this.$scope.component).subscribe((response:ComponentGenericResponse) => {
- this.$scope.component.artifacts = response.artifacts;
- this.initScope();
- this.$scope.isLoading = false;
- });
- } else {
- this.initScope();
- }
- }
-
- private initScope = ():void => {
-
- this.$scope.isLoading = false;
- this.$scope.sortBy = 'artifactDisplayName';
- this.$scope.reverse = false;
- this.$scope.setValidState(true);
- this.$scope.artifactType = 'informational';
- this.$scope.getTitle = ():string => {
- return this.$filter("resourceName")(this.$scope.component.name) + ' Artifacts';
-
- };
-
- this.$scope.tableHeadersList = [
- {title: 'Name', property: 'artifactDisplayName'},
- {title: 'Type', property: 'artifactType'},
- {title: 'Version', property: 'artifactVersion'},
- {title: 'UUID', property: 'artifactUUID'}
- ];
-
- this.$scope.artifacts = <ArtifactModel[]>_.values(this.$scope.component.artifacts);
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
-
-
- this.$scope.addOrUpdate = (artifact:ArtifactModel):void => {
- artifact.artifactGroupType = 'INFORMATIONAL';
- this.ModalsHandler.openArtifactModal(artifact, this.$scope.component).then(() => {
- this.$scope.artifacts = <ArtifactModel[]>_.values(this.$scope.component.artifacts);
- });
- };
-
- this.$scope.showNoArtifactMessage = ():boolean => {
- let artifacts:any = [];
- artifacts = _.filter(this.$scope.artifacts, (artifact:ArtifactModel)=> {
- return artifact.esId;
- });
-
- if (artifacts.length === 0) {
- return true;
- }
- return false;
- };
-
- this.$scope.delete = (artifact:ArtifactModel):void => {
-
- let onOk = ():void => {
- this.$scope.isLoading = true;
- let onSuccess = ():void => {
- this.$scope.isLoading = false;
- this.$scope.artifacts = <ArtifactModel[]>_.values(this.$scope.component.artifacts);
- };
-
- let onFailed = (error:any):void => {
- console.log('Delete artifact returned error:', error);
- this.$scope.isLoading = false;
- };
-
- this.$scope.component.deleteArtifact(artifact.uniqueId, artifact.artifactLabel).then(onSuccess, onFailed);
- };
-
- let title:string = this.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TITLE");
- let message:string = this.$filter('translate')("ARTIFACT_VIEW_DELETE_MODAL_TEXT", "{'name': '" + artifact.artifactDisplayName + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
- };
-
- this.$scope.clickArtifactName = (artifact:any) => {
- if (!artifact.esId) {
- this.$scope.addOrUpdate(artifact);
- }
-
- };
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view.html
deleted file mode 100644
index eacadb3..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts-view.html
+++ /dev/null
@@ -1,82 +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-information-artifact">
- <div data-tests-id="add-information-artifact-button" ng-if="!isViewMode()"
- data-ng-class="{'disabled': isDisableMode()}"
- data-tests-id="addGrey" class="add-btn" data-ng-click="addOrUpdate({})" type="button">Add </div>
- <div class="table-container-flex">
- <div class="table" data-ng-class="{'view-mode': isViewMode()}">
- <div class="head flex-container">
- <div class="table-header head-row hand flex-item" ng-repeat="header in tableHeadersList track by $index" data-ng-click="sort(header.property)">{{header.title}}
- <span data-ng-show="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- <div class="table-no-text-header head-row flex-item"></div>
- </div>
- <div class="body">
- <perfect-scrollbar suppress-scroll-x="true" scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <div data-ng-if="showNoArtifactMessage()" class="no-row-text" data-ng-class="{'disabled': isDisableMode()}">
- There are no information artifacts to display
- </div>
- <div data-ng-repeat-start="artifact in artifacts| orderBy:sortBy:reverse track by $index" data-tests-id="InformationalArtifactRow"
- class="flex-container data-row"
- data-ng-class="{'selected': artifact.selected}"
- data-ng-if="artifact.esId">
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="artifactDisplayName_{{artifact.artifactDisplayName}}">
- <span class="sprite table-arrow" data-ng-class="{'opened': artifact.selected}" data-tests-id="artifact_arrow_{{artifact.artifactDisplayName}}"></span>
- {{artifact.artifactDisplayName}}
- </div>
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="artifactType_{{artifact.artifactDisplayName}}">
- {{artifact.artifactType}}
- </div>
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="artifactVersion_{{artifact.artifactDisplayName}}">
- {{artifact.artifactVersion}}
- </div>
-
- <div class="table-col-general flex-item text" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="artifactUUID_{{artifact.artifactDisplayName}}"
- tooltips tooltip-content="{{artifact.artifactUUID}}">
- <span>{{artifact.artifactUUID}}</span>
- </div>
-
- <div class="table-btn-col flex-item">
- <button class="table-edit-btn" data-tests-id="edit_{{artifact.artifactDisplayName}}" data-ng-if="!isViewMode() && !artifact.isThirdParty()" data-ng-click="addOrUpdate(artifact)" data-ng-class="{'disabled': isDisableMode()}"></button>
- <button class="table-delete-btn" data-tests-id="delete_{{artifact.artifactDisplayName}}" data-ng-if="!isViewMode() && !artifact.isThirdParty()" data-ng-click="delete(artifact)" data-ng-class="{'disabled': isDisableMode()}"> </button>
- <button class="table-download-btn" download-artifact data-tests-id="download_{{artifact.artifactDisplayName}}"
- data-ng-if="artifact.artifactName" component="component" artifact="artifact"></button>
- </div>
- </div>
- <div data-ng-repeat-end="" data-ng-if="artifact.selected" class="item-opened" data-tests-id="{{artifact.artifactDisplayName}}Description" data-ng-bind="artifact.description"></div>
- <button class="add-button" data-ng-repeat="artifact in artifacts track by $index"
- data-ng-show="!artifact.esId"
- data-tests-id="{{artifact.artifactDisplayName}}"
- ng-if="!isViewMode()"
- data-ng-class="{'disabled': isDisableMode()}"
- translate="DEPLOYMENT_ARTIFACT_BUTTON_ADD_HEAT"
- translate-values="{'name': '{{artifact.artifactDisplayName}}'}"
- data-ng-click="addOrUpdate(artifact)"></button>
- <button class="add-button"
- ng-if="!isViewMode()"
- data-ng-class="{'disabled': isDisableMode()}"
- translate="DEPLOYMENT_ARTIFACT_BUTTON_ADD_OTHER"
- data-ng-click="addOrUpdate({})"></button>
- </perfect-scrollbar>
- </div>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less
deleted file mode 100644
index 5e69c44..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less
+++ /dev/null
@@ -1,57 +0,0 @@
-.workspace-information-artifact {
- width: 93%;
- display: inline-block;
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
- .table{
- height: 490px;
- margin-bottom: 0;
- }
-
- .table-container-flex {
- margin-top: 0;
-
- .item-opened{
- word-wrap: break-word;
- }
-
- .text{
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- white-space: nowrap;
- }
-
- .flex-item:nth-child(1) {
- flex-grow: 15;
- .hand;
- span.table-arrow {
- margin-right: 7px;
- }
- }
-
- .flex-item:nth-child(2) {
- flex-grow: 6;
- }
-
- .flex-item:nth-child(3) {
- flex-grow: 3;
- }
-
- .flex-item:nth-child(4) {
- flex-grow: 20;
- }
-
- .flex-item:nth-child(5) {
- flex-grow: 5;
- padding-top: 10px;
- }
-
- }
-
-}
-
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less b/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less
deleted file mode 100644
index 17c18e1..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less
+++ /dev/null
@@ -1,225 +0,0 @@
-.workspace-inputs {
-
- .sdc-workspace-container .w-sdc-main-right-container .w-sdc-main-container-body-content {
- padding: 25px 8% 25px 8%;
- }
-
- .w-sdc-main-container .w-sdc-main-right-container > div:first-child {
- /* scroll fix */
- padding-bottom: 0px;
- }
-
-
- width: 100%;
- display: flex;
-
- .text {
- padding-left: 15px;
- .no-overflow;
- }
-
- .title-text {
- color: @main_color_m;
- .f-type._13_m;
- .bold;
- text-overflow: ellipsis;
- overflow: hidden;
- }
-
- .no-overflow {
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- }
-
- .title-blue-text {
- color: @main_color_a;
- .f-type._13_m;
-
- &.property-name-text {
- padding-right: 13px;
- border-right: 1px solid rgba(120, 136, 148, 0.26);
- flex-grow: 1;
- .no-overflow;
- }
- }
-
- .instance-name-text {
- flex-grow: 1;
- }
-
- ng-include {
- width: 45%;
- }
-
- .w-sdc-inputs-search {
- padding: 10px 20px 20px 0;
- white-space: nowrap;
- position: relative;
- width: 60%;
- height: 64px;
-
- .inputs-search-icon {
- top: 9px;
- right: 11px;
- }
-
- .magnification-white {
- .sprite-new;
- .search-white-icon;
- .hand;
- }
-
- .search-icon-container {
- width: 35px;
- height: 30px;
- background-color: @main_color_a;
- white-space: nowrap;
- float: right;
- position: relative;
- bottom: 31px;
- right: 1px;
- border-radius: 0px 4px 4px 0px;
- .hand
- }
- }
-
- .total-inputs-count {
- width: 100%;
- font-weight: bold;
- text-align: left;
- }
-
- .new-input-button {
- margin: 9px 0 0 0;
- }
-
- .w-sdc-inputs-search-input {
- border: 1px solid @color_e;
- .border-radius(4px);
- height: 32px;
- margin: 0;
- padding: 0px 28px 3px 10px;
- vertical-align: 4px;
- width: 100%;
- outline: none;
- font-style: italic;
- }
-
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
- .prop-to-input-button {
- position: absolute;
- top: 50%;
- margin-right: -20px;
- margin-bottom: -10px;
-
- }
-
- .table-container-flex {
-
- .flex-item {
- line-height: 22px;
- }
- .expand-collapse-table-row {
-
- .data-row {
- background: @tlv_color_u;
- .hand;
- align-items: center;
- padding: 0 12px;
- margin: 1px 0px 1px 0px;
- min-height: 40px;
- }
-
- .data-row:hover {
- .bg_j;
- }
- }
- }
-
- .table {
- height: 640px;
- margin-bottom: 0;
- clear: both;
-
- .empty-row {
- padding: 3px;
- }
-
- .flex-item {
- line-height: 22px;
- }
-
- .table-header {
-
- line-height: 14px;
- background-color: @main_color_a;
- color: @main_color_p;
- text-align: left;
- padding: 7px 5px 7px 10px;
- .f-type._14_m;
- }
- .head {
- background-color: #e6e6e6;
- }
-
- .body {
- .scrollbar-container {
- .perfect-scrollbar;
- max-height: 610px;
- }
-
- .expand-collapse-inputs-table-icon {
- .hand;
- .sprite-new;
- .arrow-up;
- transition: .3s all;
- position: relative;
- left: 8px;
- border: none !important;
- padding: 0px 10px 0px 10px;
- }
-
- .table-col-text {
- margin-left: 14px;
- }
- }
- }
-
- .inputs-header {
- width: 100%;
- position: relative;
- bottom: 31px;
- }
-
- .inputs-tables-container {
- width: 100%;
- min-width: 100%;
- display: flex;
- }
-
- .inputs-button-container {
- width: 8%;
- min-width: 8%;
- display: flex;
-
- .right-arrow-btn {
- .sprite-new;
- .blue-right-arrow-circle;
- margin: auto;
- cursor: pointer;
- }
- }
-
- .table-container-flex {
- margin-top: 0;
- width: 46%;
- min-width: 46%;
- display: inline-block;
- float: left;
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts
index 180d789..83a2be2 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts
@@ -27,7 +27,6 @@
* limitations under the License.
*/
-
'use strict';
import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html
index 0e7c355..236289f 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="workspace-interface-operation">
<interface-operation
[component]="component"
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/management-workflow/management-workflow-view.html b/catalog-ui/src/app/view-models/workspace/tabs/management-workflow/management-workflow-view.html
index 4a97b64..ddabd68 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/management-workflow/management-workflow-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/management-workflow/management-workflow-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<loader data-display="isLoading"></loader>
<div class="workspace-management-workflow" ng-if="vendorModel">
<punch-out name="'sequence-diagram'" data="vendorModel" user="user" on-event="onVendorEvent"></punch-out>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view.html b/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view.html
index a1efb33..01343a3 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/network-call-flow/network-call-flow-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<loader data-display="isLoading"></loader>
<div ng-if="vendorMessageModel" class="workspace-network-call-flow">
<punch-out name="'sequence-diagram'" data="vendorMessageModel" user="user" on-event="onVendorEvent"></punch-out>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts
deleted file mode 100644
index d3ccbe3..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-
-* Copyright (c) 2018 AT&T Intellectual Property.
-
-*
-
-* 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.
-
-*/
-
-import {IUserProperties, Plugin} from "app/models";
-import {CacheService} from "app/services";
-import {PluginsService} from "../../../../ng2/services/plugins.service";
-import {IWorkspaceViewModelScope} from "../../workspace-view-model";
-
-
-interface IPluginsContextViewModelScope extends IWorkspaceViewModelScope {
- plugin: Plugin;
- user: IUserProperties;
- queryParams: Object;
- isLoading: boolean;
- show: boolean;
-
- onLoadingDone(plugin: Plugin): void;
-}
-
-export class PluginsContextViewModel {
- static '$inject' = [
- '$scope',
- '$stateParams',
- 'Sdc.Services.CacheService',
- 'PluginsService'
- ];
-
- constructor(private $scope: IPluginsContextViewModelScope,
- private $stateParams: any,
- private cacheService: CacheService,
- private pluginsService: PluginsService) {
-
- this.initScope();
- }
-
- private initScope = (): void => {
- this.$scope.show = false;
- this.$scope.plugin = this.pluginsService.getPluginByStateUrl(this.$stateParams.path);
- this.$scope.user = this.cacheService.get('user');
-
- this.$scope.isLoading = true;
-
- this.$scope.queryParams = {
- userId: this.$scope.user.userId,
- userRole: this.$scope.user.role,
- displayType: "context",
- contextType: this.$scope.component.getComponentSubType(),
- uuid: this.$scope.component.uuid,
- lifecycleState: this.$scope.component.lifecycleState,
- isOwner: this.$scope.component.lastUpdaterUserId === this.$scope.user.userId,
- version: this.$scope.component.version,
- parentUrl: window.location.origin,
- eventsClientId: this.$scope.plugin.pluginId
- };
-
- if (this.$stateParams.queryParams) {
- _.assign(this.$scope.queryParams, this.$stateParams.queryParams);
- }
-
- this.$scope.onLoadingDone = (plugin: Plugin) => {
- if (plugin.pluginId == this.$scope.plugin.pluginId) {
- this.$scope.isLoading = false;
- }
- };
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view.html b/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view.html
deleted file mode 100644
index 44c04e4..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view.html
+++ /dev/null
@@ -1,20 +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.
--->
-
-<loader display="isLoading && plugin.isOnline" ></loader>
-<div class="workspace-plugins">
- <plugin-frame (on-loading-done)="onLoadingDone(plugin)" [plugin]="plugin" [query-params]="queryParams"></plugin-frame>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts
index b09662d..9794209 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts
@@ -19,12 +19,12 @@
*/
'use strict';
-import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
-import {PropertyModel} from "app/models";
-import {ModalsHandler} from "app/utils";
-import {COMPONENT_FIELDS} from "../../../../utils/constants";
-import {ComponentGenericResponse} from "../../../../ng2/services/responses/component-generic-response";
-import {ComponentServiceNg2} from "../../../../ng2/services/component-services/component.service";
+import { IWorkspaceViewModelScope } from "app/view-models/workspace/workspace-view-model";
+import { PropertyModel } from "app/models";
+import { ModalsHandler } from "app/utils";
+import { ComponentGenericResponse } from "../../../../ng2/services/responses/component-generic-response";
+import { ComponentServiceNg2 } from "../../../../ng2/services/component-services/component.service";
+import { SdcUiCommon, SdcUiServices, SdcUiComponents } from "onap-ui-angular";
interface IPropertiesViewModelScope extends IWorkspaceViewModelScope {
tableHeadersList:Array<any>;
@@ -43,14 +43,16 @@
'$scope',
'$filter',
'ModalsHandler',
- 'ComponentServiceNg2'
+ 'ComponentServiceNg2',
+ 'ModalServiceSdcUI'
];
constructor(private $scope:IPropertiesViewModelScope,
private $filter:ng.IFilterService,
private ModalsHandler:ModalsHandler,
- private ComponentServiceNg2:ComponentServiceNg2) {
+ private ComponentServiceNg2:ComponentServiceNg2,
+ private modalService: SdcUiServices.ModalService) {
this.initComponentProperties();
}
@@ -101,12 +103,13 @@
this.$scope.delete = (property:PropertyModel):void => {
- let onOk = ():void => {
+ let onOk: Function = ():void => {
this.$scope.component.deleteProperty(property.uniqueId);
};
let title:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TITLE");
let message:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TEXT", "{'name': '" + property.name + "'}");
- this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
+ const okButton = {testId: "OK", text: "OK", type: SdcUiCommon.ButtonType.info, callback: onOk, closeModal: true} as SdcUiComponents.ModalButtonComponent;
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
};
}
}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view.html b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view.html
index 1505e83..1d8a2ff 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<div class="workspace-properties">
<div id="left-top-bar">
<span id="properties-count">Total Properties: {{component.properties.length}}</span>
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 566cc5f..0000000
--- 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 14b45cb..0000000
--- 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 c661afe..0000000
--- 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 928f671..0000000
--- 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
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
deleted file mode 100644
index a1f8152..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model.ts
+++ /dev/null
@@ -1,105 +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=========================================================
- */
-
-'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>;
- artifactType:string;
- downloadFile:IFileDownload;
- isLoading:boolean;
- sortBy:string;
- reverse:boolean;
-
- getTitle():string;
- download(artifact:ArtifactModel):void;
- sort(sortBy:string):void;
- showNoArtifactMessage():boolean;
-}
-
-export class ToscaArtifactsViewModel {
-
- static '$inject' = [
- '$scope',
- '$filter',
- 'ComponentServiceNg2'
- ];
-
- constructor(private $scope:IToscaArtifactsScope,
- private $filter:ng.IFilterService,
- private ComponentServiceNg2:ComponentServiceNg2) {
- this.initToscaArtifacts();
- }
-
- private initToscaArtifacts = (): void => {
-
- if(!this.$scope.component.toscaArtifacts) {
- this.$scope.isLoading = true;
- this.ComponentServiceNg2.getComponentToscaArtifacts(this.$scope.component).subscribe((response:ComponentGenericResponse) => {
- this.$scope.component.toscaArtifacts = response.toscaArtifacts;
- this.initScope();
- this.$scope.isLoading = false;
- }, () => {
- this.$scope.isLoading = false;
- });
- } else {
- this.initScope();
- }
- }
-
- private initScope = ():void => {
- this.$scope.isLoading = false;
- this.$scope.sortBy = 'artifactDisplayName';
- this.$scope.reverse = false;
- this.$scope.setValidState(true);
- this.$scope.artifactType = 'informational';
- this.$scope.getTitle = ():string => {
- return this.$filter("resourceName")(this.$scope.component.name) + ' Artifacts';
-
- };
-
- this.$scope.tableHeadersList = [
- {title: 'Name', property: 'artifactDisplayName'},
- {title: 'Type', property: 'artifactType'},
- {title: 'Version', property: 'artifactVersion'}
- ];
-
- this.$scope.artifacts = <ArtifactModel[]>_.values(this.$scope.component.toscaArtifacts);
- this.$scope.sort = (sortBy:string):void => {
- this.$scope.reverse = (this.$scope.sortBy === sortBy) ? !this.$scope.reverse : false;
- this.$scope.sortBy = sortBy;
- };
-
-
- this.$scope.showNoArtifactMessage = ():boolean => {
- if (this.$scope.artifacts.length === 0) {
- return true;
- }
- return false;
- };
-
- }
-}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view.html
deleted file mode 100644
index b354e7a..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view.html
+++ /dev/null
@@ -1,65 +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-tosca-artifact">
- <div class="table-container-flex">
- <div class="table" data-ng-class="{'view-mode': isViewMode()}">
- <div class="head flex-container">
- <div class="table-header head-row hand flex-item" ng-repeat="header in tableHeadersList track by $index" data-ng-click="sort(header.property)">{{header.title}}
- <span data-ng-show="sortBy === header.property" class="table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span>
- </div>
- <div class="table-no-text-header head-row flex-item"></div>
- </div>
- <div class="body">
- <perfect-scrollbar suppress-scroll-x="true" scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <div data-ng-if="showNoArtifactMessage()" class="no-row-text" data-ng-class="{'disabled': isDisableMode()}">
- There are no TOSCA artifacts to display
- </div>
- <div data-ng-repeat-start="artifact in artifacts| orderBy:sortBy:reverse track by $index"
- class="flex-container data-row" data-tests-id="{{artifact.artifactDisplayName}}"
- data-ng-class="{'selected': artifact.selected}">
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="name-{{$index}}">
- <span class="sprite table-arrow" data-ng-class="{'opened': artifact.selected}"></span>
- {{artifact.artifactDisplayName}}
- </div>
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="type-{{$index}}">
- {{artifact.artifactType}}
- </div>
-
- <div class="table-col-general flex-item" data-ng-click="artifact.selected = !artifact.selected" data-tests-id="version-{{$index}}">
- {{artifact.artifactVersion}}
- </div>
-
- <div class="table-btn-col flex-item download-icon-container">
- <button class="table-download-btn tosca" download-artifact data-tests-id="download-{{artifact.artifactDisplayName}}"
- data-ng-if="artifact.artifactName" component="component" artifact="artifact" show-loader="true"></button>
- </div>
- </div>
- <div data-ng-repeat-end="" data-ng-if="artifact.selected" class="item-opened" data-tests-id="details-{{$index}}">
- <div><span class="details-title">Label:</span> {{artifact.artifactLabel}}</div>
- <div><span class="details-title">UUID:</span> {{artifact.artifactUUID}}</div>
- <div><span class="details-title">Description:</span> {{artifact.description}}</div>
-
-
- </div>
-
- </perfect-scrollbar>
- </div>
- </div>
- </div>
-</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less
deleted file mode 100644
index 23be3c3..0000000
--- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less
+++ /dev/null
@@ -1,77 +0,0 @@
-.workspace-tosca-artifact {
- width: 100%;
- display: inline-block;
- .w-sdc-classic-btn {
- float: right;
- margin-bottom: 10px;
- }
-
- .details-title{
- font-weight: bold;
- margin-right: 5px;
- }
-
- .table{
- height: 490px;
- margin-bottom: 0;
- }
-
-
- .table-container-flex {
- margin-top: 0;
- .item-opened{
- word-wrap: break-word;
- }
-
-
- .flex-item:nth-child(1) {
- flex-grow: 15;
- .hand;
- span.table-arrow {
- margin-right: 7px;
- }
- }
-
- .flex-item:nth-child(2) {
- flex-grow: 6;
- }
-
- .flex-item:nth-child(3) {
- flex-grow: 1;
- }
-
- .flex-item:nth-child(4) {
- flex-grow: 1;
- }
-
-
-
-
- .table-download-btn{
- &.tosca{
- margin-left: 0;
- margin-top: 8px;
- }
- }
-
- .download-icon-container{
- position: relative;
-
- .loader{
- left: 60%;
- top: 45px;
- border: none;
- background-color: transparent;
- height: 0px;
- width: 63px;
- outline: none;
-
- }
- }
-
-
- }
-
-}
-
-
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 f4bbed2..1166728 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
@@ -22,103 +22,110 @@
* Created by obarda on 3/30/2016.
*/
'use strict';
-import * as _ from "lodash";
+import * as _ from 'lodash';
import {
- IUserProperties, IAppMenu, Resource, Component, Plugin, PluginsConfiguration, PluginDisplayOptions,
- RelationshipTypeModel, NodeTypeModel, CapabilityTypeModel
-} from "app/models";
+ IUserProperties,
+ IAppMenu,
+ Resource,
+ Component,
+ Plugin,
+ PluginsConfiguration,
+ PluginDisplayOptions
+} from 'app/models';
import {
- WorkspaceMode, ComponentFactory, ChangeLifecycleStateHandler, Role, ComponentState, MenuItemGroup, MenuHandler,
- MenuItem, ModalsHandler, States, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ResourceType, PREVIOUS_CSAR_COMPONENT
-} from "app/utils";
+ MenuItem, ModalsHandler, States, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ResourceType, PREVIOUS_CSAR_COMPONENT,
+ WorkspaceMode, ComponentFactory, ChangeLifecycleStateHandler, Role, ComponentState, MenuItemGroup, MenuHandler
+} from 'app/utils';
import {
EventListenerService,
- EntityService,
- ProgressService,
- CacheService,
- LeftPaletteLoaderService
-} from "app/services";
-import {FileUploadModel} from "../../directives/file-upload/file-upload";
-import {AutomatedUpgradeService} from "../../ng2/pages/automated-upgrade/automated-upgrade.service";
-import {ComponentServiceNg2} from "../../ng2/services/component-services/component.service";
-import {EventBusService} from "../../ng2/services/event-bus.service";
-import {PluginsService} from "../../ng2/services/plugins.service";
-import {IDependenciesServerResponse} from "../../ng2/services/responses/dependencies-server-response";
+ LeftPaletteLoaderService,
+ ProgressService
+} from 'app/services';
+import {
+ CacheService
+} from 'app/services-ng2';
+import { AutomatedUpgradeService } from '../../ng2/pages/automated-upgrade/automated-upgrade.service';
+import { CatalogService } from '../../ng2/services/catalog.service';
+import { ComponentServiceNg2 } from '../../ng2/services/component-services/component.service';
+import { EventBusService } from '../../ng2/services/event-bus.service';
+import { HomeService } from '../../ng2/services/home.service';
+import { PluginsService } from '../../ng2/services/plugins.service';
+import { IDependenciesServerResponse } from '../../ng2/services/responses/dependencies-server-response';
+import { WorkspaceNg1BridgeService } from '../../ng2/pages/workspace/workspace-ng1-bridge-service';
+import { WorkspaceService } from '../../ng2/pages/workspace/workspace.service';
export interface IWorkspaceViewModelScope extends ng.IScope {
- isLoading:boolean;
- isCreateProgress:boolean;
- component:Component;
- originComponent:Component;
- componentType:string;
- importFile:any;
- leftBarTabs:MenuItemGroup;
- isNew:boolean;
- isFromImport:boolean;
- isValidForm:boolean;
- isActiveTopBar:boolean;
- mode:WorkspaceMode;
- breadcrumbsModel:Array<MenuItemGroup>;
- sdcMenu:IAppMenu;
- changeLifecycleStateButtons:any;
- version:string;
- versionsList:Array<any>;
- changeVersion:any;
- isComposition:boolean;
- isDeployment:boolean;
- isPlugins:boolean;
- $state:ng.ui.IStateService;
- user:IUserProperties;
- thirdParty:boolean;
- disabledButtons:boolean;
- menuComponentTitle:string;
- progressService:ProgressService;
- progressMessage:string;
+ isLoading: boolean;
+ isCreateProgress: boolean;
+ component: Component;
+ originComponent: Component;
+ componentType: string;
+ importFile: any;
+ leftBarTabs: MenuItemGroup;
+ isNew: boolean;
+ isFromImport: boolean;
+ isValidForm: boolean;
+ isActiveTopBar: boolean;
+ mode: WorkspaceMode;
+ breadcrumbsModel: Array<MenuItemGroup>;
+ sdcMenu: IAppMenu;
+ changeLifecycleStateButtons: any;
+ version: string;
+ versionsList: Array<any>;
+ changeVersion: any;
+ isComposition: boolean;
+ isDeployment: boolean;
+ isPlugins: boolean;
+ $state: ng.ui.IStateService;
+ user: IUserProperties;
+ thirdParty: boolean;
+ disabledButtons: boolean;
+ menuComponentTitle: string;
+ progressService: ProgressService;
+ progressMessage: string;
ComponentServiceNg2: ComponentServiceNg2;
// leftPanelComponents:Array<Models.Components.Component>; //this is in order to load the left panel once, and not wait long time when moving to composition
- unsavedChanges:boolean;
- unsavedChangesCallback:Function;
- unsavedFile:boolean;
- capabilityTypesList: Array<CapabilityTypeModel>;
- relationshipTypesList: Array<RelationshipTypeModel>;
- nodeTypesList: Array<NodeTypeModel>;
+ unsavedChanges: boolean;
+ unsavedChangesCallback: Function;
+ unsavedFile: boolean;
+ hasNoDependencies: boolean;
- startProgress(message:string):void;
- stopProgress():void;
- updateBreadcrumbs(component:Component):void;
- updateUnsavedFileFlag(isUnsaved:boolean):void;
- showChangeStateButton():boolean;
- getComponent():Component;
- setComponent(component:Component):void;
- setOriginComponent(component:Component):void;
- onMenuItemPressed(state:string, params:any):ng.IPromise<boolean>;
- create():void;
- save():Promise<void>;
- setValidState(isValid:boolean):void;
- changeLifecycleState(state:string):void;
- handleChangeLifecycleState(state:string, newCsarVersion?:string):void;
- disableMenuItems():void;
- enableMenuItems():void;
- isDesigner():boolean;
- isViewMode():boolean;
- isEditMode():boolean;
- isCreateMode():boolean;
- isDisableMode():boolean;
- isGeneralView():boolean;
- goToBreadcrumbHome():void;
- onVersionChanged(selectedId:string):void;
- getLatestVersion():void;
- getStatus():string;
- showLifecycleIcon():boolean;
- updateSelectedMenuItem(state:string):void;
- isSelected(menuItem:MenuItem):boolean;
- uploadFileChangedInGeneralTab():void;
- updateMenuComponentName(ComponentName:string):void;
- getTabTitle():string;
- reload(component:Component):void;
+ startProgress(message: string): void;
+ stopProgress(): void;
+ updateBreadcrumbs(component: Component): void;
+ updateUnsavedFileFlag(isUnsaved: boolean): void;
+ showChangeStateButton(): boolean;
+ getComponent(): Component;
+ setComponent(component: Component): void;
+ setOriginComponent(component: Component): void;
+ onMenuItemPressed(state: string, params: any): ng.IPromise<boolean>;
+ create(): void;
+ save(): Promise<void>;
+ setValidState(isValid: boolean): void;
+ changeLifecycleState(state: string): void;
+ handleChangeLifecycleState(state: string, newCsarVersion?: string, errorFunction?: Function): void;
+ disableMenuItems(): void;
+ enableMenuItems(): void;
+ isDesigner(): boolean;
+ isViewMode(): boolean;
+ isEditMode(): boolean;
+ isCreateMode(): boolean;
+ isDisableMode(): boolean;
+ isGeneralView(): boolean;
+ goToBreadcrumbHome(): void;
+ onVersionChanged(selectedId: string): void;
+ getLatestVersion(): void;
+ getStatus(): string;
+ showLifecycleIcon(): boolean;
+ updateSelectedMenuItem(state: string): void;
+ isSelected(menuItem: MenuItem): boolean;
+ uploadFileChangedInGeneralTab(): void;
+ updateMenuComponentName(ComponentName: string): void;
+ getTabTitle(): string;
+ reload(component: Component): void;
}
export class WorkspaceViewModel {
@@ -133,53 +140,55 @@
'MenuHandler',
'Sdc.Services.CacheService',
'ChangeLifecycleStateHandler',
- 'ModalsHandler',
'LeftPaletteLoaderService',
'$filter',
'EventListenerService',
- 'Sdc.Services.EntityService',
'Notification',
'$stateParams',
+ 'HomeService',
+ 'CatalogService',
'Sdc.Services.ProgressService',
'ComponentServiceNg2',
'AutomatedUpgradeService',
'EventBusService',
- 'PluginsService'
+ 'PluginsService',
+ 'WorkspaceNg1BridgeService',
+ 'workspaceService'
];
- constructor(private $scope:IWorkspaceViewModelScope,
- private injectComponent:Component,
- private ComponentFactory:ComponentFactory,
- private $state:ng.ui.IStateService,
- private sdcMenu:IAppMenu,
- private $q:ng.IQService,
- private MenuHandler:MenuHandler,
- private cacheService:CacheService,
- private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
- private ModalsHandler:ModalsHandler,
- private LeftPaletteLoaderService:LeftPaletteLoaderService,
- private $filter:ng.IFilterService,
- private EventListenerService:EventListenerService,
- private EntityService:EntityService,
- private Notification:any,
- private $stateParams:any,
- private progressService:ProgressService,
- private ComponentServiceNg2:ComponentServiceNg2,
- private AutomatedUpgradeService:AutomatedUpgradeService,
- private eventBusService:EventBusService,
- private pluginsService:PluginsService) {
-
+ constructor(private $scope: IWorkspaceViewModelScope,
+ private injectComponent: Component,
+ private ComponentFactory: ComponentFactory,
+ private $state: ng.ui.IStateService,
+ private sdcMenu: IAppMenu,
+ private $q: ng.IQService,
+ private MenuHandler: MenuHandler,
+ private cacheService: CacheService,
+ private ChangeLifecycleStateHandler: ChangeLifecycleStateHandler,
+ private LeftPaletteLoaderService: LeftPaletteLoaderService,
+ private $filter: ng.IFilterService,
+ private EventListenerService: EventListenerService,
+ private Notification: any,
+ private $stateParams: any,
+ private homeService: HomeService,
+ private catalogService: CatalogService,
+ private progressService: ProgressService,
+ private ComponentServiceNg2: ComponentServiceNg2,
+ private AutomatedUpgradeService: AutomatedUpgradeService,
+ private eventBusService: EventBusService,
+ private pluginsService: PluginsService,
+ private workspaceNg1BridgeService: WorkspaceNg1BridgeService,
+ private workspaceService: WorkspaceService) {
-
- this.initScope();
- this.initAfterScope();
- this.$scope.updateSelectedMenuItem(this.$state.current.name);
+ this.initScope();
+ // this.initAfterScope();
+ this.$scope.updateSelectedMenuItem(this.$state.current.name);
}
- private role:string;
- private category:string;
- private components:Array<Component>;
-
+ private role: string;
+ private category: string;
+ private components: Component[];
+
private initViewMode = ():WorkspaceMode => {
let mode = WorkspaceMode.VIEW;
@@ -187,35 +196,34 @@
mode = WorkspaceMode.CREATE;
} else {
if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
- this.$scope.component.lastUpdaterUserId === this.cacheService.get("user").userId) {
- if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role == Role.DESIGNER) {
+ this.$scope.component.lastUpdaterUserId === this.cacheService.get('user').userId) {
+ if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role === Role.DESIGNER) {
mode = WorkspaceMode.EDIT;
}
}
}
+ this.workspaceNg1BridgeService.updateIsViewOnly(mode === WorkspaceMode.VIEW);
return mode;
- };
+ }
- private initChangeLifecycleStateButtons = ():void => {
- let state = this.$scope.component.isService() && (Role.OPS == this.role || Role.GOVERNOR == this.role) ? this.$scope.component.distributionStatus : this.$scope.component.lifecycleState;
+ private initChangeLifecycleStateButtons = (): void => {
+ let state: string;
+ if (this.$scope.component.isService() && this.$scope.component.lifecycleState === 'CERTIFIED') {
+ state = this.$scope.component.distributionStatus;
+ } else {
+ state = this.$scope.component.lifecycleState;
+ }
this.$scope.changeLifecycleStateButtons = (this.sdcMenu.roles[this.role].changeLifecycleStateButtons[state] || [])[this.$scope.component.componentType.toUpperCase()];
+ }
- };
-
- private initLeftPalette = ():void => {
- //this.LeftPaletteLoaderService.loadLeftPanel(this.$scope.component);
- };
-
- private initScope = ():void => {
-
+ private initScope = (): void => {
this.$scope.component = this.injectComponent;
- //this.initLeftPalette();
this.$scope.menuComponentTitle = this.$scope.component.name;
this.$scope.disabledButtons = false;
this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
this.$scope.componentType = this.$scope.component.componentType;
this.$scope.version = this.cacheService.get('version');
- this.$scope.user = this.cacheService.get("user");
+ this.$scope.user = this.cacheService.get('user');
this.role = this.$scope.user.role;
this.category = this.$scope.component.selectedCategory;
this.$scope.mode = this.initViewMode();
@@ -229,10 +237,11 @@
this.$scope.progressService = this.progressService;
this.$scope.unsavedChanges = false;
- this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
- //this.EventListenerService.registerObserverCallback(EVENTS.ON_UPDATE_VSP_FILE, this.updateVspFlag);
+ this.$scope.hasNoDependencies = true;
+ this.verifyIfDependenciesExist();
- this.$scope.getComponent = ():Component => {
+ this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
+ this.$scope.getComponent = (): Component => {
return this.$scope.component;
};
@@ -261,17 +270,17 @@
this.$scope.archiveComponent = ():void => {
this.$scope.isLoading = true;
const typeComponent = this.$scope.component.componentType;
- this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=>{
+ this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
this.$scope.isLoading = false;
- if(this.$state.params.previousState){
- switch(this.$state.params.previousState){
+ if (this.$state.params.previousState) {
+ switch (this.$state.params.previousState) {
case 'catalog':
case 'dashboard':
this.$state.go(this.$state.params.previousState);
break;
default:
break;
- }
+ }
}
this.$scope.component.archived = true;
this.deleteArchiveCache();
@@ -281,17 +290,17 @@
title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
});
}, (error) => { this.$scope.isLoading = false; });
- }
+ }
this.$scope.restoreComponent = ():void => {
this.$scope.isLoading = true;
const typeComponent = this.$scope.component.componentType;
- this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=>{
+ this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
this.$scope.isLoading = false;
this.Notification.success({
- message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
- });
+ message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
+ title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
+ });
});
this.$scope.component.archived = false;
this.deleteArchiveCache();
@@ -304,13 +313,13 @@
if(this.$scope.isValidForm){
this.$scope.save().then(() => {
this.$scope.onMenuItemPressed(toState.name, toParams);
- }, ()=> {
+ }, ()=> {
console.error("Save failed, unable to navigate to " + toState.name);
})
} else {
console.error("Form is invalid, unable to navigate to " + toState.name);
}
- }
+ }
}
});
@@ -384,7 +393,7 @@
};
this.$scope.create = () => {
-
+
this.$scope.startProgress("Creating Asset...");
_.first(this.$scope.leftBarTabs.menuItems).isDisabled = true;//disabled click on general tab (DE246274)
@@ -429,7 +438,7 @@
};
this.$scope.save = ():Promise<void> => {
-
+
this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_CLICK);
this.$scope.startProgress("Updating Asset...");
@@ -445,6 +454,7 @@
let onFailed = () => {
stopProgressAndEnableUI();
+ this.$scope.updateUnsavedFileFlag(true);
this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
reject();
@@ -459,7 +469,7 @@
});
this.$scope.updateBreadcrumbs(component);
-
+
//update the component
this.$scope.setComponent(component);
this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
@@ -467,13 +477,14 @@
if (this.cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
}
- if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)){
+ if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
}
//clear edit flags
this.$state.current.data.unsavedChanges = false;
this.$scope.unsavedFile = false;
+ this.$scope.reload(component);
resolve();
};
@@ -497,35 +508,40 @@
this.$state.go('dashboard');
};
- this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string) => {
+ this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string, onError?: Function) => {
if ('monitor' === state) {
this.$state.go('workspace.distribution');
return;
}
let data = this.$scope.changeLifecycleStateButtons[state];
- let onSuccess = (component:Component, url:string):void => {
- //Updating the component from server response
-
+ if (!data && this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
+ data = {text: 'Check Out', url: 'lifecycleState/CHECKOUT'};
+ }
+ const onSuccess = (component, url:string):void => {
+ // Updating the component from server response
+
// Creating the data object to notify the plugins with
- let eventData: any = {
+ const eventData: any = {
uuid: this.$scope.component.uuid,
version: this.$scope.component.version
};
- //the server returns only metaData (small component) except checkout (Full component) ,so we update only the statuses of distribution & lifecycle
+ // the server returns only metaData (small component) except checkout (Full component) ,so we update only the statuses of distribution & lifecycle
this.$scope.component.lifecycleState = component.lifecycleState;
this.$scope.component.distributionStatus = component.distributionStatus;
switch (url) {
case 'lifecycleState/CHECKOUT':
+ this.workspaceNg1BridgeService.updateIsViewOnly(false);
this.eventBusService.notify("CHECK_OUT", eventData, false).subscribe(() => {
// only checkOut get the full component from server
// this.$scope.component = component;
// Work around to change the csar version
if(newCsarVersion) {
this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, newCsarVersion);
- }
+ (this.$scope.component as Resource).csarVersion = newCsarVersion;
+ }
//when checking out a minor version uuid remains
const bcIdx = _.findIndex(this.components, (item) => {
@@ -542,6 +558,7 @@
this.initVersionObject();
this.$scope.isLoading = false;
this.EventListenerService.notifyObservers(EVENTS.ON_CHECKOUT, component);
+ this.workspaceService.setComponentMetadata(component);
this.Notification.success({
message: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TEXT"),
@@ -551,6 +568,7 @@
});
break;
case 'lifecycleState/CHECKIN':
+ this.workspaceNg1BridgeService.updateIsViewOnly(true);
defaultActionAfterChangeLifecycleState();
this.Notification.success({
message: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TEXT"),
@@ -566,77 +584,25 @@
});
});
break;
- case 'lifecycleState/certificationRequest':
- defaultActionAfterChangeLifecycleState();
- this.Notification.success({
- message: this.$filter('translate')("SUBMIT_FOR_TESTING_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("SUBMIT_FOR_TESTING_SUCCESS_MESSAGE_TITLE")
- });
- break;
- //Tester Role
- case 'lifecycleState/failCertification':
- defaultActionAfterChangeLifecycleState();
- this.Notification.success({
- message: this.$filter('translate')("REJECT_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("REJECT_SUCCESS_MESSAGE_TITLE")
- });
- break;
case 'lifecycleState/certify':
-
this.$scope.handleCertification(component);
-
+ this.verifyIfDependenciesExist();
+ this.$scope.reload(component);
break;
- //DE203504 Bug Fix Start
- case 'lifecycleState/startCertification':
- this.initChangeLifecycleStateButtons();
- this.Notification.success({
- message: this.$filter('translate')("START_TESTING_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("START_TESTING_SUCCESS_MESSAGE_TITLE")
- });
- break;
- case 'lifecycleState/cancelCertification':
- this.initChangeLifecycleStateButtons();
- this.Notification.success({
- message: this.$filter('translate')("CANCEL_TESTING_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("CANCEL_TESTING_SUCCESS_MESSAGE_TITLE")
- });
- break;
- //Ops Role
- case 'distribution/PROD/activate':
- this.initChangeLifecycleStateButtons();
+ case 'distribution/PROD/activate':
this.Notification.success({
message: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TEXT"),
title: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TITLE")
});
- break;
- //Governor Role
- case 'distribution-state/reject':
this.initChangeLifecycleStateButtons();
- this.Notification.success({
- message: this.$filter('translate')("REJECT_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("REJECT_SUCCESS_MESSAGE_TITLE")
- });
break;
- case 'distribution-state/approve':
- this.initChangeLifecycleStateButtons();
- this.$state.go('catalog');
- this.Notification.success({
- message: this.$filter('translate')("APPROVE_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("APPROVE_SUCCESS_MESSAGE_TITLE")
- });
- break;
- //DE203504 Bug Fix End
-
default :
defaultActionAfterChangeLifecycleState();
-
}
- if (data.url != 'lifecycleState/CHECKOUT') {
+ if (data.url !== 'lifecycleState/CHECKOUT') {
this.$scope.isLoading = false;
}
};
- //this.$scope.isLoading = true;
-
this.ChangeLifecycleStateHandler.changeLifecycleState(this.$scope.component, data, this.$scope, onSuccess);
};
@@ -663,6 +629,21 @@
return this.$scope.mode === WorkspaceMode.CREATE;
};
+ this.$scope.checkDisableButton = (button: any):boolean => {
+ // Logic moved from html to component
+ if (this.$scope.isCreateMode() || button.disabled || this.$scope.disabledButtons || !this.$scope.isValidForm || this.$scope.unsavedChanges || this.$scope.component.archived){
+ return true;
+ }
+
+ // Specific verification for Checkout - enabled only in case the component is the latest version.
+ let result: boolean = false;
+
+ if (button.url === 'lifecycleState/CHECKOUT') {
+ result = !this.$scope.component.isLatestVersion();
+ }
+ return result;
+ };
+
this.$scope.isEditMode = ():boolean => {
return this.$scope.mode === WorkspaceMode.EDIT;
};
@@ -686,18 +667,14 @@
this.initMenuItems();
- this.$scope.showChangeStateButton = ():boolean => {
- let result:boolean = true;
- if (!this.$scope.component.isLatestVersion() && Role.OPS != this.role && Role.GOVERNOR != this.role) {
+ this.$scope.showLatestVersion = (): boolean => {
+ let result: boolean = true;
+ if (!this.$scope.component.isLatestVersion()) {
result = false;
}
if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) {
result = false;
}
- if (ComponentState.CERTIFIED != this.$scope.component.lifecycleState &&
- (Role.OPS == this.role || Role.GOVERNOR == this.role)) {
- result = false;
- }
return result;
};
@@ -705,20 +682,20 @@
let stateArray:Array<string> = state.split('.', 2);
let stateWithoutInternalNavigate:string = stateArray[0] + '.' + stateArray[1];
let selectedItem:MenuItem = _.find(this.$scope.leftBarTabs.menuItems, (item:MenuItem) => {
- let itemStateArray: Array<string> = item.state.split('.', 2);
+ let itemStateArray:Array<string> = item.state.split('.', 2);
let itemStateWithoutNavigation:string = itemStateArray[0] + '.' + itemStateArray[1];
return (itemStateWithoutNavigation === stateWithoutInternalNavigate);
});
let selectedIndex = selectedItem ? this.$scope.leftBarTabs.menuItems.indexOf(selectedItem) : 0;
- if (stateArray[1] === 'plugins') {
+ if (stateArray[1] === 'plugins') {
_.forEach(PluginsConfiguration.plugins, (plugin) => {
if (plugin.pluginStateUrl == this.$state.params.path) {
return false;
}
else if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
- selectedIndex++;
+ selectedIndex++;
}
});
}
@@ -726,11 +703,11 @@
this.$scope.leftBarTabs.selectedIndex = selectedIndex;
};
- this.$scope.isSelected = (menuItem:MenuItem): boolean => {
+ this.$scope.isSelected = (menuItem: MenuItem): boolean => {
return this.$scope.leftBarTabs.selectedIndex === _.indexOf(this.$scope.leftBarTabs.menuItems, menuItem);
};
- this.$scope.$watch('$state.current.name', (newVal:string):void => {
+ this.$scope.$watch('$state.current.name', (newVal: string): void => {
if (newVal) {
this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1);
this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT;
@@ -738,20 +715,26 @@
}
});
- this.$scope.getTabTitle = ():string => {
- return this.$scope.leftBarTabs.menuItems.find((menuItem:MenuItem) => {
+ this.$scope.getTabTitle = (): string => {
+ return this.$scope.leftBarTabs.menuItems.find((menuItem: MenuItem) => {
return menuItem.state == this.$scope.$state.current.name;
}).text;
};
- this.$scope.reload = (component:Component):void => {
- this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
+ this.$scope.reload = (component: Component): void => {
+ const isGeneralTab = this.$state.current.name === 'workspace.general';
+ // nullify the componentCsar in case we are in general tab so we know we didnt came from updateVsp Modal
+ if (isGeneralTab) {
+ this.$state.go(this.$state.current.name, {id: component.uniqueId, componentCsar: null}, {reload: true});
+ } else {
+ this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
+ }
};
this.$scope.$on('$destroy', () => {
this.EventListenerService.unRegisterObserver(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES);
});
-
+
this.$scope.openAutomatedUpgradeModal = ():void => {
this.$scope.isLoading = true;
this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>)=> {
@@ -761,14 +744,14 @@
}
this.$scope.handleCertification = (certifyComponent): void => {
- if (this.$scope.component.getComponentSubType() === ResourceType.VF) {
+ if (this.$scope.component.getComponentSubType() === ResourceType.VF || this.$scope.component.isService()) {
this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>) => {
this.$scope.isLoading = false;
- let isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
+ const isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
return componentToUpgrade.dependencies && componentToUpgrade.dependencies.length > 0;
});
- if(isUpgradeNeeded.length === 0) {
+ if (isUpgradeNeeded.length === 0) {
this.onSuccessWithoutUpgradeNeeded();
return;
}
@@ -781,52 +764,54 @@
}
this.$scope.disableMenuItems = () => {
- this.$scope.leftBarTabs.menuItems.forEach((item:MenuItem) => {
- item.isDisabled = (States.WORKSPACE_GENERAL != item.state);
+ this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
+ item.isDisabled = (States.WORKSPACE_GENERAL !== item.state);
});
}
-
+
this.$scope.enableMenuItems = () => {
- this.$scope.leftBarTabs.menuItems.forEach((item:MenuItem) => {
+ this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
item.isDisabled = false;
});
- }
+ };
- this.$scope.startProgress = (message:string):void => {
+ this.$scope.startProgress = (message: string): void => {
this.progressService.initCreateComponentProgress(this.$scope.component.uniqueId);
this.$scope.isCreateProgress = true;
this.$scope.progressMessage = message;
};
- this.$scope.stopProgress = ():void => {
+ this.$scope.stopProgress = (): void => {
this.$scope.isCreateProgress = false;
this.progressService.deleteProgressValue(this.$scope.component.uniqueId);
}
- this.$scope.updateBreadcrumbs = (component:Component):void => {
+ this.$scope.updateBreadcrumbs = (component: Component): void => {
// 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
}
- }
+ };
this.$scope.updateUnsavedFileFlag = (isUnsaved:boolean) => {
this.$scope.unsavedFile = isUnsaved;
- }
+ };
- };
+ }
- private onSuccessWithoutUpgradeNeeded = ():void => {
+ private onSuccessWithoutUpgradeNeeded = (): void => {
this.$scope.isLoading = false;
this.Notification.success({
- message: this.$filter('translate')("ACCEPT_TESTING_SUCCESS_MESSAGE_TEXT"),
- title: this.$filter('translate')("ACCEPT_TESTING_SUCCESS_MESSAGE_TITLE")
+ message: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TEXT'),
+ title: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TITLE')
});
- this.$state.go('dashboard');
+ this.initVersionObject();
+ this.initChangeLifecycleStateButtons();
}
+
private refreshDataAfterChangeLifecycleState = (component:Component):void => {
this.$scope.isLoading = false;
this.$scope.mode = this.initViewMode();
@@ -835,42 +820,42 @@
this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE, component);
}
- private initAfterScope = ():void => {
+ private initAfterScope = (): void => {
// In case user select csar from the onboarding modal, need to disable checkout and submit for testing.
if (this.$state.params['disableButtons'] === true) {
this.$scope.uploadFileChangedInGeneralTab();
}
};
- private initVersionObject = ():void => {
+ private initVersionObject = (): void => {
this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse();
this.$scope.changeVersion = {
- selectedVersion: _.find(this.$scope.versionsList, (versionObj)=> {
+ selectedVersion: _.find(this.$scope.versionsList, (versionObj) => {
return versionObj.versionId === this.$scope.component.uniqueId;
})
};
- };
+ }
- private getNewComponentBreadcrumbItem = ():MenuItem => {
- let text = "";
+ private getNewComponentBreadcrumbItem = (): MenuItem => {
+ let text = '';
if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
text = this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name;
} else {
text = 'Create new ' + this.$state.params['type'];
}
return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]);
- };
+ }
- private updateMenuItemByRole = (menuItems:Array<any>, role:string) => {
- let tempMenuItems:Array<any> = new Array<any>();
- menuItems.forEach((item:any) => {
+ private updateMenuItemByRole = (menuItems: any[], role: string) => {
+ const tempMenuItems: any[] = new Array<any>();
+ menuItems.forEach((item: any) => {
//remove item if role is disabled
if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) {
tempMenuItems.push(item);
}
});
return tempMenuItems;
- };
+ }
private updateMenuItemByCategory = (menuItems:Array<any>, category:string) => {
let tempMenuItems:Array<any> = new Array<any>();
@@ -888,15 +873,15 @@
private deleteArchiveCache = () => {
- this.cacheService.remove("archiveComponents"); //delete the cache to ensure the archive is reloaded from server
- };
+ this.cacheService.remove('archiveComponents'); // delete the cache to ensure the archive is reloaded from server
+ }
private initBreadcrumbs = () => {
this.components = this.cacheService.get('breadcrumbsComponents');
- let breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
+ const breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
if (this.$scope.isCreateMode()) {
- let createItem = this.getNewComponentBreadcrumbItem();
+ const createItem = this.getNewComponentBreadcrumbItem();
if (!breadcrumbsComponentsLvl.menuItems) {
breadcrumbsComponentsLvl.menuItems = [];
}
@@ -905,25 +890,23 @@
}
this.$scope.breadcrumbsModel = [breadcrumbsComponentsLvl, this.$scope.leftBarTabs];
- };
+ }
private initMenuItems() {
- let inCreateMode = this.$scope.isCreateMode();
+ const inCreateMode = this.$scope.isCreateMode();
this.$scope.leftBarTabs = new MenuItemGroup();
- //const menuItemsObjects:Array<any> = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
- let menuItemsObjects:Array<any> = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
- if(this.$scope.component.getComponentSubType()==="SERVICE")
- {
- let menuItemsObjectsCategory:Array<any> = this.updateMenuItemByCategory(menuItemsObjects, this.category);
- menuItemsObjects = menuItemsObjectsCategory;
+ let menuItemsObjects: any[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
+ if (this.$scope.component.getComponentSubType() === 'SERVICE') {
+ const menuItemsObjectsCategory: any[] = this.updateMenuItemByCategory(menuItemsObjects, this.category);
+ menuItemsObjects = menuItemsObjectsCategory;
}
// Only adding plugins to the workspace if they can be displayed for the current user role
_.each(PluginsConfiguration.plugins, (plugin: Plugin) => {
if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
menuItemsObjects.push({
- text: plugin.pluginDisplayOptions["context"].displayName,
+ text: plugin.pluginDisplayOptions['context'].displayName,
action: 'onMenuItemPressed',
state: 'workspace.plugins',
params: {path: plugin.pluginStateUrl}
@@ -931,7 +914,7 @@
}
});
- this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item:MenuItem) => {
+ this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => {
const menuItem = new MenuItem(item.text, item.callback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory);
if (menuItem.params) {
menuItem.params.state = menuItem.state;
@@ -940,7 +923,7 @@
menuItem.params = {state: menuItem.state};
}
menuItem.callback = () => this.$scope[menuItem.action](menuItem.state, menuItem.params);
- menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL != menuItem.state) ||
+ menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL !== menuItem.state) ||
(States.WORKSPACE_DEPLOYMENT === menuItem.state && this.$scope.component.modules
&& this.$scope.component.modules.length === 0 && this.$scope.component.isResource()) ||
(menuItem.disabledCategory === true);
@@ -950,20 +933,54 @@
if (this.cacheService.get('breadcrumbsComponents')) {
this.initBreadcrumbs();
}
+ else {
+ this.initBreadcrumbsComponents();
+ }
}
-
-
private showSuccessNotificationMessage = ():void => {
this.Notification.success({
- message: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION"),
- title: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE")
+ message: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION'),
+ title: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE')
});
- };
+ }
- private setWorkspaceButtonState = (newState:boolean, callback?:Function) => {
+ private setWorkspaceButtonState = (newState: boolean, callback?: Function) => {
this.$scope.unsavedChanges = newState;
this.$scope.unsavedChangesCallback = callback;
}
+ private initBreadcrumbsComponents = (): void => {
+ let breadcrumbsComponentsObservable;
+ if (this.$stateParams.previousState === 'dashboard') {
+ breadcrumbsComponentsObservable = this.homeService.getAllComponents(true);
+ } else if (this.$stateParams.previousState === 'catalog') {
+ breadcrumbsComponentsObservable = this.catalogService.getCatalog();
+ } else {
+ this.cacheService.remove('breadcrumbsComponentsState');
+ this.cacheService.remove('breadcrumbsComponents');
+ return;
+ }
+ breadcrumbsComponentsObservable.subscribe((components) => {
+ this.cacheService.set('breadcrumbsComponentsState', this.$stateParams.previousState);
+ this.cacheService.set('breadcrumbsComponents', components);
+ this.initBreadcrumbs();
+ });
+
+ }
+
+ private verifyIfDependenciesExist(): void {
+ let containsDependencies = [];
+ if (this.$scope.component.componentType && this.$scope.component.uniqueId &&
+ this.$scope.component.lifecycleState === 'CERTIFIED' && (this.$scope.component.isService() || this.$scope.component.getComponentSubType() === 'VF')) {
+ this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: IDependenciesServerResponse[]) => {
+ containsDependencies = response.filter((version) => version.dependencies);
+ if (containsDependencies.length > 0) {
+ this.$scope.hasNoDependencies = false;
+ } else {
+ this.$scope.hasNoDependencies = true;
+ }
+ });
+ }
+ }
}
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 d22262c..79dde94 100644
--- a/catalog-ui/src/app/view-models/workspace/workspace-view.html
+++ b/catalog-ui/src/app/view-models/workspace/workspace-view.html
@@ -22,7 +22,8 @@
{{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-class="{'disabled': menuItem.isDisabled }" data-tests-id="{{menuItem.text}}LeftSideMenu" ><button type="button" class="i-sdc-designer-sidebar-section-content-item-service-cat" ng-click="menuItem.callback()" ng-disabled={{menuItem.disabledCategory}}>{{menuItem.text}}</button></div>
+ <!--<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="expand-collapse-menu-box-item-text" ng-class="{'disabled': menuItem.isDisabled }"><button data-tests-id="{{menuItem.text}}LeftSideMenu" type="button" class="i-sdc-designer-sidebar-section-content-item-service-cat" ng-click="menuItem.callback()" ng-disabled={{menuItem.disabledCategory}}>{{menuItem.text}}</button></div>
</div>
</div>
@@ -53,9 +54,11 @@
<div class="sdc-workspace-top-bar-buttons">
- <span ng-if="!isCreateMode() && !component.isLatestVersion() && !showChangeStateButton()" [disabled]="unsavedChanges">Switch to the <a ng-click="getLatestVersion()">latest version</a></span>
+ <span ng-if="!isCreateMode() && !component.isLatestVersion() && !showLatestVersion()" [disabled]="unsavedChanges">Switch to the <a data-tests-id="latest-version" ng-click="getLatestVersion()">latest version</a></span>
+
<button ng-if="isDesigner() && !isCreateMode() && component.lifecycleState === 'CERTIFIED' && (component.isService() || component.getComponentSubType() === 'VF')"
+ ng-disabled="hasNoDependencies"
ng-click="openAutomatedUpgradeModal()"
class="tlv-btn blue"
data-ng-class="{'disabled' : component.archived}"
@@ -65,13 +68,12 @@
<button ng-repeat="(key,button) in changeLifecycleStateButtons"
ng-click="changeLifecycleState(key)"
- ng-if="showChangeStateButton() && key != 'deleteVersion'"
- data-ng-disabled="isCreateMode() || button.disabled || disabledButtons || !isValidForm || unsavedChanges || component.archived"
+ ng-if="key != 'deleteVersion'"
+ data-ng-disabled="checkDisableButton(button)"
class="change-lifecycle-state-btn tlv-btn"
ng-class="$first ? 'outline green' : 'grey'"
data-tests-id="{{button.text | testsId}}" prevent-double-click>
{{button.text}}
-
</button>
@@ -104,11 +106,11 @@
</div>
<div class="w-sdc-main-container-body-content-wrapper">
<div class="w-sdc-main-container-body-content-header">
- <div class="tab-title" data-ng-if="!isComposition && !isDeployment && !isPlugins">
+ <div class="workspace-tab-title" data-ng-if="!isComposition && !isDeployment && !isPlugins">
{{getTabTitle()}}
</div>
</div>
- <div class="w-sdc-main-container-body-content" data-ng-class="{'third-party':thirdParty}" data-ui-view></div>
+ <div class="w-sdc-main-container-body-content" data-ng-class="{'deploy-body-content': isDeployment}" data-ng-class="{'third-party':thirdParty}" data-ui-view></div>
</div>
</div>
</div>
diff --git a/catalog-ui/src/app/view-models/workspace/workspace.less b/catalog-ui/src/app/view-models/workspace/workspace.less
index 518272d..5c479c7 100644
--- a/catalog-ui/src/app/view-models/workspace/workspace.less
+++ b/catalog-ui/src/app/view-models/workspace/workspace.less
@@ -109,7 +109,7 @@
.general-view-top-progress {
width: 30%;
margin: 0 auto;
- min-width: 150px;
+ min-width: 140px;
}
}
@@ -189,7 +189,7 @@
display: inline-block;
}
}
- .tab-title{
+ .workspace-tab-title {
height: 110px;
padding-left: 100px;
line-height: 110px;
@@ -199,6 +199,11 @@
.w-sdc-main-container-body-content {
height: 100%;
}
+
+ .w-sdc-main-container-body-content-wrapper {
+ height: 100%;
+ overflow:hidden;
+ }
}
.w-sdc-main-container-body-content {
// height:calc(~'100% - @{action_nav_height} - @{tab_title}');
@@ -219,7 +224,7 @@
height: calc(~'100% - @{action_nav_height}');
.w-sdc-main-container-body-content-header {
display: flex;
- .tab-title {
+ .workspace-tab-title {
flex-grow: 1;
}
.w-sdc-main-container-body-content-action-buttons {
@@ -239,4 +244,58 @@
}
}
}
+// Fix till we remove everything to angular5 and fix all workspace style
+.composition{
+ .sdc-workspace-container{
+ .w-sdc-main-container{
+ .w-sdc-main-right-container{
+ left:0;
+ //overflow-y: scroll;
+ .sdc-workspace-top-bar {
+ position: absolute;
+ left: 245px;
+ right: 0;
+ z-index: 1;
+ .not-latest{
+ left: 270px;
+ }
+ }
+ .w-sdc-main-container-body-content{
+ padding: 0 0 0 0;
+ }
+ > div:first-child{
+ padding: 0;
+ }
+ }
+ }
+ }
+}
+
+.deployment {
+
+ .sdc-workspace-container{
+ .w-sdc-main-container{
+ .w-sdc-main-right-container{
+ left:0;
+ //overflow-y: scroll;
+ .sdc-workspace-top-bar {
+ position: absolute;
+ left: 245px;
+ right: 0;
+ z-index: 1;
+ .not-latest{
+ left: 270px;
+ }
+ }
+
+ > div:first-child{
+ padding: 0;
+ }
+ .w-sdc-main-container-body-content-wrapper {
+ padding: 0px;
+ }
+ }
+ }
+ }
+}