diff options
author | Michael Lando <ml636r@att.com> | 2017-06-09 03:19:04 +0300 |
---|---|---|
committer | Michael Lando <ml636r@att.com> | 2017-06-09 03:19:04 +0300 |
commit | ed64b5edff15e702493df21aa3230b81593e6133 (patch) | |
tree | a4cb01fdaccc34930a8db403a3097c0d1e40914b /catalog-ui/src/app/ng2/components/properties-table/dynamic-property | |
parent | 280f8015d06af1f41a3ef12e8300801c7a5e0d54 (diff) |
[SDC-29] catalog 1707 rebase commit.
Change-Id: I43c3dc5cf44abf5da817649bc738938a3e8388c1
Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'catalog-ui/src/app/ng2/components/properties-table/dynamic-property')
3 files changed, 263 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html new file mode 100644 index 0000000000..17e4002ae5 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html @@ -0,0 +1,66 @@ +<div class="dynamic-property-row" + [ngClass]="{'selected': selectedPropertyId === property.uniqueId }" + [class.with-top-border]="property.isChildOfListOrMap" + (click)="onClickPropertyRow(property, $event)"> + <!-- LEFT CELL - for all NON-PropFEModel properties except for MAP)--> + <ng-container *ngIf="!isPropertyFEModel"> + <div class="table-cell" *ngIf="canBeDeclared"> <!-- simple children of complex type --> + <checkbox [label]="property.name" [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared" (checkedChange)="checkProperty.emit(property.propertiesName)" + ></checkbox> + </div> + <div class="table-cell" *ngIf="!canBeDeclared && !property.isChildOfListOrMap">{{property.name}}</div> <!-- simple children of complex type within map or list --> + </ng-container> + <!-- RIGHT CELL --> + <ng-container *ngIf="propType == derivedPropertyTypes.SIMPLE || property.isDeclared"> + <div class="table-cell" [class.full-width]="isPropertyFEModel || property.isChildOfListOrMap"> + <dynamic-element class="value-input" + pattern="validationUtils.getValidationPattern(property.type)" + [(value)]="property.value" + [type]="property.type" + [name]="property.name" + (valueChange)="propValueChanged(property);" + > <!--[disabled]="property.isDisabled || property.isDeclared" --> + </dynamic-element> + </div> + </ng-container> + <ng-container *ngIf="!property.isDeclared"> <!-- other cases need to fail if isDeclared, in which case we need to use full width value above instead) --> + + <ng-container *ngIf="propType == derivedPropertyTypes.COMPLEX && !isPropertyFEModel"> + <div class="table-cell complex" [class.full-width]="property.isChildOfListOrMap"> + <span>{{property.type | contentAfterLastDot }}</span> + </div> + </ng-container> + <ng-container *ngIf="property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP"> + <div class="table-cell map-entry"><input type="text" /></div> + <div class="table-cell" *ngIf="property.schema.property.isSimpleType"> + <input type="text" [(ngModel)]="property.value" /></div> + <div class="table-cell" *ngIf="!property.schema.property.isSimpleType"> + <span>{{property.schema.property.type | contentAfterLastDot }}</span> + </div> + </ng-container> + + <!-- ICONS: add, delete, and expand --> + <div *ngIf="(propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && !property.isChildOfListOrMap" class="table-cell"><span class="sprite-new add-item-icon" (click)="addRows()"></span></div> + <span *ngIf="property.isChildOfListOrMap" class="delete-span sprite-new delete-item-icon" (click)="deleteItem.emit(property.propertiesName)"></span> + <span *ngIf="propType == derivedPropertyTypes.COMPLEX || (property.isChildOfListOrMap && propChildren)" (click)="expandChildById(propPath)" class="expand-icon" [class.expanded]="propPath == expandedChildId">V</span> + </ng-container> + +</div> +<!-- Now, recurse into children --> +<ng-container *ngIf="propChildren && !property.isDeclared"> + <ng-container *ngFor="let prop of propChildren | filterChildProperties: expandedChildId; trackBy:prop?.propertiesName"> + <dynamic-property + [selectedPropertyId]="selectedPropertyId" + [canBeDeclared]="childrenCanBeDeclared" + [property]="prop" + [expandedChildId]="expandedChildId" + [propChildren]="" + (valueChanged)="propValueChanged(prop);" + (expandChild)="expandChildById($event)" + (deleteItem)="deleteListOrMapItem($event)" + (clickOnPropertyRow)="onClickPropertyRow($event)" + (checkProperty)="checkedChange($event)" + > + </dynamic-property> + </ng-container> +</ng-container> diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less new file mode 100644 index 0000000000..53cde3035a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less @@ -0,0 +1,48 @@ +.dynamic-property-row { + display:flex; + flex-direction:row; + position:relative; + + .table-cell { + flex: 1 0 50%; + padding:5px; + position:relative; + text-overflow: ellipsis; + white-space: nowrap; + + + &.full-width { + border-right:none; + flex: 0 0 100%; + } + + &:first-child:not(:only-child) { + border-right:#d2d2d2 solid 1px; + overflow:hidden; + } + + + } + span.delete-item-icon{ + position: absolute; + right: 25px; + top: 10px; + } + span.add-item-icon { + float:right; + } + span.expand-icon { + position: absolute; + top:6px; + right: 10px; + transition: 200ms transform ease-in-out; + } + span.expand-icon.expanded { + transform: rotate(-180deg); + } +} +.filtered { + /deep/ .checkbox-label-content{ + background-color: yellow; + } +} diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts new file mode 100644 index 0000000000..0ca93a773f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts @@ -0,0 +1,149 @@ +import {Component, Input, Output, EventEmitter} from "@angular/core"; +import { PropertyBEModel, PropertyFEModel, DerivedFEProperty, DerivedPropertyType, SchemaPropertyGroupModel, DataTypeModel } from "app/models"; +import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; +import { PropertiesUtils } from "app/ng2/pages/properties-assignment/properties.utils"; +import { DataTypeService } from "../../../services/data-type.service"; +import { UUID } from "angular2-uuid"; + + +@Component({ + selector: 'dynamic-property', + templateUrl: './dynamic-property.component.html', + styleUrls: ['./dynamic-property.component.less'] +}) +export class DynamicPropertyComponent { + + derivedPropertyTypes = DerivedPropertyType; //http://stackoverflow.com/questions/35835984/how-to-use-a-typescript-enum-value-in-an-angular2-ngswitch-statement + propType: DerivedPropertyType; + propPath: string; + isPropertyFEModel: boolean; + mapOfIDsAndKeys: Map<string, string> = new Map(); //used for map and list + + childrenCanBeDeclared: boolean; + @Input() canBeDeclared: boolean; + @Input() property: PropertyFEModel | DerivedFEProperty; + @Input() propChildren: Array<DerivedFEProperty>; + @Input() expandedChildId: string; + @Input() selectedPropertyId: string; + + @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() expandChild: EventEmitter<string> = new EventEmitter<string>(); + @Output() checkProperty: EventEmitter<string> = new EventEmitter<string>(); + @Output() deleteItem: EventEmitter<string> = new EventEmitter<string>(); + @Output() clickOnPropertyRow: EventEmitter<PropertyFEModel | DerivedFEProperty> = new EventEmitter<PropertyFEModel | DerivedFEProperty>(); + + constructor(private propertiesUtils: PropertiesUtils, private dataTypeService: DataTypeService) { + } + + ngOnInit() { + this.isPropertyFEModel = this.property instanceof PropertyFEModel; + if (this.property instanceof PropertyFEModel) { + this.propType = this.getDerivedPropertyType(this.property.type); + this.propPath = this.property.name; + } else { + this.propType = this.property.derivedDataType; + this.propPath = this.property.propertiesName; + } + + this.childrenCanBeDeclared = this.canBeDeclared && this.propType != this.derivedPropertyTypes.MAP && this.propType != this.derivedPropertyTypes.LIST; + + if (this.propType == this.derivedPropertyTypes.LIST || this.propType == this.derivedPropertyTypes.MAP) { + this.initializeValues(); + } + + } + + initializeValues = () => { + let tempValue: any; + if (this.property.value) { + tempValue = JSON.parse(this.property.value); + if (!_.isEmpty(tempValue)) { + tempValue.forEach((element, key) => { + let newChildID: string = this.createNewChildProperty(JSON.stringify(element)); + this.mapOfIDsAndKeys[newChildID] = key; + console.log(this.mapOfIDsAndKeys); + }); + } + } + //this.pseudoChildren = []; + //this.valueObjRef = []; + //TODO: generate necessary elements for existing values here + // if (this.propType == this.derivedPropertyTypes.LIST) { + // this.valueObjRef = (this.property.value) ? JSON.parse(this.property.value) : []; + // } else if (this.propType == this.derivedPropertyTypes.MAP) { + // this.valueObjRef = (this.property.value)? JSON.parse(this.property.value) : {}; + // } + console.log(this.property.value); + } + + onClickPropertyRow = (property, event) => { + // Because DynamicPropertyComponent is recrusive second time the event is fire event.stopPropagation = undefined + event && event.stopPropagation && event.stopPropagation(); + this.clickOnPropertyRow.emit(property); + } + + deleteListOrMapItem = (itemName: string) => { + this.propChildren = this.propChildren.filter(prop => prop.propertiesName.indexOf(itemName) != 0); //remove item and children; + } + + propValueChanged = (property) => { + console.log("property value change!! Prop type: " + property.type + " New value: " + property.value); + this.valueChanged.emit(property); + }; + + expandChildById = (id: string) => { + this.expandedChildId = id; + this.expandChild.emit(id); + } + + checkedChange = (propName: string) => { + this.checkProperty.emit(propName); + } + + + + addRows = (): void => { //from within the template, when creating empty item + let childPropId = this.createNewChildProperty(); + this.expandChildById(this.propPath + "#" + childPropId); + } + + createNewChildProperty = (value?:string):string => { + let propUUID:string = UUID.UUID(); + let newProp: DerivedFEProperty; + if (this.propType == this.derivedPropertyTypes.LIST) { //for list - create new prop of schema type + newProp = new DerivedFEProperty(propUUID, this.propPath, this.property.schema.property.type, value, true); + } else { //for map - create new prop of type map, with schema, but with flag that its a child + newProp = new DerivedFEProperty(propUUID, this.propPath, this.property.type, value, true, this.property.schema); + } + + + this.propChildren = this.propChildren || []; + this.propChildren.push(newProp); + + //if it's a complex type, add children properties + if (!this.property.schema.property.isSimpleType) { + let schemaDataType: DataTypeModel = this.dataTypeService.getDataTypeByTypeName(this.property.schema.property.type); + this.dataTypeService.getDerivedDataTypeProperties(schemaDataType, this.propChildren, newProp.propertiesName); + this.propertiesUtils.assignValuesRecursively(JSON.parse(value), this.propChildren, newProp.propertiesName); + console.log(JSON.stringify(this.propChildren)); + } + + return propUUID; + } + + + + //TODO: remove this and move to somewhere central!! (or make all properties be the same type...) + getDerivedPropertyType = (type) => { + if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(type) > -1) { + return DerivedPropertyType.SIMPLE; + } else if (type == PROPERTY_TYPES.LIST) { + return DerivedPropertyType.LIST; + } else if (type == PROPERTY_TYPES.MAP) { + return DerivedPropertyType.MAP; + } else { + return DerivedPropertyType.COMPLEX; + } + } + +} |