summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/utils
diff options
context:
space:
mode:
authorMichael Lando <ml636r@att.com>2017-06-09 03:19:04 +0300
committerMichael Lando <ml636r@att.com>2017-06-09 03:19:04 +0300
commited64b5edff15e702493df21aa3230b81593e6133 (patch)
treea4cb01fdaccc34930a8db403a3097c0d1e40914b /catalog-ui/src/app/utils
parent280f8015d06af1f41a3ef12e8300801c7a5e0d54 (diff)
[SDC-29] catalog 1707 rebase commit.
Change-Id: I43c3dc5cf44abf5da817649bc738938a3e8388c1 Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'catalog-ui/src/app/utils')
-rw-r--r--catalog-ui/src/app/utils/artifacts-utils.ts104
-rw-r--r--catalog-ui/src/app/utils/change-lifecycle-state-handler.ts163
-rw-r--r--catalog-ui/src/app/utils/common-utils.ts96
-rw-r--r--catalog-ui/src/app/utils/component-factory.ts161
-rw-r--r--catalog-ui/src/app/utils/component-instance-factory.ts81
-rw-r--r--catalog-ui/src/app/utils/constants.ts277
-rw-r--r--catalog-ui/src/app/utils/dictionary/dictionary.ts235
-rw-r--r--catalog-ui/src/app/utils/file-utils.ts51
-rw-r--r--catalog-ui/src/app/utils/functions.ts35
-rw-r--r--catalog-ui/src/app/utils/menu-handler.ts125
-rw-r--r--catalog-ui/src/app/utils/modals-handler.ts389
-rw-r--r--catalog-ui/src/app/utils/prototypes.ts64
-rw-r--r--catalog-ui/src/app/utils/validation-utils.ts153
13 files changed, 1934 insertions, 0 deletions
diff --git a/catalog-ui/src/app/utils/artifacts-utils.ts b/catalog-ui/src/app/utils/artifacts-utils.ts
new file mode 100644
index 0000000000..b52fe6f03e
--- /dev/null
+++ b/catalog-ui/src/app/utils/artifacts-utils.ts
@@ -0,0 +1,104 @@
+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
new file mode 100644
index 0000000000..dc59e3bb98
--- /dev/null
+++ b/catalog-ui/src/app/utils/change-lifecycle-state-handler.ts
@@ -0,0 +1,163 @@
+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";
+
+/**
+ * Created by obarda on 2/11/2016.
+ */
+
+export class ChangeLifecycleStateHandler {
+
+ static '$inject' = [
+ 'sdcConfig',
+ 'sdcMenu',
+ 'ComponentFactory',
+ '$filter',
+ 'ModalsHandler',
+ 'ServiceServiceNg2'
+ ];
+
+ constructor(private sdcConfig:IAppConfigurtaion,
+ private sdcMenu:IAppMenu,
+ private ComponentFactory:ComponentFactory,
+ private $filter:ng.IFilterService,
+ private ModalsHandler:ModalsHandler,
+ private ServiceServiceNg2:ServiceServiceNg2) {
+
+ }
+
+ 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;
+ 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 (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 => {
+
+ if (data.conformanceLevelModal) {
+ this.validateConformanceLevel(component, data, scope, onSuccessCallback, onErrorCallback);
+ } else {
+ this.actualChangeLifecycleState(component, data, scope, onSuccessCallback, onErrorCallback);
+ }
+ }
+
+ private validateConformanceLevel = (component:Component, data:any, scope:any, onSuccessCallback?:Function, onErrorCallback?:Function):void => {
+ // Validate conformance level if defined in menu.json
+ //-------------------------------------------------
+ this.ServiceServiceNg2.validateConformanceLevel(<Service>component).subscribe((res:boolean) => {
+ if (res === true) {
+ //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);
+ });
+ }
+ });
+ }
+}
diff --git a/catalog-ui/src/app/utils/common-utils.ts b/catalog-ui/src/app/utils/common-utils.ts
new file mode 100644
index 0000000000..d8019d2f96
--- /dev/null
+++ b/catalog-ui/src/app/utils/common-utils.ts
@@ -0,0 +1,96 @@
+import {Module, AttributeModel, ResourceInstance, PropertyModel, InputFEModel} from "../models";
+import {ComponentInstanceFactory} from "./component-instance-factory";
+import {PropertyBEModel, RelationshipModel} from "app/models";
+
+export class CommonUtils {
+
+ static initProperties(propertiesObj:Array<PropertyModel>, uniqueId?:string):Array<PropertyModel> {
+
+ let properties = new Array<PropertyModel>();
+ if (propertiesObj) {
+ _.forEach(propertiesObj, (property:PropertyModel):void => {
+ if (uniqueId) {
+ property.readonly = property.parentUniqueId != uniqueId;
+ }
+ properties.push(new PropertyModel(property));
+ });
+ }
+ return properties;
+ };
+
+ static initAttributes(attributesObj:Array<AttributeModel>, uniqueId?:string):Array<AttributeModel> {
+
+ let attributes = new Array<AttributeModel>();
+ if (attributesObj) {
+ _.forEach(attributesObj, (attribute:AttributeModel):void => {
+ if (uniqueId) {
+ attribute.readonly = attribute.parentUniqueId != uniqueId;
+ }
+ attributes.push(new AttributeModel(attribute));
+ });
+ }
+ return attributes;
+ };
+
+ static initComponentInstances(componentInstanceObj:Array<ResourceInstance>):Array<ResourceInstance> {
+
+ let componentInstances = new Array<ResourceInstance>();
+ if (componentInstanceObj) {
+ _.forEach(componentInstanceObj, (instance:ResourceInstance):void => {
+ componentInstances.push(ComponentInstanceFactory.createComponentInstance(instance));
+ });
+ }
+ return componentInstances;
+ };
+
+ static initModules(moduleArrayObj:Array<Module>):Array<Module> {
+
+ let modules = new Array<Module>();
+
+ if (moduleArrayObj) {
+ _.forEach(moduleArrayObj, (module:Module):void => {
+ if (module.type === "org.openecomp.groups.VfModule") {
+ modules.push(new Module(module));
+ }
+ });
+ }
+ return modules;
+ };
+
+ static initInputs(inputsObj:Array<PropertyBEModel>):Array<PropertyBEModel> {
+
+ let inputs = new Array<PropertyBEModel>();
+
+ if(inputsObj) {
+ _.forEach(inputsObj, (input:PropertyBEModel):void => {
+ inputs.push(new PropertyBEModel(input));
+ })
+ }
+
+ return inputs;
+ }
+
+ static initBeProperties(propertiesObj: Array<PropertyBEModel>): Array<PropertyBEModel> {
+
+ let properties = new Array<PropertyBEModel>();
+
+ if (propertiesObj) {
+ _.forEach(propertiesObj, (property: PropertyBEModel): void => {
+ properties.push(new PropertyBEModel(property));
+ })
+ }
+
+ return properties;
+ }
+
+ static initComponentInstanceRelations = (componentInstanceRelationsObj:Array<RelationshipModel>):Array<RelationshipModel> => {
+ if (componentInstanceRelationsObj) {
+ let componentInstancesRelations: Array<RelationshipModel> = [];
+ _.forEach(componentInstanceRelationsObj, (instanceRelation:RelationshipModel):void => {
+ componentInstancesRelations.push(new RelationshipModel(instanceRelation));
+ });
+ return componentInstancesRelations;
+ }
+ };
+}
+
diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts
new file mode 100644
index 0000000000..18edbfb02c
--- /dev/null
+++ b/catalog-ui/src/app/utils/component-factory.ts
@@ -0,0 +1,161 @@
+'use strict';
+import {DEFAULT_ICON, ResourceType, ComponentType} from "./constants";
+import {ServiceService, CacheService, ResourceService, ProductService} from "app/services";
+import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service, Product} from "app/models";
+import {ComponentMetadata} from "../models/component-metadata";
+import {ComponentServiceNg2} from "../ng2/services/component-services/component.service";
+import {ComponentGenericResponse} from "../ng2/services/responses/component-generic-response";
+
+
+export class ComponentFactory {
+
+ static '$inject' = [
+ 'Sdc.Services.Components.ResourceService',
+ 'Sdc.Services.Components.ServiceService',
+ 'Sdc.Services.Components.ProductService',
+ 'Sdc.Services.CacheService',
+ '$q',
+ 'ComponentServiceNg2'
+ ];
+
+ constructor(private ResourceService:ResourceService,
+ private ServiceService:ServiceService,
+ private ProductService:ProductService,
+ private cacheService:CacheService,
+ private $q:ng.IQService,
+ private ComponentServiceNg2: ComponentServiceNg2) {
+ }
+
+ public createComponent = (component:Component):Component => {
+ let newComponent:Component;
+ switch (component.componentType) {
+
+ case 'SERVICE':
+ newComponent = new Service(this.ServiceService, this.$q, <Service> component);
+ break;
+
+ case 'RESOURCE':
+ newComponent = new Resource(this.ResourceService, this.$q, <Resource> component);
+ break;
+
+ case 'PRODUCT':
+ newComponent = new Product(this.ProductService, this.$q, <Product> component);
+ break;
+ }
+ return newComponent;
+ };
+
+ public createProduct = (product:Product):Product => {
+ let newProduct:Product = new Product(this.ProductService, this.$q, <Product> product);
+ return newProduct;
+ };
+
+ public createService = (service:Service):Service => {
+ let newService:Service = new Service(this.ServiceService, this.$q, <Service> service);
+ return newService;
+ };
+
+ public createResource = (resource:Resource):Resource => {
+ let newResource:Resource = new Resource(this.ResourceService, this.$q, <Resource> resource);
+ return newResource;
+ };
+
+ public createFromCsarComponent = (csar:ICsarComponent):Component => {
+ let newResource:Resource = <Resource>this.createEmptyComponent(ComponentType.RESOURCE);
+ newResource.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
+ newResource.selectedCategory = selectedCategory && selectedSubCategory ? selectedCategory.name + "_#_" + selectedSubCategory.name : '';
+ newResource.categories = categories;
+ newResource.vendorName = csar.vendorName;
+ newResource.vendorRelease = csar.vendorRelease;
+ newResource.csarUUID = csar.packageId;
+ newResource.csarPackageType = csar.packageType;
+ newResource.csarVersion = csar.version;
+ newResource.packageId = csar.packageId;
+ newResource.description = csar.description;
+ return newResource;
+ };
+
+ public createEmptyComponent = (componentType:string):Component => {
+ let newComponent:Component;
+
+ switch (componentType) {
+
+ case ComponentType.SERVICE:
+ newComponent = new Service(this.ServiceService, this.$q);
+ break;
+
+ case ComponentType.RESOURCE:
+ case ResourceType.VF:
+ case ResourceType.VL:
+ case ResourceType.VFC:
+ case ResourceType.CP:
+ newComponent = new Resource(this.ResourceService, this.$q);
+ break;
+
+ case ComponentType.PRODUCT:
+ newComponent = new Product(this.ProductService, this.$q);
+ break;
+ }
+ newComponent.componentType = componentType;
+ newComponent.tags = [];
+ newComponent.icon = DEFAULT_ICON;
+ return newComponent;
+ };
+
+ public getComponentFromServer = (componentType:string, componentId:string):ng.IPromise<Component> => {
+ let newComponent:Component = this.createEmptyComponent(componentType);
+ newComponent.setUniqueId(componentId);
+ return newComponent.getComponent();
+ };
+
+ public createComponentOnServer = (componentObject:Component):ng.IPromise<Component> => {
+ let component:Component = this.createComponent(componentObject);
+ return component.createComponentOnServer();
+
+ };
+
+ public getComponentWithMetadataFromServer = (componentType:string, componentId:string):ng.IPromise<Component> => {
+ let deferred = this.$q.defer();
+ let component = this.createEmptyComponent(componentType);
+ component.setUniqueId(componentId);
+ this.ComponentServiceNg2.getComponentMetadata(component).subscribe((response:ComponentGenericResponse) => {
+ component.setComponentMetadata(response.metadata);
+ deferred.resolve(component);
+ });
+ return deferred.promise;
+ }
+}
diff --git a/catalog-ui/src/app/utils/component-instance-factory.ts b/catalog-ui/src/app/utils/component-instance-factory.ts
new file mode 100644
index 0000000000..df92f20c90
--- /dev/null
+++ b/catalog-ui/src/app/utils/component-instance-factory.ts
@@ -0,0 +1,81 @@
+/*-
+ * ============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 3/7/2016.
+ */
+'use strict';
+import {ComponentInstance, ServiceInstance, ProductInstance, ResourceInstance, Component} from "../models";
+import {LeftPaletteComponent} from "../models/components/displayComponent";
+
+export class ComponentInstanceFactory {
+
+ static createComponentInstance(componentInstance:ComponentInstance):ComponentInstance {
+ let newComponentInstance:ComponentInstance;
+ switch (componentInstance.originType) {
+ case 'SERVICE':
+ newComponentInstance = new ServiceInstance(componentInstance);
+ break;
+
+ case 'PRODUCT':
+ newComponentInstance = new ProductInstance(componentInstance);
+ break;
+
+ default :
+ newComponentInstance = new ResourceInstance(componentInstance);
+ break;
+ }
+ return newComponentInstance;
+ };
+
+ public createEmptyComponentInstance = (componentInstanceType?:string):ComponentInstance => {
+ let newComponentInstance:ComponentInstance;
+ switch (componentInstanceType) {
+ case 'SERVICE':
+ newComponentInstance = new ServiceInstance();
+ break;
+
+ case 'PRODUCT':
+ newComponentInstance = new ProductInstance();
+ break;
+
+ default :
+ newComponentInstance = new ResourceInstance();
+ break;
+ }
+ return newComponentInstance;
+ };
+
+ public createComponentInstanceFromComponent = (component:LeftPaletteComponent):ComponentInstance => {
+ let newComponentInstance:ComponentInstance = this.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();
+ //new component instance -> req. & cap. are added on successful instance creation
+ newComponentInstance.requirements = component.requirements;
+ newComponentInstance.capabilities = component.capabilities;
+ newComponentInstance.icon = component.icon;
+ newComponentInstance.componentUid = component.uniqueId;
+ return newComponentInstance;
+ };
+
+}
diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts
new file mode 100644
index 0000000000..d55079d662
--- /dev/null
+++ b/catalog-ui/src/app/utils/constants.ts
@@ -0,0 +1,277 @@
+/**
+ * Created by obarda on 2/18/2016.
+ */
+
+export let DEFAULT_ICON = 'defaulticon';
+export let CP_END_POINT = 'CpEndPoint';
+export let CHANGE_COMPONENT_CSAR_VERSION_FLAG = 'changeComponentCsarVersion';
+
+export class ComponentType {
+ static SERVICE = 'SERVICE';
+ static RESOURCE = 'RESOURCE';
+ static PRODUCT = 'PRODUCT';
+}
+
+export class ServerTypeUrl {
+ static RESOURCES = 'resources/';
+ static SERVICES = 'services/';
+ static PRODUCTS = 'product/';
+}
+
+export class ResourceType {
+ static VF = 'VF';
+ static VL = 'VL';
+ static CP = 'CP';
+ static VFC = 'VFC';
+ static VFCMT = 'VFCMT';
+}
+
+export class ComponentState {
+ static CERTIFICATION_IN_PROGRESS = 'CERTIFICATION_IN_PROGRESS';
+ static CERTIFIED = 'CERTIFIED';
+ static NOT_CERTIFIED_CHECKOUT = 'NOT_CERTIFIED_CHECKOUT';
+ static NOT_CERTIFIED_CHECKIN = 'NOT_CERTIFIED_CHECKIN';
+ static READY_FOR_CERTIFICATION = 'READY_FOR_CERTIFICATION';
+}
+
+export class DistributionStatus {
+ DISTRIBUTION_NOT_APPROVED = 'DISTRIBUTION_NOT_APPROVED';
+ DISTRIBUTION_APPROVED = 'DISTRIBUTION_APPROVED';
+ DISTRIBUTED = 'DISTRIBUTED';
+ DISTRIBUTION_REJECTED = 'DISTRIBUTION_REJECTED';
+}
+
+export class ArtifactGroupType {
+ static DEPLOYMENT = "DEPLOYMENT";
+ static INFORMATION = "INFORMATIONAL";
+ static SERVICE_API = "SERVICE_API";
+}
+
+export class ArtifactType {
+ static HEAT = "HEAT";
+ static HEAT_VOL = "HEAT_VOL";
+ static HEAT_NET = "HEAT_NET";
+ static VF_LICENSE = "VF_LICENSE";
+ static VENDOR_LICENSE = "VENDOR_LICENSE";
+ static THIRD_PARTY_RESERVED_TYPES = {
+ WORKFLOW: "WORKFLOW",
+ NETWORK_CALL_FLOW: "NETWORK_CALL_FLOW",
+ AAI_SERVICE_MODEL: "AAI_SERVICE_MODEL",
+ AAI_VF_MODEL: "AAI_VF_MODEL",
+ AAI_VF_MODULE_MODEL: "AAI_VF_MODULE_MODEL",
+ AAI_VF_INSTANCE_MODEL: "AAI_VF_INSTANCE_MODEL"
+ };
+ static TOSCA = {TOSCA_TEMPLATE: "TOSCA_TEMPLATE", TOSCA_CSAR: "TOSCA_CSAR"};
+}
+
+export class SEVERITY {
+ public static DEBUG = 'DEBUG';
+ public static INFO = 'INFO';
+ public static WARNING = 'WARNING';
+ public static ERROR = 'ERROR';
+}
+
+export class PROPERTY_TYPES {
+ public static STRING = 'string';
+ public static INTEGER = 'integer';
+ public static FLOAT = 'float';
+ public static BOOLEAN = 'boolean';
+ public static JSON = 'json';
+ public static MAP = 'map';
+ public static LIST = 'list';
+}
+
+export class SOURCES {
+ public static A_AND_AI = 'A&AI';
+ public static ORDER = 'Order';
+ public static RUNTIME = 'Runtime';
+}
+
+export class PROPERTY_DATA {
+ public static TYPES = [PROPERTY_TYPES.STRING, PROPERTY_TYPES.INTEGER, PROPERTY_TYPES.FLOAT, PROPERTY_TYPES.BOOLEAN, PROPERTY_TYPES.JSON, PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP];
+ public static SIMPLE_TYPES = [PROPERTY_TYPES.STRING, PROPERTY_TYPES.INTEGER, PROPERTY_TYPES.FLOAT, PROPERTY_TYPES.BOOLEAN, PROPERTY_TYPES.JSON];
+ public static ROOT_DATA_TYPE = "tosca.datatypes.Root";
+ public static SOURCES = [SOURCES.A_AND_AI, SOURCES.ORDER, SOURCES.RUNTIME];
+}
+
+export class PROPERTY_VALUE_CONSTRAINTS {
+ public static MAX_LENGTH = 100;
+ public static JSON_MAX_LENGTH = 4096;
+}
+
+export class Role {
+ public static ADMIN = 'ADMIN';
+ public static DESIGNER = 'DESIGNER';
+ public static PRODUCT_STRATEGIST = 'PRODUCT_STRATEGIST';
+ public static PRODUCT_MANAGER = 'PRODUCT_MANAGER';
+ public static TESTER = 'TESTER';
+ public static OPS = 'OPS';
+ public static GOVERNOR = 'GOVERNOR';
+}
+
+export enum FormState{
+ CREATE,
+ UPDATE,
+ IMPORT,
+ VIEW
+}
+
+export class WorkspaceMode {
+ public static CREATE = 'create';
+ public static EDIT = 'edit';
+ public static IMPORT = 'import';
+ public static VIEW = 'view';
+}
+
+export class ImagesUrl {
+ public static RESOURCE_ICONS = '/assets/styles/images/resource-icons/';
+ public static SERVICE_ICONS = '/assets/styles/images/service-icons/';
+ public static SELECTED_UCPE_INSTANCE = '/assets/styles/images/resource-icons/selectedUcpeInstance.png';
+ public static SELECTED_CP_INSTANCE = '/assets/styles/images/resource-icons/selectedCPInstance.png';
+ public static SELECTED_VL_INSTANCE = '/assets/styles/images/resource-icons/selectedVLInstance.png';
+ public static CANVAS_PLUS_ICON = '/assets/styles/images/resource-icons/canvasPlusIcon.png';
+ public static MODULE_ICON = '/assets/styles/images/resource-icons/module.png';
+ public static OPEN_MODULE_ICON = '/assets/styles/images/resource-icons/openModule.png';
+ public static OPEN_MODULE_HOVER_ICON = '/assets/styles/images/resource-icons/openModuleHover.png';
+ public static CLOSE_MODULE_ICON = '/assets/styles/images/resource-icons/closeModule.png';
+ public static CLOSE_MODULE_HOVER_ICON = '/assets/styles/images/resource-icons/closeModuleHover.png';
+}
+
+export class ModalType {
+ static STANDARD = 'standard';
+ static ERROR = 'error';
+ static ALERT = 'alert';
+}
+
+export class GraphColors {
+ public static NOT_CERTIFIED_LINK = 'rgb(218,31,61)';
+ public static VL_LINK = 'rgb(216,216,216)';
+ public static ACTIVE_LINK = '#30bdf2';
+ public static BASE_LINK = 'rgb(55,55,55)';
+ public static NODE_BACKGROUND_COLOR = 'rgba(46, 162, 157, 0.24)';
+ public static NODE_SHADOW_COLOR = 'rgba(198, 230, 228, 0.7)';
+ public static NODE_OVERLAPPING_BACKGROUND_COLOR = 'rgba(179, 10, 60, 0.24)';
+ public static NODE_OVERLAPPING_SHADOW_COLOR = 'rgba(236, 194, 206, 0.7)';
+ public static NODE_UCPE_CP = '#9063cd';
+ public static NODE_UCPE = '#fbfbfb';
+ public static NODE_SELECTED_BORDER_COLOR = '#30bdf2';
+}
+export class GraphTransactionLogText {
+ public static REMOVE_TEMP_LINK = "remove tempLink";
+ public static DELETE_LINK = "delete link";
+ public static ADD_LINK = "delete link";
+ public static ADD_NODE = "adding node";
+}
+
+export class GraphUIObjects {
+ public static LINK_MENU_HEIGHT = 420;
+ public static TOP_HEADER_HEIGHT = 200;
+ public static TOOLTIP_OFFSET_X = 50;
+ public static TOOLTIP_OFFSET_Y = 145;
+ public static TOOLTIP_LINK_OFFSET_X = 35;
+ public static TOOLTIP_LINK_OFFSET_Y = 75;
+ public static MENU_LINK_VL_HEIGHT_OFFSET = 250;
+ public static MENU_LINK_VL_WIDTH_OFFSET = 200;
+ public static MENU_LINK_SIMPLE_HEIGHT_OFFSET = 180;
+ public static MENU_LINK_SIMPLE_WIDTH_OFFSET = 130;
+ public static DIAGRAM_RIGHT_WIDTH_OFFSET = 248;
+ public static DIAGRAM_HEADER_OFFSET = 103;
+ public static DIAGRAM_PALETTE_WIDTH_OFFSET = 247;
+ // public static COMPOSITION_HEADER_OFFSET = 50;
+ // public static COMPOSITION_NODE_MENU_WIDTH = 230;
+ // public static COMPOSITION_NODE_MENU_HEIGHT = 200;
+ // public static COMPOSITION_RIGHT_PANEL_OFFSET = 300;
+}
+
+
+export class States {
+ public static WORKSPACE_GENERAL = 'workspace.general';
+ public static WORKSPACE_ICONS = 'workspace.icons';
+ 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_HIERARCHY = 'workspace.hierarchy';
+ public static WORKSPACE_INFORMATION_ARTIFACTS = 'workspace.information_artifacts';
+ public static WORKSPACE_TOSCA_ARTIFACTS = 'workspace.tosca_artifacts';
+ public static WORKSPACE_COMPOSITION = 'workspace.composition';
+ public static WORKSPACE_NETWORK_CALL_FLOW = 'workspace.network_call_flow';
+ public static WORKSPACE_MANAGEMENT_WORKFLOW = 'workspace.management_workflow';
+ public static WORKSPACE_DEPLOYMENT = 'workspace.deployment';
+ public static WORKSPACE_DISTRIBUTION = 'workspace.distribution';
+ public static WORKSPACE_PROPERTIES_ASSIGNMENT = 'workspace.properties_assignment';
+ public static WORKSPACE_REQUIREMENTS_AND_CAPABILITIES = 'workspace.reqAndCap';
+ public static WORKSPACE_NG2 = 'workspace.ng2';
+}
+
+export class EVENTS {
+ static RESOURCE_LEFT_PALETTE_UPDATE_EVENT = "resourceLeftPanelUpdateEvent";
+ static SERVICE_LEFT_PALETTE_UPDATE_EVENT = "serviceLeftPanelUpdateEvent";
+ static PRODUCT_LEFT_PALETTE_UPDATE_EVENT = "productLeftPanelUdateEvent";
+ static VL_LEFT_PALETTE_UPDATE_EVENT = "vlLeftPanelUdateEvent";
+ static ON_CSAR_LOADING = "onCsarLoading";
+ static DOWNLOAD_ARTIFACT_FINISH_EVENT = "downloadArtifactFinishEvent";
+ static ON_WORKSPACE_SAVE_BUTTON_CLICK = "onWorkspaceSaveButtonClick";
+ static ON_WORKSPACE_SAVE_BUTTON_SUCCESS = "onWorkspaceSaveButtonSuccess";
+ static ON_WORKSPACE_SAVE_BUTTON_ERROR = "onWorkspaceSaveButtonError";
+
+ //Loader events
+ static SHOW_LOADER_EVENT = "showLoaderEvent";
+ static HIDE_LOADER_EVENT = "hideLoaderEvent";
+}
+
+
+export class UNIQUE_GROUP_PROPERTIES_NAME {
+ public static MIN_VF_MODULE_INSTANCES = 'min_vf_module_instances';
+ public static MAX_VF_MODULE_INSTANCES = 'max_vf_module_instances';
+ public static INITIAL_COUNT = 'initial_count';
+ public static IS_BASE = 'isBase';
+ public static VF_MODULE_TYPE = 'vf_module_type';
+ public static VF_MODULE_LABEL = 'vf_module_label';
+ public static VF_MODULE_DESCRIPTION = 'vf_module_description';
+ public static VOLUME_GROUP = 'volume_group';
+}
+
+
+export class GRAPH_EVENTS {
+ static ON_COMPOSITION_GRAPH_DATA_LOADED = 'onCompositionGraphDataLoaded';
+ static ON_DEPLOYMENT_GRAPH_DATA_LOADED = 'onDeploymentGraphDataLoaded';
+ static ON_NODE_SELECTED = "onNodeSelected";
+ static ON_GRAPH_BACKGROUND_CLICKED = "onGraphBackgroundClicked";
+ static ON_PALETTE_COMPONENT_HOVER_IN = 'onPaletteComponentHoverIn';
+ static ON_PALETTE_COMPONENT_HOVER_OUT = 'onPaletteComponentHoverOut';
+ static ON_PALETTE_COMPONENT_DRAG_START = 'onPaletteComponentDragStart';
+ static ON_PALETTE_COMPONENT_DRAG_ACTION = 'onPaletteComponentDragAction';
+ static ON_COMPONENT_INSTANCE_NAME_CHANGED = 'onComponentInstanceNameChanged';
+ static ON_DELETE_COMPONENT_INSTANCE = 'onDeleteComponentInstance';
+ static ON_DELETE_MULTIPLE_COMPONENTS = 'onDeleteMultipleComponents';
+ static ON_DELETE_EDGE = 'onDeleteEdge';
+ static ON_INSERT_NODE_TO_UCPE = 'onInsertNodeToUCPE';
+ static ON_REMOVE_NODE_FROM_UCPE = 'onRemoveNodeFromUCPE';
+ static ON_VERSION_CHANGED = 'onVersionChanged';
+ static ON_CREATE_COMPONENT_INSTANCE = 'onCreateComponentInstance';
+}
+
+
+export class COMPONENT_FIELDS {
+ static COMPONENT_INSTANCES_PROPERTIES = "componentInstancesProperties";
+ static COMPONENT_INSTANCES_ATTRIBUTES = "componentInstancesAttributes";
+ static COMPONENT_ATTRIBUTES = "attributes";
+ static COMPONENT_INSTANCES = "componentInstances";
+ static COMPONENT_INSTANCES_RELATION = "componentInstancesRelations";
+ static COMPONENT_INPUTS = "inputs";
+ static COMPONENT_METADATA = "metadata";
+ static COMPONENT_DEPLOYMENT_ARTIFACTS = "deploymentArtifacts";
+ static COMPONENT_INFORMATIONAL_ARTIFACTS = "artifacts";
+ static COMPONENT_PROPERTIES = "properties";
+ static COMPONENT_CAPABILITIES = "capabilities";
+ static COMPONENT_REQUIREMENTS = "requirements";
+ static COMPONENT_TOSCA_ARTIFACTS = "toscaArtifacts";
+ static COMPONENT_GROUPS = "groups";
+
+}
+export class API_QUERY_PARAMS {
+ static INCLUDE = "include";
+}
diff --git a/catalog-ui/src/app/utils/dictionary/dictionary.ts b/catalog-ui/src/app/utils/dictionary/dictionary.ts
new file mode 100644
index 0000000000..fd2a028c34
--- /dev/null
+++ b/catalog-ui/src/app/utils/dictionary/dictionary.ts
@@ -0,0 +1,235 @@
+/**
+
+ This code was copy from collections.ts lib
+ https://github.com/basarat/typescript-collections
+ **/
+'use strict';
+
+// Used internally by dictionary
+interface IDictionaryPair<K, V> {
+ key:K;
+ value:V;
+}
+
+export class Dictionary<K, V> {
+
+ /**
+ * Object holding the key-value pairs.
+ * @type {Object}
+ * @private
+ */
+ private table:{ [key:string]:IDictionaryPair<K, V> };
+ //: [key: K] will not work since indices can only by strings in javascript and typescript enforces this.
+
+ /**
+ * Number of elements in the list.
+ * @type {number}
+ * @private
+ */
+ private nElements:number;
+
+ /**
+ * Function used to convert keys to strings.
+ * @type {function(Object):string}
+ * @private
+ */
+ private toStr:(key:K) => string;
+
+
+ /**
+ * Creates an empty dictionary.
+ * @class <p>Dictionaries map keys to values; each key can map to at most one value.
+ * This implementation accepts any kind of objects as keys.</p>
+ *
+ * <p>If the keys are custom objects a function which converts keys to unique
+ * strings must be provided. Example:</p>
+ * <pre>
+ * function petToString(pet) {
+ * return pet.name;
+ * }
+ * </pre>
+ * @constructor
+ * @param {function(Object):string=} toStrFunction optional function used
+ * to convert keys to strings. If the keys aren"t strings or if toString()
+ * is not appropriate, a custom function which receives a key and returns a
+ * unique string must be provided.
+ */
+ constructor(toStrFunction?:(key:K) => string) {
+ this.table = {};
+ this.nElements = 0;
+ this.toStr = toStrFunction || this.defaultToString;
+ }
+
+
+ /**
+ copy from angular.js isUndefined
+ */
+ private isUndefined = (value:any):boolean => {
+ return typeof value === 'undefined';
+ }
+
+ defaultToString = (item:any):string => {
+ return item.toString();
+ }
+
+ /**
+ * Returns the value to which this dictionary maps the specified key.
+ * Returns undefined if this dictionary contains no mapping for this key.
+ * @param {Object} key key whose associated value is to be returned.
+ * @return {*} the value to which this dictionary maps the specified key or
+ * undefined if the map contains no mapping for this key.
+ */
+ getValue = (key:K):V => {
+ let pair:IDictionaryPair<K, V> = this.table[this.toStr(key)];
+ if (this.isUndefined(pair)) {
+ return undefined;
+ }
+ return pair.value;
+ }
+
+
+ /**
+ * Associates the specified value with the specified key in this dictionary.
+ * If the dictionary previously contained a mapping for this key, the old
+ * value is replaced by the specified value.
+ * @param {Object} key key with which the specified value is to be
+ * associated.
+ * @param {Object} value value to be associated with the specified key.
+ * @return {*} previous value associated with the specified key, or undefined if
+ * there was no mapping for the key or if the key/value are undefined.
+ */
+ setValue = (key:K, value:V):V => {
+
+ if (this.isUndefined(key) || this.isUndefined(value)) {
+ return undefined;
+ }
+
+ let ret:V;
+ let k = this.toStr(key);
+ let previousElement:IDictionaryPair<K, V> = this.table[k];
+ if (this.isUndefined(previousElement)) {
+ this.nElements++;
+ ret = undefined;
+ } else {
+ ret = previousElement.value;
+ }
+ this.table[k] = {
+ key: key,
+ value: value
+ };
+ return ret;
+ }
+
+ /**
+ * Removes the mapping for this key from this dictionary if it is present.
+ * @param {Object} key key whose mapping is to be removed from the
+ * dictionary.
+ * @return {*} previous value associated with specified key, or undefined if
+ * there was no mapping for key.
+ */
+ remove = (key:K):V => {
+ let k = this.toStr(key);
+ let previousElement:IDictionaryPair<K, V> = this.table[k];
+ if (!this.isUndefined(previousElement)) {
+ delete this.table[k];
+ this.nElements--;
+ return previousElement.value;
+ }
+ return undefined;
+ }
+
+ /**
+ * Returns an array containing all of the keys in this dictionary.
+ * @return {Array} an array containing all of the keys in this dictionary.
+ */
+ keys = ():K[] => {
+ let array:K[] = [];
+ for (let name in this.table) {
+ if (this.table.hasOwnProperty(name)) {
+ let pair:IDictionaryPair<K, V> = this.table[name];
+ array.push(pair.key);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Returns an array containing all of the values in this dictionary.
+ * @return {Array} an array containing all of the values in this dictionary.
+ */
+ values = ():V[] => {
+ let array:V[] = [];
+ for (let name in this.table) {
+ if (this.table.hasOwnProperty(name)) {
+ let pair:IDictionaryPair<K, V> = this.table[name];
+ array.push(pair.value);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Executes the provided function once for each key-value pair
+ * present in this dictionary.
+ * @param {function(Object,Object):*} callback function to execute, it is
+ * invoked with two arguments: key and value. To break the iteration you can
+ * optionally return false.
+ */
+ forEach = (callback:(key:K, value:V) => any):void => {
+ for (let name in this.table) {
+ if (this.table.hasOwnProperty(name)) {
+ let pair:IDictionaryPair<K, V> = this.table[name];
+ let ret = callback(pair.key, pair.value);
+ if (ret === false) {
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if this dictionary contains a mapping for the specified key.
+ * @param {Object} key key whose presence in this dictionary is to be
+ * tested.
+ * @return {boolean} true if this dictionary contains a mapping for the
+ * specified key.
+ */
+ containsKey = (key:K):boolean => {
+ return !this.isUndefined(this.getValue(key));
+ }
+
+ /**
+ * Removes all mappings from this dictionary.
+ * @this {Dictionary}
+ */
+ clear = () => {
+
+ this.table = {};
+ this.nElements = 0;
+ }
+
+ /**
+ * Returns the number of keys in this dictionary.
+ * @return {number} the number of key-value mappings in this dictionary.
+ */
+ size = ():number => {
+ return this.nElements;
+ }
+
+ /**
+ * Returns true if this dictionary contains no mappings.
+ * @return {boolean} true if this dictionary contains no mappings.
+ */
+ isEmpty = ():boolean => {
+ return this.nElements <= 0;
+ }
+
+ toString = ():string => {
+ let toret = "{";
+ this.forEach((k, v) => {
+ toret = toret + "\n\t" + k.toString() + " : " + v.toString();
+ });
+ return toret + "\n}";
+ }
+} // End of dictionary
+
diff --git a/catalog-ui/src/app/utils/file-utils.ts b/catalog-ui/src/app/utils/file-utils.ts
new file mode 100644
index 0000000000..d8c18229c3
--- /dev/null
+++ b/catalog-ui/src/app/utils/file-utils.ts
@@ -0,0 +1,51 @@
+export class FileUtils {
+
+ static '$inject' = [
+ '$window'
+ ];
+
+ constructor(private $window:any) {
+ }
+
+ 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.$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/utils/functions.ts b/catalog-ui/src/app/utils/functions.ts
new file mode 100644
index 0000000000..24f8008393
--- /dev/null
+++ b/catalog-ui/src/app/utils/functions.ts
@@ -0,0 +1,35 @@
+export class QueueUtils {
+
+ private executionQueue:any;
+
+ constructor(private $q:ng.IQService) {
+ this.executionQueue = this.getDummyPromise();
+ }
+
+
+ private getDummyPromise = ():ng.IPromise<boolean> => {
+ let deferred:ng.IDeferred<boolean> = this.$q.defer();
+ deferred.resolve(true);
+ return deferred.promise;
+ };
+
+
+ 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/utils/menu-handler.ts b/catalog-ui/src/app/utils/menu-handler.ts
new file mode 100644
index 0000000000..1dc5a203e2
--- /dev/null
+++ b/catalog-ui/src/app/utils/menu-handler.ts
@@ -0,0 +1,125 @@
+'use strict';
+import {WorkspaceMode, ComponentState} from "./constants";
+import {IAppConfigurtaion, IAppMenu, Component} from "../models";
+import {ComponentFactory} from "./component-factory";
+import {ModalsHandler} from "./modals-handler";
+
+export class MenuItem {
+ text:string;
+ callback:(...args:Array<any>) => ng.IPromise<boolean>;
+ state:string;
+ action:string;
+ params:Array<any>;
+ isDisabled:boolean;
+ disabledRoles:Array<string>;
+ blockedForTypes:Array<string>; // This item will not be shown for specific components types.
+
+ //TODO check if needed
+ 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.
+
+
+ constructor(text:string, callback:(...args:Array<any>) => ng.IPromise<boolean>, state:string, action:string, params?:Array<any>, blockedForTypes?:Array<string>) {
+ this.text = text;
+ this.callback = callback;
+ this.state = state;
+ this.action = action;
+ this.params = params;
+ this.blockedForTypes = blockedForTypes;
+ }
+}
+
+export class MenuItemGroup {
+ selectedIndex:number;
+ menuItems:Array<MenuItem>;
+ itemClick:boolean;
+
+ constructor(selectedIndex?:number, menuItems?:Array<MenuItem>, itemClick?:boolean) {
+ this.selectedIndex = selectedIndex;
+ this.menuItems = menuItems;
+ this.itemClick = itemClick;
+ }
+
+ public updateSelectedMenuItemText(newText:string) {
+ this.menuItems[this.selectedIndex].text = newText;
+ }
+}
+
+
+export class MenuHandler {
+
+ static '$inject' = [
+ 'sdcConfig',
+ 'sdcMenu',
+ 'ComponentFactory',
+ '$filter',
+ 'ModalsHandler',
+ '$state',
+ '$q'
+ ];
+
+ constructor(private sdcConfig:IAppConfigurtaion,
+ private sdcMenu:IAppMenu,
+ private ComponentFactory:ComponentFactory,
+ private $filter:ng.IFilterService,
+ private ModalsHandler:ModalsHandler,
+ private $state:ng.ui.IStateService,
+ private $q:ng.IQService) {
+
+ }
+
+
+ generateBreadcrumbsModelFromComponents = (components:Array<Component>, selected:Component):MenuItemGroup => {
+ let result = new MenuItemGroup(0, [], false);
+ if (components) {
+
+ // Search the component in all components by uuid (and not uniqueid, gives access to an assets's minor versions).
+ let selectedItem = _.find(components, (item:Component) => {
+ return item.uuid === selected.uuid;
+ });
+
+ // If not found search by invariantUUID
+ if (undefined == selectedItem) {
+ selectedItem = _.find(components, (item:Component) => {
+ //invariantUUID && Certified State matches between major versions
+ return item.invariantUUID === selected.invariantUUID && item.lifecycleState === ComponentState.CERTIFIED;
+ });
+ }
+
+ // If not found search by name (name is unique).
+ if (undefined == selectedItem) {
+ selectedItem = _.find(components, (item:Component) => {
+ return item.name === selected.name;
+ });
+ }
+
+ result.selectedIndex = components.indexOf(selectedItem);
+ components[result.selectedIndex] = selected;
+ let clickItemCallback = (component:Component):ng.IPromise<boolean> => {
+ this.$state.go('workspace.general', {
+ id: component.uniqueId,
+ type: component.componentType.toLowerCase(),
+ mode: WorkspaceMode.VIEW
+ });
+ return this.$q.when(true);
+ };
+
+ components.forEach((component:Component) => {
+ let menuItem = new MenuItem(
+ // component.name,
+ component.getComponentSubType() + ': ' + this.$filter('resourceName')(component.name),
+ clickItemCallback,
+ null,
+ null,
+ [component]
+ );
+ // menuItem.text = component.name;
+ result.menuItems.push(menuItem);
+ });
+ }
+ return result;
+ };
+}
diff --git a/catalog-ui/src/app/utils/modals-handler.ts b/catalog-ui/src/app/utils/modals-handler.ts
new file mode 100644
index 0000000000..fe864cb658
--- /dev/null
+++ b/catalog-ui/src/app/utils/modals-handler.ts
@@ -0,0 +1,389 @@
+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";
+
+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):ng.IPromise<any>;
+}
+
+export class ModalsHandler implements IModalsHandler {
+
+ static '$inject' = [
+ '$uibModal',
+ '$q'
+ ];
+
+ 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):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;
+ }
+ }
+ };
+ let 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;
+ };
+
+
+ /**
+ *
+ * This function openes up the edit property modal
+ *
+ * @param property - the property to edit
+ * @param component - the component who is the owner of the property
+ * @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
+ */
+ openEditPropertyModal = (property:PropertyModel, component:Component, filteredProperties:Array<PropertyModel>, isPropertyValueOwner:boolean):ng.IPromise<any> => {
+ let deferred = this.$q.defer();
+
+ let 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;
+ },
+ component: ():Component => {
+ return <Component> component;
+ },
+ filteredProperties: ():Array<PropertyModel> => {
+ return filteredProperties;
+ },
+ isPropertyValueOwner: ():boolean => {
+ return isPropertyValueOwner;
+ }
+ }
+ };
+
+ let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions);
+ deferred.resolve(modalInstance.result);
+ return deferred.promise;
+ };
+
+
+ openEditModulePropertyModal = (property:PropertyModel, component:Component, selectedModule:DisplayModule):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.ModulePropertyView',
+ size: 'sdc-l',
+ backdrop: 'static',
+ keyboard: false,
+ resolve: {
+ originalProperty: ():PropertyModel => {
+ return property;
+ },
+ component: ():Component => {
+ return <Component> component;
+ },
+ selectedModule: ():DisplayModule => {
+ return selectedModule;
+ }
+ }
+ };
+
+ let 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/workspace/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/prototypes.ts b/catalog-ui/src/app/utils/prototypes.ts
new file mode 100644
index 0000000000..2aa718a06c
--- /dev/null
+++ b/catalog-ui/src/app/utils/prototypes.ts
@@ -0,0 +1,64 @@
+interface String {
+ format(variables:Array<string>):string
+}
+
+interface Array<T> {
+ clean(o:T):Array<T>;
+}
+
+
+/**
+ * This function will replace the %<number> with strings (from array).
+ * Example: "Requested '%1' resource was not found.".format(["MyResource"]);
+ * Note: in case the array contains empty string the function will also remove the '' or the "".
+ */
+if (!String.hasOwnProperty("format")) {
+ String.prototype["format"] = function (variables:Array<string>):string {
+
+ if (variables === null || variables === undefined || variables.length === 0) {
+ variables = [''];
+ }
+
+ for (let i = 0; i < variables.length; i++) {
+ if (variables[i] === '' || variables[i] === null) {
+ variables[i] = '--DELETE--';
+ }
+ }
+
+ let res = this.replace(/%(\d+)/g, function (_, m) {
+ return variables[--m];
+ });
+
+ res = res.replace(" '--DELETE--' ", " ");
+ res = res.replace(" \"--DELETE--\" ", " ");
+ res = res.replace("'--DELETE--'", "");
+ res = res.replace("\"--DELETE--\"", "");
+ res = res.replace("--DELETE--", "");
+
+ return res;
+ };
+}
+
+if (!String.hasOwnProperty("capitalizeFirstLetter")) {
+ String.prototype["capitalizeFirstLetter"] = function () {
+ return this.charAt(0).toUpperCase() + this.slice(1);
+ };
+}
+
+if (!String.hasOwnProperty("replaceAll")) {
+ String.prototype["replaceAll"] = function (find:string, replace:string):string {
+ return this.replace(new RegExp(find, 'g'), replace);
+ };
+}
+
+if (!Array.hasOwnProperty("clean")) {
+ Array.prototype.clean = function (deleteValue) {
+ for (let i = 0; i < this.length; i++) {
+ if (this[i] == deleteValue) {
+ this.splice(i, 1);
+ i--;
+ }
+ }
+ return this;
+ };
+}
diff --git a/catalog-ui/src/app/utils/validation-utils.ts b/catalog-ui/src/app/utils/validation-utils.ts
new file mode 100644
index 0000000000..9246d3350d
--- /dev/null
+++ b/catalog-ui/src/app/utils/validation-utils.ts
@@ -0,0 +1,153 @@
+class basePattern {
+ pattern:RegExp;
+ base:number;
+
+ constructor(pattern:RegExp, base:number) {
+ this.pattern = pattern;
+ this.base = base;
+ }
+}
+
+export interface IMapRegex {
+ integer:RegExp;
+ boolean:RegExp;
+ float:RegExp;
+ string:RegExp;
+}
+
+export class ValidationUtils {
+
+ static '$inject' = [
+ 'IntegerNoLeadingZeroValidationPattern',
+ 'FloatValidationPattern',
+ 'CommentValidationPattern',
+ 'BooleanValidationPattern',
+ 'NumberValidationPattern',
+ 'LabelValidationPattern',
+ ];
+ private trueRegex:string = '[t][r][u][e]|[t]|[o][n]|[y]|[y][e][s]|[1]';
+ private falseRegex:string = '[f][a][l][s][e]|[f]|[o][f][f]|[n]|[n][o]|[0]';
+ private heatBooleanValidationPattern:RegExp = new RegExp('^(' + this.trueRegex + '|' + this.falseRegex + ')$');
+
+
+ constructor(private IntegerNoLeadingZeroValidationPattern:RegExp,
+ private FloatValidationPattern:RegExp,
+ private CommentValidationPattern:RegExp,
+ private BooleanValidationPattern:RegExp,
+ private NumberValidationPattern:RegExp,
+ private LabelValidationPattern:RegExp) {
+ }
+
+ public stripAndSanitize(text:string):string {
+ if (!text) {
+ return null;
+ }
+ return text.replace(/\s+/g, ' ').replace(/%[A-Fa-f0-9]{2}/g, '').trim();
+ }
+
+ public getValidationPattern = (validationType:string, parameterType?:string):RegExp => {
+ switch (validationType) {
+ case 'integer':
+ return this.IntegerNoLeadingZeroValidationPattern;
+ case 'float':
+ return this.FloatValidationPattern;
+ case 'number':
+ return this.NumberValidationPattern;
+ case 'string':
+ return this.CommentValidationPattern;
+ case 'boolean':
+ {
+ //Bug Fix DE197437 [Patch]Mismatch between BE to FE regarding supported characters in Boolean filed
+ if (parameterType && parameterType === 'heat') {
+ return this.heatBooleanValidationPattern;
+ }
+ else {
+ return this.BooleanValidationPattern;
+ }
+ }
+
+ case 'label':
+ return this.LabelValidationPattern;
+ case 'category':
+ return this.LabelValidationPattern;
+ default :
+ return null;
+ }
+ };
+
+ public 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?)*$/
+ };
+ }
+
+ public 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?)*$/
+ };
+ }
+
+ public validateUniqueKeys(viewValue:string):boolean {
+ if (!viewValue) {
+ return true; //allow empty value
+ }
+
+ let json:string = "{" + viewValue.replace(/\s\s+/g, ' ') + "}";
+ try {
+ let obj:any = JSON.parse(json);
+ /*
+ //Method #1 : check json string length before & after parsing
+ let newJson:string = JSON.stringify(obj);
+ if (newJson.length < json.length) {
+ return false;
+ }*/
+
+ //Method #2 : check how many times we can find "KEY": in json string
+ let result:boolean = true;
+ Object.keys(obj).forEach((key:string) => {
+ result = result && json.split('"' + key + '":').length === 2;
+ });
+ return result;
+
+ } catch (e) {
+ return false; //not a valid JSON
+ }
+
+ //return true;
+ }
+
+ public validateJson = (json:string):boolean => {
+ try {
+ JSON.parse(json);
+ return true;
+ } catch (err) {
+ console.log('invalid json');
+ return false;
+ }
+ };
+
+ public validateIntRange = (value:string):boolean => {
+
+ let base8 = new basePattern(/^([-+]?0o[0-7]+)$/, 8);
+ let base10 = new basePattern(/^(0|[-+]?[1-9][0-9]*)$/, 10);
+ let base16 = new basePattern(/^([-+]?0x[0-9a-fA-F]+)$/, 16);
+
+ let min:number = -0x80000000;
+ let max:number = 0x7fffffff;
+ let intPatterns:Array<basePattern> = [base8, base10, base16];
+ let matchedBase = _.find(intPatterns, (item)=> {
+ return item.pattern.test(value);
+ });
+
+ let parsed:number = parseInt(value.replace('o', ''), matchedBase.base);
+ if (parsed) {
+ return min <= parsed && max >= parsed;
+ }
+ }
+}