summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJvD_Ericsson <jeff.van.dam@est.tech>2022-02-17 15:48:20 +0000
committerMichael Morris <michael.morris@est.tech>2022-03-10 13:27:17 +0000
commit767b122ea026099e17a2ffde30e6718d2abf150f (patch)
treea03f53058977efeeb8e60ec28808775aaaeacb9d
parentca1cef5e1c74dc5e8d2fb17864648e94b9b66aa0 (diff)
Support occurrences on node templates
Issue-ID: SDC-3711 Change-Id: I9f25454faa8be6987f336b7efd3821cfa09585a1 Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java2
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java14
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java1
-rw-r--r--catalog-ui/src/app/models/componentsInstances/componentInstance.ts4
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html65
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less8
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts68
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java21
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java2
9 files changed, 179 insertions, 6 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
index ca4002f26a..2f712e1e7b 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
@@ -1263,6 +1263,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
oldComponentInstance.setModificationTime(System.currentTimeMillis());
oldComponentInstance.setCustomizationUUID(UUID.randomUUID().toString());
oldComponentInstance.setDirectives(newComponentInstance.getDirectives());
+ oldComponentInstance.setMaxOccurrences(newComponentInstance.getMaxOccurrences());
+ oldComponentInstance.setMinOccurrences(newComponentInstance.getMinOccurrences());
if (oldComponentInstance.getGroupInstances() != null) {
oldComponentInstance.getGroupInstances().forEach(group -> group.setName(getNewGroupName(oldComponentInstance.getNormalizedName(),
ValidationUtils.normalizeComponentInstanceName(newComponentInstance.getName()), group.getName())));
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
index ef63a86d39..5c30d0977c 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
@@ -46,6 +46,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import com.google.common.primitives.Ints;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FilenameUtils;
@@ -912,6 +913,12 @@ public class ToscaExportHandler {
if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
}
+ if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences()!= null){
+ List<Object> occur = new ArrayList<Object>();
+ occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
+ occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
+ nodeTemplate.setOccurrences(occur);
+ }
nodeTemplate.setType(componentInstance.getToscaComponentName());
nodeTemplate.setDirectives(componentInstance.getDirectives());
nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
@@ -1015,7 +1022,12 @@ public class ToscaExportHandler {
log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
return convertNodeTemplatesRes;
}
-
+
+ private Object parseToIntIfPossible(final String value) {
+ final Integer intValue = Ints.tryParse(value);
+ return intValue == null ? value : intValue;
+ }
+
private void handleInstanceInterfaces(
Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java
index f909a9c7b1..0a75870502 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java
@@ -34,6 +34,7 @@ import org.apache.commons.collections.MapUtils;
public class ToscaNodeTemplate {
private String type;
+ private List<Object> occurrences;
private List<String> directives;
private Map<String, String> metadata;
private String description;
diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
index c3188baa47..86411b2dd5 100644
--- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
+++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
@@ -94,6 +94,8 @@ export class ComponentInstance implements IComponentInstance{
public sourceModelName:string;
public sourceModelUid:string;
public sourceModelUuid:string;
+ public minOccurrences: string;
+ public maxOccurrences: string;
//custom properties
public certified:boolean;
public iconSprite:string;
@@ -137,6 +139,8 @@ export class ComponentInstance implements IComponentInstance{
this.originArchived = componentInstance.originArchived;
this.directives = componentInstance.directives;
this.interfaces = componentInstance.interfaces;
+ this.minOccurrences = componentInstance.minOccurrences;
+ this.maxOccurrences = componentInstance.maxOccurrences;
}
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
index 86c6fea1ef..358c910c2b 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
@@ -92,6 +92,69 @@
</sdc-accordion>
</ng-container>
</div>
- </div>
+
+ </div>
+ </content>
+</ng2-expand-collapse>
+
+<ng2-expand-collapse state="0">
+ <header sdc-tooltip tooltip-text="Occurrences">OCCURRENCES</header>
+ <content>
+ <div class="w-sdc-designer-sidebar-section">
+ <div *ngIf="isUnboundedChecked != null">
+ <ng-container>
+ <sdc-accordion [title]="component.name + ' Occurrences'" [arrow-direction]="'right'" [testId]="'Occurrences'" [css-class]="'occurrences-accordion'">
+ <div class="i-sdc-designer-sidebar-section-content-item">
+ <div class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+ <checkbox [(checked)]="isOccurrencesEnabled" (change)="enableOccurrences()" [disabled]="isViewOnly"></checkbox>
+ <div>
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label"
+ [ngClass]="{'hand enabled': !isViewOnly}">Enable Occurrences</span>
+ </div>
+ </div>
+ <div *ngIf="isOccurrencesEnabled" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+ <div class="sdc-input">
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label">Min Occurrences</span>
+ <div class="min-occurrences-value">
+ <sdc-input
+ label=""
+ testId="reqOccurrencesMin"
+ [disabled]="isViewOnly"
+ [(value)]="component.minOccurrences"
+ type="number">
+ </sdc-input>
+ </div>
+ </div>
+ </div>
+ <div *ngIf="isOccurrencesEnabled" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+ <div class="sdc-input">
+ <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label">Max Occurrences</span>
+ <div class="max-occurrences-value">
+ <sdc-checkbox
+ class="checkbox-label unbounded-value"
+ testId="reqOccurrencesMaxUnbounded"
+ label="Unbounded"
+ (checkedChange)="onUnboundedChanged(component)"
+ [checked]="isUnboundedChecked"
+ [disabled]="isViewOnly">
+ </sdc-checkbox>
+ <sdc-input
+ *ngIf="!isUnboundedChecked"
+ testId="reqOccurrencesMax"
+ [disabled]="isViewOnly"
+ [(value)]="component.maxOccurrences"
+ type="number">
+ </sdc-input>
+ </div>
+ </div>
+ </div>
+ <div *ngIf="!isViewOnly && isOccurrencesEnabled" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+ <button class="tlv-btn blue" (click)="saveOccurrences()" [disabled]="!isOccurrencesFormValid(component)">Save</button>
+ </div>
+ </div>
+ </sdc-accordion>
+ </ng-container>
+ </div>
+ </div>
</content>
</ng2-expand-collapse>
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
index 5cb0697da1..ac0d1707e7 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.less
@@ -21,6 +21,10 @@
flex: 0 0 auto;
align-self: center;
}
+
+ /deep/ .checkbox-container {
+ margin-right: 10px;
+ }
}
.i-sdc-designer-sidebar-section-content-item-property-and-attribute-label {
@@ -39,14 +43,12 @@
display: block;
}
-
-
/deep/ .expand-collapse-content {
max-height: max-content;
padding: 10px 0;
.sdc-accordion .sdc-accordion-header {
-
+
background-color: #e6f6fb;
border-left: solid #009fdb 4px;
box-shadow: 0 0px 3px -1px rgba(0, 0, 0, 0.3);
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
index b4b8248ed0..99bd5e882d 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
@@ -4,6 +4,7 @@ import {
AttributeModel,
AttributesGroup,
Component as TopologyTemplate,
+ ComponentInstance,
ComponentMetadata,
FullComponentInstance,
PropertiesGroup,
@@ -14,6 +15,7 @@ import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe';
import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
+import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
import { TranslateService } from 'app/ng2/shared/translator/translate.service';
import { ModalsHandler } from 'app/utils';
@@ -33,6 +35,9 @@ export class PropertiesTabComponent implements OnInit {
propertiesMessage: string;
metadata: ComponentMetadata;
objectKeys = Object.keys;
+ isUnboundedChecked: boolean;
+ isOccurrencesEnabled: boolean = false;
+ isLoading: boolean;
@Input() isViewOnly: boolean;
@Input() componentType: SelectedComponentType;
@@ -44,6 +49,7 @@ export class PropertiesTabComponent implements OnInit {
private compositionService: CompositionService,
private modalsHandler: ModalsHandler,
private topologyTemplateService: TopologyTemplateService,
+ private componentInstanceService: ComponentInstanceServiceNg2,
private modalService: SdcUiServices.ModalService,
private translateService: TranslateService,
private groupByPipe: GroupByPipe) {
@@ -176,6 +182,15 @@ export class PropertiesTabComponent implements OnInit {
}
}
+ private initComponentOccurrences = (): void => {
+ if (this.component instanceof FullComponentInstance) {
+ if(this.component.minOccurrences != null && this.component.maxOccurrences != null){
+ this.isOccurrencesEnabled = true;
+ }
+ this.isUnboundedChecked = this.component.maxOccurrences == "UNBOUNDED" ? true: false;
+ }
+ }
+
/**
* This function is checking if the component is the value owner of the current property
* in order to notify the edit property modal which fields to disable
@@ -208,5 +223,58 @@ export class PropertiesTabComponent implements OnInit {
private initPropertiesAndAttributes = (): void => {
this.initComponentProperties();
this.initComponentAttributes();
+ this.initComponentOccurrences();
+ }
+
+ onUnboundedChanged(component: ComponentInstance) {
+ this.isUnboundedChecked = !this.isUnboundedChecked;
+ component.maxOccurrences = this.isUnboundedChecked ? "UNBOUNDED" : "1";
+ }
+
+ private updateComponentInstance(component: ComponentInstance) {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
+
+ this.componentInstanceService.updateComponentInstance(this.workspaceService.metadata.componentType,
+ this.workspaceService.metadata.uniqueId, component)
+ .subscribe((updatedComponentInstance: ComponentInstance) => {
+ component = new ComponentInstance(updatedComponentInstance);
+ this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).maxOccurrences = component.maxOccurrences;
+ this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).minOccurrences = component.minOccurrences;
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ }, (error:any) => {
+ this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
+ if (error) {
+ console.log(error);
+ }});
+ }
+
+ private enableOccurrences = () => {
+ if(this.component instanceof FullComponentInstance){
+ if(!this.isOccurrencesEnabled){
+ this.component.minOccurrences = null;
+ this.component.maxOccurrences = null;
+ } else {
+ this.component.minOccurrences = "1";
+ this.component.maxOccurrences = "1";
+ }
+ this.updateComponentInstance(this.component);
+ }
+ }
+
+ private isOccurrencesFormValid(component: FullComponentInstance) {
+ if(
+ component.minOccurrences && parseInt(component.minOccurrences) >= 0 &&
+ component.maxOccurrences && (parseInt(component.maxOccurrences) >= parseInt(component.minOccurrences) || component.maxOccurrences === "UNBOUNDED")
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private saveOccurrences = () => {
+ if(this.component instanceof FullComponentInstance && this.isOccurrencesFormValid(this.component)) {
+ this.updateComponentInstance(this.component);
+ }
}
}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java
index afcc0e6d9f..ce8dda0b39 100644
--- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java
+++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java
@@ -53,6 +53,8 @@ public class ComponentInstanceDataDefinition extends ToscaDataDefinition {
setDescription(dataDefinition.getDescription());
setPosX(dataDefinition.getPosX());
setPosY(dataDefinition.getPosY());
+ setMinOccurrences(dataDefinition.getMinOccurrences());
+ setMaxOccurrences(dataDefinition.getMaxOccurrences());
setPropertyValueCounter(dataDefinition.getPropertyValueCounter());
setNormalizedName(dataDefinition.getNormalizedName());
setOriginType(dataDefinition.getOriginType());
@@ -138,6 +140,22 @@ public class ComponentInstanceDataDefinition extends ToscaDataDefinition {
setToscaPresentationValue(JsonPresentationFields.CI_POS_Y, posY);
}
+ public String getMinOccurrences() {
+ return (String) getToscaPresentationValue(JsonPresentationFields.CI_MIN_OCCURRENCES);
+ }
+
+ public void setMinOccurrences(String minOccurrences) {
+ setToscaPresentationValue(JsonPresentationFields.CI_MIN_OCCURRENCES, minOccurrences);
+ }
+
+ public String getMaxOccurrences() {
+ return (String) getToscaPresentationValue(JsonPresentationFields.CI_MAX_OCCURRENCES);
+ }
+
+ public void setMaxOccurrences(String maxOccurrences) {
+ setToscaPresentationValue(JsonPresentationFields.CI_MAX_OCCURRENCES, maxOccurrences);
+ }
+
public String getComponentUid() {
return (String) getToscaPresentationValue(JsonPresentationFields.CI_COMPONENT_UID);
}
@@ -346,7 +364,8 @@ public class ComponentInstanceDataDefinition extends ToscaDataDefinition {
+ getAttributeValueCounter() + ", inputValueCounter=" + getInputValueCounter() + ", originType="
+ getOriginType() + ", customizationUUID=" + getCustomizationUUID() + ", componentName="
+ getComponentName() + ", componentVersion=" + getComponentVersion() + ", toscaComponentName="
- + getToscaComponentName() + ", directives =" + getDirectivesString() + "]";
+ + getToscaComponentName() + ", directives =" + getDirectivesString() + ", minOccurrences ="
+ + getMinOccurrences() + ", maxOccurrences =" + getMaxOccurrences() +"]";
}
}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
index 8fce664686..e36e4ef734 100644
--- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
+++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
@@ -200,6 +200,8 @@ public enum JsonPresentationFields {
CI_IS_PROXY("isProxy", null),
CI_DIRECTIVES("directives", null),
CI_ARTIFACTS("artifacts", null),
+ CI_MAX_OCCURRENCES("maxOccurrences", null),
+ CI_MIN_OCCURRENCES("minOccurrences", null),
//path
FORWARDING_PATH("forwardingPath", null),