diff options
author | Mojahidul Islam <mojahidul.islam@amdocs.com> | 2019-05-14 12:49:31 +0530 |
---|---|---|
committer | Mojahidul Islam <mojahidul.islam@amdocs.com> | 2019-05-14 12:50:27 +0530 |
commit | 82e531a1ee8ffa30e80b27d9097a2272ae18cdee (patch) | |
tree | 900964c5f61e15437e0568f3a5bec3c7083ca5a2 /catalog-ui/src/app | |
parent | 3d5b80b9035b9832f86326858b4c6c2cecd952a3 (diff) |
Support Capability Properties
This change includes following changes
1. Get capability properties from global types- BE
2. Show capability properties in cap/req screen
3. Support Capability Properties in assingment, operation and consumption screens
Change-Id: Ieb4fa5705007c8bed3d82eb4fe4604572aa202d7
Issue-ID: SDC-2294
Signed-off-by: Mojahidul Islam <mojahidul.islam@amdocs.com>
Diffstat (limited to 'catalog-ui/src/app')
21 files changed, 483 insertions, 96 deletions
diff --git a/catalog-ui/src/app/models/capability-types.ts b/catalog-ui/src/app/models/capability-types.ts index fc01f540a7..278d3d397c 100644 --- a/catalog-ui/src/app/models/capability-types.ts +++ b/catalog-ui/src/app/models/capability-types.ts @@ -15,6 +15,7 @@ */ import {ToscaPresentationData} from "./tosca-presentation"; +import {PropertyModel} from "./properties"; export class CapabilityTypesMap { capabilityTypesMap: CapabilityTypesMapData; @@ -30,12 +31,14 @@ export class CapabilityTypesMapData { export class CapabilityTypeModel { derivedFrom: string; + properties: Array<PropertyModel>; toscaPresentation: ToscaPresentationData; constructor(capabilityType?: CapabilityTypeModel) { if (capabilityType) { this.derivedFrom = capabilityType.derivedFrom; this.toscaPresentation = capabilityType.toscaPresentation; + this.properties = capabilityType.properties; } } }
\ No newline at end of file diff --git a/catalog-ui/src/app/models/capability.ts b/catalog-ui/src/app/models/capability.ts index caef2e87dd..4a4f821e0c 100644 --- a/catalog-ui/src/app/models/capability.ts +++ b/catalog-ui/src/app/models/capability.ts @@ -45,6 +45,13 @@ export class CapabilitiesGroup { }); return this[key]; } + + public static getFlattenedCapabilities(capabilitiesGroup: CapabilitiesGroup): Array<Capability> { + return _.reduce( + _.toArray(capabilitiesGroup), + (allCaps, capArr) => allCaps.concat(capArr), + []); + } } export class Capability implements RequirementCapabilityModel{ 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 15b9534b99..5d25142e5a 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { PropertyInputDetail, SchemaPropertyGroupModel, SchemaProperty } from "app/models"; +import {PropertyInputDetail, SchemaPropertyGroupModel, SchemaProperty, ToscaPresentationData} from "app/models"; import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; export enum DerivedPropertyType { SIMPLE, @@ -47,6 +47,7 @@ export class PropertyBEModel { getInputValues: Array<PropertyInputDetail>; getPolicyValues: Array<PropertyPolicyDetail>; name: string; + origName: string; parentUniqueId: string; password: boolean; required: boolean; @@ -58,6 +59,7 @@ export class PropertyBEModel { parentPropertyType: string; subPropertyInputPath: string; inputPath: string; + toscaPresentation: ToscaPresentationData; constructor(property?: PropertyBEModel) { if (property) { @@ -66,6 +68,7 @@ export class PropertyBEModel { this.description = property.description; this.fromDerived = property.fromDerived; this.name = property.name; + this.origName = property.origName; this.parentUniqueId = property.parentUniqueId; this.password = property.password; this.required = property.required; @@ -78,6 +81,7 @@ export class PropertyBEModel { this.getInputValues = property.getInputValues; this.parentPropertyType = property.parentPropertyType; this.subPropertyInputPath = property.subPropertyInputPath; + this.toscaPresentation = property.toscaPresentation; this.getPolicyValues = property.getPolicyValues; this.inputPath = property.inputPath; } 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 c0af885d18..664d128313 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 @@ -40,6 +40,7 @@ export class PropertyFEModel extends PropertyBEModel { valueObjOrig: any; //this is valueObj representation as saved in server valueObjIsChanged: boolean; derivedDataType: DerivedPropertyType; + origName: string; constructor(property: PropertyBEModel){ super(property); @@ -52,6 +53,7 @@ export class PropertyFEModel extends PropertyBEModel { this.valueObj = null; this.updateValueObjOrig(); this.resetValueObjValidation(); + this.origName = this.name; } diff --git a/catalog-ui/src/app/models/tosca-presentation.ts b/catalog-ui/src/app/models/tosca-presentation.ts index 3fdddde448..7cdc5c6be5 100644 --- a/catalog-ui/src/app/models/tosca-presentation.ts +++ b/catalog-ui/src/app/models/tosca-presentation.ts @@ -21,6 +21,7 @@ export class ToscaPresentationData { validTargetTypes: Array<string>; modificationTime: number; uniqueId: string; + ownerId: string; constructor(toscaPresentation?: ToscaPresentationData) { if (toscaPresentation) { @@ -30,6 +31,7 @@ export class ToscaPresentationData { this.validTargetTypes = toscaPresentation.validTargetTypes; this.modificationTime = toscaPresentation.modificationTime; this.uniqueId = toscaPresentation.uniqueId; + this.ownerId = toscaPresentation.ownerId; } } } diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index 126f99ff09..720d29f8ce 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -249,7 +249,7 @@ directiveModule.directive('ng2ServicePathSelector', downgradeComponent({ directiveModule.directive('ng2ServiceConsumption', downgradeComponent({ component: ServiceConsumptionComponent, - inputs: ['parentService', 'selectedService', 'selectedServiceInstanceId', 'instancesMappedList','parentServiceInputs', 'readonly'], + inputs: ['parentService', 'selectedService', 'selectedServiceInstanceId', 'instancesMappedList', 'parentServiceInputs', 'instancesCapabilitiesMap', 'readonly'], outputs: [] }) as angular.IDirectiveFactory); diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts index ef8d63df97..ebcf9eba22 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts @@ -29,7 +29,9 @@ import { PropertyFEModel, PropertyBEModel, InputBEModel, - InterfaceModel + InterfaceModel, + CapabilitiesGroup, + Capability } from 'app/models'; import {ServiceConsumptionCreatorComponent} from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component'; @@ -59,6 +61,7 @@ export class ConsumptionInputDetails extends ConsumptionInput { assignValueLabel: string; associatedProps: Array<string>; associatedInterfaces: Array<any>; + associatedCapabilities: Array<Capability>; origVal: string; isValid: boolean; @@ -70,6 +73,7 @@ export class ConsumptionInputDetails extends ConsumptionInput { this.assignValueLabel = input.assignValueLabel; this.associatedProps = input.associatedProps; this.associatedInterfaces = input.associatedInterfaces; + this.associatedCapabilities = input.associatedCapabilities; this.origVal = input.value || ""; this.isValid = input.isValid; } @@ -128,15 +132,18 @@ export class ServiceConsumptionComponent { @Input() selectedService: Service; @Input() selectedServiceInstanceId: string; @Input() instancesMappedList: Array<ServiceInstanceObject>; + @Input() instancesCapabilitiesMap: Map<string, Array<Capability>>; @Input() readonly: boolean; selectedInstanceSiblings: Array<ServiceInstanceObject>; selectedInstancePropertiesList: Array<PropertyBEModel> = []; + selectedInstanceCapabilitisList: Array<Capability> = []; constructor(private ModalServiceNg2: ModalService, private serviceServiceNg2: ServiceServiceNg2, private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2:ComponentInstanceServiceNg2) {} ngOnInit() { this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } ngOnChanges(changes) { @@ -146,9 +153,11 @@ export class ServiceConsumptionComponent { this.selectedService = changes.selectedService.currentValue; } this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } if(changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) { this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } } @@ -166,6 +175,13 @@ export class ServiceConsumptionComponent { this.selectedInstanceSiblings = _.filter(this.instancesMappedList, coInstance => coInstance.id !== this.selectedServiceInstanceId); } + updateSelectedServiceCapabilities() { + this.selectedInstanceCapabilitisList = _.filter( + CapabilitiesGroup.getFlattenedCapabilities(this.selectedService.capabilities), + cap => cap.properties && cap.ownerId === this.selectedService.uniqueId + ); + } + expandCollapseInterfaceGroup(currInterface) { currInterface.isExpanded = !currInterface.isExpanded; } @@ -190,7 +206,9 @@ export class ServiceConsumptionComponent { parentServiceInputs: this.parentServiceInputs, selectedServiceProperties: this.selectedInstancePropertiesList, selectedServiceInstanceId: this.selectedServiceInstanceId, - selectedInstanceSiblings: this.selectedInstanceSiblings + selectedInstanceSiblings: this.selectedInstanceSiblings, + selectedInstanceCapabilitisList: this.selectedInstanceCapabilitisList, + siblingsCapabilitiesList: this.instancesCapabilitiesMap } ); this.modalInstance.instance.open(); diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts index 9db24b6071..c2a9582ed4 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts @@ -9,14 +9,20 @@ import {Observable} from "rxjs/Observable"; import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; import {ModalService} from 'app/ng2/services/modal.service'; -import {ModalModel, ButtonModel, InputBEModel, OperationModel, InterfaceModel, WORKFLOW_ASSOCIATION_OPTIONS} from 'app/models'; +import { + InputBEModel, + OperationModel, + InterfaceModel, + WORKFLOW_ASSOCIATION_OPTIONS, + CapabilitiesGroup, + Capability +} from 'app/models'; import {IModalConfig, IModalButtonComponent} from "sdc-ui/lib/angular/modals/models/modal-config"; import {SdcUiComponents} from "sdc-ui/lib/angular"; import {ModalButtonComponent} from "sdc-ui/lib/angular/components"; import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service'; -import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response'; import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service'; import {PluginsService} from "app/ng2/services/plugins.service"; @@ -114,6 +120,7 @@ export class InterfaceOperationComponent { modalTranslation: ModalTranslation; workflowIsOnline: boolean; workflows: Array<any>; + capabilities: CapabilitiesGroup; @Input() component: IComponent; @Input() readonly: boolean; @@ -141,7 +148,8 @@ export class InterfaceOperationComponent { Observable.forkJoin( this.ComponentServiceNg2.getInterfaces(this.component), this.ComponentServiceNg2.getComponentInputs(this.component), - this.ComponentServiceNg2.getInterfaceTypes(this.component) + this.ComponentServiceNg2.getInterfaceTypes(this.component), + this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId) ).subscribe((response: Array<any>) => { const callback = (workflows) => { this.isLoading = false; @@ -150,6 +158,7 @@ export class InterfaceOperationComponent { this.inputs = response[1].inputs; this.interfaceTypes = response[2]; this.workflows = workflows; + this.capabilities = response[3].capabilities; }; if (this.enableWorkflowAssociation && this.workflowIsOnline) { this.WorkflowServiceNg2.getWorkflows().subscribe( @@ -267,7 +276,8 @@ export class InterfaceOperationComponent { readonly: this.readonly, interfaceTypes: this.interfaceTypes, validityChangedCallback: this.enableOrDisableSaveButton, - workflowIsOnline: this.workflowIsOnline + workflowIsOnline: this.workflowIsOnline, + capabilities: _.filter(CapabilitiesGroup.getFlattenedCapabilities(this.capabilities), (capability: Capability) => capability.ownerId === this.component.uniqueId) }; const modalConfig: IModalConfig = { diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html index 8f70f7f584..ec056ad6f2 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html @@ -184,16 +184,17 @@ </div> <param-row - *ngFor="let param of tableParameters" - class="data-row" - [isInputParam]="currentTab === TYPE_INPUT" - [isAssociateWorkflow]="isUsingExistingWF()" - [param]="param" - [inputProps]="inputProperties" - [operationOutputs]="operationOutputs" - [onRemoveParam]="onRemoveParam" - [readonly]="readonly" - [validityChanged]="validityChanged"> + *ngFor="let param of tableParameters" + class="data-row" + [isInputParam]="currentTab === TYPE_INPUT" + [isAssociateWorkflow]="isUsingExistingWF()" + [param]="param" + [inputProps]="inputProperties" + [capabilitiesProps]="componentCapabilities" + [operationOutputs]="operationOutputs" + [onRemoveParam]="onRemoveParam" + [readonly]="readonly" + [validityChanged]="validityChanged"> </param-row> </div> diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts index a574460478..e12905654b 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts @@ -5,7 +5,15 @@ import {Subscription} from "rxjs/Subscription"; import {TranslateService} from "app/ng2/shared/translator/translate.service"; import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service'; -import {InterfaceModel, OperationModel, OperationParameter, InputBEModel, RadioButtonModel, WORKFLOW_ASSOCIATION_OPTIONS} from 'app/models'; +import { + InterfaceModel, + OperationModel, + OperationParameter, + InputBEModel, + RadioButtonModel, + WORKFLOW_ASSOCIATION_OPTIONS, + Capability +} from 'app/models'; import {IDropDownOption} from "sdc-ui/lib/angular/form-elements/dropdown/dropdown-models"; import {Tabs, Tab} from "app/ng2/components/ui/tabs/tabs.component"; @@ -39,7 +47,8 @@ export interface OperationCreatorInput { readonly: boolean, interfaceTypes: { [interfaceType: string]: Array<string> }, validityChangedCallback: Function, - workflowIsOnline: boolean; + workflowIsOnline: boolean, + capabilities: Array<Capability> } @Component({ @@ -59,6 +68,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { interfaceTypes: { [interfaceType: string]: Array<string> }; operationNames: Array<TypedDropDownOption> = []; validityChangedCallback: Function; + capabilities: Array<Capability>; allWorkflows: Array<any>; workflows: Array<DropdownValue> = []; @@ -73,6 +83,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { outputParameters: Array<OperationParameter> = []; noAssignOutputParameters: Array<OperationParameter> = []; assignOutputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {}; + componentCapabilities: Array<Capability> = []; tableParameters: Array<OperationParameter> = []; operationOutputs: Array<OperationModel> = []; @@ -171,6 +182,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { } } this.reconstructOperation(); + this.filterCapabilities(); this.validityChanged(); this.updateTable(); } @@ -217,6 +229,10 @@ export class OperationCreatorComponent implements OperationCreatorInput { } + filterCapabilities() { + this.componentCapabilities = _.filter(this.capabilities, (cap: Capability) => cap.properties); + } + buildParams = () => { if (this.inputOperation.outputs) { diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html index 3ac9328487..4a4782eaee 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html @@ -58,6 +58,15 @@ {{output.label}} </option> </optgroup> + <optgroup + *ngFor="let cap of filteredCapabilitiesProps" + label="{{cap.capabilityName}}"> + <option + *ngFor="let prop of cap.properties" + [ngValue]="prop.value"> + {{prop.label}} + </option> + </optgroup> </select> <span *ngIf="!filteredInputProps.length && !operationOutputCats.length && isAssociateWorkflow" diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts index bdf1003a64..c18fb82094 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts @@ -1,7 +1,6 @@ import {Component, Input} from '@angular/core'; import {DataTypeService} from "app/ng2/services/data-type.service"; -import {OperationModel, OperationParameter, InputBEModel, DataTypeModel} from 'app/models'; -import {DropDownOption} from "../operation-creator.component"; +import {OperationModel, OperationParameter, InputBEModel, DataTypeModel, Capability} from 'app/models'; import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component"; class DropdownValueType extends DropdownValue { @@ -25,6 +24,7 @@ export class ParamRowComponent { @Input() param: OperationParameter; @Input() inputProps: Array<InputBEModel>; @Input() operationOutputs: Array<OperationModel>; + @Input() capabilitiesProps: Array<Capability>; @Input() onRemoveParam: Function; @Input() isAssociateWorkflow: boolean; @Input() readonly: boolean; @@ -34,6 +34,7 @@ export class ParamRowComponent { propTypeEnum: Array<string> = []; operationOutputCats: Array<{ operationName: string, outputs: Array<DropdownValueType> }> = []; filteredInputProps: Array<DropdownValue> = []; + filteredCapabilitiesProps: Array<{capabilityName: string, properties: Array<DropdownValueType>}> = []; constructor(private dataTypeService: DataTypeService) {} @@ -113,6 +114,26 @@ export class ParamRowComponent { category => category.outputs.length > 0 ); + this.filteredCapabilitiesProps = _.filter( + _.map( + this.capabilitiesProps, + cap => { + return { + capabilityName: cap.name, + properties: _.map( + _.filter(cap.properties, prop => !this.param.type || prop.type === this.param.type), + prop => new DropdownValueType( + prop.uniqueId, + prop.name, + prop.type + ) + ) + }; + } + ), + capability => capability.properties.length > 0 + ); + if (this.param.inputId) { const selProp = this.getSelectedProp(); if (selProp && selProp.type === this.param.type) { @@ -181,6 +202,12 @@ export class ParamRowComponent { (acc, cat) => [...acc, ...cat.outputs], []), (out: DropdownValueType) => this.param.inputId === out.value + ) || _.find( + _.reduce( + this.filteredCapabilitiesProps, + (acc, cap) => [...acc, ...cap.properties], + []), + (prop: DropdownValueType) => this.param.inputId === prop.value ); } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 9f406f8c76..061439800f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -21,11 +21,32 @@ import * as _ from "lodash"; import {Component, ViewChild, Inject, TemplateRef} from "@angular/core"; import { PropertiesService } from "../../services/properties.service"; -import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData, ModalModel, ButtonModel } from "app/models"; +import { + PropertyFEModel, + InstanceFePropertiesMap, + InstanceBePropertiesMap, + InstancePropertiesAPIMap, + Component as ComponentData, + FilterPropertiesAssignmentData, + ModalModel, + ButtonModel, + Capability, + ToscaPresentationData +} from "app/models"; import { ResourceType } from "app/utils"; import {ComponentServiceNg2} from "../../services/component-services/component.service"; import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service" -import { InputBEModel, InputFEModel, ComponentInstance, GroupInstance, PolicyInstance, PropertyBEModel, DerivedFEProperty, SimpleFlatProperty } from "app/models"; +import { + InputBEModel, + InputFEModel, + ComponentInstance, + GroupInstance, + PolicyInstance, + PropertyBEModel, + DerivedFEProperty, + SimpleFlatProperty, + CapabilitiesGroup +} from "app/models"; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; import {WorkspaceMode, EVENTS} from "../../../utils/constants"; import {EventListenerService} from "app/services/event-listener-service" @@ -45,6 +66,7 @@ import { SdcUiComponents } from "sdc-ui/lib/angular"; //import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"; import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config"; import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component"; +import {Observable} from "rxjs"; import { DataTypeService } from "app/ng2/services/data-type.service"; import { DataTypeModel } from "app/models"; import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils"; @@ -96,6 +118,8 @@ export class PropertiesAssignmentComponent { savingChangedData:boolean; stateChangeStartUnregister:Function; serviceBePropertiesMap: InstanceBePropertiesMap; + serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap; + selectedInstance_FlattenCapabilitiesList: Array<Capability>; @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs; @ViewChild('propertyInputTabs') propertyInputTabs: Tabs; @@ -243,12 +267,14 @@ export class PropertiesAssignmentComponent { this.loadingProperties = true; if (instance instanceof ComponentInstance) { let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + this.selectedInstance_FlattenCapabilitiesList = instance.capabilities ? CapabilitiesGroup.getFlattenedCapabilities(instance.capabilities) : []; if (this.isInput(instance.originType)) { this.componentInstanceServiceNg2 .getComponentInstanceInputs(this.component, instance) .subscribe(response => { instanceBePropertiesMap[instance.uniqueId] = response; this.processInstancePropertiesResponse(instanceBePropertiesMap, true); + this.processInstanceCapabilitiesPropertiesResponse(false); this.loadingProperties = false; }, error => { }); //ignore error @@ -260,6 +286,7 @@ export class PropertiesAssignmentComponent { .subscribe(response => { instanceBePropertiesMap[instance.uniqueId] = response; this.processInstancePropertiesResponse(instanceBePropertiesMap, false); + this.processInstanceCapabilitiesPropertiesResponse(false); this.loadingProperties = false; }, error => { }); //ignore error @@ -305,6 +332,40 @@ export class PropertiesAssignmentComponent { this.checkedChildPropertiesCount = 0; }; + processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => { + let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData); + let currentUniqueId = this.selectedInstanceData.uniqueId; + this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap(); + let isCapabilityOwnedByInstance: boolean; + this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce( + this.selectedInstance_FlattenCapabilitiesList, + (result, cap: Capability) => { + isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId || + selectedComponentInstanceData.isServiceProxy() && cap.ownerId === selectedComponentInstanceData.sourceModelUid; + if (cap.properties && isCapabilityOwnedByInstance) { + _.forEach(cap.properties, prop => { + if (!prop.origName) { + prop.origName = prop.name; + prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name) + } + }); + return result.concat(cap.properties); + } + return result; + }, []); + let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values + //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties + _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => { + prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName; + }); + //concatenate capabilitiesProps to all props list + this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]); + this.checkedPropertiesCount = 0; + }; + + isCapabilityProperty = (prop: PropertyBEModel) => { + return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId); + }; /*** VALUE CHANGE EVENTS ***/ dataChanged = (item:PropertyFEModel|InputFEModel) => { @@ -439,6 +500,33 @@ export class PropertiesAssignmentComponent { let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties); + //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties + inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] = + (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat( + _.filter( + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId], + (prop: PropertyBEModel) => this.isCapabilityProperty(prop) + ) + ); + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter( + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId], + prop => !this.isCapabilityProperty(prop) + ); + if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) { + delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId]; + } + + let isCapabilityPropertyChanged = false; + _.forEach( + inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId], + (prop: PropertyBEModel) => { + prop.name = prop.origName || prop.name; + if (this.isCapabilityProperty(prop)) { + isCapabilityPropertyChanged = true; + } + } + ); + this.componentServiceNg2 .createInput(this.component, inputsToCreate, this.isSelf()) .subscribe(response => { @@ -451,6 +539,9 @@ export class PropertiesAssignmentComponent { this.inputs.push(newInput); this.updatePropertyValueAfterDeclare(newInput); }); + if (isCapabilityPropertyChanged) { + this.reloadInstanceCapabilities(); + } }, error => {}); //ignore error }; @@ -625,18 +716,37 @@ export class PropertiesAssignmentComponent { // make request and its handlers let request; let handleSuccess, handleError; + let changedInputsProperties = [], changedCapabilitiesProperties = []; if (this.isPropertiesTabSelected) { const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => { changedProp = <PropertyFEModel>changedProp; const propBE = new PropertyBEModel(changedProp); + propBE.toscaPresentation = new ToscaPresentationData(); + propBE.toscaPresentation.ownerId = changedProp.parentUniqueId; propBE.value = changedProp.getJSONValue(); + propBE.name = changedProp.origName || changedProp.name; + delete propBE.origName; return propBE; }); + changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop)); if (this.selectedInstanceData instanceof ComponentInstance) { if (this.isInput(this.selectedInstanceData.originType)) { - request = this.componentInstanceServiceNg2 - .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedProperties); + changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop)); + if (changedInputsProperties.length && changedCapabilitiesProperties.length) { + request = Observable.forkJoin( + this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties), + this.componentInstanceServiceNg2.updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties) + ); + } + else if (changedInputsProperties.length) { + request = this.componentInstanceServiceNg2 + .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties); + } + else if (changedCapabilitiesProperties.length) { + request = this.componentInstanceServiceNg2 + .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties); + } handleSuccess = (response) => { // reset each changed property with new value and remove it from changed properties list response.forEach((resInput) => { @@ -714,6 +824,9 @@ export class PropertiesAssignmentComponent { request.subscribe( (response) => { this.savingChangedData = false; + if (changedCapabilitiesProperties.length) { + this.reloadInstanceCapabilities(); + } handleSuccess && handleSuccess(response); this.updateHasChangedData(); resolve(response); @@ -728,6 +841,19 @@ export class PropertiesAssignmentComponent { }); }; + reloadInstanceCapabilities = (): void => { + let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId); + this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => { + let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => { + if (instance.uniqueId === this.selectedInstanceData.uniqueId) { + return instance.capabilities; + } + return res; + }, new CapabilitiesGroup()); + (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData; + }); + }; + reverseChangedData = ():void => { // make reverse item handler let handleReverseItem; @@ -814,8 +940,10 @@ export class PropertiesAssignmentComponent { updatePropertyValueAfterDeclare = (input: InputFEModel) => { if (this.instanceFePropertiesMap[input.instanceUniqueId]) { + let instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1); let propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => { - return feProperty.name == input.relatedPropertyName; + return feProperty.uniqueId === input.propertyId && + (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_'))); }); let inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined; propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value diff --git a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts index 82e2e464cc..32a73efa85 100644 --- a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts @@ -62,6 +62,10 @@ export class CapabilitiesEditorComponent { let selectedCapabilityTypeObj: CapabilityTypeModel = this.input.capabilityTypesList.find(capType => capType.toscaPresentation.type === selectedCapType.value); this.capabilityData.description = selectedCapabilityTypeObj.toscaPresentation.description; this.capabilityData.validSourceTypes = selectedCapabilityTypeObj.toscaPresentation.validTargetTypes; + this.capabilityData.properties = _.forEach( + _.toArray(selectedCapabilityTypeObj.properties), + prop => prop.uniqueId = null //a requirement for the BE + ); } this.validityChanged(); } diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html index e77d880176..2c4e2886a1 100644 --- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html +++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html @@ -77,6 +77,15 @@ {{output.name}} </option> </optgroup> + <optgroup + *ngFor="let cap of consumptionInput.associatedCapabilities" + label="{{cap.name}}"> + <option + *ngFor="let prop of cap.properties" + [ngValue]="cap.name + '_' + prop.name"> + {{prop.name}} + </option> + </optgroup> </select> </div> </div> diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts index 25f412671f..2c86cc5c5c 100644 --- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts @@ -17,7 +17,17 @@ import * as _ from "lodash"; import { Component } from '@angular/core'; import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service"; -import {Service, ServiceInstanceObject, InstanceFePropertiesMap, InstanceBePropertiesMap, PropertyBEModel, InputBEModel, OperationModel, InterfaceModel} from 'app/models'; +import { + Service, + ServiceInstanceObject, + InstanceFePropertiesMap, + InstanceBePropertiesMap, + PropertyBEModel, + InputBEModel, + OperationModel, + InterfaceModel, + Capability +} from 'app/models'; import {ConsumptionInput, ConsumptionInputDetails, ServiceOperation} from 'app/ng2/components/logic/service-consumption/service-consumption.component'; import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils"; import { PROPERTY_DATA } from 'app/utils'; @@ -33,7 +43,7 @@ import { PROPERTY_DATA } from 'app/utils'; export class ServiceConsumptionCreatorComponent { input: { - interfaceId: string; + interfaceId: string, serviceOperationIndex: number, serviceOperations: Array<ServiceOperation>, parentService: Service, @@ -41,7 +51,9 @@ export class ServiceConsumptionCreatorComponent { parentServiceInputs: Array<InputBEModel>, selectedServiceProperties: Array<PropertyBEModel>, selectedServiceInstanceId: String, - selectedInstanceSiblings: Array<ServiceInstanceObject> + selectedInstanceSiblings: Array<ServiceInstanceObject>, + selectedInstanceCapabilitisList: Array<Capability>, + siblingsCapabilitiesList: Map<string, Array<Capability>> }; sourceTypes: Array<any> = []; serviceOperationsList: Array<ServiceOperation>; @@ -80,16 +92,24 @@ export class ServiceConsumptionCreatorComponent { initSourceTypes() { this.sourceTypes = [ - { label: this.SOURCE_TYPES.STATIC, value: this.SOURCE_TYPES.STATIC, options: [], interfaces: []}, + { + label: this.SOURCE_TYPES.STATIC, + value: this.SOURCE_TYPES.STATIC, + options: [], + interfaces: [], + capabilities: [] + }, { label: this.SOURCE_TYPES.SELF + ' (' + this.selectedService.name + ')', value: this.selectedServiceInstanceId, options: this.selectedServiceProperties, - interfaces: this.selectedService.interfaces + interfaces: this.selectedService.interfaces, + capabilities: this.input.selectedInstanceCapabilitisList }, { label: this.parentService.name, value: this.parentService.uniqueId, options: this.parentServiceInputs, - interfaces: [] + interfaces: [], + capabilities: [] } ]; _.forEach(this.input.selectedInstanceSiblings, sib => @@ -97,7 +117,8 @@ export class ServiceConsumptionCreatorComponent { label: sib.name, value: sib.id, options: _.unionBy(sib.inputs, sib.properties, 'uniqueId'), - interfaces: sib.interfaces + interfaces: sib.interfaces, + capabilities: this.input.siblingsCapabilitiesList[sib.id] }) ); } @@ -160,6 +181,7 @@ export class ServiceConsumptionCreatorComponent { consumptionInputDetails.assignValueLabel = this.getAssignValueLabel(sourceVal); consumptionInputDetails.associatedProps = filteredListsObj.associatedPropsList; consumptionInputDetails.associatedInterfaces = filteredListsObj.associatedInterfacesList; + consumptionInputDetails.associatedCapabilities = filteredListsObj.associatedCapabilitiesList; return new ConsumptionInputDetails(consumptionInputDetails); }); } @@ -171,6 +193,7 @@ export class ServiceConsumptionCreatorComponent { let filteredListsObj = this.getFilteredProps(consumptionInput.source, consumptionInput.type); consumptionInput.associatedProps = filteredListsObj.associatedPropsList; consumptionInput.associatedInterfaces = filteredListsObj.associatedInterfacesList; + consumptionInput.associatedCapabilities = filteredListsObj.associatedCapabilitiesList; if(consumptionInput.source === this.SOURCE_TYPES.STATIC) { if(PROPERTY_DATA.SIMPLE_TYPES.indexOf(consumptionInput.type) !== -1) { consumptionInput.value = consumptionInput.defaultValue || ""; @@ -184,7 +207,7 @@ export class ServiceConsumptionCreatorComponent { private getFilteredProps(sourceVal, inputType) { let currentSourceObj = this.sourceTypes.find(s => s.value === sourceVal); - let associatedInterfacesList = [], associatedPropsList = []; + let associatedInterfacesList = [], associatedPropsList = [], associatedCapabilitiesPropsList: Array<Capability> = []; if(currentSourceObj) { if (currentSourceObj.interfaces) { associatedInterfacesList = this.getFilteredInterfaceOutputs(currentSourceObj, inputType); @@ -195,10 +218,22 @@ export class ServiceConsumptionCreatorComponent { } return result; }, []); + associatedCapabilitiesPropsList = + _.reduce(currentSourceObj.capabilities, + (filteredCapsList, capability: Capability) => { + let filteredProps = _.filter(capability.properties, prop => prop.type === inputType); + if (filteredProps.length) { + let cap = new Capability(capability); + cap.properties = filteredProps; + filteredCapsList.push(cap); + } + return filteredCapsList + }, []); } return { associatedPropsList: associatedPropsList, - associatedInterfacesList: associatedInterfacesList + associatedInterfacesList: associatedInterfacesList, + associatedCapabilitiesList: associatedCapabilitiesPropsList } } diff --git a/catalog-ui/src/app/ng2/services/component-services/service.service.ts b/catalog-ui/src/app/ng2/services/component-services/service.service.ts index 406ac77ec4..dce4e814ec 100644 --- a/catalog-ui/src/app/ng2/services/component-services/service.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/service.service.ts @@ -115,7 +115,9 @@ export class ServiceServiceNg2 extends ComponentServiceNg2 { COMPONENT_FIELDS.COMPONENT_INSTANCES_INTERFACES, COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_INPUTS, - COMPONENT_FIELDS.COMPONENT_INPUTS + COMPONENT_FIELDS.COMPONENT_INPUTS, + COMPONENT_FIELDS.COMPONENT_INSTANCES, + COMPONENT_FIELDS.COMPONENT_CAPABILITIES ]); } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts index 20e99b0d39..737002303b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts @@ -16,7 +16,17 @@ import {ICompositionViewModelScope} from "../../composition-view-model"; -import {Service, PropertiesGroup, InputsGroup, ServiceInstanceObject, InterfaceModel, InputBEModel} from 'app/models'; +import { + Service, + PropertiesGroup, + InputsGroup, + ServiceInstanceObject, + InterfaceModel, + InputBEModel, + CapabilitiesGroup, + Capability, + ComponentInstance +} from 'app/models'; import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service"; @@ -27,6 +37,8 @@ interface IServiceConsumptionViewModelScope extends ICompositionViewModelScope { componentInstancesInputs: InputsGroup; componentInstancesInterfaces: Map<string, Array<InterfaceModel>>; componentInputs: Array<InputBEModel>; + componentCapabilities: Array<Capability>; + instancesCapabilitiesMap: Map<string, Array<Capability>>; } @@ -49,10 +61,20 @@ export class ServiceConsumptionViewModel { this.$scope.componentInstancesInputs = genericResponse.componentInstancesInputs; this.$scope.componentInstancesInterfaces = genericResponse.componentInstancesInterfaces; this.$scope.componentInputs = genericResponse.inputs; + this.buildInstancesCapabilitiesMap(genericResponse.componentInstances); this.updateInstanceAttributes(); }); } + buildInstancesCapabilitiesMap = (componentInstances: Array<ComponentInstance>): void => { + this.$scope.instancesCapabilitiesMap = new Map(); + let flattenCapabilities = []; + _.forEach(componentInstances, componentInstance => { + flattenCapabilities = CapabilitiesGroup.getFlattenedCapabilities(componentInstance.capabilities); + this.$scope.instancesCapabilitiesMap[componentInstance.uniqueId] = _.filter(flattenCapabilities, cap => cap.properties && cap.ownerId === componentInstance.uniqueId); + }); + } + private updateInstanceAttributes = ():void => { if (this.$scope.isComponentInstanceSelected() && this.$scope.componentInstancesProperties) { this.$scope.instancesMappedList = this.$scope.service.componentInstances.map(coInstance => new ServiceInstanceObject({ diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html index 835ded33f6..8404a7f653 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html @@ -14,6 +14,7 @@ [selected-service-instance-id]="currentComponent.selectedInstance.uniqueId" [instances-mapped-list]="instancesMappedList" [parent-service-inputs]="componentInputs" + [instances-capabilities-map]="instancesCapabilitiesMap" [readonly]="isViewMode() || !isDesigner()"> </ng2-service-consumption> </div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html index 14bc49e28b..8e1822193b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html @@ -96,8 +96,8 @@ <div class="flex-container data-row" data-ng-class="{'editable-row': req.isCreatedManually}" data-ng-click="req.isCreatedManually && onEditRequirement(req)"> <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{req.name}}"> - <span data-tests-id="{{req.name}}">{{req.name}}</span> + tooltip-content="{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}"> + <span data-tests-id="{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}">{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}</span> </div> <div class="table-col-general flex-item text ellipsis-text" tooltips tooltip-content="{{req.capability}}"> @@ -148,17 +148,22 @@ <div data-ng-if="filteredCapabilitiesList.length === 0" class="no-row-text" data-tests-id="no-rows-in-table"> There are no capabilities to display - </div> - <div data-ng-repeat="capability in filteredCapabilitiesList | orderBy:capabilitiesSortTableDefined.sortByField:capabilitiesSortTableDefined.reverse track by $index" + <div data-ng-repeat-start="capability in filteredCapabilitiesList | orderBy:capabilitiesSortTableDefined.sortByField:capabilitiesSortTableDefined.reverse track by $index" class="flex-container data-row" data-ng-class="{'selected': capability.selected, 'editable-row': capability.isCreatedManually}" data-ng-click="capability.isCreatedManually && onEditCapability(capability)" data-tests-id="capabilities-table-row"> <div class="table-col-general flex-item text ellipsis-text" tooltips - tooltip-content="{{capability.name}}"> - <span data-tests-id="{{capability.name}}">{{capability.name}}</span> + tooltip-content="{{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}}"> + <span class="sprite-new arrow-up-small hand" + data-ng-class="{'hideme': !capability.properties.length, 'opened': capability.selected}" + data-ng-click="capability.selected = !capability.selected; $event.stopPropagation();"></span> + <span data-tests-id="{{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}}" + class="name-col" data-ng-class="{'opened': capability.selected}"> + {{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}} + </span> </div> <div class="table-col-general flex-item text ellipsis-text" tooltips tooltip-content="{{capability.type}}"> @@ -188,6 +193,51 @@ data-ng-click="onDeleteCap($event, capability)"></svg-icon> </div> </div> + <div data-ng-repeat-end data-ng-if="capability.selected" class="item-opened properties-section"> + <p class="properties-title">Properties</p> + <div class="table-container-flex properties-table"> + <div class="table" data-ng-class="{'view-mode': true}"> + <div class="head flex-container"> + <div class="table-header head-row hand flex-item" + data-ng-repeat="header in capabilityPropertiesTableHeadersList track by $index" + data-ng-click="sort(header.property, propertiesSortTableDefined)"> + {{header.title}} + <span data-ng-if="propertiesSortTableDefined.sortByField === header.property" + class="table-header-sort-arrow" + data-ng-class="{'down': propertiesSortTableDefined.reverse, 'up':!propertiesSortTableDefined.reverse}"> </span> + </div> + </div> + + <div class="body"> + <div data-ng-repeat="property in capability.properties | orderBy:propertiesSortTableDefined.sortByField:propertiesSortTableDefined.reverse track by $index" + data-tests-id="propertyRow" + class="flex-container data-row"> + <div class="table-col-general flex-item text" + data-tests-id="{{property.name}}" + tooltips tooltip-content="{{property.name}}"> + {{property.name}} + </div> + <div class="table-col-general flex-item text" + data-tests-id="{{property.type}}" + tooltips tooltip-content="{{property.type}}"> + {{property.type}} + </div> + <div class="table-col-general flex-item text" + data-tests-id="{{property.schema.property.type}}" + tooltips tooltip-content="{{property.schema.property.type}}"> + {{property.schema.property.type}} + </div> + <div class="table-col-general flex-item text" + tooltips tooltip-content="{{property.description}}" + data-tests-id="{{property.description}}"> + {{property.description}} + </div> + </div> + </div> + + </div> + </div> + </div> </perfect-scrollbar> </div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less index fa6623f089..928f6719c6 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less @@ -319,63 +319,100 @@ } } } - .table-container-flex .table .head .head-row { - text-align: left; - &.description { - flex: 2; - } - &.other { - flex: 0.25; - text-align: center; - } - &.occurrences { - flex: 0.75; - } - } - .data-row { - .ellipsis-text { - overflow: hidden; - text-overflow: ellipsis; - } - &:not(.editable-row) { - background: @tlv_color_t; - cursor: default; - color: @main_color_n; - } - &.editable-row { - cursor: pointer; - .table-col-general:hover { - color: @main_color_b; + .table-container-flex .table { + .head .head-row { + text-align: left; + &.description { + flex: 2; } - } - .description-col { - flex: 2; - } - .occurrences-col { - flex: 0.75; - } - .other-col { - display: flex; - justify-content: center; - align-items: center; - flex: 0.25; - .trash-icon { - visibility: hidden; + &.other { + flex: 0.25; + text-align: center; + } + &.occurrences { + flex: 0.75; } } - &:hover { - .trash-icon { - visibility: visible; + .body .data-row { + border-bottom: none; + border-top: @main_color_o solid 1px; + .ellipsis-text { + overflow: hidden; + text-overflow: ellipsis; + } + &:not(.editable-row) { + background-color: @tlv_color_t; + cursor: default; + color: @main_color_n; + } + &.editable-row { + cursor: pointer; + .table-col-general:hover { + color: @main_color_b; + } + } + &.selected { + background-color: @tlv_color_v; + .name-col { + color: @main_color_a; + } + .sprite-new.arrow-up-small { + background-position: -858px -137px; + margin-bottom: 2px; + } } + .description-col { + flex: 2; + } + .occurrences-col { + flex: 0.75; + } + .other-col { + display: flex; + justify-content: center; + align-items: center; + flex: 0.25; + .trash-icon { + visibility: hidden; + } + } + &:hover { + .trash-icon { + visibility: visible; + } + } + .multiline-ellipsis { + line-height: 1.5em; + padding: 1px 0 1px 0; + /deep/ .ellipsis-directive-more-less { + float: none; + margin-left: 5px; + color: @main_color_a; + } + } + } + } + + .item-opened.properties-section { + border: 4px solid @tlv_color_v !important; + max-height: 263px; + overflow: auto; + .properties-title { + .s_10; + margin-top: 10px; } - .multiline-ellipsis { - line-height: 1.5em; - padding: 1px 0 1px 0; - /deep/ .ellipsis-directive-more-less { - float: none; - margin-left: 5px; - color: @main_color_a; + .properties-table { + &.table-container-flex { + margin-top: 18px; + } + .table { + .head { + border-bottom: 1px solid @main_color_o; + } + .head, .table-col-general { + background-color: @main_color_p; + } } } } -} +}
\ No newline at end of file |