diff options
author | Michael Lando <ml636r@att.com> | 2017-06-11 14:22:02 +0300 |
---|---|---|
committer | Michael Lando <ml636r@att.com> | 2017-06-11 17:48:32 +0300 |
commit | b3d4898d9e8452ea0b8d848c048e712d43b8d9a3 (patch) | |
tree | 0609319203be13f6c29ccbe24cb39c9d64f90095 /catalog-ui/src/app/ng2/components | |
parent | af9929df75604ce407d0ca542b200630164e0ae6 (diff) |
[SDC-29] rebase continue work to align source
Change-Id: I218f1c5ee23fb2c8314f1c70921d3ad8682c10f4
Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'catalog-ui/src/app/ng2/components')
42 files changed, 919 insertions, 913 deletions
diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts index de5965e488..84ac46c4cf 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts @@ -4,6 +4,7 @@ import { UiElementDropDownComponent, DropdownValue } from './elements-ui/dropdow import { UiElementInputComponent } from './elements-ui/input/ui-element-input.component'; import {UiElementPopoverInputComponent} from "./elements-ui/popover-input/ui-element-popover-input.component"; import {ValidationConfiguration} from "app/models"; +import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; @Component({ selector: 'dynamic-element', @@ -13,7 +14,8 @@ import {ValidationConfiguration} from "app/models"; UiElementInputComponent, UiElementDropDownComponent, UiElementCheckBoxComponent, - UiElementPopoverInputComponent + UiElementPopoverInputComponent, + UiElementIntegerInputComponent ] }) export class DynamicElementComponent { @@ -21,6 +23,7 @@ export class DynamicElementComponent { @ViewChild('target', { read: ViewContainerRef }) target: any; @Input() type: any; @Input() name: string; + @Input() readonly:boolean; value:any; // Two way binding for value (need to write the "Change" word like this) @@ -50,17 +53,16 @@ export class DynamicElementComponent { // Factory to create component based on type or peroperty name. switch(this.type) { case 'list': - case 'integer': - this.createComponent(UiElementInputComponent); + case 'integer': + this.createComponent(UiElementIntegerInputComponent); this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; break; case 'string': - switch(this.name.toUpperCase()) { - case 'SUBNETPOOLID': - this.createComponent(UiElementPopoverInputComponent); - break; - default: - this.createComponent(UiElementInputComponent); + if (this.name.toUpperCase().indexOf("SUBNETPOOLID") !== -1) { + this.createComponent(UiElementPopoverInputComponent); + } + else { + this.createComponent(UiElementInputComponent); } break; case 'boolean': @@ -84,6 +86,7 @@ export class DynamicElementComponent { this.cmpRef.instance.name = this.name; this.cmpRef.instance.type = this.type; this.cmpRef.instance.value = this.value; + this.cmpRef.instance.readonly = this.readonly; } // Subscribe to change event of of ui-element-basic and fire event to change the value diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts index 18b044bc9d..f53b8616ac 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts @@ -8,6 +8,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { UiElementPopoverInputComponent } from "./elements-ui/popover-input/ui-element-popover-input.component"; import {PopoverModule} from "../popover/popover.module"; import {TooltipModule} from "../tooltip/tooltip.module"; +import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; @NgModule({ declarations: [ @@ -15,7 +16,8 @@ import {TooltipModule} from "../tooltip/tooltip.module"; UiElementInputComponent, UiElementCheckBoxComponent, UiElementDropDownComponent, - UiElementPopoverInputComponent + UiElementPopoverInputComponent, + UiElementIntegerInputComponent ], imports: [ BrowserModule, diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html index 2ad3d8e94a..a3e28c5f0b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html @@ -1 +1 @@ -<input #{{name}} [(ngModel)]="value" type="checkbox" (change)="onSave(value)" /> +<input #{{name}} [(ngModel)]="value" type="checkbox" (change)="onSave(value)" [ngClass]="{'disabled':readonly}"/> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html index 589d00e42d..bfb927af71 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html @@ -1,3 +1,3 @@ -<select name='{{name}}' [(ngModel)]="value" #t (change)="onSave()"> +<select name='{{name}}' [(ngModel)]="value" #t (change)="onSave()" [ngClass]="{'disabled':readonly}"> <option *ngFor="let ddvalue of values" [value]="ddvalue.value">{{ddvalue.label}}</option> </select> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts index 208bf54983..b1fb37a186 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts @@ -18,7 +18,6 @@ export class DropdownValue { styleUrls: ['./ui-element-dropdown.component.less'], }) export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { - @Input() values: DropdownValue[]; @@ -27,7 +26,7 @@ export class UiElementDropDownComponent extends UiElementBase implements UiEleme } onSave() { - this.baseEmitter.emit(this.value); + this.baseEmitter.emit(JSON.parse(this.value)); } } diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html index 00fea65b72..814ebfd28b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html @@ -10,4 +10,6 @@ [pattern]="pattern" [formControl]="control" tooltip="{{value}}" + [readonly]="readonly" + [ngClass]="{'disabled':readonly}" /> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts index 5a14d8f206..2d64d9b713 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts @@ -1,4 +1,4 @@ -import { Component, ViewChild, ElementRef, ContentChildren } from '@angular/core'; +import {Component, ViewChild, ElementRef, ContentChildren, Input} from '@angular/core'; import { BrowserModule } from '@angular/platform-browser' import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; @@ -8,7 +8,6 @@ import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.comp styleUrls: ['./ui-element-input.component.less'], }) export class UiElementInputComponent extends UiElementBase implements UiElementBaseInterface { - constructor() { super(); this.pattern = this.validation.validationPatterns.comment; diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html new file mode 100644 index 0000000000..e5518d453f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html @@ -0,0 +1,15 @@ +<input + class="value-input" + [ngClass]="{'error': control.invalid}" + type="text" + [name]="name" + [(ngModel)]="value" + (change)="onSave()" + [attr.maxlength]="validation.propertyValue.max" + [attr.minlength]="validation.propertyValue.min" + [pattern]="pattern" + [formControl]="control" + tooltip="{{value}}" + [readonly]="readonly" + [ngClass]="{'disabled':readonly}" +/> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less new file mode 100644 index 0000000000..8073c3858e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less @@ -0,0 +1,17 @@ +@import '../../../../../../assets/styles/variables'; + +/deep/ ui-element-integer-input { + + input { + text-indent: 6px; + border: solid 1px @main_color_o; + } + + .error { + border: solid 1px @func_color_q; + color: @func_color_q; + outline: none; + box-sizing: border-box; + } + +} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts new file mode 100644 index 0000000000..d42c80a89e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts @@ -0,0 +1,21 @@ +import {Component, ViewChild, ElementRef, ContentChildren, Input} from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser' +import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; + +@Component({ + selector: 'ui-element-integer-input', + templateUrl: './ui-element-integer-input.component.html', + styleUrls: ['./ui-element-integer-input.component.less'], +}) +export class UiElementIntegerInputComponent extends UiElementBase implements UiElementBaseInterface { + constructor() { + super(); + this.pattern = this.validation.validationPatterns.comment; + } + + onSave() { + if (!this.control.invalid){ + this.baseEmitter.emit(JSON.parse(this.value)); + } + } +} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html index 5adceb49a0..3bd51b4e36 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html @@ -4,10 +4,10 @@ type="text" [ngClass]="{'error': control.invalid}" [name]="name" - [value]="value" + [value]="value!=undefined?value:''" disabled /> - <button [popover]="popoverForm">Edit</button> + <button [popover]="popoverForm" [ngClass]="{'disabled':readonly}">Edit</button> </div> <popover-content #popoverForm [title]="name" [buttons]="buttonsArray" [placement]="'top'" [closeOnClickOutside]="true"> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts index 7300417686..84dd884d1f 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts @@ -1,4 +1,4 @@ -import {Component, ViewChild, ElementRef} from '@angular/core'; +import {Component, ViewChild, ElementRef, Input} from '@angular/core'; import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component"; import {ButtonsModelMap, ButtonModel} from "app/models"; import { PopoverContentComponent } from "app/ng2/components/popover/popover-content.component" @@ -10,7 +10,6 @@ import { PopoverComponent } from "app/ng2/components/popover/popover.component" styleUrls: ['./ui-element-popover-input.component.less'] }) export class UiElementPopoverInputComponent extends UiElementBase implements UiElementBaseInterface { - @ViewChild('textArea') textArea: ElementRef; @ViewChild('popoverForm') popoverContentComponent: PopoverContentComponent; diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts index b60271f6f0..fa2be1048c 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts +++ b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts @@ -25,6 +25,7 @@ export class UiElementBase { protected type: string; protected value: any; protected pattern: any; + protected readonly:boolean; constructor() { //this.control = new FormControl('', [Validators.required]); diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less b/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less index c1341b8dcf..afed54672c 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less +++ b/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less @@ -6,6 +6,13 @@ form{ &:not(:last-child){ border-bottom: solid 1px @main_color_o; } + input{ + &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */ + &:-moz-placeholder { font-style: italic; } /* Firefox 18- */ + &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */ + &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */ + &:-ms-input-placeholder { font-style: italic; } /* Edge */ + } } /deep/ [ng-reflect-checked="true"]{ /deep/ .checkbox-label-content{ @@ -16,7 +23,7 @@ form{ .open-filter-button{ cursor: pointer; - width: 25px; + width: 32px; height: 34px; display: inline-block; &.open{ @@ -29,6 +36,7 @@ form{ } .filter-icon{ top: 8px; + right: 2px; position: relative; } } diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html new file mode 100644 index 0000000000..7fdd95b304 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html @@ -0,0 +1,3 @@ +<modal #confirmationModal title="Delete Input" size="sm" [buttons]="footerButtons"> + Are you sure you want to delete this input? +</modal> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts new file mode 100644 index 0000000000..24c37b5636 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts @@ -0,0 +1,38 @@ +/** + * Created by rc2122 on 6/1/2017. + */ +import {Component, Output, EventEmitter, ViewChild} from "@angular/core"; +import {ButtonsModelMap, ButtonModel} from "app/models/button"; +import {ModalComponent} from "app/ng2/components/modal/modal.component"; + +@Component({ + selector: 'confirm-delete-input', + templateUrl: './confirmation-delete-input.component.html' +}) +export class ConfirmationDeleteInputComponent { + + @Output() deleteInput: EventEmitter<any> = new EventEmitter<any>(); + @ViewChild ('confirmationModal') confirmationModal:ModalComponent; + footerButtons:ButtonsModelMap = {}; + + constructor (){ + } + + ngOnInit() { + this.footerButtons['Delete'] = new ButtonModel('Delete', 'blue', this.onDeleteInput); + this.footerButtons['Close'] = new ButtonModel('Close', 'grey', this.closeModal); + } + + onDeleteInput = (input) => { + this.deleteInput.emit(input); + this.closeModal(); + }; + + openModal = () => { + this.confirmationModal.open(); + } + + closeModal = () => { + this.confirmationModal.close(); + } +} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html index e7801b82cf..fb6b04013f 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html @@ -1,4 +1,5 @@ <div class="properties-table"> + <loader [display]="isLoading" size="large" [relative]="true"></loader> <div class="table-header"> <div class="table-cell col1">Property Name</div> <div class="table-cell col2">Type</div> @@ -7,31 +8,39 @@ </div> <div class="table-body"> <div class="no-data" *ngIf="!inputs || !inputs.length">No data to display</div> - <div class="table-row" *ngFor="let input of inputs"> - <div class="table-cell col1"> - <span tooltip="{{input.name}}" >{{input.name}}</span> - <span *ngIf="input.description" - class="property-description-icon sprite-new show-desc" - tooltip="{{input.description}}"></span> - </div> - <div class="table-cell col2">{{input.type | contentAfterLastDot}}</div> - <div class="table-cell col3">{{input.schema && input.schema.property && input.schema.property.type ? (input.schema.property.type | contentAfterLastDot) : ''}}</div> - <div class="table-cell valueCol input-value-col" [class.inner-table-container]="input.childrenProperties || !input.isSimpleType"> - <dynamic-element class="value-input" - *ngIf="input.isSimpleType" - pattern="validationUtils.getValidationPattern(input.type)" - [(value)]="input.defaultValue" - [type]="input.type" - [name]="input.name" - (change)="onInputValueChanged(input);"> - </dynamic-element> - <div class="delete-button-container"> - <span class="sprite-new delete-btn" (click)="onDeleteInput(input)"></span> + <div> + <div class="table-row" *ngFor="let input of inputs" (click)="selectedInputId = input.path" [ngClass]="{'selected': selectedInputId && selectedInputId === input.path}"> + <div class="table-cell col1"> + <div class="inner-cell-div" tooltip="{{input.name}}"><span class="property-name">{{input.name}}</span></div> + <span *ngIf="input.description" + class="property-description-icon sprite-new show-desc" + tooltip="{{input.description}}"></span> + </div> + <div class="table-cell col2"> + <div class="inner-cell-div" tooltip="{{input.type | contentAfterLastDot}}"> + <span>{{input.type | contentAfterLastDot}}</span> + </div> + </div> + <div class="table-cell col3">{{input.schema && input.schema.property && input.schema.property.type ? (input.schema.property.type | contentAfterLastDot) : ''}}</div> + <div class="table-cell valueCol input-value-col" [class.inner-table-container]="input.childrenProperties || !input.isSimpleType"> + <dynamic-element class="value-input" + *ngIf="input.isSimpleType" + pattern="validationUtils.getValidationPattern(input.type)" + [(value)]="input.defaultValue" + [type]="input.type" + [name]="input.name" + (change)="onInputValueChanged(input);" + [readonly]="readonly"> + </dynamic-element> + <div class="delete-button-container"> + <span *ngIf="!input.ownerId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)"></span> + </div> </div> - </div> + </div> </div> </div> </div> +<confirm-delete-input #deleteInputConfirmation (deleteInput)="onDeleteInput()"></confirm-delete-input> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less new file mode 100644 index 0000000000..93f96470bc --- /dev/null +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less @@ -0,0 +1,178 @@ + +@import './../../../../assets/styles/variables.less'; + +:host /deep/ input { width:100%;} + +.properties-table { + display:flex; + flex-direction:column; + flex: 1; + height:100%; + text-align:left; + + dynamic-property { + width:100%; + } + + /deep/ .dynamic-property-row { + border-top:solid #d2d2d2 1px; + } + + /deep/ dynamic-property dynamic-property:first-of-type .dynamic-property-row:not(.with-top-border) { + border-top: none; + } + + .table-header { + font-weight:bold; + border-top: #d2d2d2 solid 1px; + background-color: #eaeaea; + + .valueCol { + justify-content: flex-start; + padding: 5px; + } + } + .table-header, .table-row { + display: flex; + flex-direction:row; + flex: 0 0 auto; + } + + .table-body { + display:flex; + flex-direction: column; + overflow-y:auto; + flex: 1; + + .no-data { + border: #d2d2d2 solid 1px; + border-top:none; + text-align: center; + height: 100%; + padding: 20px; + } + /deep/.selected{ + background-color: #e6f6fb; + color: #009fdb; + } + } + + .table-rows-header { + font-size:16px; + flex:1; + border: #d2d2d2 solid 1px; + border-top:none; + padding: 5px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + background-color: @tlv_color_v; + } + + .table-row { + &:hover { + background-color:#f8f8f8; cursor:pointer; + } + + &:last-child { + flex: 1 0 auto; + } + .selected-row { + background-color:#e6f6fb; + } + } + .cut-inner-long-text{ + text-overflow: ellipsis; + overflow: hidden; + } + .table-cell { + font-size:13px; + flex:1; + border: #d2d2d2 solid 1px; + border-right:none; + border-top:none; + padding: 5px; + text-overflow: ellipsis; + white-space: nowrap; + + + &:last-child { + border-right:#d2d2d2 solid 1px; + } + &.col1 { + flex: 0 0 300px; + max-width:300px; + display: flex; + justify-content: space-between; + + .property-name { + flex: 1; + } + + .property-description-icon { + float: right; + margin-top: 4px; + margin-left: 5px; + flex: 0 0 auto; + } + } + &.col2 { + flex: 0 0 150px; + max-width:150px; + } + + &.col3 { + flex:0 0 120px; + max-width:120px; + } + + &.valueCol { + flex: 1 0 auto; + min-width: 350px; + display: flex; + justify-content: flex-end; + padding: 0px; + + .value-input { + flex: 1; + max-height: 24px; + border: none; + background-color: inherit; + + &:focus, &:active { + border:none; + outline:none; + } + } + + .delete-btn { + flex: 0 0 auto; + } + + .delete-button-container { + max-height: 24px; + } + + &.inner-table-container { + padding: 0px; + + .delete-button-container { + padding: 3px 5px 0 0 ; + } + } + } + + &.input-value-col { + padding: 5px; + } + + + } + + .filtered { + /deep/ .checkbox-label-content{ + background-color: yellow; + } + } + +} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts index ea01edf043..83c0bda991 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts @@ -1,20 +1,25 @@ /** * Created by rc2122 on 5/4/2017. */ -import {Component, Input, Output, EventEmitter} from "@angular/core"; +import {Component, Input, Output, EventEmitter, ViewChild} from "@angular/core"; import {InputFEModel} from "app/models"; +import {ConfirmationDeleteInputComponent} from "./confirmation-delete-input/confirmation-delete-input.component"; @Component({ selector: 'inputs-table', templateUrl: './inputs-table.component.html', - styleUrls: ['../properties-table/properties-table.component.less'] + styleUrls: ['../inputs-table/inputs-table.component.less'] }) export class InputsTableComponent { @Input() inputs: Array<InputFEModel>; - + @Input() readonly:boolean; + @Input() isLoading:boolean; @Output() inputValueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() deleteInput: EventEmitter<any> = new EventEmitter<any>(); + @ViewChild ('deleteInputConfirmation') deleteInputConfirmation:ConfirmationDeleteInputComponent; + + selectedInputToDelete:InputFEModel; constructor (){ } @@ -23,11 +28,14 @@ export class InputsTableComponent { this.inputValueChanged.emit(input); }; - onDeleteInput = (input) => { - this.deleteInput.emit(input); - } - + onDeleteInput = () => { + this.deleteInput.emit(this.selectedInputToDelete); + }; + openDeleteModal = (input:InputFEModel) => { + this.selectedInputToDelete = input; + this.deleteInputConfirmation.openModal(); + } } diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.html b/catalog-ui/src/app/ng2/components/loader/loader.component.html new file mode 100644 index 0000000000..0e13cee674 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/loader/loader.component.html @@ -0,0 +1,5 @@ +<div *ngIf="display" data-tests-id="tlv-loader"> + <div class="tlv-loader-back" [ngClass]="{'tlv-loader-relative':relative}"></div> + <div class="tlv-loader {{size}}"></div> +</div> + diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.less b/catalog-ui/src/app/ng2/components/loader/loader.component.less new file mode 100644 index 0000000000..054b6021a1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/loader/loader.component.less @@ -0,0 +1,75 @@ +@import '../../../../assets/styles/variables'; +.tlv-loader-back { + background-color: @main_color_p; + position: fixed; + top: 50px; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + opacity: 0.5; +} + +.tlv-loader-relative { position: absolute; top: 0;} + +.tlv-loader { + z-index: 10002; +} + +@keyframes fadein { + from { opacity: 0; } + to { opacity: 0.8; } +} + +/* Firefox < 16 */ +@-moz-keyframes fadein { + from { opacity: 0; } + to { opacity: 0.8; } +} + +/* Safari, Chrome and Opera > 12.1 */ +@-webkit-keyframes fadein { + from { opacity: 0; } + to { opacity: 0.8; } +} + +/* Internet Explorer */ +@-ms-keyframes fadein { + from { opacity: 0; } + to { opacity: 0.8; } +} + +/* Opera < 12.1 */ +@-o-keyframes fadein { + from { opacity: 0; } + to { opacity: 0.8; } +} + +@keyframes fadeout { + from { opacity: 0.8; } + to { opacity: 0; } +} + +/* Firefox < 16 */ +@-moz-keyframes fadeout { + from { opacity: 0.8; } + to { opacity: 0; } +} + +/* Safari, Chrome and Opera > 12.1 */ +@-webkit-keyframes fadeout { + from { opacity: 0.8; } + to { opacity: 0; } +} + +/* Internet Explorer */ +@-ms-keyframes fadeout { + from { opacity: 0.8; } + to { opacity: 0; } +} + +/* Opera < 12.1 */ +@-o-keyframes fadeout { + from { opacity: 0.8; } + to { opacity: 0; } +} diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/loader/loader.component.ts new file mode 100644 index 0000000000..4d90b2853d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/loader/loader.component.ts @@ -0,0 +1,92 @@ +/** + * Created by rc2122 on 6/6/2017. + */ +import {Component, Input, ElementRef, Renderer, SimpleChanges} from "@angular/core"; +@Component({ + selector: 'loader', + templateUrl: './loader.component.html', + styleUrls: ['./loader.component.less'] +}) +export class LoaderComponent { + + @Input() display:boolean; + @Input() size:string;// small || medium || large + @Input() elementSelector:string; // required if is relative true + @Input() relative:boolean; + + interval; + + constructor (private el: ElementRef, private renderer: Renderer){ + } + + ngOnInit() { + + if (this.elementSelector) { + let elemParent = angular.element(this.elementSelector); + let positionStyle:string = elemParent.css('position'); + this.setStyle(positionStyle); + } + + if (this.relative === true) { + let positionStyle:string = this.el.nativeElement.parentElement.style.position; + this.setStyle(positionStyle); + } + if (!this.size) { + this.size = 'large'; + } + } + + ngOnDestroy(){ + clearInterval(this.interval); + } + + calculateSizesForFixPosition = (positionStyle:string):void => { + // This is problematic, I do not want to change the parent position. + // set the loader on all the screen + let parentLeft = this.el.nativeElement.parentElement.offsetLeft; + let parentTop = this.el.nativeElement.parentElement.offsetTop; + let parentWidth = this.el.nativeElement.parentElement.offsetWidth; + let parentHeight = this.el.nativeElement.parentElement.offsetHeight; + this.renderer.setElementStyle(this.el.nativeElement, 'position', positionStyle); + this.renderer.setElementStyle(this.el.nativeElement, 'top', parentTop); + this.renderer.setElementStyle(this.el.nativeElement, 'left', parentLeft); + this.renderer.setElementStyle(this.el.nativeElement, 'width', parentWidth); + this.renderer.setElementStyle(this.el.nativeElement, 'height', parentHeight); + }; + + setStyle = (positionStyle:string):void => { + + switch (positionStyle) { + case 'absolute': + case 'fixed': + // The parent size is not set yet, still loading, so need to use interval to update the size. + this.interval = window.setInterval(()=> { + this.calculateSizesForFixPosition(positionStyle); + }, 2000); + break; + default: + // Can change the parent position to relative without causing style issues. + this.renderer.setElementStyle(this.el.nativeElement.parentElement,'position', 'relative'); + break; + } + }; + + ngOnChanges(changes: SimpleChanges) { + if(changes.display){ + this.changeLoaderDisplay(false); + if ( this.display ) { + window.setTimeout(():void => { + this.changeLoaderDisplay(true); + }, 500); + } else { + window.setTimeout(():void => { + this.changeLoaderDisplay(false); + }, 0); + } + } + } + + changeLoaderDisplay = (display:boolean):void => { + this.renderer.setElementStyle(this.el.nativeElement, 'display', display ? 'block' : 'none'); + } +} diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.html b/catalog-ui/src/app/ng2/components/modal/modal.component.html new file mode 100644 index 0000000000..4882449596 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.html @@ -0,0 +1,18 @@ +<div class="custom-modal {{size}}"> + <div class="ng2-modal-content"> + <div class="ng2-modal-header"> + <span class="title">{{ title }}</span> + <span class="close-button" (click)="close()"></span> + </div> + <div class="ng2-modal-body"> + <ng-content></ng-content> + </div> + <div class="ng2-modal-footer"> + <button *ngFor="let buttonName of buttonsNames" + class="tlv-btn {{buttons[buttonName].cssClass}}" + [disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()" + (click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button> + </div> + </div> +</div> +<div class="modal-background"></div> diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.less b/catalog-ui/src/app/ng2/components/modal/modal.component.less new file mode 100644 index 0000000000..a35f829e6a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.less @@ -0,0 +1,115 @@ +@import '../../../../assets/styles/variables'; +@import '../../../../assets/styles/mixins'; +@import '../../../../assets/styles/sprite-old'; +/deep/ modal { + display: none; + + .custom-modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1000; + overflow: auto; + margin: auto; + display: flex; + align-items: center; + + .ng2-modal-content { + background: #fff; + width: 100%; + box-shadow: 0 5px 15px rgba(0,0,0,.5); + border-radius: 4px; + .ng2-modal-body{ + padding: 20px; + } + + .ng2-modal-header{ + .m_18_m; + font-weight: bold; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + height: 50px; + line-height: 50px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + text-align: left; + border-bottom: solid 1px @main_color_o; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: 0px 20px; + .title{ + -webkit-box-flex: 999; + -ms-flex-positive: 999; + flex-grow: 999; + } + .close-button{ + .sprite; + .sprite.x-btn-black; + cursor: pointer; + } + } + + .ng2-modal-footer{ + background-color: @tlv_color_t; + padding: 17px 30px; + clear: both; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + border-radius: 4px; + button{ + margin: 0 12px 0 6px; + } + } + } + } + + .modal-background { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #000; + opacity: 0.5; + z-index: 900; + } +} + +.xl { + width: 1200px; +} + +.l { + width: 875px; +} + +.md { + width: 650px; +} + +.sm { + width: 552px; +} + +.xsm { + width: 432px; +} + +body.modal-open { + overflow: hidden; +} diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/modal/modal.component.ts new file mode 100644 index 0000000000..4a00871b21 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.ts @@ -0,0 +1,46 @@ +/** + * Created by rc2122 on 6/1/2017. + */ +import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core'; +import * as $ from 'jquery'; +import {ButtonsModelMap} from "app/models/button"; + +@Component({ + selector: 'modal', + templateUrl: './modal.component.html', + styleUrls:['modal.component.less'] +}) + +export class ModalComponent implements OnInit, OnDestroy { + @Input() size: string; 'xl|l|md|sm|xsm' + @Input() title: string; + @Input() public buttons:ButtonsModelMap; + private modalElement: JQuery; + private buttonsNames:Array<string>; + + constructor( el: ElementRef ) { + this.modalElement = $(el.nativeElement); + } + + ngOnInit(): void { + let modal = this; + this.modalElement.appendTo('body'); + if(this.buttons){ + this.buttonsNames = Object.keys(this.buttons); + } + } + + ngOnDestroy(): void { + this.modalElement.remove(); + } + + open(): void { + this.modalElement.show(); + $('body').addClass('modal-open'); + } + + close(): void { + this.modalElement.hide(); + $('body').removeClass('modal-open'); + } +} diff --git a/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.html deleted file mode 100644 index 6e7d4e882b..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.html +++ /dev/null @@ -1,24 +0,0 @@ -<!-- TODO: refactor this to be dynamic --> -<div class="derived-property-row" *ngIf="propertyObj.isDeclared || propertyObj.derivedDataType == derivedPropertyTypes.SIMPLE"> - <div class="table-cell" [ngClass]="{'iltered':propertyObj.name === propertyNameSearchText}"><checkbox [label]="propertyObj.name" [(checked)]="propertyObj.isSelected" [disabled]="propertyObj.isDisabled ||propertyObj.isDeclared" (checkedChange)="checkedChange($event)"></checkbox></div> - - <div class="table-cell simple"> - <input type="text" [(ngModel)]="propertyObj.value" [disabled]="propertyObj.isDisabled || propertyObj.isDeclared" (change)="valueChanged.emit()" /> - </div> -</div> -<div class="derived-property-row" *ngIf="!propertyObj.isDeclared && propertyObj.derivedDataType == derivedPropertyTypes.COMPLEX"> - <div class="table-cell" [ngClass]="{'filtered':propertyObj.name === propertyNameSearchText}"><checkbox [label]="propertyObj.name" [(checked)]="propertyObj.isSelected" [disabled]="propertyObj.isDisabled ||propertyObj.isDeclared" (checkedChange)="checkedChange($event)"></checkbox></div> - <div class="table-cell complex"> - <span class="datatype-text">{{propertyObj.type | contentAfterLastDot }}</span> - <span (click)="expandChildById(propertyObj.propertiesName)" class="expand-icon" [class.expanded]="expanded">V</span> - </div> -</div> -<div class="derived-property-row" *ngIf="!propertyObj.isDeclared && propertyObj.derivedDataType == derivedPropertyTypes.SIMPLELIST ||propertyObj.derivedDataType == derivedPropertyTypes.SIMPLEMAP"> - <div class="table-cell"> - <span [ngClass]="{'filtered':propertyObj.name === propertyNameSearchText}">{{propertyObj.name}}</span> - </div> - <div class="table-cell simple2"> - <div class="sprite-new add-item-icon" (click)="addRows(propertyObj)"></div> - </div> -</div> - diff --git a/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.less b/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.less deleted file mode 100644 index 3102c5ceb8..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.less +++ /dev/null @@ -1,35 +0,0 @@ -.derived-property-row { - display:flex; - flex-direction:row; - position:relative; - border-top: #d2d2d2 solid 1px; - - &:first-child { - border-top:none; - } - .table-cell { - flex: 0 0 50%; - padding:5px; - position:relative; - text-overflow: ellipsis; - white-space: nowrap; - - &:first-child { - border-right:#d2d2d2 solid 1px; - overflow:hidden; - } - span.expand-icon { - position: absolute; - 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/derived-property/derived-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.ts deleted file mode 100644 index 16f069a685..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/derived-property/derived-property.component.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Created by rc2122 on 4/20/2017. - */ -import {Component, Input, Output, EventEmitter} from "@angular/core"; -import { DerivedFEProperty, DerivedPropertyType} from "app/models"; -import {PropertiesService} from "../../../services/properties.service"; - -@Component({ - selector: 'derived-property', - templateUrl: './derived-property.component.html', - styleUrls: ['./derived-property.component.less'] -}) -export class DerivedPropertyComponent { - - derivedPropertyTypes = DerivedPropertyType; //http://stackoverflow.com/questions/35835984/how-to-use-a-typescript-enum-value-in-an-angular2-ngswitch-statement - - @Input() propertyObj: DerivedFEProperty; - @Input() propertyNameSearchText: string; - @Input() expanded: boolean; - @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); - @Output() expandChild: EventEmitter<string> = new EventEmitter<string>(); - @Output() selectProperty: EventEmitter<boolean> = new EventEmitter<boolean>(); - - - constructor ( private propertiesService:PropertiesService){ - } - - - propValueChanged = () => { - this.valueChanged.emit(this.propertyObj); - }; - - expandChildById = (id: string) => { - this.expandChild.emit(id); - } - - checkedChange = (isChecked:boolean) => { - this.selectProperty.emit(isChecked); - } - - addRows = (flatProperty: DerivedFEProperty): void => { - console.log("ADDING A ROW OF TYPE " + flatProperty.type); - console.log(flatProperty); - } - -} 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 index 17e4002ae5..d6ee568c0c 100644 --- 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 @@ -1,66 +1,65 @@ <div class="dynamic-property-row" - [ngClass]="{'selected': selectedPropertyId === property.uniqueId }" + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName }" [class.with-top-border]="property.isChildOfListOrMap" (click)="onClickPropertyRow(property, $event)"> - <!-- LEFT CELL - for all NON-PropFEModel properties except for MAP)--> + <!-- LEFT CELL --> <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)" + <div class="table-cell" *ngIf="canBeDeclared" [ngClass]="{'filtered':property.name === propertyNameSearchText}"> <!-- simple children of complex type --> + <checkbox [label]="property.name" [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared || readonly" (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 --> + <div class="table-cell map-entry" *ngIf="property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP"><!-- map left cell --> + <input [value]="property.mapKey" #mapKey (change)="mapKeyChanged.emit(mapKey.value)" [readonly]="readonly" type="text" [ngClass]="{'disabled':readonly}" /> + </div> </ng-container> - <!-- RIGHT CELL --> - <ng-container *ngIf="propType == derivedPropertyTypes.SIMPLE || property.isDeclared"> - <div class="table-cell" [class.full-width]="isPropertyFEModel || property.isChildOfListOrMap"> + <!-- RIGHT CELL OR FULL WIDTH CELL--> + <ng-container *ngIf="propType == derivedPropertyTypes.SIMPLE || property.isDeclared || (property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP && property.schema.property.isSimpleType)"> + <div class="table-cell"> <dynamic-element class="value-input" pattern="validationUtils.getValidationPattern(property.type)" - [(value)]="property.value" - [type]="property.type" + [(value)]="property.valueObj" + [type]="property.isDeclared ? 'string' : property.type" [name]="property.name" - (valueChange)="propValueChanged(property);" + (valueChange)="valueChanged.emit();" + [readonly]="readonly||property.isDeclared" > <!--[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 *ngIf="!isPropertyFEModel && propType != derivedPropertyTypes.SIMPLE && !property.isDeclared"> <!-- right cell for complex elements, or list complex --> + <div class="table-cell" *ngIf="propType == derivedPropertyTypes.COMPLEX">{{property.type | contentAfterLastDot }}</div> + <div class="table-cell" *ngIf="propType == derivedPropertyTypes.MAP && !property.schema.property.isSimpleType">{{property.schema.property.type | contentAfterLastDot }}</div> + </ng-container> + <ng-container *ngIf="isPropertyFEModel && (propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP)"><!-- empty, full-width table cell - for PropertyFEModel of type list or map --> + <div class="table-cell empty"></div> + </ng-container> + <!-- ICONS: add, delete, and expand --> + <ng-container *ngIf="!property.isDeclared"> + <span *ngIf="(propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && !property.isChildOfListOrMap" class="property-icon sprite-new add-item-icon" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly}"></span> + <span *ngIf="property.isChildOfListOrMap" (click)="deleteItem.emit(property);" class="property-icon sprite-new delete-item-icon" [ngClass]="{'disabled':readonly}"></span> + <span *ngIf="!isPropertyFEModel && (propType == derivedPropertyTypes.COMPLEX || hasChildren())" (click)="expandChildById(propPath)" class="property-icon 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"> +<!-- FLAT CHILDREN --> +<div class="flat-children-container" *ngIf="isPropertyFEModel && !property.isDeclared"> + <ng-container *ngFor="let prop of property.flattenedChildren | filterChildProperties: expandedChildId; trackBy:prop?.propertiesName"> <dynamic-property [selectedPropertyId]="selectedPropertyId" - [canBeDeclared]="childrenCanBeDeclared" + [canBeDeclared]="prop.canBeDeclared" [property]="prop" [expandedChildId]="expandedChildId" - [propChildren]="" - (valueChanged)="propValueChanged(prop);" + [propertyNameSearchText]="propertyNameSearchText" + [readonly]="readonly" + (valueChanged)="childValueChanged(prop)" + (mapKeyChanged)="removeValueFromParent(prop, $event)" (expandChild)="expandChildById($event)" (deleteItem)="deleteListOrMapItem($event)" (clickOnPropertyRow)="onClickPropertyRow($event)" (checkProperty)="checkedChange($event)" + (addChildPropsToParent)="addChildProps($event, prop.propertiesName)" > </dynamic-property> </ng-container> -</ng-container> +</div> 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 index 53cde3035a..cb7cd39640 100644 --- 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 @@ -1,40 +1,40 @@ +.flat-children-container { + dynamic-property:first-child .dynamic-property-row:not(.with-top-border) { + border-top:none; + } + .dynamic-property-row { + border-top: solid 1px #CCC; + } +} .dynamic-property-row { display:flex; flex-direction:row; - position:relative; - + align-items: center; + .table-cell { - flex: 1 0 50%; + flex: 1; padding:5px; - position:relative; text-overflow: ellipsis; white-space: nowrap; - + overflow:hidden; + min-height:32px; - &.full-width { - border-right:none; - flex: 0 0 100%; - } - - &:first-child:not(:only-child) { + &:first-child { + flex: 0 0 50%; border-right:#d2d2d2 solid 1px; - overflow:hidden; + + + &:only-of-type { + flex: 1 1 100%; + border-right:none; + } } - - } - span.delete-item-icon{ - position: absolute; - right: 25px; - top: 10px; } - span.add-item-icon { - float:right; + .property-icon { + flex: 0 0 auto; } span.expand-icon { - position: absolute; - top:6px; - right: 10px; transition: 200ms transform ease-in-out; } span.expand-icon.expanded { 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 index 0ca93a773f..1c7fbfac7a 100644 --- 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 @@ -3,7 +3,6 @@ import { PropertyBEModel, PropertyFEModel, DerivedFEProperty, DerivedPropertyTyp 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({ @@ -17,64 +16,33 @@ export class DynamicPropertyComponent { propType: DerivedPropertyType; propPath: string; isPropertyFEModel: boolean; - mapOfIDsAndKeys: Map<string, string> = new Map(); //used for map and list + childrenCount: number; - childrenCanBeDeclared: boolean; @Input() canBeDeclared: boolean; @Input() property: PropertyFEModel | DerivedFEProperty; - @Input() propChildren: Array<DerivedFEProperty>; @Input() expandedChildId: string; @Input() selectedPropertyId: string; + @Input() propertyNameSearchText: string; + @Input() readonly: boolean; @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>(); + @Output() mapKeyChanged: EventEmitter<string> = new EventEmitter<string>(); + @Output() addChildPropsToParent: EventEmitter<Array<DerivedFEProperty>> = new EventEmitter<Array<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(); - } - + this.propType = this.property.derivedDataType; + this.propPath = (this.property instanceof PropertyFEModel) ? this.property.name : this.property.propertiesName; } - 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 @@ -82,68 +50,106 @@ export class DynamicPropertyComponent { 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); + this.expandChild.emit(id); } checkedChange = (propName: string) => { this.checkProperty.emit(propName); } + hasChildren = (): number => { + return (this.property.valueObj && typeof this.property.valueObj == 'object') ? Object.keys(this.property.valueObj).length : 0; + } + createNewChildProperty = (): void => { + + let newProps: Array<DerivedFEProperty> = this.propertiesUtils.createListOrMapChildren(this.property, "", null); + if (this.property instanceof PropertyFEModel) { + this.addChildProps(newProps, this.property.name); + } else { + this.addChildPropsToParent.emit(newProps); + } + } - addRows = (): void => { //from within the template, when creating empty item - let childPropId = this.createNewChildProperty(); - this.expandChildById(this.propPath + "#" + childPropId); + addChildProps = (newProps: Array<DerivedFEProperty>, childPropName: string) => { + + if (this.property instanceof PropertyFEModel) { + let insertIndex: number = this.property.getIndexOfChild(childPropName) + this.property.getCountOfChildren(childPropName); //insert after parent prop and existing children + this.property.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator + this.expandChildById(newProps[0].propertiesName); + } } - 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); + childValueChanged = (property: DerivedFEProperty) => { //value of child property changed + + if (this.property instanceof PropertyFEModel) { // will always be the case + let parentNames = this.getParentNamesArray(property.propertiesName, []); + if (parentNames.length) { + _.set(this.property.valueObj, parentNames.join('.'), property.valueObj); + } + console.log(parentNames); + this.valueChanged.emit(this.property.name); } + } + deleteListOrMapItem = (item: DerivedFEProperty) => { + if (this.property instanceof PropertyFEModel) { + this.removeValueFromParent(item); + this.property.flattenedChildren.splice(this.property.getIndexOfChild(item.propertiesName), this.property.getCountOfChildren(item.propertiesName)); + this.expandChildById(item.propertiesName); + } + } - this.propChildren = this.propChildren || []; - this.propChildren.push(newProp); + removeValueFromParent = (item: DerivedFEProperty, replaceKey?: string) => { + if (this.property instanceof PropertyFEModel) { + let itemParent = (item.parentName == this.property.name) ? this.property : this.property.flattenedChildren.find(prop => prop.propertiesName == item.parentName); + + if (item.derivedDataType == DerivedPropertyType.MAP) { + let oldKey = item.mapKey; + if (typeof replaceKey == 'string') { //allow saving empty string + _.set(itemParent.valueObj, replaceKey, itemParent.valueObj[oldKey]); + item.mapKey = replaceKey; + } + delete itemParent.valueObj[oldKey]; + } else { + let itemIndex: number = this.property.flattenedChildren.filter(prop => prop.parentName == item.parentName).map(prop => prop.propertiesName).indexOf(item.propertiesName); + itemParent.valueObj.splice(itemIndex, 1); + } - //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)); + if (itemParent instanceof PropertyFEModel) { //direct child + this.valueChanged.emit(this.property.name); + } else { //nested child - need to update parent prop by getting flattened name (recurse through parents and replace map/list keys, etc) + this.childValueChanged(itemParent); + } } + } - return propUUID; - } + getParentNamesArray = (parentPropName: string, parentNames?: Array<string>): Array<string> => { + if (this.property instanceof PropertyFEModel) { + if (parentPropName.indexOf("#") == -1) { return parentNames; } //finished recursing parents. return - //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; + let parentProp: DerivedFEProperty = this.property.flattenedChildren.find(prop => prop.propertiesName === parentPropName); + let nameToInsert: string = parentProp.name; + + if (parentProp.isChildOfListOrMap) { + if (parentProp.derivedDataType == DerivedPropertyType.MAP) { + nameToInsert = parentProp.mapKey; + } else { //LIST + let siblingProps = this.property.flattenedChildren.filter(prop => prop.parentName == parentProp.parentName).map(prop => prop.propertiesName); + nameToInsert = siblingProps.indexOf(parentProp.propertiesName).toString(); + } + } + + parentNames.splice(0, 0, nameToInsert); //add prop name to array + return this.getParentNamesArray(parentProp.parentName, parentNames); //continue recursing + } } + } diff --git a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.html deleted file mode 100644 index a251d33649..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.html +++ /dev/null @@ -1,33 +0,0 @@ -<div class="add-data-row"> - <div class="sprite-new add-item-icon" (click)="addListItem()"></div> -</div> -<div *ngIf="property.schema.property.isSimpleType && property.valueObjectRef && property.valueObjectRef.length"> - <!--the ngFor runs on dummy array in the list array length and not on list array in order to prevent from page do the ngFor again when user changes an item--> - <div class="simple-list-item" *ngFor="let item of getNumber(property.valueObjectRef); let i = index"> - <input class="value-input" [(ngModel)]="property.valueObjectRef[i]" - type="property.schema.property.derivedFromSimpleTypeName || property.schema.property.type" - (change)="propValueChanged()"/> - <span class="delete-span sprite-new delete-item-icon" (click)="deleteListItem(i)"></span> - </div> -</div> -<div class="test" *ngIf="property.schema.property.isDataType && property.childrenProperties && property.childrenProperties.length"> - <template ngFor let-item [ngForOf]="property.childrenProperties" let-i="index"> - <div class="table-inner-row" (click)="onChildPropertySelected(item)" [ngClass]="{'selected': selectedPropertyId === item.treeNodeId}"> - <div class="table-cell">{{item.name}}</div> - <div class="table-cell"> - <span class="delete-span sprite-new delete-item-icon" (click)="deleteListItem(i)"></span> - <span (click)="property.updateExpandedChildPropertyId(item.treeNodeId)">V</span> - </div> - </div> - <div class="table-inner-row" *ngIf="property.expandedChildPropertyId == item.treeNodeId"> - <div class="inner-table-container"> - <properties-value-inner-table [property]="item" - (selectChildProperty)="onChildPropertySelected($event)" - [selectedPropertyId]="selectedPropertyId" - [propertyNameSearchText]="propertyNameSearchText" - (valueChanged)="propValueChanged()"></properties-value-inner-table> - </div> - </div> - </template> - -</div> diff --git a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.less b/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.less deleted file mode 100644 index 7c4d90a38d..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.less +++ /dev/null @@ -1,3 +0,0 @@ -.simple-list-item{ - position: relative; -} diff --git a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.ts deleted file mode 100644 index 96f8c680a2..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/list-property/list-property.component.ts +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Created by rc2122 on 4/23/2017. - */ -import {Component, Input, Output, EventEmitter} from "@angular/core"; -import { PropertyFEModel} from "app/models"; -import {PropertiesService} from "app/ng2/services/properties.service"; -import { ContentAfterLastDotPipe } from "app/ng2/pipes/contentAfterLastDot.pipe"; -import {UUID} from "angular2-uuid"; -import {ComponentType} from "app/utils"; - -@Component({ - selector: 'list-property', - templateUrl: './list-property.component.html', - styleUrls: ['../properties-value-inner-table/properties-value-inner-table.component.less', './list-property.component.less'] -}) -export class ListPropertyComponent { - - @Input() property: PropertyFEModel; - @Input() selectedPropertyId: string; - @Input() propertyNameSearchText:string; - - @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); - @Output() selectChildProperty: EventEmitter<any> = new EventEmitter<PropertyFEModel>(); - - constructor ( private propertiesService:PropertiesService, private contentAfterLastDotPipe:ContentAfterLastDotPipe ){ - } - - propValueChanged = () => { - this.valueChanged.emit(this.property); - }; - - onChildPropertySelected = (property) => { - this.selectChildProperty.emit(property); - }; - - getNumber = (valueObjectRef: any): Array<any> => { - let num: number = (valueObjectRef) ? valueObjectRef.length : 0; - return new Array(num); - } - - createNewChildProperty = ():void => { - let newProperty: PropertyFEModel = new PropertyFEModel(this.contentAfterLastDotPipe.transform(this.property.schema.property.type), - this.property.schema.property.type, - UUID.UUID(), - this.property, - this.property.valueObjectRef[this.property.childrenProperties.length] - ); - this.propertiesService.createPropertiesTreeForProp(newProperty); - this.property.childrenProperties.push(newProperty); - } - - addListItem = ():void => { - this.property.valueObjectRef = this.property.valueObjectRef || []; - this.property.childrenProperties = this.property.childrenProperties || []; - if (this.property.schema.property.isSimpleType){ - if( this.property.valueObjectRef.indexOf("") == -1 ) {//prevent insert multiple empty simple type items to list - this.property.valueObjectRef.push(""); - } - }else{ - this.property.valueObjectRef[this.property.childrenProperties.length] = {}; - this.property.childrenProperties = this.property.childrenProperties || []; - this.createNewChildProperty(); - this.valueChanged.emit(this.property); - } - } - - deleteListItem = (indexInList:number):void => { - this.property.valueObjectRef.splice(indexInList, 1); - if(this.property.childrenProperties){ - this.property.childrenProperties.splice(indexInList, 1); - } - if (!this.property.valueObjectRef.length) {//only when user removes all items from list - put the default - if ( this.property.defaultValue ) { - angular.copy(JSON.parse(this.property.defaultValue), this.property.valueObjectRef); - if (this.property.schema.property.isDataType){ - _.forEach(this.property.valueObjectRef, () => { - this.createNewChildProperty(); - }); - } - } - } - this.valueChanged.emit(this.property); - } - -} diff --git a/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.html deleted file mode 100644 index e1975175a8..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.html +++ /dev/null @@ -1,38 +0,0 @@ -<div class="add-data-row"> - <div class="sprite-new add-item-icon" (click)="addMapItemFields()"></div> -</div> - -<!--the ngFor runs on dummy array in mapKey array length and not on maKeys array in order to prevent from page do the ngFor again when user changes a key--> -<template ngFor let-num [ngForOf]="getNumber(mapKeys.length)" let-i="index"> - <div class="table-inner-row" - [ngClass]="{'selected': property.schema.property.isDataType && selectedPropertyId === property.childrenProperties[i].treeNodeId}" - (click)="property.schema.property.isDataType && onChildPropertySelected(property.childrenProperties[i])"> - <div class="table-cell"> - <input class="value-input" (keyup)="changeKeyOfMap(mapKeys[i], i);$event.stopPropagation();" - [(ngModel)]="mapKeys[i]" - name="mapKey{{property.treeNodeId}}{{i}}" - (change)="propValueChanged()"/> - </div> - <div class="table-cell"> - <input class="value-input" *ngIf="property.schema.property.isSimpleType" - [(ngModel)]="property.valueObjectRef[mapKeys[i]]" - type="property.schema.property.derivedFromSimpleTypeName || property.schema.property.type" - (change)="propValueChanged()"/> - <div *ngIf="property.schema.property.isDataType"> - <div>{{ property.schema.property.type | contentAfterLastDot }}</div> - <span (click)="property.updateExpandedChildPropertyId(property.childrenProperties[i].treeNodeId)">V</span> - </div> - <span class="delete-span sprite-new delete-item-icon" (click)="deleteMapItem(i)"></span> - </div> - </div> - <div class="table-inner-row" *ngIf="property.schema.property.isDataType && property.expandedChildPropertyId == property.childrenProperties[i].treeNodeId"> - <div class="inner-table-container"> - <properties-value-inner-table [property]="property.childrenProperties[i]" - [selectedPropertyId]="selectedPropertyId" - [propertyNameSearchText]="propertyNameSearchText" - (selectChildProperty)="onChildPropertySelected($event)" - (valueChanged)="propValueChanged()"></properties-value-inner-table> - </div> - </div> -</template> - diff --git a/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.ts deleted file mode 100644 index d62d0b94e3..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/map-property/map-property.component.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Created by rc2122 on 4/24/2017. - */ -/** - * Created by rc2122 on 4/23/2017. - */ -import {Component, Input, Output, EventEmitter} from "@angular/core"; -import { PropertyFEModel} from "app/models"; -import { PropertiesService } from "../../../services/properties.service"; -import {ComponentType} from "app/utils"; -import {UUID} from "angular2-uuid"; - -@Component({ - selector: 'map-property', - templateUrl: './map-property.component.html', - styleUrls: ['../properties-value-inner-table/properties-value-inner-table.component.less'] -}) -export class MapPropertyComponent { - - @Input() property: PropertyFEModel; - @Input() selectedPropertyId: string; - @Input() propertyNameSearchText:string; - - @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); - @Output() selectChildProperty: EventEmitter<any> = new EventEmitter<PropertyFEModel>(); - - constructor ( private propertiesService:PropertiesService){ - } - - mapKeys:Array<string>; - - ngOnInit() { - this.mapKeys = Object.keys(this.property.valueObjectRef); - } - - propValueChanged = () => { - this.valueChanged.emit(this.property); - }; - - onChildPropertySelected = (property) => { - this.selectChildProperty.emit(property); - }; - - getNumber = (num:number):Array<any> => { - return new Array(num); - } - - createNewChildProperty = (mapKey:string):void => { - - let newProperty: PropertyFEModel = new PropertyFEModel(mapKey, - this.property.schema.property.type, - UUID.UUID(), this.property, - this.property.valueObjectRef[mapKey]); - this.propertiesService.createPropertiesTreeForProp(newProperty); - this.property.childrenProperties = this.property.childrenProperties || []; - this.property.childrenProperties.push(newProperty); - } - - //get: new key and the index of this item in the map - //This method checks if the new key isn't exist already in the map and update the object and the children array with the new key - changeKeyOfMap = (newKey:string, index:number):void => { - //let fieldName:string = "mapKey" + this.property.treeNodeId + index; - let oldKey:string = Object.keys(this.property.valueObjectRef)[index]; - let existsKeyIndex:number = Object.keys(this.property.valueObjectRef).indexOf(newKey); - if (existsKeyIndex > -1 && existsKeyIndex != index) { - //error for exists key validation - } else { - //remove error for exists key validation and if the form is valid - update the map object - let newObj = {}; - angular.forEach(this.property.valueObjectRef,function(value:any,key:string){ - if(key == oldKey){ - newObj[newKey] = value; - }else{ - newObj[key] = value; - } - }); - this.property.valueObjectRef = newObj; - this.property.parent.valueObjectRef[this.property.name] = this.property.valueObjectRef;//in order to prevent break ref - if(this.property.childrenProperties){ - this.property.childrenProperties[index].name = newKey;//update this property childrenProperties with the new key - } - } - } - - //get: index of the item in the map - //This method removes item from map. - deleteMapItem = (index:number):void=> { - delete this.property.valueObjectRef[this.mapKeys[index]]; - this.mapKeys.splice(index, 1); - if(this.property.childrenProperties){ - this.property.childrenProperties.splice(index, 1); - } - if (!this.mapKeys.length) {//only when user removes all pairs of key-value fields - put the default - if (this.property.defaultValue) { - angular.copy(JSON.parse(this.property.defaultValue), this.property.valueObjectRef); - this.mapKeys = Object.keys(this.property.valueObjectRef); - if (this.property.schema.property.isDataType){ - angular.forEach(this.property.valueObjectRef, (value, key) => { - this.createNewChildProperty(key); - }, this); - } - } - } - this.valueChanged.emit(this.property); - } - - //This method inserts new empty item to map - addMapItemFields = ():void => { - this.property.valueObjectRef = this.property.valueObjectRef || {}; - if (this.property.schema.property.isSimpleType){ - this.property.valueObjectRef[''] = null; - }else{ - if(!this.property.valueObjectRef['']){ - this.property.valueObjectRef[''] = {}; - this.createNewChildProperty(''); - } - } - this.mapKeys = Object.keys(this.property.valueObjectRef); - } -} - diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html index 3ab47074e7..426ae3ab23 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html +++ b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html @@ -1,6 +1,5 @@ - - <div class="properties-table"> + <loader [display]="isLoading" size="large" [relative]="true"></loader> <div class="table-header"> <div class="table-cell col1">Property Name</div> <div class="table-cell col2">Type</div> @@ -13,16 +12,27 @@ <div *ngFor="let instanceName of feInstancesNames; trackBy:instanceName"> <div class="table-rows-header">{{instanceName | contentAfterLastDot}}</div> - <div class="table-row" *ngFor="let property of fePropertiesMap[instanceName]; trackBy:property?.name" (click)="onClickPropertyRow(property, instanceName, $event)" [ngClass]="{'selected': selectedPropertyId === property.uniqueId}"> - <div class="table-cell col1"> - <checkbox [label]="property.name" - [(checked)]="property.isSelected" - [disabled]="property.isDisabled || property.isDeclared" - (checkedChange)="propertyChecked(property)" - tooltip="{{property.name}}"></checkbox> - <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}"></span> + <div class="table-row" + *ngFor="let property of fePropertiesMap[instanceName] | searchFilter:'name':searchTerm; trackBy:property?.name" + (click)="onClickPropertyRow(property, instanceName, $event)" + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name }"> + + <div class="table-cell col1" [ngClass]="{'filtered':property.name === propertyNameSearchText}"> + <div class="property-name cut-inner-long-text"> + <checkbox [(checked)]="property.isSelected" + [disabled]="property.isDisabled || property.isDeclared || readonly" + (checkedChange)="propertyChecked(property)"></checkbox> + <div class="inner-cell-div" tooltip="{{property.name}}"> + <span>{{property.name}}</span> + </div> + </div> + <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}"></span> + </div> + <div class="table-cell col2"> + <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}"> + <span>{{property.type | contentAfterLastDot}}</span> + </div> </div> - <div class="table-cell col2">{{property.type | contentAfterLastDot}}</div> <div class="table-cell col3">{{property.schema && property.schema.property && property.schema.property.type ? (property.schema.property.type | contentAfterLastDot) : ''}}</div> <div class="table-cell valueCol"> @@ -32,7 +42,8 @@ [canBeDeclared]="true" [property]="property" [expandedChildId]="property.expandedChildPropertyId" - [propChildren]="property.flattenedChildren | filterChildProperties : property.expandedChildPropertyId" + [propertyNameSearchText]="propertyNameSearchText" + [readonly]="readonly" (valueChanged)="propValueChanged(property);" (expandChild)="property.updateExpandedChildPropertyId($event)" (clickOnPropertyRow)="onClickPropertyInnerRow($event, instanceName)" @@ -42,94 +53,8 @@ </div> </div> -<!-- - <div *ngIf="!property.isSimpleType && !property.isDeclared" class="table-cell valueCol child-property-container"> - - <div class="child-property-row" *ngFor="let flatProperty of property.flattenedChildren | filterChildProperties : property.expandedChildPropertyId" - [ngClass]="{'selected': selectedPropertyId === flatProperty.uniqueId}" (click)="clickOnPropertyRow(flatProperty, instanceName, $event)" [@fadeIn]="''"> - <derived-property [propertyObj]="flatProperty" [propertyNameSearchText]="propertyNameSearchText" [expanded]="flatProperty.propertiesName == property.expandedChildPropertyId" - (selectProperty)="propertySelected(property, $event, flatProperty.propertiesName)" (valueChanged)="propValueChanged(property)" (expandChild)="property.updateExpandedChildPropertyId($event)"></derived-property> - </div> - - </div> - <!-- - - - <property [propertyObj]="flatProperty" - [expanded]="flatProperty.parentName == property.expandedChildPropertyId" - (valueChanged)="propValueChanged($event)" - (selectChildProperty)="onChildPropertySelected($event)"></property> - <list-property *ngIf="property.type == 'list'" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (valueChanged)="propValueChanged($event)" - (selectChildProperty)="onChildPropertySelected($event)"></list-property> - <map-property *ngIf="property.type == 'map'" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (valueChanged)="propValueChanged($event)" - (selectChildProperty)="onChildPropertySelected($event)"></map-property> - <properties-value-inner-table *ngIf="property.isDataType" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (selectChildProperty)="onChildPropertySelected($event)" - (valueChanged)="propValueChanged($event)"></properties-value-inner-table> - --> - - </div> </div> </div> -<!-- -<div class="properties-table" style="display:block"> - <div class="table-header"> - <div class="table-cell col1">Property Name</div> - <div class="table-cell col2">Type</div> - <div class="table-cell col3">ES</div> - <div class="table-cell valueCol">Value</div> - </div> - <div class="table-body"> - <div class="no-data" *ngIf="!properties || !properties.length">No data to display</div> - <div class="table-row" *ngFor="let property of properties" (click)="clickOnPropertyRow(property)"> - <div class="table-cell col1"><checkbox [label]="property.name" [(checked)]="property.isSelected" (checkedChange)="propSelected(property)" [disabled]="property.isDisabled"></checkbox></div> - <div class="table-cell col2">{{property.type | contentAfterLastDot}}</div> - <div class="table-cell col3">{{property.schema && property.schema.property && property.schema.property.type ? (property.schema.property.type | contentAfterLastDot) : ''}}</div> - <div class="table-cell valueCol" [class.inner-table-container]="property.childrenProperties || !property.isSimpleType"> - <!--<input class="value-input" *ngIf="property.isSimpleType" - type="property.derivedFromSimpleTypeName || property.type" - [(ngModel)]="property.value" - (change)="putDefaultValueInEmptyProperty(property);propValueChanged(property);" - pattern="validationUtils.getValidationPattern(property.type)"/> - <dynamic-element - class="value-input" - *ngIf="property.isSimpleType" - [(value)]="property.value" - (valueChange)="putDefaultValueInEmptyProperty(property);propValueChanged(property);" - [type]="property.derivedFromSimpleTypeName || property.type" - [name]="property.name"> - </dynamic-element> - <list-property *ngIf="property.type == 'list'" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (valueChanged)="propValueChanged($event)" - (selectChildProperty)="onChildPropertySelected($event)"></list-property> - <map-property *ngIf="property.type == 'map'" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (valueChanged)="propValueChanged($event)" - (selectChildProperty)="onChildPropertySelected($event)"></map-property> - <properties-value-inner-table *ngIf="property.isDataType" - [property]="property" - [selectedPropertyId]="selectedPropertyId" - (selectChildProperty)="onChildPropertySelected($event)" - (valueChanged)="propValueChanged($event)"></properties-value-inner-table> - </div> - - </div> - </div> -</div> --> - - - diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less index de080dfdc9..bb019a768b 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less +++ b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less @@ -10,38 +10,17 @@ height:100%; text-align:left; - - .child-property-container { - display:flex; - flex-direction:column; - - &.table-cell { - padding:0; - } - - .child-property-row { - border-bottom: #d2d2d2 solid 1px; - &:last-child { - border-bottom:none; - } - } - } - - - derived-property, dynamic-property { - width:100%; - } - - /deep/ dynamic-property dynamic-property .dynamic-property-row { - border-top:solid #d2d2d2 1px; - } - - /deep/ dynamic-property dynamic-property:first-of-type .dynamic-property-row:not(.with-top-border) { - border-top: none; + .inner-cell-div{ + max-width: 100%; + text-overflow: ellipsis; + overflow: hidden; + height: 20px; } - - properties-value-inner-table { - width: 100%; + + .table-header, .table-row { + display: flex; + flex-direction:row; + flex: 0 0 auto; } .table-header { @@ -54,10 +33,17 @@ padding: 5px; } } - .table-header, .table-row { - display: flex; - flex-direction:row; - flex: 0 0 auto; + + .table-rows-header { + font-size:16px; + flex:1; + border: #d2d2d2 solid 1px; + border-top:none; + padding: 5px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + background-color: @tlv_color_v; } .table-body { @@ -79,17 +65,6 @@ } } - .table-rows-header { - font-size:16px; - flex:1; - border: #d2d2d2 solid 1px; - border-top:none; - padding: 5px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - background-color: @tlv_color_v; - } .table-row { &:hover { @@ -103,6 +78,10 @@ background-color:#e6f6fb; } } + .cut-inner-long-text{ + text-overflow: ellipsis; + overflow: hidden; + } .table-cell { font-size:13px; flex:1; @@ -112,7 +91,7 @@ padding: 5px; text-overflow: ellipsis; white-space: nowrap; - overflow: hidden; + display: flex; &:last-child { border-right:#d2d2d2 solid 1px; @@ -120,10 +99,24 @@ &.col1 { flex: 0 0 300px; max-width:300px; + display: flex; + justify-content: space-between; + + .property-name { + flex: 1; + display: flex; + max-width: 270px; + } .property-description-icon { float: right; margin-top: 4px; + margin-left: 5px; + flex: 0 0 auto; + } + + /deep/ .checkbox-container { + margin-right: 5px; } } &.col2 { @@ -137,46 +130,12 @@ } &.valueCol { - flex: 1 0 auto; + flex: 1; min-width: 350px; display: flex; justify-content: flex-end; padding: 0px; - - .value-input { - flex: 1; - max-height: 24px; - border: none; - background-color: inherit; - - &:focus, &:active { - border:none; - outline:none; - } - } - - .delete-btn { - flex: 0 0 auto; - } - - .delete-button-container { - max-height: 24px; - } - - &.inner-table-container { - padding: 0px; - - .delete-button-container { - padding: 3px 5px 0 0 ; - } - } } - - &.input-value-col { - padding: 5px; - } - - } .filtered { @@ -184,5 +143,9 @@ background-color: yellow; } } + + dynamic-property { + width:100%; + } } diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts index d5a9b40425..58214ca16b 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts @@ -2,8 +2,6 @@ import { Component, Input, Output, EventEmitter, SimpleChanges, ViewChild, Eleme import { trigger, state, style, transition, animate} from '@angular/core'; import {PropertyFEModel, DerivedFEProperty, DerivedPropertyType, InstanceFePropertiesMap} from "app/models"; import {PropertiesService} from "../../services/properties.service"; -// import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe'; -//import {PropertiesValueInnerTableComponent} from "./properties-table/properties-value-inner-table/properties-value-inner-table"; import { DynamicElementComponent } from 'app/ng2/components/dynamic-element/dynamic-element.component'; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; @@ -19,7 +17,10 @@ export class PropertiesTableComponent { @Input() selectedPropertyId: string; @Input() displayDeleteButton: boolean; @Input() propertyNameSearchText:string; - + @Input() searchTerm:string; + @Input() readonly:boolean; + @Input() isLoading:boolean; + @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>(); @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); @@ -50,6 +51,7 @@ export class PropertiesTableComponent { // Click on main row (row of propertyFEModel) onClickPropertyRow = (property:PropertyFEModel, instanceName:string, event?) => { //event && event.stopPropagation(); + this.selectedPropertyId = property.name; let propertyRowSelectedEvent:PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); this.selectPropertyRow.emit(propertyRowSelectedEvent); }; @@ -72,14 +74,6 @@ export class PropertiesTableComponent { this.updateCheckedPropertyCount.emit(isChecked); } - putDefaultValueInEmptyProperty = (property:PropertyFEModel):void => { - property.value = property.value || property.defaultValue; - } - - // clickOnInstanceRow = (instanceName:string) =>{ - // this.selectInstanceRow.emit(instanceName); - // }; - } export class PropertyRowSelectedEvent { diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.html b/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.html deleted file mode 100644 index 61555cac50..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.html +++ /dev/null @@ -1,41 +0,0 @@ - -<template ngFor let-childProp [ngForOf]="property.childrenProperties" let-i="index"> - <div class="table-inner-row" (click)="onChildPropertySelected(childProp)" [ngClass]="{'selected': selectedPropertyId === childProp.treeNodeId}"> - <div class="table-cell" [ngClass]="{'filtered':childProp.name === propertyNameSearchText}"> - <checkbox [label]="childProp.name" [(checked)]="childProp.isSelected" [disabled]="property.isDisabled"></checkbox> - </div> - <div class="table-cell prop-value"> - <input class="value-input" *ngIf="childProp.isSimpleType" - [(ngModel)]="property.valueObjectRef[childProp.name]" - (change)="putDefaultValueInEmptyChildProperty(childProp);propValueChanged();" - type="childProp.derivedFromSimpleTypeName || childProp.type"/> - <span class="datatype-text" *ngIf="childProp.isDataType">{{ childProp.type | contentAfterLastDot }}</span> - <span *ngIf="!childProp.isSimpleType" (click)="property.updateExpandedChildPropertyId(childProp.treeNodeId)">V</span> - </div> - </div> - <div class="table-inner-row" *ngIf="childProp.type === 'list' && property.expandedChildPropertyId === childProp.treeNodeId"> - <list-property [property]="childProp" - [selectedPropertyId]="selectedPropertyId" - [propertyNameSearchText]="propertyNameSearchText" - (valueChanged)="propValueChanged()" - (selectChildProperty)="onChildPropertySelected($event)"></list-property> - - </div> - <div class="table-inner-row" *ngIf="childProp.type === 'map' && property.expandedChildPropertyId == childProp.treeNodeId"> - <map-property [property]="childProp" - [selectedPropertyId]="selectedPropertyId" - [propertyNameSearchText]="propertyNameSearchText" - (valueChanged)="propValueChanged()" - (selectChildProperty)="onChildPropertySelected($event)"></map-property> - - </div> - <div class="table-inner-row" *ngIf="childProp.isDataType && property.expandedChildPropertyId == childProp.treeNodeId"> - <properties-value-inner-table [property]="childProp" - [selectedPropertyId]="selectedPropertyId" - [propertyNameSearchText]="propertyNameSearchText" - (selectChildProperty)="onChildPropertySelected($event)" - (valueChanged)="propValueChanged()"></properties-value-inner-table> - </div> -</template> - - diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.less b/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.less deleted file mode 100644 index 1b7f6d4cd1..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.less +++ /dev/null @@ -1,71 +0,0 @@ -table { width:100%;} -tr {border-bottom: #d2d2d2 solid 1px;} -tr:last-child { border-bottom:none;} -td { border:none; padding:5px;} -td:first-child { border-right:#d2d2d2 solid 1px;} - -.prop-value{ - span { - position: absolute; - top: 5px; - right: 2px; - - &.delete-span { - right:20px; - } - - &.datatype-text { - position:static; - } - - } -} - -.add-data-row { - padding:5px; - text-align:right; - border-bottom: #d2d2d2 solid 1px; - - &:last-child { - border-bottom:none; - } -} -.table-inner-row { - display:flex; - flex-direction:row; - border-bottom: #d2d2d2 solid 1px; - flex: 0 0 100%; - position:relative; - - &:last-child { - border-bottom:none; - } - - .table-cell { - flex: 0 0 50%; - padding:5px; - position:relative; - text-overflow: ellipsis; - white-space: nowrap; - - &:first-child { - border-right:#d2d2d2 solid 1px; - overflow:hidden; - } - - - } - - .table-inner-container, .inner-table-container { - flex: 0 0 100%; - } -} -/deep/ map-property, /deep/ properties-value-inner-table, /deep/ list-property{ - width:100%; -} - -.filtered { - /deep/ .checkbox-label-content{ - background-color: yellow; - } -} diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.ts b/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.ts deleted file mode 100644 index 7d0b219ffe..0000000000 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-value-inner-table/properties-value-inner-table.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Created by rc2122 on 4/20/2017. - */ -import {Component, Input, Output, EventEmitter} from "@angular/core"; -import {PropertyFEModel} from "app/models"; -import {PropertiesService} from "../../../services/properties.service"; - -@Component({ - selector: 'properties-value-inner-table', - templateUrl: './properties-value-inner-table.component.html', - styleUrls: ['./properties-value-inner-table.component.less'] -}) -export class PropertiesValueInnerTableComponent { - - @Input() property: PropertyFEModel; - @Input() selectedPropertyId: string; - @Input() propertyNameSearchText:string; - - @Output() selectChildProperty: EventEmitter<any> = new EventEmitter<PropertyFEModel>(); - @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); - - constructor ( private propertiesService:PropertiesService){ - } - - - onChildPropertySelected = (property) => { - this.selectChildProperty.emit(property); - }; - - propValueChanged = () => { - this.valueChanged.emit(this.property); - }; - - putDefaultValueInEmptyChildProperty = (childProp:PropertyFEModel):void => { - this.property.valueObjectRef[childProp.name] = this.property.valueObjectRef[childProp.name] || childProp.defaultValue; - } -} |