diff options
author | vasraz <vasyl.razinkov@est.tech> | 2021-02-16 17:37:57 +0000 |
---|---|---|
committer | Christophe Closset <christophe.closset@intl.att.com> | 2021-02-17 15:57:55 +0000 |
commit | 26e5029d922779fd7e786c1a31b6b37492132388 (patch) | |
tree | 8e8e68a6913749e1405fce951bc7816d4fa35ba3 /catalog-ui/src/app/models | |
parent | f2c0a4118c3c0b6360b639622766543bd754b59c (diff) |
Implement Attributes/Outputs FE
Change-Id: I014bb0ebc07f3fea4266a4f295172eadee546705
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Issue-ID: SDC-3448
Diffstat (limited to 'catalog-ui/src/app/models')
21 files changed, 925 insertions, 117 deletions
diff --git a/catalog-ui/src/app/models/attributes-outputs/attribute-be-model.ts b/catalog-ui/src/app/models/attributes-outputs/attribute-be-model.ts new file mode 100644 index 0000000000..e06a807264 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/attribute-be-model.ts @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {PROPERTY_DATA, PROPERTY_TYPES} from 'app/utils/constants'; +import {ToscaPresentationData} from '../tosca-presentation'; +import {AttributeOutputDetail} from "app/models/attributes-outputs/attribute-output-detail"; +import {SchemaAttribute, SchemaAttributeGroupModel} from "../schema-attribute"; + +export enum DerivedAttributeType { + SIMPLE, + LIST, + MAP, + COMPLEX +} + +export class AttributeBEModel { + + constraints: any[]; + defaultValue: string; + definition: boolean; + description: string; + fromDerived: boolean; + getOutputValues: AttributeOutputDetail[]; + name: string; + origName: string; + parentUniqueId: string; + password: boolean; + required: boolean; + schema: SchemaAttributeGroupModel; + schemaType: string; + type: string; + uniqueId: string; + value: string; + parentAttributeType: string; + subAttributeOutputPath: string; + outputPath: string; + toscaPresentation: ToscaPresentationData; + + constructor(attribute?: AttributeBEModel) { + if (attribute) { + this.constraints = attribute.constraints; + this.defaultValue = attribute.defaultValue; + this.description = attribute.description; + this.fromDerived = attribute.fromDerived; + this.name = attribute.name; + this.origName = attribute.origName; + this.parentUniqueId = attribute.parentUniqueId; + this.password = attribute.password; + this.required = attribute.required; + this.schema = attribute.schema; + this.schemaType = attribute.schemaType; + this.type = attribute.type; + this.uniqueId = attribute.uniqueId; + this.value = attribute.value; + this.definition = attribute.definition; + this.getOutputValues = attribute.getOutputValues; + this.parentAttributeType = attribute.parentAttributeType; + this.subAttributeOutputPath = attribute.subAttributeOutputPath; + this.toscaPresentation = attribute.toscaPresentation; + this.outputPath = attribute.outputPath; + } + + if (!this.schema || !this.schema.property) { + this.schema = new SchemaAttributeGroupModel(new SchemaAttribute()); + } else { // forcing creating new object, so editing different one than the object in the table + this.schema = new SchemaAttributeGroupModel(new SchemaAttribute(this.schema.property)); + } + } + + public toJSON = (): any => { + 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 getDerivedAttributeType = () => { + if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1) { + return DerivedAttributeType.SIMPLE; + } else if (this.type === PROPERTY_TYPES.LIST) { + return DerivedAttributeType.LIST; + } else if (this.type === PROPERTY_TYPES.MAP) { + return DerivedAttributeType.MAP; + } else { + return DerivedAttributeType.COMPLEX; + } + } +} diff --git a/catalog-ui/src/app/models/attributes-outputs/attribute-declare-api-model.ts b/catalog-ui/src/app/models/attributes-outputs/attribute-declare-api-model.ts new file mode 100644 index 0000000000..aa05b39ae6 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/attribute-declare-api-model.ts @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {AttributeBEModel} from "./attribute-be-model"; +import {AttributeFEModel} from "./attribute-fe-model"; +import {DerivedFEAttribute} from "./derived-fe-attribute"; + +export class AttributeDeclareAPIModel extends AttributeBEModel { + output: AttributeBEModel; + attributesName: string; + + constructor(attribute: AttributeFEModel, childAttribute?: DerivedFEAttribute) { + super(attribute); + if (childAttribute) { + this.output = childAttribute; + this.attributesName = childAttribute.attributesName; + } + } + +} diff --git a/catalog-ui/src/app/models/attributes-outputs/attribute-fe-map.ts b/catalog-ui/src/app/models/attributes-outputs/attribute-fe-map.ts new file mode 100644 index 0000000000..e962e919a8 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/attribute-fe-map.ts @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {AttributeBEModel} from "./attribute-be-model"; +import {AttributeFEModel} from "./attribute-fe-model"; + +export class InstanceBeAttributesMap { + [instanceId: string]: Array<AttributeBEModel>; +} + +export class InstanceFeAttributesMap { + [instanceId: string]: Array<AttributeFEModel>; +} + +export class InstanceAttributesAPIMap { + componentInstanceAttributes: InstanceBeAttributesMap; + componentInstanceOutputsMap: InstanceBeAttributesMap; + + constructor(outputsMapData: InstanceBeAttributesMap, attributesMapData: InstanceBeAttributesMap) { + this.componentInstanceOutputsMap = outputsMapData ? outputsMapData : new InstanceBeAttributesMap(); + this.componentInstanceAttributes = attributesMapData ? attributesMapData : new InstanceBeAttributesMap(); + } + +} diff --git a/catalog-ui/src/app/models/attributes-outputs/attribute-fe-model.ts b/catalog-ui/src/app/models/attributes-outputs/attribute-fe-model.ts new file mode 100644 index 0000000000..a939783e8f --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/attribute-fe-model.ts @@ -0,0 +1,326 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {PROPERTY_DATA, PROPERTY_TYPES} from 'app/utils'; +import { + AttributeBEModel, + DerivedAttributeType +} from "app/models/attributes-outputs/attribute-be-model"; +import {DerivedFEAttribute} from "app/models/attributes-outputs/derived-fe-attribute"; + +export class AttributeFEModel extends AttributeBEModel { + + expandedChildAttributeId: string; + flattenedChildren: Array<DerivedFEAttribute>; + isDeclared: boolean; + isDisabled: boolean; + isSelected: boolean; + isSimpleType: boolean; //for convenience only - we can really just check if derivedDataType == derivedPropertyTypes.SIMPLE to know if the attrib is simple + attributesName: string; + uniqueId: string; + valueObj: any; //this is the only value we relate to in the html templates + valueObjValidation: any; + valueObjIsValid: boolean; + valueObjOrig: any; //this is valueObj representation as saved in server + valueObjIsChanged: boolean; + derivedDataType: DerivedAttributeType; + origName: string; + + constructor(attribute: AttributeBEModel) { + super(attribute); + this.value = attribute.value ? attribute.value : attribute.defaultValue;//In FE if a attribute doesn't have value - display the default value + this.isSimpleType = PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1; + this.setNonDeclared(); + this.derivedDataType = this.getDerivedAttributeType(); + this.flattenedChildren = []; + this.attributesName = this.name; + this.valueObj = null; + this.updateValueObjOrig(); + this.resetValueObjValidation(); + this.origName = this.name; + } + + + public updateValueObj(valueObj: any, isValid: boolean) { + this.valueObj = AttributeFEModel.cleanValueObj(valueObj); + this.valueObjValidation = this.valueObjIsValid = isValid; + this.valueObjIsChanged = this.hasValueObjChanged(); + } + + public updateValueObjOrig() { + this.valueObjOrig = _.cloneDeep(this.valueObj); + this.valueObjIsChanged = false; + } + + public calculateValueObjIsValid(valueObjValidation?: any) { + valueObjValidation = (valueObjValidation !== undefined) ? valueObjValidation : this.valueObjValidation; + if (valueObjValidation instanceof Array) { + return valueObjValidation.every((v) => this.calculateValueObjIsValid(v)); + } else if (valueObjValidation instanceof Object) { + return Object.keys(valueObjValidation).every((k) => this.calculateValueObjIsValid(valueObjValidation[k])); + } + return Boolean(valueObjValidation); + } + + public resetValueObjValidation() { + if (this.derivedDataType === DerivedAttributeType.SIMPLE) { + this.valueObjValidation = null; + } else if (this.derivedDataType === DerivedAttributeType.LIST) { + this.valueObjValidation = []; + } else { + this.valueObjValidation = {}; + } + this.valueObjIsValid = true; + } + + public getJSONValue = (): string => { + return AttributeFEModel.stringifyValueObj(this.valueObj, this.schema.property.type, this.derivedDataType); + } + + public getValueObj = (): any => { + return AttributeFEModel.parseValueObj(this.value, this.type, this.derivedDataType, this.defaultValue); + } + + public setNonDeclared = (childPath?: string): void => { + if (!childPath) { //un-declaring a child attrib + this.isDeclared = false; + } else { + let childProp: DerivedFEAttribute = this.flattenedChildren.find(child => child.attributesName == childPath); + childProp.isDeclared = false; + } + } + + public setAsDeclared = (childNameToDeclare?: string): void => { + if (!childNameToDeclare) { //declaring a child attrib + this.isSelected = false; + this.isDeclared = true; + } else { + let childProp: DerivedFEAttribute = this.flattenedChildren.find(child => child.attributesName == childNameToDeclare); + if (!childProp) { + console.log("ERROR: Unabled to find child: " + childNameToDeclare, this); + return; + } + childProp.isSelected = false; + childProp.isDeclared = true; + } + } + + //For expand-collapse functionality - used within HTML template + public updateExpandedChildAttributeId = (childAttributeId: string): void => { + if (childAttributeId.lastIndexOf('#') > -1) { + this.expandedChildAttributeId = (this.expandedChildAttributeId == childAttributeId) ? (childAttributeId.substring(0, childAttributeId.lastIndexOf('#'))) : childAttributeId; + } else { + this.expandedChildAttributeId = this.name; + } + } + + public getIndexOfChild = (childPropName: string): number => { + return this.flattenedChildren.findIndex(attrib => attrib.attributesName.indexOf(childPropName) === 0); + } + + public getCountOfChildren = (childPropName: string): number => { + let matchingChildren: Array<DerivedFEAttribute> = this.flattenedChildren.filter(attrib => attrib.attributesName.indexOf(childPropName) === 0) || []; + return matchingChildren.length; + } + + + /* Updates parent valueObj when a child attrib's value has changed */ + public childPropUpdated = (childProp: DerivedFEAttribute): void => { + let parentNames = this.getParentNamesArray(childProp.attributesName, []); + if (parentNames.length) { + const childPropName = parentNames.join('.'); + // unset value only if is null and valid, and not in a list + if (childProp.valueObj === null && childProp.valueObjIsValid) { + const parentChildProp = this.flattenedChildren.find((ch) => ch.attributesName === childProp.parentName) || this; + if (parentChildProp.derivedDataType !== DerivedAttributeType.LIST) { + _.unset(this.valueObj, childPropName); + this.valueObj = AttributeFEModel.cleanValueObj(this.valueObj); + } else { + _.set(this.valueObj, childPropName, null); + } + } else { + _.set(this.valueObj, childPropName, childProp.valueObj); + } + if (childProp.valueObjIsChanged) { + _.set(this.valueObjValidation, childPropName, childProp.valueObjIsValid); + this.valueObjIsValid = childProp.valueObjIsValid && this.calculateValueObjIsValid(); + this.valueObjIsChanged = true; + } else { + _.unset(this.valueObjValidation, childPropName); + this.valueObjIsValid = this.calculateValueObjIsValid(); + this.valueObjIsChanged = this.hasValueObjChanged(); + } + } + }; + + childPropMapKeyUpdated = (childProp: DerivedFEAttribute, newMapKey: string, forceValidate: boolean = false) => { + if (!childProp.isChildOfListOrMap || childProp.derivedDataType !== DerivedAttributeType.MAP) { + return; + } + + const childParentNames = this.getParentNamesArray(childProp.parentName); + const oldActualMapKey = childProp.getActualMapKey(); + + childProp.mapKey = newMapKey; + if (childProp.mapKey === null) { // null -> remove map key + childProp.mapKeyError = null; + } else if (!childProp.mapKey) { + childProp.mapKeyError = 'Key cannot be empty.'; + } else if (this.flattenedChildren + .filter((fch) => fch !== childProp && fch.parentName === childProp.parentName) // filter sibling child props + .map((fch) => fch.mapKey) + .indexOf(childProp.mapKey) !== -1) { + childProp.mapKeyError = 'This key already exists.'; + } else { + childProp.mapKeyError = null; + } + const newActualMapKey = childProp.getActualMapKey(); + const newMapKeyIsValid = !childProp.mapKeyError; + + // if mapKey was changed, then replace the old key with the new one + if (newActualMapKey !== oldActualMapKey) { + const oldChildPropNames = childParentNames.concat([oldActualMapKey]); + const newChildPropNames = (newActualMapKey) ? childParentNames.concat([newActualMapKey]) : null; + + // add map key to valueObj and valueObjValidation + if (newChildPropNames) { + const newChildVal = _.get(this.valueObj, oldChildPropNames); + if (newChildVal !== undefined) { + _.set(this.valueObj, newChildPropNames, newChildVal); + _.set(this.valueObjValidation, newChildPropNames, _.get(this.valueObjValidation, oldChildPropNames, childProp.valueObjIsValid)); + } + } + + // remove map key from valueObj and valueObjValidation + _.unset(this.valueObj, oldChildPropNames); + _.unset(this.valueObjValidation, oldChildPropNames); + + // force validate after map key change + forceValidate = true; + } + + if (forceValidate) { + // add custom entry for map key validation: + const childMapKeyNames = childParentNames.concat(`%%KEY:${childProp.name}%%`); + if (newActualMapKey) { + _.set(this.valueObjValidation, childMapKeyNames, newMapKeyIsValid); + } else { + _.unset(this.valueObjValidation, childMapKeyNames); + } + + this.valueObjIsValid = newMapKeyIsValid && this.calculateValueObjIsValid(); + this.valueObjIsChanged = this.hasValueObjChanged(); + } + }; + + /* Returns array of individual parents for given attrib path, with list/map UUIDs replaced with index/mapkey */ + public getParentNamesArray = (parentPropName: string, parentNames?: Array<string>, noHashKeys: boolean = false): Array<string> => { + parentNames = parentNames || []; + if (parentPropName.indexOf("#") == -1) { + return parentNames; + } //finished recursing parents. return + + let parentAttrib: DerivedFEAttribute = this.flattenedChildren.find(attrib => attrib.attributesName === parentPropName); + let nameToInsert: string = parentAttrib.name; + + if (parentAttrib.isChildOfListOrMap) { + if (!noHashKeys && parentAttrib.derivedDataType == DerivedAttributeType.MAP) { + nameToInsert = parentAttrib.getActualMapKey(); + } else { //LIST + let siblingProps = this.flattenedChildren.filter(attrib => attrib.parentName == parentAttrib.parentName).map(attrib => attrib.attributesName); + nameToInsert = siblingProps.indexOf(parentAttrib.attributesName).toString(); + } + } + + parentNames.splice(0, 0, nameToInsert); //add attrib name to array + return this.getParentNamesArray(parentAttrib.parentName, parentNames, noHashKeys); //continue recursing + } + + public hasValueObjChanged() { + return !_.isEqual(this.valueObj, this.valueObjOrig); + } + + static stringifyValueObj(valueObj: any, attributeType: PROPERTY_TYPES, derivedAttributeType: DerivedAttributeType): string { + // if valueObj is null, return null + if (valueObj === null || valueObj === undefined) { + return null; + } + + //If type is JSON, need to try parsing it before we stringify it so that it appears property in TOSCA - change per Bracha due to AMDOCS + //TODO: handle this.derivedDataType == DerivedAttributeType.MAP + if (derivedAttributeType == DerivedAttributeType.LIST && attributeType == PROPERTY_TYPES.JSON) { + try { + return JSON.stringify(valueObj.map(item => (typeof item == 'string') ? JSON.parse(item) : item)); + } catch (e) { + } + } + + // if type is anything but string, then stringify valueObj + if ((typeof valueObj) !== 'string') { + return JSON.stringify(valueObj); + } + + // return string value as is + return valueObj; + } + + static parseValueObj(value: string, attributeType: PROPERTY_TYPES, derivedAttributeType: DerivedAttributeType, defaultValue?: string): any { + let valueObj; + if (derivedAttributeType === DerivedAttributeType.SIMPLE) { + valueObj = value || defaultValue || null; // use null for empty value object + if (valueObj && + attributeType !== PROPERTY_TYPES.STRING && + attributeType !== PROPERTY_TYPES.JSON && + PROPERTY_DATA.SCALAR_TYPES.indexOf(<string>attributeType) == -1) { + valueObj = JSON.parse(value); // the value object contains the real value ans not the value as string + } + } else if (derivedAttributeType == DerivedAttributeType.LIST) { + valueObj = _.merge([], JSON.parse(defaultValue || '[]'), JSON.parse(value || '[]')); // value object should be merged value and default value. Value takes higher precedence. Set value object to empty obj if undefined. + } else { + valueObj = _.merge({}, JSON.parse(defaultValue || '{}'), JSON.parse(value || '{}')); // value object should be merged value and default value. Value takes higher precedence. Set value object to empty obj if undefined. + } + return valueObj; + } + + static cleanValueObj(valueObj: any, unsetEmpty?: boolean): any { + // By default - unsetEmpty undefined - will make valueObj cleaned (no null or empty objects, but array will keep null or empty objects). + if (valueObj === undefined || valueObj === null || valueObj === '') { + return null; + } + if (valueObj instanceof Array) { + const cleanArr = valueObj.map((v) => AttributeFEModel.cleanValueObj(v)).filter((v) => v !== null); + valueObj.splice(0, valueObj.length, ...cleanArr) + } else if (valueObj instanceof Object) { + Object.keys(valueObj).forEach((k) => { + // clean each item in the valueObj (by default, unset empty objects) + valueObj[k] = AttributeFEModel.cleanValueObj(valueObj[k], unsetEmpty !== undefined ? unsetEmpty : true); + if (valueObj[k] === null) { + delete valueObj[k]; + } + }); + // if unsetEmpty flag is true and valueObj is empty + if (unsetEmpty && !Object.keys(valueObj).length) { + return null; + } + } + return valueObj; + } +} diff --git a/catalog-ui/src/app/models/attributes-outputs/attribute-output-detail.ts b/catalog-ui/src/app/models/attributes-outputs/attribute-output-detail.ts new file mode 100644 index 0000000000..e646878b77 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/attribute-output-detail.ts @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 class AttributeOutputDetail { + outputId: string; + outputName: string; + outputPath: string; + list: boolean; +} diff --git a/catalog-ui/src/app/models/attributes-outputs/derived-fe-attribute.ts b/catalog-ui/src/app/models/attributes-outputs/derived-fe-attribute.ts new file mode 100644 index 0000000000..e9fad4d6cb --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/derived-fe-attribute.ts @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {SchemaAttribute, SchemaAttributeGroupModel} from '../../models'; +import {PROPERTY_TYPES} from 'app/utils'; +import {UUID} from "angular2-uuid"; +import {AttributeBEModel, DerivedAttributeType} from "./attribute-be-model"; +import {AttributeFEModel} from "./attribute-fe-model"; + +export class DerivedFEAttribute extends AttributeBEModel { + valueObj: any; + valueObjIsValid: boolean; + valueObjOrig: any; + valueObjIsChanged: boolean; + parentName: string; + attributesName: string; + derivedDataType: DerivedAttributeType; + isDeclared: boolean; + isSelected: boolean; + isDisabled: boolean; + hidden: boolean; + isChildOfListOrMap: boolean; + canBeDeclared: boolean; + mapKey: string; + mapKeyError: string; + + constructor(attribute: AttributeBEModel, parentName?: string, createChildOfListOrMap?: boolean, key?: string, value?: any) { + if (createChildOfListOrMap) { //creating a direct child of list or map (ie. Item that can be deleted, with UUID instead of name) + super(null); + this.isChildOfListOrMap = true; + this.canBeDeclared = false; + this.name = UUID.UUID(); + this.parentName = parentName; + this.attributesName = parentName + '#' + this.name; + + if (attribute.type == PROPERTY_TYPES.LIST) { + this.mapKey = attribute.schema.property.type.split('.').pop(); + this.mapKeyError = null; + this.type = attribute.schema.property.type; + } else { //map + if (key) { + this.mapKey = key; + this.mapKeyError = null; + } else { + this.mapKey = ''; + this.mapKeyError = 'Key cannot be empty.'; + } + this.type = attribute.type; + } + this.valueObj = (this.type == PROPERTY_TYPES.JSON && typeof value == 'object') ? JSON.stringify(value) : value; + this.schema = new SchemaAttributeGroupModel(new SchemaAttribute(attribute.schema.property)); + this.updateValueObjOrig(); + } else { //creating a standard derived prop + super(attribute); + this.parentName = parentName ? parentName : null; + this.attributesName = (parentName) ? parentName + '#' + attribute.name : attribute.name; + this.canBeDeclared = true; //defaults to true + } + this.valueObjIsValid = true; + this.derivedDataType = this.getDerivedAttributeType(); + } + + public getActualMapKey() { + return (this.mapKeyError) ? this.name : this.mapKey; + } + + public updateValueObj(valueObj: any, isValid: boolean) { + this.valueObj = AttributeFEModel.cleanValueObj(valueObj); + this.valueObjIsValid = isValid; + this.valueObjIsChanged = this.hasValueObjChanged(); + } + + public updateValueObjOrig() { + this.valueObjOrig = _.cloneDeep(this.valueObj); + this.valueObjIsChanged = false; + } + + public hasValueObjChanged() { + return !_.isEqual(this.valueObj, this.valueObjOrig); + } +} diff --git a/catalog-ui/src/app/models/attributes-outputs/output-be-model.ts b/catalog-ui/src/app/models/attributes-outputs/output-be-model.ts new file mode 100644 index 0000000000..c5f0bfabd3 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/output-be-model.ts @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {AttributeBEModel} from "./attribute-be-model"; + +export class OutputBEModel extends AttributeBEModel { + + outputPath: string; + outputs: Array<OutputComponentInstanceModel>; + instanceUniqueId: string; + ownerId: string; + attributeId: string; + attributes: Array<OutputComponentInstanceModel>; + + constructor(output?: OutputBEModel) { + super(output); + this.instanceUniqueId = output.instanceUniqueId; + this.attributeId = output.attributeId; + this.attributes = output.attributes; + this.outputs = output.outputs; + this.ownerId = output.ownerId; + this.outputPath = output.outputPath; + } + +} + +export interface OutputComponentInstanceModel extends OutputBEModel { + componentInstanceId: string; + componentInstanceName: string; +} diff --git a/catalog-ui/src/app/models/attributes-outputs/output-fe-model.ts b/catalog-ui/src/app/models/attributes-outputs/output-fe-model.ts new file mode 100644 index 0000000000..8806562d06 --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/output-fe-model.ts @@ -0,0 +1,76 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 {PROPERTY_DATA} from "../../utils/constants"; +import {OutputBEModel} from "./output-be-model"; +import {AttributeFEModel} from "./attribute-fe-model"; +import {DerivedAttributeType} from "./attribute-be-model"; + +export class OutputFEModel extends OutputBEModel { + isSimpleType: boolean; + relatedAttributeValue: any; + relatedAttributeName: string; + defaultValueObj: any; + defaultValueObjIsValid: boolean; + defaultValueObjOrig: any; + defaultValueObjIsChanged: boolean; + derivedDataType: DerivedAttributeType; + + constructor(output?: OutputBEModel) { + super(output); + if (output) { + this.isSimpleType = PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1; + let relatedAttribute = output.attributes && output.attributes[0] || output.outputs && output.outputs[0]; + if (relatedAttribute) { + this.relatedAttributeValue = relatedAttribute.value; + this.relatedAttributeName = relatedAttribute.name; + } + this.derivedDataType = this.getDerivedAttributeType(); + this.resetDefaultValueObjValidation(); + this.updateDefaultValueObjOrig(); + } + } + + public updateDefaultValueObjOrig() { + this.defaultValueObjOrig = _.cloneDeep(this.defaultValueObj); + this.defaultValueObjIsChanged = false; + } + + public getJSONDefaultValue(): string { + return AttributeFEModel.stringifyValueObj(this.defaultValueObj, this.schema.property.type, this.derivedDataType); + } + + public getDefaultValueObj(): any { + return AttributeFEModel.parseValueObj(this.defaultValueObj, this.type, this.derivedDataType); + } + + public resetDefaultValueObjValidation() { + this.defaultValueObjIsValid = true; + } + + hasDefaultValueChanged(): boolean { + return !_.isEqual(this.defaultValueObj, this.defaultValueObjOrig); + } + + hasChanged(): boolean { + return this.hasDefaultValueChanged() ; + } +} diff --git a/catalog-ui/src/app/models/attributes-outputs/simple-flat-attribute.ts b/catalog-ui/src/app/models/attributes-outputs/simple-flat-attribute.ts new file mode 100644 index 0000000000..bd8b0cdf7f --- /dev/null +++ b/catalog-ui/src/app/models/attributes-outputs/simple-flat-attribute.ts @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. 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 class SimpleFlatAttribute { + uniqueId: string; + path: string; + name: string; + parentName: string; + instanceName: string; + + constructor(uniqueId?: string, path?: string, name?: string, parentName?: string, instanceName?: string) { + this.uniqueId = uniqueId; + this.path = path; + this.name = name; + this.parentName = parentName; + this.instanceName = instanceName; + } +} diff --git a/catalog-ui/src/app/models/attributes.ts b/catalog-ui/src/app/models/attributes.ts index a51358cdc4..ae5eac0281 100644 --- a/catalog-ui/src/app/models/attributes.ts +++ b/catalog-ui/src/app/models/attributes.ts @@ -20,120 +20,130 @@ 'use strict'; import * as _ from "lodash"; -import {SchemaAttributeGroupModel, SchemaAttribute} from "./schema-attribute"; -import {SchemaPropertyGroupModel, SchemaProperty} from "./aschema-property"; +import {SchemaAttribute, SchemaAttributeGroupModel} from "./schema-attribute"; +import {AttributeOutputDetail} from "app/models/attributes-outputs/attribute-output-detail"; +import {AttributeBEModel} from "app/models/attributes-outputs/attribute-be-model"; export class AttributesGroup { - constructor(attributesObj?:AttributesGroup) { - _.forEach(attributesObj, (attributes:Array<AttributeModel>, instance) => { - this[instance] = []; - _.forEach(attributes, (attribute:AttributeModel):void => { - attribute.resourceInstanceUniqueId = instance; - attribute.readonly = true; - this[instance].push(new AttributeModel(attribute)); - }); - }); - } + constructor(attributesObj?: AttributesGroup) { + _.forEach(attributesObj, (attributes: Array<AttributeModel>, instance) => { + this[instance] = []; + _.forEach(attributes, (attribute: AttributeModel): void => { + attribute.resourceInstanceUniqueId = instance; + attribute.readonly = true; + this[instance].push(new AttributeModel(attribute)); + }); + }); + } } export interface IAttributeModel { - //server data - uniqueId:string; - name:string; - _default:string; - description:string; - type:string; - schema:SchemaAttributeGroupModel; - status:string; - value:string; - parentUniqueId:string; - //custom data - resourceInstanceUniqueId:string; - readonly:boolean; - valueUniqueUid:string; + //server data + uniqueId: string; + name: string; + _default: string; + description: string; + type: string; + schema: SchemaAttributeGroupModel; + status: string; + value: string; + parentUniqueId: string; + //custom data + resourceInstanceUniqueId: string; + readonly: boolean; + valueUniqueUid: string; } -export class AttributeModel implements IAttributeModel { - - //server data - uniqueId:string; - name:string; - _default:string; - description:string; - type:string; - schema:SchemaAttributeGroupModel; - status:string; - value:string; - parentUniqueId:string; - //custom data - resourceInstanceUniqueId:string; - readonly:boolean; - valueUniqueUid:string; - - constructor(attribute?:AttributeModel) { - if (attribute) { - this.uniqueId = attribute.uniqueId; - this.name = attribute.name; - this._default = attribute._default; - this.description = attribute.description; - this.type = attribute.type; - this.status = attribute.status; - this.schema = attribute.schema; - this.value = attribute.value; - this.parentUniqueId = attribute.parentUniqueId; - this.resourceInstanceUniqueId = attribute.resourceInstanceUniqueId; - this.readonly = attribute.readonly; - this.valueUniqueUid = attribute.valueUniqueUid; - } else { - this._default = ''; - } - - 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 - this.schema = new SchemaAttributeGroupModel(new SchemaAttribute(this.schema.property)); - } - - this.convertValueToView(); +export class AttributeModel extends AttributeBEModel implements IAttributeModel { + + //server data + uniqueId: string; + name: string; + _default: string; + description: string; + type: string; + schema: SchemaAttributeGroupModel; + status: string; + value: string; + parentUniqueId: string; + //custom data + resourceInstanceUniqueId: string; + readonly: boolean; + valueUniqueUid: string; + + getOutputValues: AttributeOutputDetail[]; + subAttributeOutputPath: string; + outputPath: string; + + constructor(attribute?: AttributeModel) { + super(attribute); + if (attribute) { + this.uniqueId = attribute.uniqueId; + this.name = attribute.name; + this._default = attribute._default; + this.description = attribute.description; + this.type = attribute.type; + this.status = attribute.status; + this.schema = attribute.schema; + this.value = attribute.value; + this.parentUniqueId = attribute.parentUniqueId; + this.resourceInstanceUniqueId = attribute.resourceInstanceUniqueId; + this.readonly = attribute.readonly; + this.valueUniqueUid = attribute.valueUniqueUid; + + this.getOutputValues = attribute.getOutputValues; + this.subAttributeOutputPath = attribute.subAttributeOutputPath; + this.outputPath = attribute.outputPath; + } else { + this._default = ''; + } + + if (!this.schema || !this.schema.property) { + this.schema = new SchemaAttributeGroupModel(new SchemaAttribute()); + } else { + //forcing creating new object, so editing different one than the object in the table + this.schema = new SchemaAttributeGroupModel(new SchemaAttribute(this.schema.property)); + } + + this.convertValueToView(); + } + + public convertToServerObject(): string { + if (this._default && this.type === 'map') { + this._default = '{' + this._default + '}'; + } + if (this._default && this.type === 'list') { + this._default = '[' + this._default + ']'; + } + this._default = this._default != "" && this._default != "[]" && this._default != "{}" ? this._default : null; + + return JSON.stringify(this); + } + + + public convertValueToView() { + //unwrapping value {} or [] if type is complex + if (this._default && (this.type === 'map' || this.type === 'list') && + ['[', '{'].indexOf(this._default.charAt(0)) > -1 && + [']', '}'].indexOf(this._default.slice(-1)) > -1) { + this._default = this._default.slice(1, -1); } - public convertToServerObject():string { - if (this._default && this.type === 'map') { - this._default = '{' + this._default + '}'; - } - if (this._default && this.type === 'list') { - this._default = '[' + this._default + ']'; - } - this._default = this._default != "" && this._default != "[]" && this._default != "{}" ? this._default : null; - - return JSON.stringify(this); - }; - - - public convertValueToView() { - //unwrapping value {} or [] if type is complex - if (this._default && (this.type === 'map' || this.type === 'list') && - ['[', '{'].indexOf(this._default.charAt(0)) > -1 && - [']', '}'].indexOf(this._default.slice(-1)) > -1) { - this._default = this._default.slice(1, -1); - } - - //also for value - for the modal in canvas - if (this.value && (this.type === 'map' || this.type === 'list') && - ['[', '{'].indexOf(this.value.charAt(0)) > -1 && - [']', '}'].indexOf(this.value.slice(-1)) > -1) { - this.value = this.value.slice(1, -1); - } + //also for value - for the modal in canvas + if (this.value && (this.type === 'map' || this.type === 'list') && + ['[', '{'].indexOf(this.value.charAt(0)) > -1 && + [']', '}'].indexOf(this.value.slice(-1)) > -1) { + this.value = this.value.slice(1, -1); } + } - public toJSON = ():any => { - if (!this.resourceInstanceUniqueId) { - this.value = undefined; - } - this.readonly = undefined; - this.resourceInstanceUniqueId = undefined; - return this; - }; + public toJSON = (): any => { + if (!this.resourceInstanceUniqueId) { + this.value = undefined; + } + this.readonly = undefined; + this.resourceInstanceUniqueId = undefined; + return this; + }; } diff --git a/catalog-ui/src/app/models/data-type-properties.ts b/catalog-ui/src/app/models/data-type-properties.ts index c278ad3af2..7717f8ad65 100644 --- a/catalog-ui/src/app/models/data-type-properties.ts +++ b/catalog-ui/src/app/models/data-type-properties.ts @@ -22,7 +22,7 @@ * Created by rcohen on 9/25/2016. */ 'use strict'; -import {SchemaPropertyGroupModel} from "./aschema-property"; +import {SchemaPropertyGroupModel} from "./schema-property"; import {PropertyModel} from "./properties"; export class DataTypePropertyModel extends PropertyModel{ diff --git a/catalog-ui/src/app/models/data-types.ts b/catalog-ui/src/app/models/data-types.ts index dc36d78b8f..d72211cc57 100644 --- a/catalog-ui/src/app/models/data-types.ts +++ b/catalog-ui/src/app/models/data-types.ts @@ -23,6 +23,7 @@ */ 'use strict'; import {PropertyBEModel} from "./properties-inputs/property-be-model"; +import {AttributeBEModel} from "./attributes-outputs/attribute-be-model"; export class DataTypeModel { @@ -34,6 +35,7 @@ export class DataTypeModel { creationTime:string; modificationTime:string; properties: Array<PropertyBEModel>; + attributes: Array<AttributeBEModel>; constructor(dataType:DataTypeModel) { if (dataType) { @@ -43,6 +45,7 @@ export class DataTypeModel { this.creationTime = dataType.creationTime; this.modificationTime = dataType.modificationTime; this.properties = dataType.properties; + this.attributes = dataType.attributes; } } diff --git a/catalog-ui/src/app/models/input-property-base.ts b/catalog-ui/src/app/models/input-property-base.ts index 33803b1034..752493391b 100644 --- a/catalog-ui/src/app/models/input-property-base.ts +++ b/catalog-ui/src/app/models/input-property-base.ts @@ -22,7 +22,7 @@ * Created by obarda on 1/22/2017. */ 'use strict'; -import {SchemaPropertyGroupModel} from "./aschema-property"; +import {SchemaPropertyGroupModel} from "./schema-property"; export interface InputPropertyBase { diff --git a/catalog-ui/src/app/models/inputs.ts b/catalog-ui/src/app/models/inputs.ts index 562db98168..e267d5fcc4 100644 --- a/catalog-ui/src/app/models/inputs.ts +++ b/catalog-ui/src/app/models/inputs.ts @@ -24,7 +24,7 @@ 'use strict'; import {PropertyModel} from "./properties"; import {InputPropertyBase} from "./input-property-base"; -import {SchemaPropertyGroupModel} from "./aschema-property"; +import {SchemaPropertyGroupModel} from "./schema-property"; export class InputsGroup { constructor(inputsObj?: InputsGroup) { 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 82f15a83d4..ac05f19b7b 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 @@ -19,7 +19,7 @@ */ import * as _ from "lodash"; -import { SchemaPropertyGroupModel, SchemaProperty } from '../aschema-property'; +import { SchemaPropertyGroupModel, SchemaProperty } from '../schema-property'; import { DerivedPropertyType, PropertyBEModel, PropertyFEModel } from '../../models'; import { PROPERTY_TYPES } from 'app/utils'; import { UUID } from "angular2-uuid"; diff --git a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts index 909f712a4e..347b8a1665 100644 --- a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts @@ -19,7 +19,7 @@ */ import * as _ from "lodash"; -import { SchemaPropertyGroupModel, SchemaProperty } from "../aschema-property"; +import { SchemaPropertyGroupModel, SchemaProperty } from "../schema-property"; import {PropertyFEModel} from "../../models"; import {PROPERTY_DATA} from "../../utils/constants"; import {InputBEModel} from "./input-be-model"; 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 b997ea4563..aea5707d89 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 @@ -19,7 +19,7 @@ */ import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils/constants'; -import { SchemaProperty, SchemaPropertyGroupModel } from '../aschema-property'; +import { SchemaProperty, SchemaPropertyGroupModel } from '../schema-property'; import { ToscaPresentationData } from '../tosca-presentation'; import { PropertyInputDetail } from './property-input-detail'; import { Metadata } from '../metadata'; diff --git a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts index 06c735db33..3b8c2d1351 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts @@ -21,7 +21,7 @@ */ import * as _ from "lodash"; -import {SchemaPropertyGroupModel, SchemaProperty} from '../aschema-property'; +import {SchemaPropertyGroupModel, SchemaProperty} from '../schema-property'; import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; import { FilterPropertiesAssignmentData, PropertyBEModel, DerivedPropertyType, DerivedFEPropertyMap, DerivedFEProperty } from 'app/models'; diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts index b87edff0c1..e292a6ceef 100644 --- a/catalog-ui/src/app/models/properties.ts +++ b/catalog-ui/src/app/models/properties.ts @@ -20,7 +20,7 @@ 'use strict'; import * as _ from "lodash"; -import {SchemaPropertyGroupModel, SchemaProperty} from "./aschema-property"; +import {SchemaPropertyGroupModel, SchemaProperty} from "./schema-property"; import {InputPropertyBase} from "./input-property-base"; import {PropertyBEModel} from "./properties-inputs/property-be-model"; diff --git a/catalog-ui/src/app/models/schema-attribute.ts b/catalog-ui/src/app/models/schema-attribute.ts index 35211d4db8..e222007dc9 100644 --- a/catalog-ui/src/app/models/schema-attribute.ts +++ b/catalog-ui/src/app/models/schema-attribute.ts @@ -20,14 +20,14 @@ 'use strict'; -import { SchemaProperty } from './aschema-property'; +import {SchemaProperty} from './schema-property'; export class SchemaAttributeGroupModel { - property: SchemaAttribute; + property: SchemaAttribute; - constructor(schemaAttribute?: SchemaAttribute) { - this.property = schemaAttribute; - } + constructor(schemaAttribute?: SchemaAttribute) { + this.property = schemaAttribute; + } } export class SchemaAttribute extends SchemaProperty { diff --git a/catalog-ui/src/app/models/aschema-property.ts b/catalog-ui/src/app/models/schema-property.ts index b0d22d7f91..b0d22d7f91 100644 --- a/catalog-ui/src/app/models/aschema-property.ts +++ b/catalog-ui/src/app/models/schema-property.ts |