diff options
author | Michael Lando <ml636r@att.com> | 2018-03-04 14:53:33 +0200 |
---|---|---|
committer | Michael Lando <ml636r@att.com> | 2018-03-07 13:19:05 +0000 |
commit | a5445100050e49e83f73424198d73cd72d672a4d (patch) | |
tree | cacf4df817df31be23e4e790d1dda857bdae061e /catalog-ui/src/app/ng2/components/ui | |
parent | 51157f92c21976cba4914c378aaa3cba49826931 (diff) |
Sync Integ to Master
Change-Id: I71e3acc26fa612127756ac04073a522b9cc6cd74
Issue-ID: SDC-977
Signed-off-by: Gitelman, Tal (tg851x) <tg851x@intl.att.com>
Diffstat (limited to 'catalog-ui/src/app/ng2/components/ui')
31 files changed, 625 insertions, 80 deletions
diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html new file mode 100644 index 0000000000..e279e3f704 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html @@ -0,0 +1,11 @@ +<div class="sdc-canvas-zone {{class}}-zone" [class.minimized]="minifyZone" [class.hidden]="!showZone"> + <div class="sdc-canvas-zone__header" (click)="unminifyZone()" > + <div class="sdc-canvas-zone__title">{{title}} + <span class="sdc-canvas-zone__counter">{{count}}</span> + </div> + <span class="sdc-canvas-zone__state-button">–</span> + </div> + <div class="sdc-canvas-zone__container"> + <ng-content></ng-content> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less new file mode 100644 index 0000000000..3e77c5ca3b --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less @@ -0,0 +1,62 @@ +.sdc-canvas-zone { + width: 280px; + max-height:186px; + display:flex; + flex-direction:column; + align-self: flex-end; + color:white; + font-family:OpenSans-Regular, sans-serif; + transition: width .2s ease-in-out, max-height .2s ease-in-out .1s; + position:relative; + bottom:0px; + + .sdc-canvas-zone__header { + background: #5A5A5A; + border-radius: 2px 2px 0 0; + padding: 5px 10px; + display:flex; + justify-content: space-between; + font-size: 14px; + text-transform:uppercase; + .sdc-canvas-zone__state-button { + font-weight:bold; + cursor:pointer; + } + } + + .sdc-canvas-zone__container { + padding:5px; + background-color: #5A5A5A; + opacity:0.9; + flex: 1; + display:flex; + flex-direction: row; + align-items: flex-start; + flex-wrap:wrap; + overflow-y:auto; + min-height: 80px; + max-height: 170px; + } + + + &.minimized { + max-height:30px; + width:120px; + cursor:pointer; + + .sdc-canvas-zone__state-button { + display:none; + } + .sdc-canvas-zone__container { + flex: 0 0 0; + min-height: 0; + padding: 0; + overflow-y:hidden; + transition: min-height .2s ease-in-out .2s; + transition: padding .1s ease-in-out 0s; + } + } + &.hidden { + display:none; + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts new file mode 100644 index 0000000000..7e60cb37a6 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts @@ -0,0 +1,25 @@ +import { Component, Input, Output, ViewEncapsulation, EventEmitter } from '@angular/core'; +import { EventListenerService } from 'app/services'; +import { GRAPH_EVENTS } from 'app/utils'; + +@Component({ + selector: 'zone-container', + templateUrl: './zone-container.component.html', + styleUrls: ['./zone-container.component.less'], + encapsulation: ViewEncapsulation.None +}) + +export class ZoneContainerComponent { + @Input() title:string; + @Input() class:string; + @Input() count:number; + @Input() showZone:boolean; + @Input() minifyZone:boolean; + constructor(private eventListenerService:EventListenerService) {} + + private unminifyZone = () => { + this.minifyZone = !this.minifyZone; + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_SIZE_CHANGE); + } + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html new file mode 100644 index 0000000000..d36b7aec6f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html @@ -0,0 +1,8 @@ +<div class="zone-child mode-{{config.mode}}" [class.locked]="activeInstanceMode > MODE.HOVER" + (mouseenter)="setMode(MODE.HOVER)" (mouseleave)="setMode(MODE.NONE)" (click)="setMode(MODE.SELECTED)"> + <div class="zone-child__handle" (click)="setMode(MODE.TAG, $event)">+</div> + <div class="zone-child__body"> + <div class="zone-child__body-content">{{config.count || defaultIconText}}</div> + </div> + <div class="zone-child__name">{{config.name}}</div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less new file mode 100644 index 0000000000..a1d56df96e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less @@ -0,0 +1,110 @@ +.zone-child { + position:relative; + width:76px; + margin:5px; + + .zone-child__handle { + display:none; + position:absolute; + right:4px; + top:10px; + width:22px; + height:22px; + cursor:pointer; + border: solid white 1px; + border-radius: 2px; + text-align: center; + font-weight:bold; + } + + .zone-child__body { + margin:0 auto; + width:43px; + height:43px; + display:flex; + padding:3px; + + } + + .zone-child__body-content { + border-radius: 2px; + flex:1; + color:white; + font-size:18px; + text-align:center; + display:flex; + align-items: center; + justify-content: center; + } + + .zone-child__name { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + text-align:center; + } + /* Dynamic classes below */ + + &.mode-1, &.mode-2, &.mode-3 { //hover, selected, tag + .zone-child__body { + border:solid 2px; + border-radius: 2px; + padding:2px; + cursor:pointer; + } + .zone-child__handle{ + display:block; + cursor:pointer; + } + } + + &.locked { + cursor: default; + } + + // &:not(.locked):hover .zone-child__handle{ + // display:block; + // } + .zone-child__body { + cursor: default; + } + &.mode-3 .zone-child__handle { + width:24px; + height:24px; + right:3px; + top:9px; + display:block; + background-image: linear-gradient(-140deg, #009E98 0%, #97D648 100%); + border: 2px solid #FFFFFF; + border-radius: 2px; + box-shadow: inset 2px -2px 3px 0 #007A3E; + cursor: pointer; + } + +} +.sdc-canvas-zone.group-zone { + .zone-child__handle { + background-color:#009FDB; + } + .zone-child__body { + border-color:#009FDB; + } + .zone-child__body-content { + background: #009FDB; + } +} + +.sdc-canvas-zone.policy-zone { + .zone-child__handle { + background-color:#0568AE; + } + .zone-child__body { + border-color:#1287D9; + .zone-child__body-content { + background: #1287D9; + } + } + .zone-child__body-content { + background: #0568AE; + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts new file mode 100644 index 0000000000..8057ae908a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts @@ -0,0 +1,28 @@ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +import { ZoneInstanceConfig, ZoneInstanceMode } from 'app/models/graph/zones/zone-child'; + +@Component({ + selector: 'zone-instance', + templateUrl: './zone-instance.component.html', + styleUrls: ['./zone-instance.component.less'], + encapsulation: ViewEncapsulation.None +}) +export class ZoneInstanceComponent { + + @Input() config:ZoneInstanceConfig; + @Input() defaultIconText:string; + @Input() isActive:boolean; + @Input() activeInstanceMode: ZoneInstanceMode; + @Output() modeChange: EventEmitter<any> = new EventEmitter<any>(); + private MODE = ZoneInstanceMode; + + private setMode = (mode:ZoneInstanceMode, event?:any):void => { + if(!this.isActive || this.isActive && mode == ZoneInstanceMode.TAG){ //when active, do not allow hover/select mode toggling + this.modeChange.emit({newMode: mode, instance: this.config}); + } + if(event){ + event.stopPropagation(); + } + } + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts index 53d1590b1c..d1e68f3088 100644 --- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts @@ -18,14 +18,25 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core' import {ValidationConfiguration} from "app/models"; +import {IUiElementChangeEvent} from "../form-components/ui-element-base.component"; import {UiElementInputComponent} from "../form-components/input/ui-element-input.component"; import {UiElementPopoverInputComponent} from "../form-components/popover-input/ui-element-popover-input.component"; import {UiElementIntegerInputComponent} from "../form-components/integer-input/ui-element-integer-input.component"; import {UiElementDropDownComponent, DropdownValue} from "../form-components/dropdown/ui-element-dropdown.component"; import {PROPERTY_DATA} from "../../../../utils/constants"; +enum DynamicElementComponentCreatorIdentifier { + STRING, + INTEGER, + FLOAT, + BOOLEAN, + SUBNETPOOLID, + DEFAULT +} + @Component({ selector: 'dynamic-element', template: `<div #target></div>`, @@ -44,16 +55,14 @@ export class DynamicElementComponent { @Input() name: string; @Input() readonly:boolean; @Input() path:string;//optional param. used only for for subnetpoolid type - value:any; - // Two way binding for value (need to write the "Change" word like this) - @Output('valueChange') emitter: EventEmitter<string> = new EventEmitter<any>(); - @Input('value') set setValueValue(value) { - this.value = value; - } + @Input() value: any; + @Output() valueChange: EventEmitter<any> = new EventEmitter<any>(); + @Output('elementChanged') emitter: EventEmitter<IUiElementChangeEvent> = new EventEmitter<IUiElementChangeEvent>(); cmpRef: ComponentRef<any>; private isViewInitialized: boolean = false; + private elementCreatorIdentifier: DynamicElementComponentCreatorIdentifier; validation = ValidationConfiguration.validation; constructor( @@ -66,29 +75,72 @@ export class DynamicElementComponent { if (!this.isViewInitialized) { return; } - if (this.cmpRef) { - this.cmpRef.destroy(); - } - // Factory to create component based on type or peroperty name. + // Factory to create component based on type or other property attributes. + const prevElementCreatorIdentifier: DynamicElementComponentCreatorIdentifier = this.elementCreatorIdentifier; switch(true) { case this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1: + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.SUBNETPOOLID; + break; + case this.type === 'integer': + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.INTEGER; + break; + case this.type === 'float': + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.FLOAT; + break; + case PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1: + case this.type === 'string': + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.STRING; + break; + case this.type === 'boolean': + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.BOOLEAN; + break; + default: + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.DEFAULT; + } + + // In case the dynamic element creator is changed, then destroy old and build new. + if (this.elementCreatorIdentifier !== prevElementCreatorIdentifier) { + if (this.cmpRef) { + this.cmpRef.destroy(); + } + this.createComponentByIdentifier(); + } + + // Update attributes in base element class + if (this.cmpRef) { + this.cmpRef.instance.name = this.name; + this.cmpRef.instance.type = this.type; + this.cmpRef.instance.value = this.value; + this.cmpRef.instance.readonly = this.readonly; + } + } + + createComponentByIdentifier() { + switch(this.elementCreatorIdentifier) { + case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID: if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name let pathArray = this.path.split("#"); this.name = pathArray[pathArray.length - 2]; } this.createComponent(UiElementPopoverInputComponent); break; - case this.type == 'integer': + + case DynamicElementComponentCreatorIdentifier.INTEGER: this.createComponent(UiElementIntegerInputComponent); this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; break; - case PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1: - case this.type == 'string': + + case DynamicElementComponentCreatorIdentifier.FLOAT: + this.createComponent(UiElementIntegerInputComponent); + this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/; + break; + + case DynamicElementComponentCreatorIdentifier.STRING: this.createComponent(UiElementInputComponent); break; - case this.type == 'boolean': + case DynamicElementComponentCreatorIdentifier.BOOLEAN: this.createComponent(UiElementDropDownComponent); // Build drop down values @@ -96,25 +148,20 @@ export class DynamicElementComponent { tmp.push(new DropdownValue(true,'TRUE')); tmp.push(new DropdownValue(false,'FALSE')); this.cmpRef.instance.values = tmp; + if(!_.isUndefined(this.value)){//contains the real value (and not a string) + this.value = JSON.parse(this.value); + } break; + + case DynamicElementComponentCreatorIdentifier.DEFAULT: default: this.createComponent(UiElementInputComponent); console.log("ERROR: No ui component to handle type: " + this.type); } - // Additional attributes in base element class - if (this.cmpRef) { - 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 - this.cmpRef.instance.baseEmitter.subscribe((value):void => { - this.emitter.emit(value) - }); - + this.cmpRef.instance.baseEmitter.subscribe((event) => { this.emitter.emit(event); }); + this.cmpRef.instance.valueChange.subscribe((event) => { this.valueChange.emit(event); }); } createComponent(ComponentToCreate:any):void { diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html index c6b8384183..805e5ac295 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html @@ -1,3 +1,3 @@ -<select name='{{name}}' [(ngModel)]="value" (change)="onSave()" [ngClass]="{'disabled':readonly}" data-tests-id="SelectType"> +<select name='{{name}}' [(ngModel)]="value" (change)="onChange()" [ngClass]="{'disabled':readonly}" data-tests-id="SelectType"> <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue">{{ddvalue.label||ddvalue}}</option> </select> diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts index 5abf32c61b..03a1fc6040 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts @@ -43,9 +43,4 @@ export class UiElementDropDownComponent extends UiElementBase implements UiEleme constructor() { super(); } - - onSave() { - this.baseEmitter.emit(this.value); - } - } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html index b7d7c859c7..057e731ada 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html @@ -4,7 +4,7 @@ type="text" [name]="name" [(ngModel)]="value" - (change)="onSave()" + (input)="onChange()" [attr.maxlength]="validation.propertyValue.max" [attr.minlength]="validation.propertyValue.min" [pattern]="pattern" diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts index fb3b3db859..ce231e76e8 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts @@ -32,10 +32,4 @@ export class UiElementInputComponent extends UiElementBase implements UiElementB super(); this.pattern = this.validation.validationPatterns.comment; } - - onSave() { - if (!this.control.invalid){ - this.baseEmitter.emit(this.value); - } - } } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html index 9fbc9e1094..e1555e87fd 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html @@ -4,7 +4,7 @@ type="text" [name]="name" [(ngModel)]="value" - (change)="onSave()" + (input)="onChange()" [attr.maxlength]="validation.propertyValue.max" [attr.minlength]="validation.propertyValue.min" [pattern]="pattern" diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts index 1667f4393d..9aa4b5872c 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts @@ -33,9 +33,8 @@ export class UiElementIntegerInputComponent extends UiElementBase implements UiE //this.pattern = this.validation.validationPatterns.comment; } - onSave() { - if (!this.control.invalid){ - this.baseEmitter.emit(this.value ? JSON.parse(this.value) : this.value); - } + onChange() { + this.value = this.control.valid && this.value ? JSON.parse(this.value) : this.value; + super.onChange(); } } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts index 61688df3f0..525cd1742c 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts @@ -35,17 +35,10 @@ export class UiElementPopoverInputComponent extends UiElementBase implements UiE saveButton: ButtonModel; buttonsArray: ButtonsModelMap; - onSave = ():void => { - if (!this.control.invalid){ - this.baseEmitter.emit(this.value); - this.popoverContentComponent.hide(); - } - } - constructor() { super(); // Create Save button and insert to buttons map - this.saveButton = new ButtonModel('save', 'blue', this.onSave); + this.saveButton = new ButtonModel('save', 'blue', this.onChange); this.buttonsArray = { 'test': this.saveButton }; // Define the regex pattern for this controller diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts index 0f80e2ad44..3e8c3b5813 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts @@ -12,10 +12,6 @@ import {UiElementBaseInterface, UiElementBase} from "../ui-element-base.componen }) export class RadioButtonComponent extends UiElementBase implements UiElementBaseInterface { - onSave() { - this.baseEmitter.emit(this.value); - } - @Input() options:Array<RadioButtonModel>; @Input() readonly:boolean; @Input() direction:string = 'vertical'; //get 'horizontal' | 'vertical' @@ -23,7 +19,7 @@ export class RadioButtonComponent extends UiElementBase implements UiElementBas select(value:any) { this.value = value; - this.baseEmitter.emit(this.value); + this.onChange(); } } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts index ae2013ff70..b4e9e7d36a 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts @@ -23,7 +23,12 @@ import { ValidationConfiguration } from "app/models"; import { FormControl, Validators } from '@angular/forms'; export interface UiElementBaseInterface { - onSave(); + onChange(); +} + +export interface IUiElementChangeEvent { + value: any; + isValid: boolean; } @Component({ @@ -35,21 +40,29 @@ export class UiElementBase { protected validation = ValidationConfiguration.validation; protected control: FormControl; - // Two way binding for value (need to write the "Change" word like this) - @Output('valueChange') baseEmitter: EventEmitter<string> = new EventEmitter<any>(); - @Input('value') set setValueValue(value) { - this.value = value; - } + @Input() value: any; + @Output() valueChange: EventEmitter<any> = new EventEmitter<any>(); + @Output('elementChanged') baseEmitter: EventEmitter<IUiElementChangeEvent> = new EventEmitter<IUiElementChangeEvent>(); @Input() name: string; @Input() type: string; - @Input() value: any; @Input() pattern: any; @Input() readonly:boolean; constructor() { //this.control = new FormControl('', [Validators.required]); this.control = new FormControl('', []); + + this.baseEmitter.subscribe((changeEvent: IUiElementChangeEvent) => { + this.valueChange.emit(changeEvent.value); + }) + } + + onChange() { + this.baseEmitter.emit({ + value: this.value, + isValid: this.control.valid + }); } } diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts index f66aa551e2..585c36660e 100644 --- a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts @@ -74,10 +74,10 @@ export class LoaderComponent { if (this.relative === true) { let parentElement = this.viewContainerRef.element.nativeElement.parentElement; this.offset = { - left: (parentElement.offsetLeft) ? parentElement.offsetLeft + "px" : undefined, - top: (parentElement.offsetTop) ? parentElement.offsetTop + "px" : undefined, - width: (parentElement.offsetWidth) ? parentElement.offsetWidth + "px" : undefined, - height: (parentElement.offsetHeight) ? parentElement.offsetHeight + "px" : undefined + left: (parentElement.offsetLeft !== undefined) ? parentElement.offsetLeft + "px" : undefined, + top: (parentElement.offsetTop !== undefined) ? parentElement.offsetTop + "px" : undefined, + width: (parentElement.offsetWidth !== undefined) ? parentElement.offsetWidth + "px" : undefined, + height: (parentElement.offsetHeight !== undefined) ? parentElement.offsetHeight + "px" : undefined }; } this.isVisible = true; diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html index 9a0fdf6bf4..6fc55d19e7 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html @@ -1,6 +1,14 @@ <div class="custom-modal {{input.size}}"> - <div class="ng2-modal-content"> - <div class="ng2-modal-header modal-type-{{input.type}}"> + <div class="ng2-modal-content" + ngDraggable + [ngDraggable]="input.isMovable" + [handle]="ModalHandle" + [bounds]="ModalBounds" + [inBounds]="true" + [preventDefaultEvent]="false"> + <div #ModalHandle + class="ng2-modal-header modal-type-{{input.type}}" + [ngClass]="{'movable': input.isMovable}"> <span class="title">{{ input.title }}</span> <span class="close-button" (click)="close()"></span> </div> @@ -18,4 +26,4 @@ </div> </div> </div> -<div class="modal-background"></div> +<div #ModalBounds class="modal-background" [ngClass]="{'transparent': input.isMovable}"></div> diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less index fac1ae74a8..03b2a70667 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less @@ -12,7 +12,7 @@ bottom: 0; left: 0; z-index: 15007; - overflow: auto; + overflow: visible; margin: auto; display: flex; align-items: center; @@ -22,6 +22,8 @@ width: 100%; box-shadow: 0 5px 15px rgba(0,0,0,.5); border-radius: 4px; + + .ng2-modal-body{ padding: 20px; } @@ -29,19 +31,28 @@ .ng2-modal-header{ .m_18_r; font-weight: bold; + -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; + height: 50px; line-height: 50px; + margin: 0px 20px; + display: -webkit-box; display: -ms-flexbox; display: flex; + text-align: left; -webkit-box-align: center; -ms-flex-align: center; align-items: center; - margin: 0px 20px; + + &.ng-draggable { + cursor: move; + user-select: none; + } &.modal-type-standard { border-bottom: solid 3px @main_color_a; @@ -101,9 +112,14 @@ background-color: #000; opacity: 0.5; z-index: 900; + + &.transparent { + background-color: transparent; + } } + .xl { width: 1200px; } diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts index 89db8d1140..777e9bdc06 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts @@ -33,6 +33,7 @@ import { ButtonsModelMap, ModalModel } from 'app/models'; }) export class ModalComponent implements OnInit, OnDestroy { + @Input() isMovable: boolean; @Input() input: ModalModel; @Input() dynamicContent: any; @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpService's catchError() for example. diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts index c38e60194b..2999528d13 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts @@ -1,5 +1,6 @@ import { NgModule } from "@angular/core"; import { CommonModule } from '@angular/common'; +import { AngularDraggableModule } from 'angular2-draggable'; import { ModalService } from 'app/ng2/services/modal.service'; import { ErrorMessageComponent } from "./error-message/error-message.component"; import {ModalComponent} from "./modal.component"; @@ -9,7 +10,7 @@ import {ModalComponent} from "./modal.component"; ModalComponent, ErrorMessageComponent ], - imports: [CommonModule], + imports: [CommonModule, AngularDraggableModule], exports: [ModalComponent, ErrorMessageComponent], entryComponents: [ //need to add anything that will be dynamically created ModalComponent, diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html new file mode 100644 index 0000000000..2a776d444f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html @@ -0,0 +1,4 @@ +<div class="palette-animation-wrapper" [style.top]="from.y + 50 + 'px'" [style.left]="from.x + 'px'" [style.transform]="transformStyle" [class.hidden]="!visible" + (transitionend)="animationComplete()"> +<div class="medium small sprite-resource-icons sprite-{{iconName}}-icons {{iconName}}" ></div> +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less new file mode 100644 index 0000000000..54f04189c0 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less @@ -0,0 +1,5 @@ +.palette-animation-wrapper{ + position: absolute; + z-index: 100; + transition: all 2s ease-in-out; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts new file mode 100644 index 0000000000..609a1fc5e1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import {Component, Input } from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +import { setTimeout } from 'core-js/library/web/timers'; +import { EventListenerService } from 'app/services'; +import { GRAPH_EVENTS } from 'app/utils'; +import { Point } from 'app/models'; + + + +@Component({ + selector: 'palette-animation', + templateUrl: './palette-animation.component.html', + styleUrls:['./palette-animation.component.less'], +}) + +export class PaletteAnimationComponent { + + @Input() from : Point; + @Input() to : Point; + @Input() iconName : string; + @Input() data : any; + + public animation; + private visible:boolean = false; + private transformStyle:string = ""; + + + constructor(private eventListenerService:EventListenerService) {} + + public runAnimation() { + this.visible = true; + let positionDiff:Point = new Point(this.to.x - this.from.x, this.to.y - this.from.y); + setTimeout(()=>{ + this.transformStyle = 'translate('+ positionDiff.x + 'px,' + positionDiff.y +'px)'; + }, 0); + }; + + public animationComplete = (e) => { + this.visible = false; + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_FINISH_ANIMATION_ZONE); + }; + + +} diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts new file mode 100644 index 0000000000..8674571138 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { PaletteAnimationComponent } from "./palette-animation.component"; + + +@NgModule({ + declarations: [ + PaletteAnimationComponent + ], + imports: [ CommonModule ], + exports: [ PaletteAnimationComponent ] +}) + +export class PaletteAnimationModule { + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html new file mode 100644 index 0000000000..ed172bf2b0 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html @@ -0,0 +1,9 @@ +<div class="popup-panel" [ngClass]="{'hide':!isShowPanel}" [style.left]="popupPanelPosition.x + 'px'" [style.top]="popupPanelPosition.y + 'px'" + (mousedown)="addZoneInstance()" + (mouseenter)="onMouseEnter()" + (mouseleave)="onMouseLeave()"> + <div class="popup-panel-group"> + <div class="popup-panel-plus">+</div> + <div class="popup-panel-title">{{panelTitle}}</div> + </div> +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less new file mode 100644 index 0000000000..24f0485e76 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less @@ -0,0 +1,37 @@ +.popup-panel { + position: absolute; + display: inline-block; + background-color: white; + border: solid 1px #d2d2d2; + border-top: solid 3px #13a7df; + left: 208px; top: 0px; + width: 140px; + height: 40px; + z-index: 10000; + + &:hover { + background-color: whitesmoke; + } + + .popup-panel-group { + padding-left: 8px; + padding-top: 8px; + cursor: pointer; + + .popup-panel-plus { + border-radius: 50%; + color: white; + background-color: #13a7df; + width: 20px; + text-align: center; + display: inline-block; + } + + .popup-panel-title { + padding-left: 10px; + display: inline-block; + } + + } + +} diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts new file mode 100644 index 0000000000..d30d5f6178 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts @@ -0,0 +1,87 @@ +import {Component, OnInit} from '@angular/core'; +import {GRAPH_EVENTS} from "app/utils"; +import {LeftPaletteComponent, Point} from "app/models"; +import {EventListenerService} from "app/services"; +import {LeftPaletteMetadataTypes} from "../../../../models/components/displayComponent"; + +@Component({ + selector: 'app-palette-popup-panel', + templateUrl: './palette-popup-panel.component.html', + styleUrls: [ './palette-popup-panel.component.less' ], +}) +export class PalettePopupPanelComponent implements OnInit { + + public panelTitle: string; + public isShowPanel: boolean; + private component: Component; + private displayComponent: LeftPaletteComponent; + private popupPanelPosition:Point = new Point(0,0); + + constructor(private eventListenerService: EventListenerService) { + this.isShowPanel = false; + } + + ngOnInit() { + this.registerObserverCallbacks(); + } + + public onMouseEnter() { + this.isShowPanel = true; + } + + public onMouseLeave() { + this.isShowPanel = false; + } + + public addZoneInstance(): void { + if(this.displayComponent) { + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ADD_COMPONENT_INSTANCE_ZONE_START, this.component, this.displayComponent, this.popupPanelPosition); + } + } + + private registerObserverCallbacks() { + + this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, + (component: Component, displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => { + + this.component = component; + this.showPopupPanel(displayComponent, sectionElem); + }); + + this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL, () => this.hidePopupPanel()); + } + + private getPopupPanelPosition (sectionElem: HTMLElement):Point { + let pos: ClientRect = sectionElem.getBoundingClientRect(); + let offsetX: number = -30; + const offsetY: number = pos.height / 2; + return new Point((pos.right + offsetX), (pos.top - offsetY + window.pageYOffset)); + }; + + private setPopupPanelTitle(component: LeftPaletteComponent): void { + if (component.categoryType === LeftPaletteMetadataTypes.Group) { + this.panelTitle = "Add Group"; + return; + } + + if (component.categoryType === LeftPaletteMetadataTypes.Policy) { + this.panelTitle = "Add Policy"; + return; + } + } + + private showPopupPanel(displayComponent:LeftPaletteComponent, sectionElem: HTMLElement) { + if(!this.isShowPanel){ + this.displayComponent = displayComponent; + this.setPopupPanelTitle(displayComponent); + this.popupPanelPosition = this.getPopupPanelPosition(sectionElem); + this.isShowPanel = true; + } + }; + + private hidePopupPanel() { + if(this.isShowPanel){ + this.isShowPanel = false; + } + }; +} diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html index 6d76f0ad06..fc6e821f34 100644 --- a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html @@ -15,7 +15,8 @@ <ng-content></ng-content> <div class="popover-footer"> <button *ngFor="let buttonName of buttonsNames" - class="tlv-btn {{buttons[buttonName].cssClass}}" + class="tlv-btn {{buttons[buttonName].cssClass}}" + [attr.data-tests-id]="'filter-' + buttons[buttonName].text.toLowerCase() + '-button'" [disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()" (click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button> </div> diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts index 21d2bbad43..f4b410347b 100644 --- a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts @@ -23,6 +23,8 @@ import { Tab } from './tab/tab.component'; import { ViewEncapsulation } from '@angular/core'; import { trigger, state, style, transition, animate, keyframes } from '@angular/core'; +export {Tab}; + @Component({ selector: 'tabs', templateUrl: './tabs.component.html', diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts index 526096524c..44314734c3 100644 --- a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts @@ -27,6 +27,10 @@ import {ModalModule} from "./modal/modal.module"; import {PopoverModule} from "./popover/popover.module"; import {SearchBarComponent} from "./search-bar/search-bar.component"; import {SearchWithAutoCompleteComponent} from "./search-with-autocomplete/search-with-autocomplete.component"; +import {PalettePopupPanelComponent} from "./palette-popup-panel/palette-popup-panel.component"; +import {ZoneContainerComponent} from "./canvas-zone/zone-container.component"; +import {ZoneInstanceComponent } from "./canvas-zone/zone-instance/zone-instance.component"; +import {PaletteAnimationComponent} from "./palette-animation/palette-animation.component" import {TabModule} from "./tabs/tabs.module"; import {TooltipModule} from "./tooltip/tooltip.module"; import {CommonModule} from "@angular/common"; @@ -35,15 +39,21 @@ import {BrowserModule} from "@angular/platform-browser"; import {MultiStepsWizardModule} from "./multi-steps-wizard/multi-steps-wizard.module"; import {MenuListModule} from "./menu/menu-list.module"; import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module"; +//import {SdcUiComponentsModule} from "sdc-ui/lib/angular"; @NgModule({ declarations: [ LoaderComponent, SearchBarComponent, - SearchWithAutoCompleteComponent - ], + SearchWithAutoCompleteComponent, + PalettePopupPanelComponent, + ZoneContainerComponent, + ZoneInstanceComponent, + PaletteAnimationComponent +], imports: [ + //SdcUiComponentsModule, BrowserModule, FormsModule, CommonModule, @@ -63,6 +73,9 @@ import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-n MultiStepsWizardModule, SearchBarComponent, SearchWithAutoCompleteComponent, + PalettePopupPanelComponent, + ZoneContainerComponent, + ZoneInstanceComponent, DynamicElementModule, NavbarModule, FormElementsModule, @@ -71,10 +84,10 @@ import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-n TabModule, TooltipModule, MenuListModule, - MenuListNg2Module + MenuListNg2Module, + PaletteAnimationComponent ], - - entryComponents: [SearchWithAutoCompleteComponent] + entryComponents: [SearchWithAutoCompleteComponent, PalettePopupPanelComponent, ZoneContainerComponent, ZoneInstanceComponent, PaletteAnimationComponent] }) export class UiElementsModule {} |