diff options
Diffstat (limited to 'vid-webpack-master/src/app/shared')
80 files changed, 2993 insertions, 215 deletions
diff --git a/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.html b/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.html index 5145784e2..3dff92cdc 100644 --- a/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.html +++ b/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.html @@ -14,7 +14,14 @@ </div> </div> <div class="col-md-8 right-panel"> - <div class="row" *ngIf="showVidStatus"><span class="table-title">VID status</span></div> + <div class="row" *ngIf="showVidStatus"> + <div class="col-md-6 leftColumn"><span class="table-title">VID status</span></div> + <div class="col-md-6 rightColumn"><span *ngIf="showMoreAuditInfoLink"> + <a id="full_screen_link" target="_parent" title="Full-screen audit info" [href]="readOnlyRetryUrl()"> + <i class="fa fa-external-link"></i> + </a> + </span></div> + </div> <div class="row" *ngIf="showVidStatus"> <table id="service-instantiation-audit-info-vid" class="table table-bordered"> <thead class="thead-dark"> diff --git a/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.ts b/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.ts index 95e9825da..3a7f4ecfa 100644 --- a/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.ts +++ b/vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.ts @@ -10,6 +10,7 @@ import {IframeService} from "../../utils/iframe.service"; import {NgRedux} from "@angular-redux/store"; import {AppState} from "../../store/reducers"; import {AuditInfoModalComponentService} from "./auditInfoModal.component.service"; +import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service"; @Component({ selector: 'audit-info-modal', @@ -19,11 +20,13 @@ import {AuditInfoModalComponentService} from "./auditInfoModal.component.service export class AuditInfoModalComponent { static openModal: Subject<ServiceInfoModel> = new Subject<ServiceInfoModel>(); static openInstanceAuditInfoModal: Subject<{instanceId , type, model, instance}> = new Subject<{instanceId , type, model, instance}>(); - @ViewChild('auditInfoModal') public auditInfoModal: ModalDirective; + @ViewChild('auditInfoModal', {static: false}) public auditInfoModal: ModalDirective; title: string = 'Service Instantiation Information'; modelInfoItems: ModelInformationItem[] = []; serviceModel: ServiceModel; serviceModelName: string; + serviceModelId: string; + jobId: string; vidInfoData: AuditStatus[] = []; msoInfoData: AuditStatus[] = []; isAlaCarte: boolean; @@ -32,15 +35,18 @@ export class AuditInfoModalComponent { model: any; instanceId: string; isALaCarteFlagOn: boolean; + showMoreAuditInfoLink: boolean; type : string = "Service"; showVidStatus : boolean = true; auditInfoModalComponentService : AuditInfoModalComponentService; constructor(private _serviceInfoService: ServiceInfoService, private _iframeService : IframeService, private _auditInfoModalComponentService : AuditInfoModalComponentService, + private _featureFlagsService: FeatureFlagsService, private store: NgRedux<AppState>) { this.auditInfoModalComponentService = this._auditInfoModalComponentService; AuditInfoModalComponent.openModal.subscribe((jobData: ServiceInfoModel) => { this.isALaCarteFlagOn = this.store.getState().global.flags['FLAG_A_LA_CARTE_AUDIT_INFO']; + this.showMoreAuditInfoLink = _featureFlagsService.getFlagState(Features.FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO); this.initializeProperties(); this.showVidStatus = true; if (jobData) { @@ -48,6 +54,8 @@ export class AuditInfoModalComponent { this.openAuditInfoModal(jobData); _iframeService.addClassOpenModal(this.parentElementClassName); this.serviceModelName = jobData.serviceModelName ? jobData.serviceModelName : ''; + this.serviceModelId = jobData.serviceModelId; + this.jobId = jobData.jobId; this.auditInfoModal.show(); } else { _iframeService.removeClassCloseModal(this.parentElementClassName); @@ -57,6 +65,7 @@ export class AuditInfoModalComponent { AuditInfoModalComponent.openInstanceAuditInfoModal.subscribe(({instanceId , type , model, instance}) => { this.showVidStatus = false; + this.showMoreAuditInfoLink = false; this.initializeProperties(); this.setModalTitles(type); this.serviceModelName = AuditInfoModalComponentService.getInstanceModelName(model); @@ -118,5 +127,8 @@ export class AuditInfoModalComponent { onNavigate(){ window.open("http://ecompguide.web.att.com:8000/#ecomp_ug/c_ecomp_ops_vid.htmll#r_ecomp_ops_vid_bbglossary", "_blank"); } + + readOnlyRetryUrl = (): string => + `../../serviceModels.htm?more#/servicePlanning/RETRY?serviceModelId=${this.serviceModelId}&jobId=${this.jobId}` } diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html new file mode 100644 index 000000000..a50522a67 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html @@ -0,0 +1,16 @@ +<div> + <button class="custom-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}" + [disabled]="disabled || show_spinner" + [attr.data-tests-id]="testId"> + <custom-icon + *ngIf="icon_name" + [name]="icon_name" + [mode]="icon_mode" + [size]="'medium'" + > + </custom-icon> + {{text}} + </button> + <custom-icon *ngIf="show_spinner" name="spinner" [size]="'medium'" class="sdc-button__spinner" + [ngClass]="{left: spinner_position === placement.right}"></custom-icon> +</div> diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss new file mode 100644 index 000000000..89f90d44d --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss @@ -0,0 +1,273 @@ +.custom-button { + order: 1; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + flex-direction: row; + outline: none; + border-radius: 2px; + padding: 0 12px; + height: 36px; + line-height: 36px; + width: 120px; + min-width: 90px; + cursor: pointer; + text-align: center; + text-transform: uppercase; + font-family: OpenSans-Regular, Arial, sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + /*** Sizes ***/ + /*** Sizes ***/ + /*** Buttons with icons ***/ +} + +.custom-button:disabled { + cursor: default; +} + +.custom-button.sdc-button__primary { + border: 1px solid transparent; + background-color: #009fdb; + color: #ffffff; +} + +.custom-button.sdc-button__primary:not(:disabled):hover, .custom-button.sdc-button__primary:not(:disabled):active { + background-color: #1eb9f3; +} + +.custom-button.sdc-button__primary:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #1eb9f3; + box-shadow: 0px 0px 0px 1px #1eb9f3; +} + +.custom-button.sdc-button__primary:disabled { + background: #9dd9ef; +} + +.custom-button.sdc-button__secondary { + border: 1px solid #009fdb; + background-color: transparent; + color: #009fdb; +} + +.custom-button.sdc-button__secondary:not(:disabled):hover, .custom-button.sdc-button__secondary:not(:disabled):active { + background-color: #1eb9f3; + color: #ffffff; +} + +.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active) { + color: #1eb9f3; + box-shadow: inset 0px 0px 0px 0px #0568ae, 0px 0px 0px 1px #009fdb; +} + +.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active):hover { + color: #ffffff; +} + +.custom-button.sdc-button__secondary:disabled { + color: #9dd9ef; + border-color: #9dd9ef; +} + +.custom-button.sdc-button__link { + background-color: transparent; + color: #009fdb; + fill: #009fdb; + border: none; +} + +.custom-button.sdc-button__link:not(:disabled):hover, .custom-button.sdc-button__link:not(:disabled):active { + color: #1eb9f3; +} + +.custom-button.sdc-button__link:not(:disabled):focus:not(:active) { + border: 1px solid #0568ae; + color: #1eb9f3; +} + +.custom-button.sdc-button__link:disabled { + color: #9dd9ef; +} + +.custom-button.sdc-button__success { + border: 1px solid transparent; + background-color: #4ca90c; + color: #ffffff; +} + +.custom-button.sdc-button__success:not(:disabled):hover, .custom-button.sdc-button__success:not(:disabled):active { + background-color: #57c00e; +} + +.custom-button.sdc-button__success:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #57c00e; + box-shadow: 0px 0px 0px 1px #57c00e; +} + +.custom-button.sdc-button__success:disabled { + background: #a5d485; +} + +.custom-button.sdc-button__error, .custom-button.sdc-button__alert { + border: 1px solid transparent; + background-color: #cf2a2a; + color: #ffffff; +} + +.custom-button.sdc-button__error:not(:disabled):hover, .custom-button.sdc-button__error:not(:disabled):active, .custom-button.sdc-button__alert:not(:disabled):hover, .custom-button.sdc-button__alert:not(:disabled):active { + background-color: #ed4141; +} + +.custom-button.sdc-button__error:not(:disabled):focus:not(:active), .custom-button.sdc-button__alert:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #ed4141; + box-shadow: 0px 0px 0px 1px #ed4141; +} + +.custom-button.sdc-button__error:disabled, .custom-button.sdc-button__alert:disabled { + background: #f4adad; +} + +.custom-button.sdc-button__warning { + border: 1px solid transparent; + background-color: #ffb81c; + color: #ffffff; +} + +.custom-button.sdc-button__warning:not(:disabled):hover, .custom-button.sdc-button__warning:not(:disabled):active { + background-color: #f6c632; +} + +.custom-button.sdc-button__warning:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #f6c632; + box-shadow: 0px 0px 0px 1px #f6c632; +} + +.custom-button.sdc-button__warning:disabled { + background: #ffdb8d; +} + +.custom-button.sdc-button__info { + border: 1px solid transparent; + background-color: #009fdb; + color: #ffffff; +} + +.custom-button.sdc-button__info:not(:disabled):hover, .custom-button.sdc-button__info:not(:disabled):active { + background-color: #1eb9f3; +} + +.custom-button.sdc-button__info:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #1eb9f3; + box-shadow: 0px 0px 0px 1px #1eb9f3; +} + +.custom-button.sdc-button__info:disabled { + background: #9dd9ef; +} + +.custom-button.sdc-button__file-opener input[type=file] { + height: 36px; + opacity: 0; + position: absolute; + cursor: pointer; +} + +.custom-button.btn-xx-large { + width: 350px; +} + +.custom-button.btn-xx-large input[type=file] { + width: 350px; +} + +.custom-button.btn-x-large { + width: 250px; +} + +.custom-button.btn-x-large input[type=file] { + width: 250px; +} + +.custom-button.btn-large { + width: 180px; +} + +.custom-button.btn-large input[type=file] { + width: 180px; +} + +.custom-button.btn-medium { + width: 140px; +} + +.custom-button.btn-medium input[type=file] { + width: 140px; +} + +.custom-button.btn-small { + width: 110px; +} + +.custom-button.btn-small input[type=file] { + width: 110px; +} + +.custom-button.btn-x-small { + width: 90px; +} + +.custom-button.btn-x-small input[type=file] { + width: 90px; +} + +.custom-button.btn-default { + width: auto; +} + +.custom-button.btn-default input[type=file] { + width: auto; +} + +.custom-button.sdc-icon-right { + flex-direction: row-reverse; +} + +.custom-button.sdc-icon-right .svg-icon { + margin-left: 15px; +} + +.custom-button.sdc-icon-left { + flex-direction: row; +} + +.custom-button.sdc-icon-left .svg-icon { + margin-right: 15px; +} + +.custom-button svg { + display: inline-block; + vertical-align: middle; +} + +.sdc-button__wrapper { + display: inline-flex; +} + +.sdc-button__spinner { + padding-top: 6px; + margin: 0 2px; +} + +.sdc-button__spinner.left { + order: 2; +} diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts new file mode 100644 index 000000000..61fa02832 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts @@ -0,0 +1,65 @@ +import {Component, HostBinding, Input, OnInit} from "@angular/core"; +import {IButtonComponent} from "../customModal/models/modal-button.model"; +import {ButtonType} from "../customModal/models/button.type"; +import {Mode} from "./models/mode.model"; +import {Placement} from "../customModal/models/modal.placement"; + + +@Component({ + selector: "sdc-button", + templateUrl: './custom-button.component.html', + styleUrls: ['./custom-button.component.scss'] + +}) + +export class CustomButtonComponent implements OnInit, IButtonComponent { + @Input() public text: string; + @Input() public disabled: boolean; + @Input() public type: ButtonType; + @Input() public icon_mode: Mode; + @Input() public size: string; + @Input() public preventDoubleClick: boolean; + @Input() public icon_name: string; + @Input() public icon_position: string; + @Input() public show_spinner: boolean; + @Input() public spinner_position: Placement; + @Input() public testId: string; + + public placement = Placement; + private lastClick: Date; + public iconPositionClass: string; + + @HostBinding('class.sdc-button__wrapper') true; + + constructor() { + this.type = ButtonType.primary; + this.size = "default"; + this.disabled = false; + } + + public ngOnInit(): void { + this.iconPositionClass = this.icon_position ? 'sdc-icon-' + this.icon_position : ''; + } + + public onClick = (e): void => { + const now: Date = new Date(); + if (this.preventDoubleClick && this.lastClick && (now.getTime() - this.lastClick.getTime()) <= 500) { + e.preventDefault(); + e.stopPropagation(); + } + this.lastClick = now; + } + + public disableButton = () => { + if (!this.disabled) { + this.disabled = true; + } + } + + public enableButton = () => { + if (this.disabled) { + this.disabled = false; + } + } + +} diff --git a/vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts b/vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts new file mode 100644 index 000000000..c8a7ddef3 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts @@ -0,0 +1,10 @@ +export enum Mode { + primary = 'primary', + primary2 = 'primary2', + secondary = 'secondary', + success = 'success', + error = 'error', + warning = 'warning', + info = 'info', + white = 'white' +} diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html new file mode 100644 index 000000000..0ac56d2d2 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html @@ -0,0 +1,2 @@ +<div [ngClass]="classes" [attr.disabled]="disabled || undefined" [innerHtml]="svgIconContentSafeHtml" + [attr.data-tests-id]="testId"></div> diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss new file mode 100644 index 000000000..54b375702 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss @@ -0,0 +1,297 @@ +@import 'node_modules/onap-ui-common/lib/scss/variables.scss'; + +:host { + display: inline-flex; +} + +@mixin color-icon($primary-color) { + color: $primary-color; + fill: $primary-color; +} + +@mixin color-icon-hover($secondary-color) { + &.clickable { + cursor: pointer; + &:not([disabled]):hover, &:active, &:focus { + @include color-icon($secondary-color); + } + } +} + +@mixin color-icon-label($primary-color) { + @include color-icon($primary-color); + + .custom-icon { + @include color-icon($primary-color); + } +} + +@mixin color-icon-label-hover($secondary-color) { + &.clickable { + &:not([disabled]):hover, &:active, &:focus { + @include color-icon-label($secondary-color); + } + } +} + +/deep/ .custom-icon { + display: inline-flex; + width: 24px; + height: 24px; + box-sizing: content-box; + + & > svg { + width: 100%; + height: 100%; + } + + &[disabled] { + opacity: 0.7; + } + + &.mode-primary { + @include color-icon($blue); + @include color-icon-hover($light-blue); + } + + &.mode-primary2 { + @include color-icon($dark-gray); + @include color-icon-hover($light-blue); + } + + &.mode-secondary { + @include color-icon($gray); + @include color-icon-hover($dark-gray); + } + + &.mode-success { + @include color-icon($green); + } + + &.mode-error { + @include color-icon($red); + } + + &.mode-warning { + @include color-icon($yellow); + } + + &.mode-info { + @include color-icon($text-black); + @include color-icon-hover($dark-blue); + } + + &.mode-white { + @include color-icon($white); + @include color-icon-hover($light-gray); + } + + &.size-x_small { + width: 8px; + height: 8px; + } + + &.size-small { + width: 12px; + height: 12px; + } + + &.size-medium { + width: 16px; + height: 16px; + } + + &.size-large { + width: 24px; + height: 24px; + } + + &.size-x_large { + width: 36px; + height: 36px; + } + + &.size-x_x_large { + width: 48px; + height: 48px; + } + + &.bg-type-circle { + border-radius: 50%; + padding: 6px; + } + + &.bg-type-rectangle { + padding: 6px; + } + + &.bg-color-purple { + background-color: $purple; + } + + &.bg-color-light-blue { + background-color: $light-blue; + } + + &.bg-color-green { + background-color: $green; + } + + &.bg-color-red { + background-color: $red; + } + + &.bg-color-yellow { + background-color: $yellow; + } + + &.bg-color-blue { + background-color: $blue; + } + + &.bg-color-lightBlue { + background-color: $light-blue; + } + + &.bg-color-darkBlue { + background-color: $dark-blue; + } + + &.bg-color-darkBlue2 { + background-color: $dark-blue2; + } + + &.bg-color-disabledBlue { + background-color: $disabled-blue; + } + + &.bg-color-gray { + background-color: $gray; + } + + &.bg-color-white { + background-color: $white; + } + + &.bg-color-transparent { + background-color:transparent; + } + &.bg-color-silver { + background-color: $light-silver; + } +} + +.custom-icon-wrapper { + display: inline-flex; + justify-content: center; + align-items: center; + + &.custom-icon-label { + } + + &.custom-icon { + } + + &[disabled] { + opacity: 0.7; + } + + &.label-placement-bottom { + flex-direction: column; + .custom-icon-label { + margin-top: 0.25em; + } + } + + &.label-placement-right { + .custom-icon-label { + margin-left: 0.25em; + } + } + + &.label-placement-top { + flex-direction: column-reverse; + .custom-icon-label { + margin-bottom: 0.25em; + } + } + + &.label-placement-left { + flex-direction: row-reverse; + .custom-icon-label { + margin-right: 0.25em; + } + } + + &.mode-primary { + @include color-icon-label($blue); + @include color-icon-label-hover($light-blue); + } + + &.mode-secondary { + @include color-icon-label($gray); + @include color-icon-label-hover($light-blue); + } + + &.mode-success { + @include color-icon-label($green); + } + + &.mode-error { + @include color-icon-label($red); + } + + &.mode-warning { + @include color-icon-label($yellow); + } + + &.mode-info { + @include color-icon-label($text-black); + @include color-icon-label-hover($light-blue); + } + + &.size-x_small { + font-size: 8px; + line-height: 10px; + + .custom-icon { + @extend .custom-icon.size-x_small; + } + } + + &.size-small { + font-size: 12px; + line-height: 14px; + + .custom-icon { + @extend .custom-icon.size-small; + } + } + + &.size-medium { + font-size: 16px; + line-height: 20px; + + .custom-icon { + @extend .custom-icon.size-medium; + } + } + + &.size-large { + font-size: 24px; + line-height: 28px; + + .custom-icon { + @extend .custom-icon.size-large; + } + } + + &.size-x_large { + font-size: 34px; + line-height: 40px; + + .custom-icon { + @extend .custom-icon.size-x_large; + } + } +} diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts new file mode 100644 index 000000000..c59bc5945 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts @@ -0,0 +1,85 @@ +import {Component, Input, OnChanges, SimpleChanges} from "@angular/core"; +import {Mode} from "../customButton/models/mode.model"; +import {Size} from "./models/icon-size.model"; +import {BackgroundShape} from "./models/background-shape.model"; +import {BackgroundColor} from "./models/background-color.model"; +import {DomSanitizer, SafeHtml} from "@angular/platform-browser"; +import {iconsMap} from 'onap-ui-common'; + +@Component({ + selector: 'custom-icon', + templateUrl: './custom-icon.component.html', + styleUrls: ['./custom-icon.component.scss'], +}) +export class SvgIconComponent implements OnChanges { + + @Input() public name: string; + @Input() public type: string; + @Input() public mode: Mode; + @Input() public size: Size; + @Input() public backgroundShape: BackgroundShape; + @Input() public backgroundColor: BackgroundColor; + @Input() public disabled: boolean; + @Input() public clickable: boolean; + @Input() public className: any; + @Input() public testId: string; + + public svgIconContent: string; + public svgIconContentSafeHtml: SafeHtml; + public svgIconCustomClassName: string; + public classes: string; + + constructor(protected domSanitizer: DomSanitizer) { + this.size = Size.medium; + this.disabled = false; + this.type = this.type || "common"; + } + + static Icons(): { [key: string]: string } { + return iconsMap; + } + + public ngOnChanges(changes: SimpleChanges) { + this.updateSvgIconByName(); + this.buildClasses(); + } + + protected updateSvgIconByName() { + this.svgIconContent = iconsMap[this.type][this.name] || null; + if (this.svgIconContent) { + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.svgIconContent); + this.svgIconCustomClassName = '__' + this.name.replace(/\s+/g, '_'); + } else { + this.svgIconContentSafeHtml = null; + this.svgIconCustomClassName = 'missing'; + } + } + + private buildClasses = (): void => { + const _classes = ['svg-icon']; + if (this.mode) { + _classes.push('mode-' + this.mode); + } + if (this.size) { + _classes.push('size-' + this.size); + } + if (this.clickable) { + !this.disabled && _classes.push('clickable'); + } + if (this.svgIconCustomClassName) { + _classes.push(this.svgIconCustomClassName); + } + if (this.className) { + _classes.push(this.className); + } + if (this.backgroundShape) { + _classes.push('bg-type-' + this.backgroundShape); + } + if (this.backgroundShape && this.backgroundColor) { + _classes.push('bg-color-' + this.backgroundColor); + } else if (this.backgroundShape && !this.backgroundColor) { + _classes.push('bg-color-primary'); + } + this.classes = _classes.join(" "); + } +} diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts new file mode 100644 index 000000000..324f51ba4 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts @@ -0,0 +1,15 @@ +export enum BackgroundColor { + gray = 'gray', + purple = 'purple', + blue = 'blue', + lightBlue = 'light-blue', + darkBlue = 'dark-blue', + darkBlue2 = 'dark-blue2', + disabledBlue = 'disabled-blue', + white = 'white', + transparent = 'transparent', + green = 'green', + red = 'red', + yellow = 'yellow', + silver ='silver' +} diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts new file mode 100644 index 000000000..924ce3da1 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts @@ -0,0 +1,4 @@ +export enum BackgroundShape { + circle = 'circle', + rectangle = 'rectangle' +} diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts new file mode 100644 index 000000000..a6cd9f537 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts @@ -0,0 +1,7 @@ +export enum Size { + x_large = 'x_large', + large = 'large', + medium = 'medium', + small = 'small', + x_small = 'x_small' +} diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html new file mode 100644 index 000000000..999d5d3f9 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html @@ -0,0 +1,15 @@ +<div> + <div class="custom-loader-wrapper" *ngIf="!global" [attr.data-tests-id]="testId"> + <div class="custom-loader-background" *ngIf="active" + [style.top]="offset.top" [style.left]="offset.left" [style.width]="offset.width" + [style.height]="offset.height"> + <div class="custom-loader {{ size }}" *ngIf="active"></div> + </div> + <ng-content></ng-content> + </div> + <div *ngIf="global && active" [attr.data-tests-id]="testId"> + <div class="custom-loader-global-wrapper custom-loader-background"> + <div class="custom-loader {{ size }}"></div> + </div> + </div> +</div> diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss new file mode 100644 index 000000000..7572c6e11 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss @@ -0,0 +1,222 @@ +.custom-loader-background { + background-color: #000000; + position: absolute; + z-index: 9999; + opacity: 0.5; + display: flex; + justify-content: center; + align-items: center; } + +.sdc-loader-wrapper-absolute { + position: absolute; + top: 0; } + +.custom-loader { + z-index: 10002; } + +.custom-loader-global-wrapper { + position: fixed; + width: 100%; + height: 100%; } + +.loader-fixed { + display: block; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; } +@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; } } + +.custom-loader { + height: 63px; + width: 63px; + position: absolute; } + +.custom-loader.small { + transform: scale(0.26); } + +.custom-loader.medium { + transform: scale(0.5); } + +.custom-loader.large { + transform: scale(1); } + +.custom-loader::before { + background-color: #eaeaea; + border-radius: 50%; + box-shadow: 21px 21px 0px 0px #eaeaea, 0px 42px 0px 0px #eaeaea, -21px 21px 0px 0px #eaeaea; + content: ''; + display: block; + height: 21px; + width: 21px; + position: absolute; + left: 50%; + margin-left: -10.5px; } + +.custom-loader::after { + border-radius: 50%; + content: ''; + display: block; + position: absolute; + height: 21px; + width: 21px; + animation: dot-move-2 4.5s infinite ease-in; } + +@keyframes dot-move { + 0% { + background-color: #1eb9f3; + left: 21px; + top: 0; } + 25% { + background-color: #ffb81c; + left: 42px; + top: 21px; } + 50% { + background-color: #caa2dd; + left: 21px; + top: 42px; } + 75% { + background-color: #f6c632; + left: 0; + top: 21px; } + 100% { + background-color: #1eb9f3; + left: 21px; + top: 0; } } + +@keyframes dot-move-2 { + 0% { + background-color: #1eb9f3; + left: 21px; + top: 0; } + 6.25% { + background-color: #1eb9f3; + left: 42px; + top: 21px; } + 12.5% { + background-color: #1eb9f3; + left: 21px; + top: 42px; } + 18.75% { + background-color: #1eb9f3; + left: 0; + top: 21px; } + 25% { + background-color: #ffb81c; + left: 21px; + top: 0; } + 31.25% { + background-color: #ffb81c; + left: 42px; + top: 21px; } + 37.5% { + background-color: #ffb81c; + left: 21px; + top: 42px; } + 43.75% { + background-color: #ffb81c; + left: 0; + top: 21px; } + 50% { + background-color: #caa2dd; + left: 21px; + top: 0; } + 56.25% { + background-color: #caa2dd; + left: 42px; + top: 21px; } + 62.5% { + background-color: #caa2dd; + left: 21px; + top: 42px; } + 68.75% { + background-color: #caa2dd; + left: 0; + top: 21px; } + 75% { + background-color: #f6c632; + left: 21px; + top: 0; } + 81.25% { + background-color: #f6c632; + left: 42px; + top: 21px; } + 87.5% { + background-color: #f6c632; + left: 21px; + top: 42px; } + 93.75% { + background-color: #f6c632; + left: 0; + top: 21px; } + 100% { + background-color: #1eb9f3; + left: 21px; + top: 0; } } diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts new file mode 100644 index 000000000..98bcce1a1 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts @@ -0,0 +1,76 @@ +import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewContainerRef} from "@angular/core"; +import {LoaderSize} from "./models/loader-size.model"; +import {LoaderService} from "./custom-loader.service"; + +@Component({ + selector: "custom-loader", + templateUrl: './custom-loader.component.html', + styleUrls: ['./custom-loader.component.scss'] + +}) + +export class LoaderComponent implements OnInit, OnDestroy { + @Input() active: number; + @Input() size?: LoaderSize; + @Input() global?: boolean; + @Input() name?: string; + @Input() testId: string; + @Input() relative: boolean; + @Output() activeChange: EventEmitter<number> = new EventEmitter<number>(); + private offset : { + top: string; + left: string; + width: string; + height: string; + }; + + constructor(private loaderService: LoaderService, private viewContainerRef: ViewContainerRef) { + this.active = 0; + this.size = LoaderSize.large; + this.global = false; + } + + public ngOnInit(): void { + if (this.name !== undefined) { + this.loaderService.register(this.name, this); + } + this.setLoaderPlace(); + } + + public ngOnDestroy(): void { + if (this.name !== undefined) { + this.loaderService.unregister(this.name); + } + } + + public activate() { + this.active++; + this.activeChange.emit(this.active); + } + + public deactivate() { + if (this.active > 0) { + this.active--; + this.activeChange.emit(this.active); + } + } + public setLoaderPlace = () => { + if (this.relative === true) { + let parentElement = this.viewContainerRef.element.nativeElement.parentElement; + this.offset = { + 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 + }; + } else { + this.offset = { + left: '0px', + top: '0px', + width: '100%', + height: '100%' + } + } + } + +} diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts new file mode 100644 index 000000000..398eac233 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts @@ -0,0 +1,34 @@ +import {Injectable} from "@angular/core"; +import {LoaderComponent} from "./custom-loader.component"; + +@Injectable() +export class LoaderService { + + private mainLoaderName = 'general'; + public registeredLoaders = {}; + + register(name: string, loader: LoaderComponent) { + if (!this.registeredLoaders[name]) { + this.registeredLoaders[name] = loader; + } + } + + unregister(name: string) { + if (this.registeredLoaders[name]) { + delete this.registeredLoaders[name]; + } + } + + activate(name: string = this.mainLoaderName) { + if (this.registeredLoaders[name]) { + this.registeredLoaders[name].activate(); + } + } + + deactivate(name: string = this.mainLoaderName) { + if (this.registeredLoaders[name]) { + this.registeredLoaders[name].deactivate(); + } + } + +} diff --git a/vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts b/vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts new file mode 100644 index 000000000..d5400efb5 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts @@ -0,0 +1,5 @@ +export enum LoaderSize { + large = 'large', + medium = 'medium', + small = 'small', +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html new file mode 100644 index 000000000..a50522a67 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html @@ -0,0 +1,16 @@ +<div> + <button class="custom-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}" + [disabled]="disabled || show_spinner" + [attr.data-tests-id]="testId"> + <custom-icon + *ngIf="icon_name" + [name]="icon_name" + [mode]="icon_mode" + [size]="'medium'" + > + </custom-icon> + {{text}} + </button> + <custom-icon *ngIf="show_spinner" name="spinner" [size]="'medium'" class="sdc-button__spinner" + [ngClass]="{left: spinner_position === placement.right}"></custom-icon> +</div> diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss new file mode 100644 index 000000000..89f90d44d --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss @@ -0,0 +1,273 @@ +.custom-button { + order: 1; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + flex-direction: row; + outline: none; + border-radius: 2px; + padding: 0 12px; + height: 36px; + line-height: 36px; + width: 120px; + min-width: 90px; + cursor: pointer; + text-align: center; + text-transform: uppercase; + font-family: OpenSans-Regular, Arial, sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + /*** Sizes ***/ + /*** Sizes ***/ + /*** Buttons with icons ***/ +} + +.custom-button:disabled { + cursor: default; +} + +.custom-button.sdc-button__primary { + border: 1px solid transparent; + background-color: #009fdb; + color: #ffffff; +} + +.custom-button.sdc-button__primary:not(:disabled):hover, .custom-button.sdc-button__primary:not(:disabled):active { + background-color: #1eb9f3; +} + +.custom-button.sdc-button__primary:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #1eb9f3; + box-shadow: 0px 0px 0px 1px #1eb9f3; +} + +.custom-button.sdc-button__primary:disabled { + background: #9dd9ef; +} + +.custom-button.sdc-button__secondary { + border: 1px solid #009fdb; + background-color: transparent; + color: #009fdb; +} + +.custom-button.sdc-button__secondary:not(:disabled):hover, .custom-button.sdc-button__secondary:not(:disabled):active { + background-color: #1eb9f3; + color: #ffffff; +} + +.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active) { + color: #1eb9f3; + box-shadow: inset 0px 0px 0px 0px #0568ae, 0px 0px 0px 1px #009fdb; +} + +.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active):hover { + color: #ffffff; +} + +.custom-button.sdc-button__secondary:disabled { + color: #9dd9ef; + border-color: #9dd9ef; +} + +.custom-button.sdc-button__link { + background-color: transparent; + color: #009fdb; + fill: #009fdb; + border: none; +} + +.custom-button.sdc-button__link:not(:disabled):hover, .custom-button.sdc-button__link:not(:disabled):active { + color: #1eb9f3; +} + +.custom-button.sdc-button__link:not(:disabled):focus:not(:active) { + border: 1px solid #0568ae; + color: #1eb9f3; +} + +.custom-button.sdc-button__link:disabled { + color: #9dd9ef; +} + +.custom-button.sdc-button__success { + border: 1px solid transparent; + background-color: #4ca90c; + color: #ffffff; +} + +.custom-button.sdc-button__success:not(:disabled):hover, .custom-button.sdc-button__success:not(:disabled):active { + background-color: #57c00e; +} + +.custom-button.sdc-button__success:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #57c00e; + box-shadow: 0px 0px 0px 1px #57c00e; +} + +.custom-button.sdc-button__success:disabled { + background: #a5d485; +} + +.custom-button.sdc-button__error, .custom-button.sdc-button__alert { + border: 1px solid transparent; + background-color: #cf2a2a; + color: #ffffff; +} + +.custom-button.sdc-button__error:not(:disabled):hover, .custom-button.sdc-button__error:not(:disabled):active, .custom-button.sdc-button__alert:not(:disabled):hover, .custom-button.sdc-button__alert:not(:disabled):active { + background-color: #ed4141; +} + +.custom-button.sdc-button__error:not(:disabled):focus:not(:active), .custom-button.sdc-button__alert:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #ed4141; + box-shadow: 0px 0px 0px 1px #ed4141; +} + +.custom-button.sdc-button__error:disabled, .custom-button.sdc-button__alert:disabled { + background: #f4adad; +} + +.custom-button.sdc-button__warning { + border: 1px solid transparent; + background-color: #ffb81c; + color: #ffffff; +} + +.custom-button.sdc-button__warning:not(:disabled):hover, .custom-button.sdc-button__warning:not(:disabled):active { + background-color: #f6c632; +} + +.custom-button.sdc-button__warning:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #f6c632; + box-shadow: 0px 0px 0px 1px #f6c632; +} + +.custom-button.sdc-button__warning:disabled { + background: #ffdb8d; +} + +.custom-button.sdc-button__info { + border: 1px solid transparent; + background-color: #009fdb; + color: #ffffff; +} + +.custom-button.sdc-button__info:not(:disabled):hover, .custom-button.sdc-button__info:not(:disabled):active { + background-color: #1eb9f3; +} + +.custom-button.sdc-button__info:not(:disabled):focus:not(:active) { + border: 1px solid #ffffff; + background-color: #1eb9f3; + box-shadow: 0px 0px 0px 1px #1eb9f3; +} + +.custom-button.sdc-button__info:disabled { + background: #9dd9ef; +} + +.custom-button.sdc-button__file-opener input[type=file] { + height: 36px; + opacity: 0; + position: absolute; + cursor: pointer; +} + +.custom-button.btn-xx-large { + width: 350px; +} + +.custom-button.btn-xx-large input[type=file] { + width: 350px; +} + +.custom-button.btn-x-large { + width: 250px; +} + +.custom-button.btn-x-large input[type=file] { + width: 250px; +} + +.custom-button.btn-large { + width: 180px; +} + +.custom-button.btn-large input[type=file] { + width: 180px; +} + +.custom-button.btn-medium { + width: 140px; +} + +.custom-button.btn-medium input[type=file] { + width: 140px; +} + +.custom-button.btn-small { + width: 110px; +} + +.custom-button.btn-small input[type=file] { + width: 110px; +} + +.custom-button.btn-x-small { + width: 90px; +} + +.custom-button.btn-x-small input[type=file] { + width: 90px; +} + +.custom-button.btn-default { + width: auto; +} + +.custom-button.btn-default input[type=file] { + width: auto; +} + +.custom-button.sdc-icon-right { + flex-direction: row-reverse; +} + +.custom-button.sdc-icon-right .svg-icon { + margin-left: 15px; +} + +.custom-button.sdc-icon-left { + flex-direction: row; +} + +.custom-button.sdc-icon-left .svg-icon { + margin-right: 15px; +} + +.custom-button svg { + display: inline-block; + vertical-align: middle; +} + +.sdc-button__wrapper { + display: inline-flex; +} + +.sdc-button__spinner { + padding-top: 6px; + margin: 0 2px; +} + +.sdc-button__spinner.left { + order: 2; +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts new file mode 100644 index 000000000..d93c67851 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts @@ -0,0 +1,28 @@ +import {Component, EventEmitter, HostListener, Input, Output} from "@angular/core"; +import {CustomButtonComponent} from "../../../customButton/custom-button.component"; + +@Component({ + selector: "custom-modal-button", + templateUrl: './modal-button.component.html', + styleUrls: ['./modal-button.component.scss'] +}) +export class CustomModalButtonComponent extends CustomButtonComponent { + + @Input() public id?: string; + @Input() public callback: Function; + @Input() public closeModal: boolean; + @Output() closeModalEvent: EventEmitter<any> = new EventEmitter<any>(); + @HostListener('click') invokeCallback = (): void => { + if (this.callback) { + this.callback(); + } + if (this.closeModal) { + this.closeModalEvent.emit(); + } + } + + constructor() { + super(); + this.closeModal = false; + } +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts b/vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts new file mode 100644 index 000000000..9528f778d --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts @@ -0,0 +1,36 @@ +import {Component, ComponentRef, Input} from "@angular/core"; +import {ModalComponent} from "../../modal.component"; +import {CustomButtonComponent} from "../../../customButton/custom-button.component"; +import {RippleAnimationAction} from "../../directives/ripple-click.animation.directive"; + + +@Component({ + selector: "sdc-modal-close-button", + template: ` + <div class="sdc-modal__close-button" + customRippleClickAnimation + [ngClass]="disabled ? 'disabled' : ''" + [rippleOnAction]="!disabled && rippleAnimationAction" + [attr.data-tests-id]="testId" + (click)="!disabled && closeModal('close')" + > + <custom-icon name="close" [mode]="disabled? 'secondary' : 'info'" size="small"></custom-icon> + </div> + ` +}) +export class ModalCloseButtonComponent extends CustomButtonComponent { + + @Input() testId: string; + @Input() disabled: boolean; + @Input() modalInstanceRef: ComponentRef<ModalComponent>; + + public rippleAnimationAction: RippleAnimationAction = RippleAnimationAction.MOUSE_ENTER; + + constructor() { + super(); + } + + public closeModal = (btnName: string): void => { + this.modalInstanceRef.instance.closeModal(btnName); + } +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts b/vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts new file mode 100644 index 000000000..d343d5dc2 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts @@ -0,0 +1,47 @@ +import { Directive, Input, HostBinding, HostListener } from "@angular/core"; + +export enum RippleAnimationAction { + CLICK = 0, + MOUSE_ENTER = 1 +} + +@Directive({ + selector: `[customRippleClickAnimation]` +}) +export class CustomRippleClickAnimationDirective { + private animated: boolean; + + @Input() rippleClickDisabled: boolean; + @Input() rippleOnAction:RippleAnimationAction = RippleAnimationAction.CLICK; + + @HostBinding('class.sdc-ripple-click__animated') animationClass: string; + + @HostListener('click') onClick() { + if(this.rippleOnAction === RippleAnimationAction.CLICK){ + this.animateStart(); + } + } + + @HostListener('mouseenter') onMouseEnter() { + //console.log("Mouseenter!", this.rippleOnAction); + if(this.rippleOnAction === RippleAnimationAction.MOUSE_ENTER){ + this.animateStart(); + } + } + + private animateStart():void{ + if (!this.rippleClickDisabled) { + this.animated = true; + this.animationClass = 'sdc-ripple-click__animated'; + } + } + @HostListener('animationend') onAnimationComplete() { + this.animated = false; + this.animationClass = ''; + } + + constructor() { + this.rippleClickDisabled = false; + this.animated = false; + } +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/modal.component.html b/vid-webpack-master/src/app/shared/components/customModal/modal.component.html new file mode 100644 index 000000000..059eb8a3f --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/modal.component.html @@ -0,0 +1,46 @@ +<div> + <div class="modal-background" [@toggleBackground]="modalVisible" ></div> + <div class="sdc-modal {{size}}"> + <div class="sdc-modal__wrapper sdc-modal-type-{{type}}" [@toggleModal]="modalVisible" (@toggleModal.done)="modalToggled($event)"> + + <div class="sdc-modal__header sdc-{{type}}__header"> + <div class="sdc-modal__icon" *ngIf="type!='custom'" [innerHtml]="svgIconContentSafeHtml"></div> + + <div *ngIf="title" class="title" > + {{ title }} + <custom-icon + *ngIf="titleIcon" + [name]="titleIcon.iconName" + [mode]="titleIcon.iconMode" + [size]="titleIcon.iconSize"> + </custom-icon> + </div> + <sdc-modal-close-button #modalCloseButton [testId]="'close' | calculateTestId : testId" [modalInstanceRef]="instanceRef"></sdc-modal-close-button> + </div> + + <div class="sdc-modal__content"> + <div *ngIf="message" [innerHtml]="message"></div> + <div #dynamicContentContainer></div> + <div class="disabled-modal" *ngIf="isDisabled"></div> + </div> + + <div class="sdc-modal__footer"> + <custom-modal-button *ngFor="let button of buttons" + [text]="button.text" + [type]="button.type || 'primary'" + [disabled]="button.disabled" + [size] = "button.size ? button.size : 'default'" + [closeModal]="button.closeModal" + [spinner_position]="button.spinner_position" + [show_spinner]="button.show_spinner" + [callback]="button.callback" + [testId]="'button-' + button.text | calculateTestId : testId" + (closeModalEvent)="closeModal(button.text)" + > + </custom-modal-button> + </div> + + </div> + </div> +</div> + diff --git a/vid-webpack-master/src/app/shared/components/customModal/modal.component.ts b/vid-webpack-master/src/app/shared/components/customModal/modal.component.ts new file mode 100644 index 000000000..eb001c068 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/modal.component.ts @@ -0,0 +1,166 @@ +import { + Component, + ComponentRef, + EventEmitter, + Input, + OnInit, + Output, + Renderer, + ViewChild, + ViewContainerRef +} from "@angular/core"; +import {animate, style, transition, trigger} from "@angular/animations"; +import {TitleIconDetails} from "./models/modal.model"; +import {ModalType} from "./models/modal.type"; +import {DomSanitizer, SafeHtml} from "@angular/platform-browser"; +import {ModalCloseButtonComponent} from "./components/modalCloseButton/modal-close-button.component"; +import {CustomModalButtonComponent} from "./components/modalButton/modal-button.component"; + +@Component({ + selector: 'sdc-modal', + templateUrl: './modal.component.html', + animations: [ + trigger('toggleBackground', [ + transition('* => 1', [style({ opacity: 0 }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), + transition('1 => *', [animate('.35s cubic-bezier(0.23, 1, 0.32, 1)', style({ opacity: 0 }))]) + ]), + trigger('toggleModal', [ + transition('* => 1', [style({ opacity: 0, transform: 'translateY(-80px)' }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), + transition('1 => *', [style({ opacity: 1, transform: 'translateY(0px)' }), animate('.35s ease-in-out', style({ opacity: 0, transform: 'translateY(-80px)' }))]) + ]) + ] +}) + +export class ModalComponent implements OnInit { + + @Input() size: string; 'xl|l|md|sm|xsm'; + @Input() title: string; + @Input() titleIcon: TitleIconDetails; + @Input() message: string; + @Input() buttons: CustomModalButtonComponent[]; + @Input() type: ModalType; + @Input() testId: string; + @Input() isDisabled: boolean; + @Input() instanceRef: ComponentRef<ModalComponent>; // the component ref is injected to the component in order to destroy the componet from itself + + @Output() onClose : EventEmitter<string> = new EventEmitter<string>(); + + @ViewChild('modalCloseButton', {static: false}) + set refCloseButton(_modalCloseButton: ModalCloseButtonComponent) { + this.modalCloseButton = _modalCloseButton; + } + + modalVisible: boolean; + // Allows for custom component as body instead of simple message. + @ViewChild('dynamicContentContainer', { read: ViewContainerRef, static: true }) dynamicContentContainer: ViewContainerRef; + innerModalContent: ComponentRef<any>; + + public calculatedTestId: string; + public modalCloseButton: ModalCloseButtonComponent; + public svgIconContentSafeHtml: SafeHtml; + + + private infoSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"> + <defs><path fill="#000" id="info-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.101 4.9,22 11,22 C17.1,22 22,17.101 22,11 C22,4.9 17.1,0 11,0 M11,10 C10.4, + 10 10,10.4 10,11 L10,15 C10,15.601 10.4,16 11,16 C11.6,16 12,15.601 12,15 L12,11 C12,10.4 11.6,10 11,10 M10.2998,6.2998 C10.0998,6.4998 9.9998,6.6998 9.9998,6.9998 C9.9998,7.2998 10.0998,7.4998 10.2998,7.6998 C10.4998, + 7.9008 10.6998,7.9998 10.9998,7.9998 C11.2998,7.9998 11.4998,7.9008 11.6998,7.6998 C11.9008,7.4998 11.9998,7.2998 11.9998,6.9998 C11.9998,6.6998 11.9008,6.4998 11.6998,6.2998 C11.2998,5.9008 10.6998,5.9008 10.2998,6.2998"/> + </defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#info-a"/></g></svg>`; + private warningSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="alert-a" d="M20.5815,18.7997 C20.3815, + 18.9997 20.0815,19.0997 19.8815,19.0997 L2.8815,19.0997 C2.6815,19.0997 2.5815,19.0997 2.3815,18.9997 C1.8815,18.6997 1.7815,18.0997 1.9815,17.5997 L10.4815,3.4997 C10.5815,3.4007 10.6815,3.1997 10.7815,3.1997 C11.2815, + 2.9007 11.8815,3.0997 12.1815,3.4997 L20.6825,17.5997 C20.7815,17.6997 20.7815,17.9007 20.7815,18.0997 C20.8815,18.4007 20.6825,18.5997 20.5815,18.7997 M22.3815,16.5997 L13.9815,2.4007 C13.5815,1.6997 12.8815,1.1997 12.0815, + 0.9997 C11.2815,0.7997 10.4815,0.9007 9.7815,1.2997 C9.3815,1.4997 8.9815,1.9007 8.7815,2.2997 L0.3815,16.5997 C-0.4185,17.9997 0.0815,19.9007 1.4815,20.6997 C1.8815,20.9997 2.3815,21.0997 2.8815,21.0997 L19.8815, + 21.0997 C20.6825,21.0997 21.4815,20.7997 21.9815,20.1997 C22.5815,19.5997 22.8815,18.9007 22.8815,18.0997 C22.7815,17.5997 22.6825,16.9997 22.3815,16.5997 M11,7 C10.4,7 10,7.4 10,8 L10,12 C10,12.601 10.4,13 11,13 C11.6,13 12, + 12.601 12,12 L12,8 C12,7.4 11.6,7 11,7 M10.3,15.3 C10.1,15.499 10,15.699 10,15.999 C10,16.3 10.1,16.499 10.3,16.699 C10.5,16.9 10.7,16.999 11,16.999 C11.3,16.999 11.5,16.9 11.7,16.699 C11.9,16.499 12,16.199 12,15.999 C12, + 15.8 11.9,15.499 11.7,15.3 C11.3,14.9 10.7,14.9 10.3,15.3"/></defs><g fill="#ffb81c" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#alert-a"/></g></svg>`; + private errorSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="x-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11, + 2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.1 4.9,22 11,22 C17.1,22 22,17.1 22,11 C22,4.9 17.1,0 11,0 M14.2591,7.29935 C13.8591,6.90035 13.2591,6.90035 12.8591,7.29935 L10.5591,9.59935 L8.2591, + 7.29935 C7.8591,6.90035 7.2591,6.90035 6.8591,7.29935 C6.4591,7.69935 6.4591,8.29935 6.8591,8.69935 L9.1581,10.99935 L6.8591,13.29935 C6.4591,13.69935 6.4591,14.29935 6.8591,14.69935 C7.0591,14.90035 7.2591,14.99935 7.5591, + 14.99935 C7.8591,14.99935 8.0591,14.90035 8.2591,14.69935 L10.5591,12.40035 L12.8591,14.69935 C13.0591,14.90035 13.3591,14.99935 13.5591,14.99935 C13.7591,14.99935 14.0591,14.90035 14.2591,14.69935 C14.6581,14.29935 14.6581, + 13.69935 14.2591,13.29935 L11.9591,10.99935 L14.2591,8.69935 C14.6581,8.29935 14.6581,7.69935 14.2591,7.29935"/></defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)"> + <use class="sdc-modal__svg-use" xlink:href="#x-a"/></g></svg>`; + private successSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24" fill="#4ca90c"><path id="success+20-a" d="M20.1825992,10.445793 C20.6735306, + 10.445793 21.0008182,10.7730806 21.0008182,11.264012 L21.0008182,12.0004091 C21.0008182,16.9915451 16.9915451,21 12.0004091,21 C7.00927315,21 3,16.9915451 3,12.0004091 C3,7.00927315 7.00927315,3 12.0004091,3 C13.3095595,3 14.536888, + 3.3272876 15.6823947,3.81821901 C16.0915042,3.98186281 16.255148,4.47279422 16.0915042,4.88190372 C15.9278604,5.29101323 15.436929,5.45465703 15.0278194,5.29101323 C14.0459566,4.88190372 13.0640938,4.63643802 12.0004091, + 4.63643802 C7.90931406,4.63643802 4.63643802,7.90931406 4.63643802,12.0004091 C4.63643802,16.0906859 7.90931406,19.363562 12.0004091,19.363562 C16.0915042,19.363562 19.3643802,16.0906859 19.3643802,12.0004091 L19.3643802, + 11.264012 C19.3643802,10.7730806 19.6916678,10.445793 20.1825992,10.445793 Z M21.5737352,4.06343925 C21.9002046,4.39072685 21.9002046,4.88165826 21.5737352,5.20894586 L12.5733261,14.209355 C12.4096823,14.3729988 12.1642166, + 14.4548207 12.0005728,14.4548207 C11.836929,14.4548207 11.5914632,14.3729988 11.4278194,14.209355 L8.97316242,11.7546979 C8.64587481,11.4274103 8.64587481,10.9364789 8.97316242,10.6091913 C9.30045002,10.2819037 9.79138143, + 10.2819037 10.118669,10.6091913 L12.0005728,12.491095 L20.4282286,4.06343925 C20.7555162,3.73615164 21.2464476,3.73615164 21.5737352,4.06343925 Z"></path></svg>`; + private noSvg = ``; + + constructor(private renderer: Renderer, + private domSanitizer: DomSanitizer) { + this.modalVisible = true; + } + + ngOnInit() { + + switch (this.type) { + case ModalType.info: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.infoSvg); + break; + case ModalType.warning: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.warningSvg); + break; + case ModalType.error: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.errorSvg); + break; + case ModalType.success: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.successSvg); + break; + default: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.noSvg); + } + } + + public modalToggled = (toggleEvent: any) => { + if (!toggleEvent.toState) { + this.instanceRef.destroy(); + } + } + + public getCloseButton = (): ModalCloseButtonComponent => { + return this.modalCloseButton; + } + + public getButtonById = (id: string): CustomModalButtonComponent => { + // Support ES5 + // return this.buttons.find((button) => { + return this.buttons.filter((button) => { + return button.id && button.id === id; + })[0]; + } + + public getButtons = (): CustomModalButtonComponent[] => { + return this.buttons; + } + + public setButtons = (_buttons: CustomModalButtonComponent[]): void => { + this.buttons = _buttons; + } + + public getTitle = (): string => { + return this.title; + } + + public setTitle = (_title: string): void => { + this.title = _title; + } + + public hoverAnimation(evn: MouseEvent) { + this.renderer.setElementClass(evn.target as HTMLElement, 'sdc-ripple-click__animated', true); + // evn.taregt.classList.add('sdc-ripple-click__animated'); + } + + public closeModal = (btnName : string): void => { + this.onClose.emit(btnName); + this.modalVisible = false; + } + + public disabledModal = (isDisabled: boolean): void => { + this.isDisabled = isDisabled; + this.buttons.forEach((button: CustomModalButtonComponent) => { + button.disabled = isDisabled; + }); + this.modalCloseButton.disabled = false; + } +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts b/vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts new file mode 100644 index 000000000..a0673013d --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts @@ -0,0 +1,8 @@ +export enum ButtonType { + primary = 'primary', + secondary = 'secondary', + success = 'success', + error = 'error', + warning = 'warning', + info = 'info' +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts new file mode 100644 index 000000000..5e1f4a4a8 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts @@ -0,0 +1,15 @@ +import {ButtonType} from "onap-ui-angular/dist/dist/common"; +import {Placement} from "./modal.placement"; + +export interface IButtonComponent { + text: string; + disabled?: boolean; + type?: ButtonType; + testId?: string; + preventDoubleClick?: boolean; + icon_name?: string; + icon_position?: string; + show_spinner?: boolean; + spinner_position?: Placement; + size?: string; +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts new file mode 100644 index 000000000..4b814f0aa --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts @@ -0,0 +1,26 @@ +import {ModalType} from "./modal.type"; +import {IButtonComponent} from "./modal-button.model"; + +export interface IModalConfig { + size?: string; // xl|l|md|sm|xsm + title?: string; + titleIcon?: TitleIconDetails; + message?: string; + buttons?: IModalButtonComponent[]; + testId?: string; + type?: ModalType; +} + +export interface IModalButtonComponent extends IButtonComponent { + id?: string; + callback?: () => void; + closeModal?: boolean; +} + +export interface TitleIconDetails { + iconName?: string; + iconMode?: string; + iconSize?: string; +} + + diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts new file mode 100644 index 000000000..f7f229cd4 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts @@ -0,0 +1,6 @@ +export enum Placement { + left = 'left', + right = 'right', + top = 'top', + bottom = 'bottom' +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts new file mode 100644 index 000000000..0a96810c7 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts @@ -0,0 +1,7 @@ +export enum ModalSize { + xlarge = "xl", + large = "l", + medium = "md", + small = "sm", + xsmall = "xsm" +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts new file mode 100644 index 000000000..ca987ebba --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts @@ -0,0 +1,10 @@ +export enum ModalType { + info = 'info', + warning = 'warning', + error = 'error', + success = 'success', + action = 'action', + custom = 'custom' +} + + diff --git a/vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts b/vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts new file mode 100644 index 000000000..64fe66ce6 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts @@ -0,0 +1,107 @@ +import { + ApplicationRef, + ComponentFactoryResolver, + ComponentRef, + EmbeddedViewRef, + Injectable, + Injector, Type, ViewContainerRef +} from "@angular/core"; + +@Injectable() +export class CreateDynamicComponentService { + + constructor(private componentFactoryResolver: ComponentFactoryResolver, + private applicationRef: ApplicationRef, + private injector: Injector) { + } + + /** + * Gets the root view container to inject the component to. + * + * @returns {ComponentRef<any>} + * + * @memberOf InjectionService + */ + private getRootViewContainer(): ComponentRef<any> { + const rootComponents = this.applicationRef['components']; + if (rootComponents.length) { + return rootComponents[0]; + } + throw new Error('View Container not found! ngUpgrade needs to manually set this via setRootViewContainer.'); + } + + /** + * Gets the html element for a component ref. + * + * @param {ComponentRef<any>} componentRef + * @returns {HTMLElement} + * + * @memberOf InjectionService + */ + private getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement { + return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement; + } + + /** + * Gets the root component container html element. + * + * @returns {HTMLElement} + * + * @memberOf InjectionService + */ + private getRootViewContainerNode(): HTMLElement { + return this.getComponentRootNode(this.getRootViewContainer()); + } + + /** + * Projects the inputs onto the component + * + * @param {ComponentRef<any>} component + * @param {*} options + * @returns {ComponentRef<any>} + * + * @memberOf InjectionService + */ + private projectComponentInputs(component: ComponentRef<any>, options: any): ComponentRef<any> { + if (options) { + const props = Object.getOwnPropertyNames(options); + for (const prop of props) { + component.instance[prop] = options[prop]; + } + } + + return component; + } + + public createComponentDynamically<T>(componentClass: Type<T>, options: any = {}, location: Element = this.getRootViewContainerNode()): ComponentRef<any> { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass); + const componentRef = componentFactory.create(this.injector); + const componentRootNode = this.getComponentRootNode(componentRef); + + // project the options passed to the component instance + this.projectComponentInputs(componentRef, options); + this.applicationRef.attachView(componentRef.hostView); + + componentRef.onDestroy(() => { + this.applicationRef.detachView(componentRef.hostView); + }); + + location.appendChild(componentRootNode); + return componentRef; + } + + /** + * Inserts a component into an existing viewContainer + * @param componentType - type of component to create + * @param options - Inputs to project on new component + * @param vcRef - viewContainerRef in which to insert the newly created component + */ + public insertComponentDynamically<T>(componentType: Type<T>, options: any = {}, vcRef: ViewContainerRef): ComponentRef<any> { + const factory = this.componentFactoryResolver.resolveComponentFactory(componentType); + const dynamicComponent = factory.create(vcRef.parentInjector); + this.projectComponentInputs(dynamicComponent, options); + vcRef.insert(dynamicComponent.hostView); + return dynamicComponent; + } + +} diff --git a/vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts b/vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts new file mode 100644 index 000000000..f46ee4896 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts @@ -0,0 +1,64 @@ +import {ComponentRef, Injectable, Type} from "@angular/core"; +import {CreateDynamicComponentService} from "./create-dynamic-component.service"; +import {ModalType} from "../models/modal.type"; +import {ButtonType} from "../models/button.type"; +import {ModalButtonComponent} from "onap-ui-angular/dist/modals/modal-button.component"; +import {ModalSize} from "../models/modal.size"; +import {IModalConfig} from "../models/modal.model"; +import {ModalComponent} from "../modal.component"; + + +@Injectable() +export class ModalService { + + constructor(private createDynamicComponentService: CreateDynamicComponentService) { + } + + private getBaseModal = (type: ModalType | ButtonType, title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + const modalConfig = { + size: ModalSize.small, + title: title, + message: message, + testId: testId, + buttons: buttons ? buttons : [{text: 'OK', type: type, closeModal: true}], + type: type + } as IModalConfig; + const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); + return modalInstance.instance; + }; + + /* Shortcut method to open basic modals with title, message, and OK button that simply closes the modal. */ + public openInfoModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + + return this.getBaseModal(ModalType.info, title, message, testId, buttons); + }; + + public openWarningModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.warning, title, message, testId, buttons); + }; + + public openErrorModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.error, title, message, testId, buttons); + }; + + public openSuccessModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.success, title, message, testId, buttons); + }; + + public openCustomModal = (modalConfig: IModalConfig, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => { + const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); + this.createInnnerComponent(modalInstance, dynamicComponentType, dynamicComponentInput); + return modalInstance.instance; + }; + + public createInnnerComponent = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput?: any): void => { + modalInstance.instance.innerModalContent = this.createDynamicComponentService.insertComponentDynamically(dynamicComponentType, dynamicComponentInput, modalInstance.instance.dynamicContentContainer); + }; + + public openModal = (customModalData: IModalConfig): ComponentRef<ModalComponent> => { + let modalInstance: ComponentRef<ModalComponent> = this.createDynamicComponentService.createComponentDynamically(ModalComponent, customModalData); + modalInstance.instance.instanceRef = modalInstance; + return modalInstance; + } + +} diff --git a/vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts b/vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts new file mode 100644 index 000000000..a8163a6d8 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts @@ -0,0 +1,20 @@ +import {AfterViewInit, Component, ViewChild, ViewContainerRef} from "@angular/core"; +import {BehaviorSubject} from "rxjs"; + +@Component({ + selector: 'tooltip-template', + template: ` + <div class="custom-tooltip-template-container"> + <ng-container #templateContainer></ng-container> + </div>` +}) + +export class TooltipTemplateComponent implements AfterViewInit { + @ViewChild('templateContainer', {read: ViewContainerRef, static: true}) public container: ViewContainerRef; + + public viewReady: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + + ngAfterViewInit() : void { + this.viewReady.next(true); + } +} diff --git a/vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts b/vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts new file mode 100644 index 000000000..4c3b8bd3d --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts @@ -0,0 +1,461 @@ +import {Directive, ElementRef, HostListener, Input, OnInit, Renderer, TemplateRef} from "@angular/core"; +import {CreateDynamicComponentService} from "../customModal/services/create-dynamic-component.service"; +import {TooltipTemplateComponent} from "./custom-tooltip.component"; + +const pixel = 'px'; +const leftStyle = 'left'; +const topStyle = 'top'; +const showSuffix = 'show'; +const rightBottomSuffix = 'right__bottom'; +const centerMiddleSuffix = 'center__middle'; + +@Directive({ + selector: '[custom-tooltip]' +}) +export class TooltipDirective implements OnInit { + @Input('tooltip-text') public text; + @Input('tooltip-placement') public placement: TooltipPlacement = TooltipPlacement.Top; + @Input('tooltip-css-class') public customCssClass: string; + @Input('tooltip-template') public template: TemplateRef<any>; + @Input('tooltip-arrow-offset') public arrowOffset: number = 10; + @Input('tooltip-arrow-placement') public arrowPlacement: ArrowPlacement = ArrowPlacement.LeftTop; + @Input('tooltip-offset') public tooltipOffset: number = 3; + + private cssClass: string = 'sdc-tooltip'; // default css class + private tooltip: any; // tooltip html element + private elemPosition: any; + private tooltipTemplateContainer: any; + + private scrollEventHandler = () => {}; + + constructor( + private elementRef: ElementRef, + private service: CreateDynamicComponentService, + private renderer: Renderer) { + + this.elementRef.nativeElement.title = ""; + } + + @HostListener('mouseenter') + public onMouseEnter() { + this.show(); + this.activateScrollEvent(); + } + + @HostListener('mouseleave') + public onMouseLeave() { + this.hide(); + this.deactivateScrollEvent(); + } + + ngOnInit(): void { + this.initScrollEvent(); + } + + private get ScreenWidth() { + return document.documentElement.clientWidth; + } + + private get ScreenHeight() { + return document.documentElement.clientHeight; + } + + private create() { + this.tooltipTemplateContainer = this.service.createComponentDynamically(TooltipTemplateComponent, document.body); + + /** + * Creating a view (injecting our template) from template in our component. + */ + this.tooltip = this.tooltipTemplateContainer.location.nativeElement.querySelector( + '.sdc-tooltip-template-container'); + + if (this.template) { + this.tooltipTemplateContainer.instance.container.createEmbeddedView(this.template); + } else if(this.text) { + this.tooltip.textContent = this.text; + } else { + this.tooltip = undefined; + } + + this.setCssClass(true); + } + + private destroy() { + this.tooltipTemplateContainer.destroy(); + this.tooltip = null; + } + + private show() { + this.create(); + + /** + * View is ready (AfterViewInit event in template component) + */ + this.tooltipTemplateContainer.instance.viewReady.subscribe((isReady) => { + if (isReady) { + this.setPosition(); + this.toggleShowCssClass(true); // add css class + } + }); + } + + private hide() { + this.toggleShowCssClass(false); // remove css class + + this.destroy(); + } + + private toggleShowCssClass(isAdd: boolean) { + if (this.tooltip) { + this.setCssClass(isAdd, '-' + showSuffix); + } + } + + /** + * Adds placement css class and sets tooltip position in style + */ + private setPosition() { + const tooltipPos: IPlacementData = this.getPlacementData(); + + const placementSuffix: string = TooltipPlacement[tooltipPos.placement].toLowerCase(); + + this.setCssClass(true, '-' + placementSuffix); + + this.setAdditionalCssClass(placementSuffix); + + this.renderer.setElementStyle(this.tooltip, topStyle, tooltipPos.top + pixel); + this.renderer.setElementStyle(this.tooltip, leftStyle, tooltipPos.left + pixel); + } + + private setAdditionalCssClass(placementSuffix: string) { + if (this.arrowPlacement === ArrowPlacement.RightBottom) { + this.setCssClass(true, '-' + placementSuffix + '-' + rightBottomSuffix); + } else if (this.arrowPlacement === ArrowPlacement.CenterMiddle) { + this.setCssClass(true, '-' + placementSuffix + '-' + centerMiddleSuffix); + } + } + + private setCssClass(isAdd: boolean, suffix: string = '') { + this.renderer.setElementClass(this.tooltip, this.cssClass + suffix, isAdd); + + if (this.customCssClass) { + this.renderer.setElementClass(this.tooltip, this.customCssClass + suffix, isAdd); + } + } + + /** + * Checks the specified placement (first element in array), if it is not valid - checks other placements + * @returns {IPlacementData} + */ + private getPlacementData(): IPlacementData { + const placement: TooltipPlacement = this.placement; + let tooltipPos: IPlacementData; + + const tooltipPosWithPlacement = this.getPlacement.bind(this, placement); + + // TODO add comments - done + switch (placement) { + case TooltipPlacement.Left: + tooltipPos = tooltipPosWithPlacement( + TooltipPlacement.Right, + TooltipPlacement.Top, + TooltipPlacement.Bottom); + break; + + case TooltipPlacement.Right: + tooltipPos = tooltipPosWithPlacement( + TooltipPlacement.Left, + TooltipPlacement.Top, + TooltipPlacement.Bottom); + break; + + case TooltipPlacement.Top: + tooltipPos = tooltipPosWithPlacement( + TooltipPlacement.Bottom, + TooltipPlacement.Left, + TooltipPlacement.Right); + break; + + case TooltipPlacement.Bottom: + tooltipPos = tooltipPosWithPlacement( + TooltipPlacement.Top, + TooltipPlacement.Left, + TooltipPlacement.Right); + break; + } + + return tooltipPos; + } + + /** + * Returns valid tooltip position data + * @param {TooltipPlacement} placement + * @param {TooltipPlacement} additionalPlacements + * @returns {IPlacementData} + */ + private getPlacement(placement: TooltipPlacement, + ...additionalPlacements: TooltipPlacement[] + ): IPlacementData { + const placements: TooltipPlacement[] = [placement, ...additionalPlacements]; + const filterPlacements = placements + .map((pl) => this.getPosition(pl)) + .filter((item) => this.validatePosition(item)); + return filterPlacements.length > 0 ? filterPlacements[0] : this.getPosition(placement); + } + + /** + * Returns input data for getPosition method + * @returns {ITooltipPositionParams} + */ + private getPlacementInputParams(): ITooltipPositionParams { + this.elemPosition = this.elementRef.nativeElement.getBoundingClientRect(); + + return { + elemHeight: this.elementRef.nativeElement.offsetHeight, + elemLeft: this.elemPosition.left, + elemTop: this.elemPosition.top, + elemWidth: this.elementRef.nativeElement.offsetWidth, + pageYOffset: window.pageYOffset, + tooltipHeight: this.tooltip.offsetHeight, // .clientHeight, + tooltipOffset: this.tooltipOffset, + tooltipWidth: this.tooltip.offsetWidth, + arrowOffset: this.arrowOffset + }; + } + + /** + * Returns tooltip position data + * @param {TooltipPlacement} placement (left, top, right, bottom) + * @returns {IPlacementData} + */ + private getPosition(placement: TooltipPlacement): IPlacementData { + switch(this.arrowPlacement) { + case ArrowPlacement.LeftTop: + return this.getLeftTopPosition(placement); + + case ArrowPlacement.RightBottom: + return this.getRightBottomPosition(placement); + } + + return this.getCenterMiddlePosition(placement); + } + + /** + * Returns tooltip position data (center / middle arrow) + * @param {TooltipPlacement} placement (left, top, right, bottom) + * @returns {IPlacementData} + */ + private getCenterMiddlePosition(placement: TooltipPlacement): IPlacementData { + let left = 0; + let top = 0; + + const inputPos: ITooltipPositionParams = this.getPlacementInputParams(); + switch (placement) { + case TooltipPlacement.Left: + left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight / 2; + break; + + case TooltipPlacement.Right: + left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight / 2; + break; + + case TooltipPlacement.Top: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth / 2; + top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset; + break; + + case TooltipPlacement.Bottom: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth / 2; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset; + break; + } + + return { + height: inputPos.tooltipHeight, + left, + placement, + top, + width: inputPos.tooltipWidth, + pageYOffset: inputPos.pageYOffset + } as IPlacementData; + } + + /** + * Returns tooltip position data (left / top arrow) + * @param {TooltipPlacement} placement (left, top, right, bottom) + * @returns {IPlacementData} + */ + private getLeftTopPosition(placement: TooltipPlacement): IPlacementData { + let left = 0; + let top = 0; + + const inputPos: ITooltipPositionParams = this.getPlacementInputParams(); + switch (placement) { + case TooltipPlacement.Left: + left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.arrowOffset; + break; + + case TooltipPlacement.Right: + left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.arrowOffset; + break; + + case TooltipPlacement.Top: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.arrowOffset; + top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset; + break; + + case TooltipPlacement.Bottom: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.arrowOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset; + break; + } + + return { + height: inputPos.tooltipHeight, + left, + placement, + top, + width: inputPos.tooltipWidth, + pageYOffset: inputPos.pageYOffset + } as IPlacementData; + } + + /** + * Returns tooltip position data (right / bottom arrow) + * @param {TooltipPlacement} placement (left, top, right, bottom) + * @returns {IPlacementData} + */ + private getRightBottomPosition(placement: TooltipPlacement): IPlacementData { + let left = 0; + let top = 0; + + const inputPos: ITooltipPositionParams = this.getPlacementInputParams(); + switch (placement) { + case TooltipPlacement.Left: + left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight + inputPos.arrowOffset; + break; + + case TooltipPlacement.Right: + left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight + inputPos.arrowOffset; + break; + + case TooltipPlacement.Top: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth + inputPos.arrowOffset; + top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset; + break; + + case TooltipPlacement.Bottom: + left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth + inputPos.arrowOffset; + top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset; + break; + } + + return { + height: inputPos.tooltipHeight, + left, + placement, + top, + width: inputPos.tooltipWidth, + pageYOffset: inputPos.pageYOffset + } as IPlacementData; + } + + /** + * Checks if tooltip position is valid + * @param {IPlacementData} pos + * @returns {boolean} + */ + private validatePosition(pos: IPlacementData): boolean { + if (pos.left < 0 || pos.left + pos.width - 1 > this.ScreenWidth) { + return false; + } + + if (pos.top - pos.pageYOffset < 0 || pos.top - pos.pageYOffset + pos.height - 1 > this.ScreenHeight) { + return false; + } + + return true; + } + + /** + * Scrolling + */ + + private debounce(func: Function, wait: number, immediate?: boolean) { + let timeout; + return function() { + const context = this; + const args = arguments; + const later = () => { + timeout = null; + if (!immediate) { + func.apply(context, args); + } + }; + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func.apply(context, args); + } + }; + } + + private initScrollEvent() { + this.scrollEventHandler = this.debounce(() => { + try { + this.setPosition(); + } catch (e) { + + } + }, 10); + } + + private activateScrollEvent() { + window.addEventListener('scroll', this.scrollEventHandler , true); + } + + private deactivateScrollEvent() { + window.removeEventListener('scroll', this.scrollEventHandler , true); + } +} + +export enum TooltipPlacement { + Left, + Right, + Top, + Bottom +} + +export enum ArrowPlacement { + CenterMiddle, + LeftTop, + RightBottom +} + +interface ITooltipPositionParams { + elemLeft: number; + elemTop: number; + elemWidth: number; + elemHeight: number; + tooltipWidth: number; + tooltipHeight: number; + tooltipOffset: number; + pageYOffset: number; + arrowOffset: number; +} + +interface IPlacementData { + left: number; + top: number; + width: number; + height: number; + pageYOffset: number; + placement?: TooltipPlacement; +} diff --git a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts index a7b8ac744..9828645bf 100644 --- a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts +++ b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts @@ -6,7 +6,7 @@ import * as _ from 'lodash'; selector: 'custom-ellipsis', template: ` <span - sdc-tooltip + custom-tooltip class="ellipsis" [attr.data-tests-id]="dataTestId" id="{{id}}" diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html index 26362ebed..fe7744e43 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html +++ b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html @@ -8,4 +8,9 @@ data-toggle="toggle"> <label class="checkbox-label" for="{{data?.dataTestId}}">{{data?.displayName}}</label> + <div *ngFor="let extraContent of data?.extraContents" class="form-conrtols"> + <div [ngSwitch]="extraContent.type"> + <upload-files *ngSwitchCase="'UPLOAD_FILE'" [uploadFilesModel]="extraContent" [form]="form"></upload-files> + </div> + </div> </div> diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss index 005e28cc6..81180e06f 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss +++ b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss @@ -11,6 +11,7 @@ .details-item label { position: relative; cursor: pointer; + float: left; } .details-item label:before { diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/file/file.formControl.component.ts b/vid-webpack-master/src/app/shared/components/formControls/component/file/file.formControl.component.ts index 2c2172005..aadf13ebe 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/file/file.formControl.component.ts +++ b/vid-webpack-master/src/app/shared/components/formControls/component/file/file.formControl.component.ts @@ -11,7 +11,7 @@ import {FileFormControl} from "../../../../models/formControlModels/fileFormCont export class FileFormControlComponent { @Input() data: FileFormControl = null; @Input() form: FormGroup; - @ViewChild('fileUploader') + @ViewChild('fileUploader', {static: false}) fileUploader:ElementRef ; onDelete(event, data, form) { diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/input/input.formControl.component.ts b/vid-webpack-master/src/app/shared/components/formControls/component/input/input.formControl.component.ts index 1e8c28104..7a7ab72d0 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/input/input.formControl.component.ts +++ b/vid-webpack-master/src/app/shared/components/formControls/component/input/input.formControl.component.ts @@ -9,7 +9,7 @@ import {FormGroup} from "@angular/forms"; }) export class InputFormControlComponent{ - @ViewChild('customInput') element:ElementRef; + @ViewChild('customInput', {static: false}) element:ElementRef; @Input() data: InputFormControl = null; @Input() form: FormGroup; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts index e82ea5d85..83f722704 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts @@ -133,13 +133,14 @@ export class SharedControllersService { }) }; - getSDNCControl = (instance: any): FormControlModel => { + getSDNCControl = (instance: any, extraContents? : object[]): FormControlModel => { return new CheckboxFormControl({ controlName: SDN_C_PRE_LOAD, displayName: 'SDN-C pre-load', dataTestId: 'sdncPreLoad', value: instance ? instance.sdncPreLoad : false, - validations: [new ValidatorModel(ValidatorOptions.required, 'is required')] + validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], + extraContents }) }; @@ -167,7 +168,7 @@ export class SharedControllersService { placeHolder: (!isEcompGeneratedNaming) ? 'Instance name' : 'Automatically generated when not provided', validations: validations, isVisible : true, - value : (!isEcompGeneratedNaming || (!_.isNil(instance) && !_.isNil(instance.instanceName))) + value : (!isEcompGeneratedNaming || (!_.isNil(instance) && !_.isNil(instance.instanceName) && instance.instanceName !== "")) ? this._basicControlGenerator.getDefaultInstanceName(instance, model) : null, onKeypress : (event) => { const pattern:RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts index f3d32b9bb..154c60f9e 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts @@ -6,12 +6,20 @@ import {AaiService} from "../../../../services/aaiService/aai.service"; import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; import {LogService} from "../../../../utils/log/log.service"; -import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; +import { + FormControlModel, + ValidatorModel, + ValidatorOptions +} from "../../../../models/formControlModels/formControl.model"; import {FormControlNames, VfModuleControlGenerator} from "./vfModule.control.generator"; -import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; +import {FeatureFlagsService, Features} from "../../../../services/featureFlag/feature-flags.service"; import {VfModuleInstance} from "../../../../models/vfModuleInstance"; import {VfModule} from "../../../../models/vfModule"; import {SharedControllersService} from "../sharedControlles/shared.controllers.service"; +import {AppState} from "../../../../store/reducers"; +import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; +import {instance, mock, when} from "ts-mockito"; +import each from "jest-each"; class MockAppStore<T> { getState() { @@ -914,6 +922,9 @@ describe('VFModule Control Generator', () => { let injector; let service: VfModuleControlGenerator; let httpMock: HttpTestingController; + let store : NgRedux<AppState>; + let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService); + beforeAll(done => (async () => { TestBed.configureTestingModule({ @@ -925,7 +936,8 @@ describe('VFModule Control Generator', () => { AaiService, FormBuilder, LogService, - {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, + SharedTreeService, + {provide: FeatureFlagsService, useValue: instance(mockFeatureFlagsService)}, {provide: NgRedux, useClass: MockAppStore}] }); await TestBed.compileComponents(); @@ -933,10 +945,28 @@ describe('VFModule Control Generator', () => { injector = getTestBed(); service = injector.get(VfModuleControlGenerator); httpMock = injector.get(HttpTestingController); + store = injector.get(NgRedux); jest.spyOn(console, 'error'); })().then(done).catch(done.fail)); + let formControlsWithoutLcpRegionTenantLegacy : string[] = + [FormControlNames.INSTANCE_NAME, + FormControlNames.VOLUME_GROUP_NAME, + FormControlNames.ROLLBACK_ON_FAILURE, + SDN_C_PRE_LOAD,]; + + let formControlsWithLcpRegionTenantLegacy : string[] = + [FormControlNames.INSTANCE_NAME, + FormControlNames.VOLUME_GROUP_NAME, + FormControlNames.LCPCLOUD_REGION_ID, + FormControlNames.LEGACY_REGION, + FormControlNames.TENANT_ID, + FormControlNames.ROLLBACK_ON_FAILURE, + SDN_C_PRE_LOAD,]; + + + test(' getMacroFormControls gets vnfStoreKey === null', () => { const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; const vnfStoreKey: string = null; @@ -1049,20 +1079,15 @@ describe('VFModule Control Generator', () => { expect(console.error).toHaveBeenCalled(); }); - test('getAlaCarteFormControls should return the correct order of controls', () => { + each([ + [true, 4, formControlsWithoutLcpRegionTenantLegacy], + [false, 7,formControlsWithLcpRegionTenantLegacy] + ]). + test('getAlaCarteFormControls should return the correct order of controls', (flag: boolean, controlAmount: number, orderedControls: string[]) => { + when(mockFeatureFlagsService.getFlagState(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)).thenReturn(flag); const controls:FormControlModel[] = getAlaCarteFormControls(); - const orderedControls : string[] = [ - FormControlNames.INSTANCE_NAME, - FormControlNames.VOLUME_GROUP_NAME, - FormControlNames.LCPCLOUD_REGION_ID, - FormControlNames.LEGACY_REGION, - FormControlNames.TENANT_ID, - FormControlNames.ROLLBACK_ON_FAILURE, - SDN_C_PRE_LOAD, - ]; - - expect(controls.length).toEqual(7); + expect(controls.length).toEqual(controlAmount); for(let i = 0 ; i < orderedControls.length ; i++) { expect(controls[i].controlName).toEqual(orderedControls[i]); } @@ -1084,26 +1109,6 @@ describe('VFModule Control Generator', () => { return controls; } - test('getAlaCarteFormControls responce with wrong order of controls', () => { - const controls:FormControlModel[] = getAlaCarteFormControls(); - - const orderedControls : string[] = [ - FormControlNames.INSTANCE_NAME, - FormControlNames.VOLUME_GROUP_NAME, - FormControlNames.LCPCLOUD_REGION_ID, - FormControlNames.TENANT_ID, // TENANT_ID must be after LEGACY_REGION - FormControlNames.LEGACY_REGION, - FormControlNames.ROLLBACK_ON_FAILURE, - SDN_C_PRE_LOAD, - ]; - - for(let i = 0 ; i < orderedControls.length ; i++) { - if (controls[i].controlName === 'legacyRegion') { - expect(orderedControls[i]).toEqual('tenantId'); - } - } - }); - test('getMacroFormControls should return the correct order of controls', () => { const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; const vnfStoreKey: string = 'VF_vGeraldine 0'; @@ -1140,23 +1145,28 @@ describe('VFModule Control Generator', () => { expect(instanceNameValidator.validatorArg).toEqual(/^[a-zA-Z0-9._-]*$/); }); - test(' getAlaCarteFormControls gets null service', () => { - const controls:FormControlModel[] = getAlaCarteFormControls(); - expect(controls.length).toEqual(7); - const orderedControls : string[] = [ - FormControlNames.INSTANCE_NAME, - FormControlNames.VOLUME_GROUP_NAME, - FormControlNames.LCPCLOUD_REGION_ID, - FormControlNames.LEGACY_REGION, - FormControlNames.TENANT_ID, - FormControlNames.ROLLBACK_ON_FAILURE, - SDN_C_PRE_LOAD, - ]; + test('when flag is active - response should contains upload file', ()=>{ + spyOn(store, 'getState').and.returnValue( { + "global": { + "flags": { + "FLAG_2006_VFM_SDNC_PRELOAD_FILES" : true + } + } + }); + + const extraContent = service.getSdncExtraContents(); + console.log("extraContent", extraContent); + const uploadFileData = <any>extraContent[0]; + + expect(uploadFileData.type).toEqual('UPLOAD_FILE'); + expect(uploadFileData.dataTestId).toEqual('sdnc_pereload_upload_link'); + expect(uploadFileData.uploadMethod).toBeDefined(); + expect(uploadFileData.isDisabled).toBeDefined(); + expect(uploadFileData.onSuccess).toBeDefined(); + expect(uploadFileData.onFailed).toBeDefined(); + + }) - for(let i = 0 ; i < orderedControls.length ; i++) { - expect(controls[i].controlName).toEqual(orderedControls[i]); - } - }); }); diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts index 60ffc3e96..b614ecf30 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts @@ -3,7 +3,7 @@ import {GenericFormService} from "../../generic-form.service"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {NgRedux} from "@angular-redux/store"; import {HttpClient} from "@angular/common/http"; -import {ControlGeneratorUtil} from "../control.generator.util.service"; +import {ControlGeneratorUtil, SDN_C_PRE_LOAD} from "../control.generator.util.service"; import { CustomValidatorOptions, FormControlModel, @@ -20,6 +20,10 @@ import {VNFModel} from "../../../../models/vnfModel"; import {VnfInstance} from "../../../../models/vnfInstance"; import * as _ from 'lodash'; import {SharedControllersService} from "../sharedControlles/shared.controllers.service"; +import {MessageModal} from "../../../messageModal/message-modal.service"; +import {ButtonType} from "../../../customModal/models/button.type"; +import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; +import {FeatureFlagsService, Features} from "../../../../services/featureFlag/feature-flags.service"; export enum FormControlNames { INSTANCE_NAME = 'instanceName', @@ -35,15 +39,17 @@ export enum FormControlNames { export class VfModuleControlGenerator { aaiService: AaiService; vfModuleModel: VfModule; - isUpdateMode : boolean; + isUpdateMode: boolean; constructor(private genericFormService: GenericFormService, private _basicControlGenerator: ControlGeneratorUtil, private _sharedControllersService: SharedControllersService, + private _sharedTreeService: SharedTreeService, private store: NgRedux<AppState>, private http: HttpClient, private _aaiService: AaiService, - private _logService: LogService) { + private _logService: LogService, + private _featureFlagsService:FeatureFlagsService) { this.aaiService = _aaiService; } @@ -52,7 +58,7 @@ export class VfModuleControlGenerator { if (isUpdateMode && this.store.getState().service.serviceInstance[serviceId] && _.has(this.store.getState().service.serviceInstance[serviceId].vnfs, vnfStoreKey) && _.has(this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules, UUIDData['modelName'])) { - vfModuleInstance = Object.assign({},this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]); + vfModuleInstance = Object.assign({}, this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]); } return vfModuleInstance; }; @@ -63,11 +69,11 @@ export class VfModuleControlGenerator { return vfModule; } - getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] { + getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] { this.isUpdateMode = isUpdateMode; this.extractVfAccordingToVfModuleUuid(serviceId, uuidData); if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) { - if(isUpdateMode){ + if (isUpdateMode) { this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId); return []; } @@ -76,21 +82,28 @@ export class VfModuleControlGenerator { const vfModuleInstance = this._basicControlGenerator.retrieveInstanceIfUpdateMode(this.store, this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode)); const vfModuleModel = this.vfModuleModel; const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey]; - const vnfModelName: string = vnf.originalName; - const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]); + const vnfModel = this.newVNFModel(serviceId, vnf); let result: FormControlModel[] = []; if (!_.isNil(vfModuleModel)) { result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false); } - if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { + if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance); } return result; } - pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{ + private newVNFModel(serviceId: string, vnf: VnfInstance) { + const vnfModelName: string = this._sharedTreeService.modelUniqueNameOrId(vnf); + + const serviceModelFromHierarchy = this.store.getState().service.serviceHierarchy[serviceId]; + const model = this._sharedTreeService.modelByIdentifiers(serviceModelFromHierarchy, "vnfs", vnfModelName); + return new VNFModel(model); + } + + pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean): FormControlModel[] { result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming)); if (this.vfModuleModel.volumeGroupAllowed) { result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte)); @@ -98,46 +111,85 @@ export class VfModuleControlGenerator { return result; } - getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] { + getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] { this.isUpdateMode = isUpdateMode; this.extractVfAccordingToVfModuleUuid(serviceId, uuidData); if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) { - if(isUpdateMode){ + if (isUpdateMode) { this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId); return []; } } - const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey] ; - const vnfModelName: string = vnf.originalName; - const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]); + const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey]; + const vnfModel = this.newVNFModel(serviceId, vnf); const vfModuleInstance = this._basicControlGenerator.retrieveInstanceIfUpdateMode(this.store, this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode)); let result: FormControlModel[] = []; this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, true); - result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vfModuleInstance, result)); - result.push(this._sharedControllersService.getLegacyRegion(vfModuleInstance)); - result.push(this._sharedControllersService.getTenantControl(serviceId, vfModuleInstance)); + if( !this._featureFlagsService.getFlagState(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)) { + result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vfModuleInstance, result)); + result.push(this._sharedControllersService.getLegacyRegion(vfModuleInstance)); + result.push(this._sharedControllersService.getTenantControl(serviceId, vfModuleInstance)); + } result.push(this._sharedControllersService.getRollbackOnFailureControl(vfModuleInstance)); - result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance)); - if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { + result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance, this.getSdncExtraContents())); + if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance); } return result; } - getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel { - let formControlModel:FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel); - formControlModel.onBlur = (event, form : FormGroup) => { - if(!_.isNil(form.controls['volumeGroupName'])&& event.target.value.length > 0){ - form.controls['volumeGroupName'].setValue(event.target.value + "_vol"); + getSdncExtraContents() : object[] { + return _.compact([ + !!this.store.getState().global.flags['FLAG_2006_VFM_SDNC_PRELOAD_FILES'] ? { + type: 'UPLOAD_FILE', + dataTestId: 'sdnc_pereload_upload_link', + uploadMethod: (form: FormGroup) : Promise<boolean> => { + // this -> files item + return this._aaiService.sdncPreload().toPromise() + .then((response : boolean)=>{ + return response; + }).catch(err => { + return false; + }); + }, + isDisabled: (form: FormGroup): boolean => { + return !form.controls[SDN_C_PRE_LOAD].value; + }, + onSuccess: (form: FormGroup): void => { + MessageModal.showMessageModal({ + text: 'The pre-load file(s) have been uploaded successfully.', + type: "success", + title: 'Success', + buttons: [{type: ButtonType.success, size: 'large', text: 'OK', closeModal: true}] + }) + }, + onFailed: (form: FormGroup) : void=> { + MessageModal.showMessageModal({ + text: 'Failed to upload one or more of the files, please retry.', + type: "error", + title: 'Failure', + buttons: [{type: ButtonType.error, size: 'large', text: 'OK', closeModal: true}] + }) } - }; + } : null + ]); + } + + + getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel { + let formControlModel: FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel); + formControlModel.onBlur = (event, form: FormGroup) => { + if (!_.isNil(form.controls['volumeGroupName']) && event.target.value.length > 0) { + form.controls['volumeGroupName'].setValue(event.target.value + "_vol"); + } + }; return formControlModel; } getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string { - if ((!_.isNil(instance) && instance.volumeGroupName)) { + if ((!_.isNil(instance) && instance.volumeGroupName)) { return instance.volumeGroupName; } if (isEcompGeneratedNaming) { @@ -157,12 +209,12 @@ export class VfModuleControlGenerator { displayName: 'Volume Group Name', dataTestId: 'volumeGroupName', validations: validations, - tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' + - 'When empty, the module is created without a Volume Group.', - isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte), + tooltip: 'When filled, VID will create a Volume Group by this name and associate with this module.\n' + + 'When empty, the module is created without a Volume Group.', + isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming, isALaCarte), value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming), onKeypress: (event) => { - const pattern:RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX; + const pattern: RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX; if (pattern) { if (!pattern.test(event['key'])) { event.preventDefault(); @@ -174,7 +226,7 @@ export class VfModuleControlGenerator { } private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) { - if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){ + if ((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte) { return true; } return false; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts index 018130eec..4572fa443 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts @@ -957,7 +957,8 @@ describe('VNF Control Generator', () => { FormControlNames.INSTANCE_NAME, FormControlNames.LCPCLOUD_REGION_ID, FormControlNames.TENANT_ID, - 'platformName' + 'platformName', + FormControlNames.PRODUCT_FAMILY_ID ]; for(let i = 0 ; i < mandatoryControls.length ; i++){ diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts index 14b31b4b7..169780b29 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts @@ -50,7 +50,7 @@ export class VnfControlGenerator { if (!_.isNil(vnfModel)) { result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); - result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, false)); + result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, true)); result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result)); result.push(this._sharedControllersService.getLegacyRegion(vnfInstance)); result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance)); @@ -74,7 +74,7 @@ export class VnfControlGenerator { if (!_.isNil(vnfModel)) { const flags = this.store.getState().global.flags; result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); - result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, false)); + result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, true)); result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result)); result.push(this._sharedControllersService.getLegacyRegion(vnfInstance)); result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance)); diff --git a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html index edf86823c..627f6426a 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html +++ b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html @@ -3,7 +3,7 @@ <div *ngFor="let formControl of formControls" class="form-conrtols"> <div [ngSwitch]="formControl.type"> <form-control-input *ngSwitchCase="'INPUT'" [data]="formControl" [form]="dynamicFormGroup"></form-control-input> - <checkbox-form-control *ngSwitchCase="'CHECKBOX'" [data]="formControl" [form]="dynamicFormGroup" ></checkbox-form-control> + <checkbox-form-control *ngSwitchCase="'CHECKBOX'" [data]="formControl" [form]="dynamicFormGroup"></checkbox-form-control> <dropdown-form-control *ngSwitchCase="'DROPDOWN'" [data]="formControl" [form]="dynamicFormGroup" ></dropdown-form-control> <file-form-control *ngSwitchCase="'FILE'" [data]="formControl" [form]="dynamicFormGroup"></file-form-control> <multiselect-form-control *ngSwitchCase="'MULTI_SELECT'" diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html new file mode 100644 index 000000000..6f59c0ce2 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html @@ -0,0 +1,15 @@ +<div> + <a [attr.data-tests-id]="uploadFilesModel.dataTestId" + (click)="uploadFilesTrigger()" + href="javascript:void(0)" + class="upload-text" + [class.disabled]="uploadFilesModel.isDisabled && uploadFilesModel.isDisabled(form)">{{uploadFilesModel.uploadText || 'Upload'}}</a> + <span class="hide-span"> + <input + type="file" + #fileInput + ng2FileSelect + [uploader]="uploader" + [attr.data-tests-id]="uploadFilesModel.dataTestId + '-input'"/> + </span> +</div> diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss new file mode 100644 index 000000000..ce9e14fbe --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss @@ -0,0 +1,23 @@ +.upload-text { + margin-left: 30px; + font-family: OpenSans-Semibold; + font-size: 14px; + line-height: 23px; +} + +a.disabled { + color: gray; + cursor: not-allowed; + text-decoration: underline; +} + +.hide-span { + visibility: hidden; + position: absolute; + overflow: hidden; + width: 0px; + height: 0px; + border: none; + margin: 0; + padding: 0 +} diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts new file mode 100644 index 000000000..803d5d053 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts @@ -0,0 +1,41 @@ +import {Component, ElementRef, Input, OnInit, ViewChild} from "@angular/core"; +import {FileItem, FileUploader} from "ng2-file-upload"; +import {UploadFilesLinkModel} from "./upload-files-link.model"; +import {FormGroup} from "@angular/forms"; + +@Component({ + selector: 'upload-files', + templateUrl: './upload-files-link.component.html', + styleUrls: ['./upload-files-link.component.scss'] +}) +export class UploadFilesLinkComponent implements OnInit { + uploader: FileUploader; + @Input() uploadFilesModel: UploadFilesLinkModel; + @Input() form: FormGroup; + @ViewChild('fileInput', {static: false}) fileInput: ElementRef; + + ngOnInit(): void { + this.uploader = new FileUploader({}); + + this.uploader.onAfterAddingAll = async (files: FileItem[]) => { + const result = await this.uploadFilesModel.uploadMethod.call(files, this.form); + if (result && this.uploadFilesModel.onSuccess) { + this.uploadFilesModel.onSuccess.call(this.form); + } else if (!result && this.uploadFilesModel.onFailed) { + this.uploadFilesModel.onFailed.call(this.form); + } + this.uploadFilesModel.uploadText = result ? 'Upload another' : 'Upload' + }; + this.resetUpload(); + } + + resetUpload(): void { + this.fileInput.nativeElement.value = ''; + } + + uploadFilesTrigger() { + if (this.uploadFilesModel.isDisabled && !this.uploadFilesModel.isDisabled(this.form)) { + this.fileInput.nativeElement.click(); + } + } +} diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts new file mode 100644 index 000000000..beb54f43a --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts @@ -0,0 +1,30 @@ +import {FileItem} from "ng2-file-upload"; + +export class UploadFilesLinkModel { + uploadText?: string; + + /********************************************************************* + Implement success method - run after uploadMethod return true result + **********************************************************************/ + onSuccess?: (...args) => void; + + /********************************************************************* + Implement failed method - run after uploadMethod return false result + **********************************************************************/ + onFailed?: (...args) => void; + + /********************************************************************************* + Implement upload method and return the upload result status (false/true) + *********************************************************************************/ + uploadMethod: (file: FileItem[], ...args) => Promise<boolean>; + + /******************************** + Should upload file be disabled + ********************************/ + isDisabled?: (...args) => boolean; + + /******************************** + a tag data test id + ********************************/ + dataTestId : string; +} diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html index 6bb1ff156..031357403 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html @@ -61,12 +61,6 @@ (click)="openTemplateModal()" ><span>Template</span></button> <button - *ngIf="isShowPreviousInstantiationBtn" - [attr.data-tests-id]="'ShowPreviousInstancesButton'" - type="button" class="btn btn-success submit" - (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)" - ><span>Previous Instantiation</span></button> - <button [attr.data-tests-id]="'cancelButton'" type="button" class="btn btn-default cancel" (click)="formPopupDetails.onCancel(formPopupDetails.that, dynamicForm); clearModalIsUpdateMode()" diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts index 9063e6723..7368dd698 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts @@ -47,7 +47,6 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole type: PopupType; uuidData: UUIDData; showTemplateBtn: boolean = false; - isShowPreviousInstantiationBtn: boolean = false; isUpdateMode: boolean; node: ITreeNode = null; hasGeneralApiError: boolean = false; @@ -89,7 +88,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole .subscribe(params => { this.serviceModelId = params['serviceModelId']; if (this.serviceModelId && params['isCreate'] == "true") { - this.onInitForCreateNewServicePopup(params['hasTemplate']); + this.onInitForCreateNewServicePopup(params['isInstantiationTemplateExists']); } }); @@ -107,7 +106,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole } } - private onInitForCreateNewServicePopup(hasTemplate : boolean) { + private onInitForCreateNewServicePopup(isInstantiationTemplateExists : boolean) { this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => { this.uuidData = <any>{ bulkSize: 1, @@ -117,8 +116,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole popupService: this._servicePopupService, }; - this.showTemplateBtn = this._genericFormPopupService.shouldShowTemplateBtn(hasTemplate); - this.isShowPreviousInstantiationBtn = !!this._store.getState().global.flags["FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER"]; + this.showTemplateBtn = this._genericFormPopupService.shouldShowTemplateBtn(isInstantiationTemplateExists); this.uuidData.popupService.closeDialogEvent.subscribe((that) => { this.closeDialog(that); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts index 53f345af0..e69cd5692 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts @@ -24,6 +24,7 @@ import {VfModuleUpgradePopupService} from "./genericFormServices/vfModuleUpgrade import {SharedControllersService} from "../genericForm/formControlsServices/sharedControlles/shared.controllers.service"; import {AppState} from "../../store/reducers"; import each from 'jest-each'; +import {SharedTreeService} from "../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; class MockAppStore<T>{ getState() { @@ -977,6 +978,7 @@ describe('Generic Form popup Service', () => { VfModuleUpgradePopupService, VfModuleControlGenerator, FeatureFlagsService, + SharedTreeService, {provide: ActivatedRoute, useClass: ActivatedRouteMock}, {provide: NgRedux, useClass: MockAppStore}] }); @@ -1074,14 +1076,14 @@ describe('Generic Form popup Service', () => { const shouldShowTemplateBtnDataProvider = [ - ['shouldShowTemplateBtn : should return true if flag is true and has template', true , true, true], - ['shouldShowTemplateBtn : should return false if flag is false and has template',false , true, false], - ['shouldShowTemplateBtn : should return false if flag is true and has no template',true , false, false], - ['shouldShowTemplateBtn : should return false if flag is false and has no template',false , false, false]]; - each(shouldShowTemplateBtnDataProvider).test('%s', (desc : string, flag : boolean, hasTemplate : boolean, expected : boolean ) => { + ['shouldShowTemplateBtn : should return true if flag is true and has instantiation template', true , true, true], + ['shouldShowTemplateBtn : should return false if flag is false and has instantiation template',false , true, false], + ['shouldShowTemplateBtn : should return false if flag is true and has no instantiation template',true , false, false], + ['shouldShowTemplateBtn : should return false if flag is false and has no instantiation template',false , false, false]]; + each(shouldShowTemplateBtnDataProvider).test('%s', (desc : string, flag : boolean, isInstantiationTemplateExists : boolean, expected : boolean ) => { spyOn(_featureFlagsService, 'getFlagState').and.returnValue(flag) - const result: boolean = service.shouldShowTemplateBtn(hasTemplate); + const result: boolean = service.shouldShowTemplateBtn(isInstantiationTemplateExists); expect(result).toEqual(expected); }); }); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.ts index 2998ba92b..e3cdaef85 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.ts @@ -95,10 +95,10 @@ export class GenericFormPopupService { - shouldShowTemplateBtn = (hasTemplate: boolean) : boolean => { + shouldShowTemplateBtn = (isInstantiationTemplateExists: boolean) : boolean => { const instantiationTemplateFlag = this._featureFlagsService.getFlagState(Features.FLAG_2004_INSTANTIATION_TEMPLATES_POPUP); if(instantiationTemplateFlag){ - return hasTemplate; + return isInstantiationTemplateExists; } return false; } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts index 9bcc02d73..13438929b 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts @@ -11,9 +11,9 @@ import {IframeService} from "../../../utils/iframe.service"; import {DefaultDataGeneratorService} from "../../../services/defaultDataServiceGenerator/default.data.generator.service"; import {FormControlModel} from "../../../models/formControlModels/formControl.model"; import {BasicPopupService} from "./basic.popup.service"; -import {SdcUiServices} from "onap-ui-angular"; import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service"; import {getTestBed, TestBed} from "@angular/core/testing"; +import {ModalService} from "../../customModal/services/modal.service"; class MockAppStore<T> {} @@ -1996,7 +1996,7 @@ describe('Basic popup service', () => { {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockReduxStore}, {provide: HttpClient, useClass: MockAppStore}, - {provide: SdcUiServices.ModalService, useClass: MockModalService} + {provide: ModalService, useClass: MockModalService} ] }); await TestBed.compileComponents(); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts index 34d6850eb..a32320ea4 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts @@ -14,6 +14,7 @@ import {BasicPopupService} from "../basic.popup.service"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; import {getTestBed, TestBed} from "@angular/core/testing"; import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service"; +import {ModalService} from "../../../customModal/services/modal.service"; class MockAppStore<T> {} @@ -2001,7 +2002,7 @@ describe('Network popup service', () => { {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockReduxStore}, {provide: HttpClient, useClass: MockAppStore}, - {provide: SdcUiServices.ModalService, useClass: MockModalService} + {provide: ModalService, useClass: MockModalService} ] }); await TestBed.compileComponents(); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts index 3a106ec93..13b72f080 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts @@ -11,10 +11,10 @@ import {BasicPopupService} from "../basic.popup.service"; import {ServicePopupService} from "./service.popup.service"; import {ServiceControlGenerator} from "../../../genericForm/formControlsServices/service.control.generator"; import {FormControlModel} from "../../../../models/formControlModels/formControl.model"; -import {SdcUiServices} from "onap-ui-angular"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; import {getTestBed, TestBed} from "@angular/core/testing"; import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service"; +import {ModalService} from "../../../customModal/services/modal.service"; class MockModalService<T> {} @@ -2067,7 +2067,7 @@ describe('Service popup service', () => { {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockReduxStore}, {provide: HttpClient, useClass: MockAppStore}, - {provide: SdcUiServices.ModalService, useClass: MockModalService} + {provide: ModalService, useClass: MockModalService} ] }); await TestBed.compileComponents(); @@ -2142,33 +2142,6 @@ describe('Service popup service', () => { expect(service.closeDialogEvent.next).toHaveBeenCalledWith(that); }); - test('showPreviousInstantiations should trigger postMessage', () => { - let that = <any>{ - parentElementClassName: 'content', - _iframeService: iframeService, - resetPopupData : () =>{ }, - serviceModel:{ - uuid:'1111' - } - - }; - - let expectedMessage= { - eventId: 'showPreviousInstantiations', - data: { - serviceModelId: that.serviceModel.uuid - } - }; - - jest.spyOn(window.parent, 'postMessage'); - - service.showPreviousInstantiations(that, fb.group({})); - - expect( window.parent.postMessage).toHaveBeenCalledWith(expectedMessage,"*") - - }); - - test('getDynamicInputs should return list of controls' ,() => { const result: FormControlModel[] = service.getDynamicInputs('6b528779-44a3-4472-bdff-9cd15ec93450'); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts index d25ab2c7f..588d2345b 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts @@ -61,9 +61,6 @@ export class ServicePopupService implements GenericPopupInterface { (that, form: FormGroup) => {that.onSubmit(that, form);}, (that: any, form: FormGroup) => { that.onCancel(that, form); - }, - (that: any, form: FormGroup) => { - that.showPreviousInstantiations(that, form); } ); } @@ -133,12 +130,6 @@ export class ServicePopupService implements GenericPopupInterface { this.onCancel(that, form); } - showPreviousInstantiations(that, form: FormGroup,): void { - const eventId = 'showPreviousInstantiations'; - this.postMessageToWindowParent(eventId, that.serviceModel.uuid); - this.onCancel(that, form); - } - private postMessageToWindowParent(eventId: string, serviceModelId:string) { window.parent.postMessage({ eventId: eventId, diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service.spec.ts index b16c5bdc0..b8a592247 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service.spec.ts @@ -10,10 +10,11 @@ import {DefaultDataGeneratorService} from "../../../../services/defaultDataServi import {BasicPopupService} from "../basic.popup.service"; import {VfModulePopupService} from "./vfModule.popup.service"; import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator"; -import {SdcUiServices} from "onap-ui-angular"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; import {getTestBed, TestBed} from "@angular/core/testing"; import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service"; +import {ModalService} from "../../../customModal/services/modal.service"; +import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; class MockModalService<T> {} @@ -1993,10 +1994,11 @@ describe('VFModule popup service', () => { AaiService, LogService, BasicPopupService, + SharedTreeService, {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockReduxStore}, {provide: HttpClient, useClass: MockAppStore}, - {provide: SdcUiServices.ModalService, useClass: MockModalService} + {provide: ModalService, useClass: MockModalService} ] }); await TestBed.compileComponents(); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts index 2ca992f08..578c37ef0 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts @@ -1,10 +1,6 @@ import {LogService} from "../../../../utils/log/log.service"; import {NgRedux} from "@angular-redux/store"; -import { - ControlGeneratorUtil, - SDN_C_PRE_LOAD, - SUPPLEMENTARY_FILE -} from "../../../genericForm/formControlsServices/control.generator.util.service"; +import {ControlGeneratorUtil, SDN_C_PRE_LOAD, SUPPLEMENTARY_FILE} from "../../../genericForm/formControlsServices/control.generator.util.service"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {HttpClient} from "@angular/common/http"; import {GenericFormService} from "../../../genericForm/generic-form.service"; @@ -26,6 +22,7 @@ import {ServiceActions} from "../../../../storeUtil/utils/service/service.action import {FormControlModel} from "../../../../models/formControlModels/formControl.model"; import * as _ from "lodash"; import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service"; +import {ModalService} from "../../../customModal/services/modal.service"; class MockModalService<T> {} @@ -87,7 +84,7 @@ describe('VFModule popup service', () => { {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockReduxStore}, {provide: HttpClient, useClass: MockAppStore}, - {provide: SdcUiServices.ModalService, useClass: MockModalService} + {provide: ModalService, useClass: MockModalService} ] }); await TestBed.compileComponents(); @@ -191,7 +188,7 @@ describe('VFModule popup service', () => { }; form.controls = { supplementaryFile_hidden_content : { - value: '{"c": "c", "d": 1}' + value: '[{"name": "c", "value": "c"}, {"name": "d", "value": "1"}]' }, supplementaryFile_hidden : { value: { @@ -203,7 +200,7 @@ describe('VFModule popup service', () => { let expectedMergePayload = { a: "value", b: "another", - supplementaryFileContent: {c: "c", d: 1}, + supplementaryFileContent: [{"name": "c", "value": "c"}, {"name": "d", "value": "1"}], supplementaryFileName: "name" }; diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html index 84783c273..39c6da4f4 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html @@ -56,7 +56,6 @@ <th class="header-title" id="header-summary">Summary</th> <th class="header-title" id="header-region">Region</th> <th class="header-title" id="header-tenant">Tenant</th> - <th class="header-title" id="header-aicZone">AIC Zone</th> </tr> </thead> <tbody> @@ -139,16 +138,6 @@ </custom-ellipsis> </div> </td> - <td> - <div> - <custom-ellipsis - [dataTestId]="'aicZone-' + item.jobId" - [id]="item.aicZone" - [value]="item.aicZone" - [breakWord]="true"> - </custom-ellipsis> - </div> - </td> </tr> </tbody> </table> diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts index 61f75e84b..a479e0cbf 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts @@ -17,9 +17,6 @@ class ActivatedRouteMock<T> { } } -// - - class MockAppStore {} describe('instantiation templates modal service', () => { @@ -123,7 +120,6 @@ describe('instantiation templates modal service', () => { expect(tableRows[0].instantiationStatus).toEqual('FAILED'); expect(tableRows[0].region).toEqual('hvf6 (AAA1)'); expect(tableRows[0].tenant).toEqual('AIN Web Tool-15-D-SSPtestcustome'); - expect(tableRows[0].aicZone).toEqual('VSDKYUTP-BAN1'); expect(tableRows[0].jobId).toEqual('9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c'); }); @@ -136,6 +132,14 @@ describe('instantiation templates modal service', () => { expect(result.region).toEqual('regionId (OWNER)'); }); + test('getRegion if null should return empty string', () => { + let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({ + owningEntityName: 'att-owner', + regionId: null + }); + expect(result.region).toEqual('(OWNER)'); + }); + test('getCloudOwner should not return owningEntityName if not exist', () => { let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({owningEntityName: null, regionId: 'regionId'}); expect(result.region).toEqual('regionId'); @@ -173,7 +177,7 @@ describe('instantiation templates modal service', () => { service.navigateToNewServiceModal(serviceModelId); - expect(_router.navigate).toBeCalledWith(["/servicePopup"], {"queryParams": {"isCreate": true, "serviceModelId": serviceModelId, hasTemplate : true}, "queryParamsHandling": "merge"}); + expect(_router.navigate).toBeCalledWith(["/servicePopup"], {"queryParams": {"isCreate": true, "serviceModelId": serviceModelId, isInstantiationTemplateExists : true}, "queryParamsHandling": "merge"}); }) }); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts index c7c198fcb..5c092e9af 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts @@ -30,7 +30,7 @@ export class InstantiationTemplatesModalService { navigateToNewServiceModal(serviceModelId: string) { - this._router.navigate(['/servicePopup'], { queryParams: { serviceModelId: serviceModelId, isCreate:true, hasTemplate : true}, queryParamsHandling: 'merge' }); + this._router.navigate(['/servicePopup'], { queryParams: { serviceModelId: serviceModelId, isCreate:true, isInstantiationTemplateExists : true}, queryParamsHandling: 'merge' }); } } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts index f2eda9df3..56f76b32f 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts @@ -10,7 +10,6 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{ readonly summary?: string; readonly region?: string; readonly tenant?: string; - readonly aicZone?: string; constructor(data) { super(data); @@ -21,7 +20,6 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{ this.summary = this.convertRequestSummaryFromMapToString(data.requestSummary); this.region = this.getRegion(data.regionId, data.owningEntityName); this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null; - this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null; } @@ -36,7 +34,8 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{ getRegion = (regionId: string, owningEntityName: string): string => { const convertOwning = !_.isNil(owningEntityName) ? `(${this.getCloudOwner(owningEntityName)})` : ''; - return `${regionId} ${convertOwning}`.trim(); + const region = !_.isNil(regionId) ? regionId : ''; + return `${region} ${convertOwning}`.trim(); }; diff --git a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts index c610110fd..5251a0aae 100644 --- a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts +++ b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts @@ -30,7 +30,7 @@ import { Component } from '@angular/core'; import { MessageBoxData} from './messageBox.data'; import { MessageBoxService } from './messageBox.service'; -import { SdcUiServices} from "onap-ui-angular"; +import {ModalService} from "../customModal/services/modal.service"; @Component({ selector: 'message-box', @@ -38,9 +38,9 @@ import { SdcUiServices} from "onap-ui-angular"; }) export class MessageBoxComponent { - modalService: SdcUiServices.ModalService; + modalService: ModalService; isOpened : boolean = false; - constructor(modalService: SdcUiServices.ModalService, private _messageBoxService : MessageBoxService) { + constructor(modalService: ModalService, private _messageBoxService : MessageBoxService) { this.modalService = modalService; MessageBoxService.openModal.subscribe((messageBoxData: MessageBoxData) => { diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts new file mode 100644 index 000000000..d29144095 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts @@ -0,0 +1,15 @@ +import {ButtonType} from "../customModal/models/button.type"; + +export class MessageModalModel { + title : string; + text : string; + type : 'error' | 'info' | 'success'; + buttons : {text: string, size: string, type : ButtonType, closeModal: boolean}[]; + + constructor( title : string, text : string, type , buttons : {text: string, size: string, type : ButtonType, closeModal: boolean}[]){ + this.title = title; + this.text = text; + this.type = type; + this.buttons = buttons; + } +} diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts new file mode 100644 index 000000000..ffaccb198 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts @@ -0,0 +1,56 @@ +import {MessageModal} from "./message-modal.service"; +import {getTestBed, TestBed} from "@angular/core/testing"; +import {SdcUiCommon} from "onap-ui-angular"; +import each from "jest-each"; +import {MessageBoxService} from "../messageBox/messageBox.service"; +import {MessageModalModel} from "./message-modal.model"; +import {MessageBoxData} from "../messageBox/messageBox.data"; + + +describe('Message Modal Service', () => { + let injector; + let service: MessageModal; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [], + providers: [MessageModal] + }); + await TestBed.compileComponents(); + + injector = getTestBed(); + service = injector.get(MessageModal); + })().then(done).catch(done.fail)); + + + each([ + ["error", SdcUiCommon.ModalType.error], + ["info", SdcUiCommon.ModalType.info], + ["success", SdcUiCommon.ModalType.success] + ]).test('getModalType with type %s should return %s', (inputMessageType, expectedResult) => { + + let message = { + type: inputMessageType + }; + + const type = MessageModal.getModalType(<any>message) + expect(type).toEqual(expectedResult); + }); + + test('showMessageModal should call open modal with all data' , async (done)=>{ + spyOn(MessageBoxService.openModal, 'next'); + let message : MessageModalModel = new MessageModalModel('title', 'text', "success", []); + + MessageModal.showMessageModal(message); + setTimeout(()=>{ + const messageBoxData = new MessageBoxData( message.title, + message.text, + SdcUiCommon.ModalType.success, + SdcUiCommon.ModalSize.medium, + message.buttons) + expect(MessageBoxService.openModal.next).toHaveBeenCalledWith(messageBoxData); + done(); + }, 500) + }); + +}); diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts new file mode 100644 index 000000000..e1f85bdb0 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts @@ -0,0 +1,39 @@ +import {Injectable} from "@angular/core"; +import {MessageBoxService} from '../messageBox/messageBox.service'; +import {MessageBoxData} from '../messageBox/messageBox.data'; +import {SdcUiCommon} from "onap-ui-angular"; +import {MessageModalModel} from "./message-modal.model"; + +@Injectable() +export class MessageModal { + static showMessageModal(message: MessageModalModel): void { + setTimeout(() => { + let messageBoxData: MessageBoxData = new MessageBoxData( + message.title, + message.text, + this.getModalType(message), + SdcUiCommon.ModalSize.medium, + message.buttons); + MessageBoxService.openModal.next(messageBoxData); + } + , 500); + }; + + + static getModalType = (message: MessageModalModel): string => { + switch (message.type) { + case "error": { + return SdcUiCommon.ModalType.error + } + case "info": { + return SdcUiCommon.ModalType.info; + } + case "success": { + return SdcUiCommon.ModalType.success; + } + } + }; +} + + + diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/search-elements-modal.component.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-elements-modal.component.ts index 47f849059..7d9561c9a 100644 --- a/vid-webpack-master/src/app/shared/components/searchMembersModal/search-elements-modal.component.ts +++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-elements-modal.component.ts @@ -44,7 +44,7 @@ export class SearchElementsModalComponent extends DialogComponent<{ modalInforma }) } - @ViewChild('ElementsTableComponent') membersTable; + @ViewChild('ElementsTableComponent', {static: false}) membersTable; ngOnInit(selectedRowsIds?: string[]): void { const genericModalHelper = this._store.getState().global.genericModalHelper; diff --git a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html index 238f7693d..f0a4da99f 100644 --- a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html +++ b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html @@ -1,6 +1,6 @@ -<sdc-loader name= "global" +<custom-loader name= "global" #globalLoader [global] = "global" [size]="size" - [(active)] = "show"></sdc-loader> + [(active)] = "show"></custom-loader> diff --git a/vid-webpack-master/src/app/shared/components/svg/svg-component.ts b/vid-webpack-master/src/app/shared/components/svg/svg-component.ts index 2e4642432..2b5727bb3 100644 --- a/vid-webpack-master/src/app/shared/components/svg/svg-component.ts +++ b/vid-webpack-master/src/app/shared/components/svg/svg-component.ts @@ -10,14 +10,14 @@ import * as _ from 'lodash'; @Component({ selector : 'vid-svg-icon', - template: ` - <svg-icon + template: ` + <custom-icon [mode]="mode" [size]="size" [name]="name" [testId]="testId" [clickable]="clickable"> - </svg-icon> + </custom-icon> `, diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts index f505b5667..1675917d2 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts @@ -1,11 +1,13 @@ import {FormControlModel} from "./formControl.model"; import {FormControlType} from "./formControlTypes.enum"; +import * as _ from "lodash"; export class CheckboxFormControl extends FormControlModel{ - + extraContents : object[]; constructor(data) { super(data); this.type = FormControlType.CHECKBOX; this.validations = []; + this.extraContents = !_.isNil(data.extraContents) ? data.extraContents : null; } } diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts index 24116549e..b3a53d9f2 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts @@ -43,6 +43,7 @@ export class FormControlModel { this.preventionsAttribute = data.preventionsAttribute || []; this.onBlur = function(){}; this.onChange = data.onChange ? data.onChange: function () {} + } isRequired() : boolean { diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts index 40d74d63f..36704e28e 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts @@ -14,8 +14,6 @@ export class FormPopupDetails { modelInformationItems: ModelInformationItem[]; onSubmit : (that : any, form: FormGroup , ...args) => void; onCancel : (that : any, form: FormGroup) => void; - onOtherAction: (that: any, form: FormGroup) => void; - constructor(that : any, popupTypeName : PopupType , @@ -27,8 +25,7 @@ export class FormPopupDetails { dynamicInputsControlList : FormControlModel[], modelInformationItems : ModelInformationItem[], onSubmit : (that : any, form : FormGroup, ...args) => void, - onCancel: (that: any, form: FormGroup) => void, - onOtherAction?: (that: any, form: FormGroup) => void) { + onCancel: (that: any, form: FormGroup) => void) { this.title = title; this.leftSubTitle = leftSubTitle; this.rightSubTitle = rightSubTitle; @@ -37,7 +34,6 @@ export class FormPopupDetails { this.modelInformationItems = modelInformationItems; this.onSubmit = onSubmit; this.onCancel = onCancel; - this.onOtherAction = onOtherAction; this.popupTypeName = popupTypeName; this.UUIDData = UUIDData; this.that = that; diff --git a/vid-webpack-master/src/app/shared/models/treeNodeModel.ts b/vid-webpack-master/src/app/shared/models/treeNodeModel.ts index 9242add85..39f56228e 100644 --- a/vid-webpack-master/src/app/shared/models/treeNodeModel.ts +++ b/vid-webpack-master/src/app/shared/models/treeNodeModel.ts @@ -3,6 +3,7 @@ import {NodeModel} from "./nodeModel"; import {ServiceNodeTypes} from "./ServiceNodeTypes"; import * as _ from 'lodash'; import {ServiceInstanceActions} from "./serviceInstanceActions"; + export enum TreeLevel { Level_0 , Level_1, Level_2 @@ -16,6 +17,7 @@ interface TreeNodeInstanceInterface { export class TreeNodeModel { type: String; modelId: string; + modelInvariantId?: string; modelCustomizationId?: string; modelUniqueId?: string; id: string; @@ -32,6 +34,7 @@ export class TreeNodeModel { instanceName?: string; constructor(instance: ChildNodeInstance, nodeModel: NodeModel){ + this.modelInvariantId = nodeModel.invariantUuid; this.modelCustomizationId = nodeModel.customizationUuid; this.modelId = nodeModel.uuid; this.modelUniqueId = this.modelCustomizationId || this.modelId; diff --git a/vid-webpack-master/src/app/shared/services/aaiService/aai.epics.ts b/vid-webpack-master/src/app/shared/services/aaiService/aai.epics.ts index a850d55da..3a05157ae 100644..100755 --- a/vid-webpack-master/src/app/shared/services/aaiService/aai.epics.ts +++ b/vid-webpack-master/src/app/shared/services/aaiService/aai.epics.ts @@ -22,7 +22,6 @@ import { updateProductFamilies, updateUserId } from "../../storeUtil/utils/general/general.actions"; import {createServiceInstance} from "../../storeUtil/utils/service/service.actions"; -import {delay, mapTo} from "rxjs/operators"; const notFetchedAlready = (state: AppState): boolean => state.service.productFamilies !== null; @@ -30,7 +29,6 @@ const notFetchedAlready = (state: AppState): boolean => state.service.productFam export class AAIEpics { constructor(private aaiService: AaiService) { } - public createEpic() { return combineEpics( this.loadProductFamiliesEpic @@ -49,7 +47,11 @@ export class AAIEpics { private loadProductFamiliesEpic = (action$, store) => action$ .ofType(LOAD_PRODUCT_FAMILIES) - .switchMap(() => this.aaiService.getProductFamilies().map(data => updateProductFamilies(data))); + .switchMap(() => + this.aaiService.getProductFamilies() + .map(data => + updateProductFamilies(data) + )); private loadCategoryParameters = (action$, store) => action$ .ofType(LOAD_CATEGORY_PARAMETERS) @@ -64,7 +66,9 @@ export class AAIEpics { private loadServiceAccordingToUuid = (action$, store) => action$ .ofType(LOAD_SERVICE_MDOEL_BY_UUID) .switchMap((action) => this.aaiService.getServiceModelById(action.modelId) - .map(data => createServiceInstance(action.uuid, data))); + .map(data => + createServiceInstance(action.uuid, data)) + ); private loadUserId = (action$, store) => action$ .ofType(LOAD_USER_ID) diff --git a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts index 1cc5593f7..9026a5648 100644 --- a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts +++ b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts @@ -44,6 +44,11 @@ export class AaiService { } + sdncPreload(): Observable<boolean> { + let pathQuery: string = Constants.Path.PRE_LOAD; + return this.http.post<boolean>(pathQuery, {}) + } + getServiceModelById = (serviceModelId: string): Observable<any> => { if (_.has(this.store.getState().service.serviceHierarchy, serviceModelId)) { return of(<any> JSON.parse(JSON.stringify(this.store.getState().service.serviceHierarchy[serviceModelId]))); diff --git a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts index cccade887..5842662fb 100644 --- a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts +++ b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts @@ -15,8 +15,11 @@ export enum Features { FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS', FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER', FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE', - FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER ='FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER', - FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP' + FLAG_2006_VFM_SDNC_PRELOAD_FILES = 'FLAG_2006_VFM_SDNC_PRELOAD_FILES', + FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO = 'FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO', + FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP', + FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY= 'FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY', + FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF = 'FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF', } @Injectable() diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts index f95f86149..bae7c11f9 100644 --- a/vid-webpack-master/src/app/shared/shared.module.ts +++ b/vid-webpack-master/src/app/shared/shared.module.ts @@ -49,7 +49,6 @@ import {ServicePopupService} from "./components/genericFormPopup/genericFormServ import {GenericFormPopupService} from "./components/genericFormPopup/generic-form-popup.service"; import {FormGeneralErrorsService} from "./components/formGeneralErrors/formGeneralErrors.service"; import {VnfPopupService} from "./components/genericFormPopup/genericFormServices/vnf/vnf.popup.service"; -import {SdcUiComponentsModule, SdcUiServices} from "onap-ui-angular"; import {SafePipe} from "./pipes/safe/safe.pipe"; import {ViewEditResolver} from "./resolvers/viewEdit/viewEdit.resolver"; import {FlagsResolve} from "./resolvers/flag/flag.resolver"; @@ -80,6 +79,24 @@ import {SearchFilterPipe} from "./pipes/searchFilter/search-filter.pipe"; import {RecreateResolver} from "./resolvers/recreate/recreate.resolver"; import {InstantiationTemplatesService} from "./services/templateService/instantiationTemplates.service"; import {SharedControllersService} from "./components/genericForm/formControlsServices/sharedControlles/shared.controllers.service"; +import {DuplicateVnfComponent} from "../drawingBoard/service-planning/duplicate/duplicate-vnf.component"; +import {ModalService} from "./components/customModal/services/modal.service"; +import {CreateDynamicComponentService} from "./components/customModal/services/create-dynamic-component.service"; +import {ModalComponent} from "./components/customModal/modal.component"; +import {ModalCloseButtonComponent} from './components/customModal/components/modalCloseButton/modal-close-button.component'; +import {CustomButtonComponent} from "./components/customButton/custom-button.component"; +import {CustomModalButtonComponent} from "./components/customModal/components/modalButton/modal-button.component"; +import {CustomRippleClickAnimationDirective} from "./components/customModal/directives/ripple-click.animation.directive"; +import {LoaderComponent} from "./components/customLoader/custom-loader.component"; +import {LoaderService} from "./components/customLoader/custom-loader.service"; +import {SvgIconComponent} from "./components/customIcon/custom-icon.component"; +import {TooltipTemplateComponent} from "./components/customTooltip/custom-tooltip.component"; +import {TooltipDirective} from "./components/customTooltip/tooltip.directive"; +import {SdcUiComponentsModule} from "onap-ui-angular"; +import {UploadFilesLinkComponent} from "./components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component"; +import { FileUploadModule } from 'ng2-file-upload'; +import {MessageModal} from "./components/messageModal/message-modal.service"; + @NgModule({ @@ -92,12 +109,13 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer FeatureFlagModule.forRoot(), FormsModule, ReactiveFormsModule, - TooltipModule, SdcUiComponentsModule, + TooltipModule, AngularMultiSelectModule, BootstrapModalModule, DataTableModule, - ModalModule.forRoot() + ModalModule.forRoot(), + FileUploadModule ], declarations: [ PopoverComponent, @@ -110,6 +128,8 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer NumberFormControlComponent, InputPreventionPatternDirective, ClickOutsideDirective, + TooltipDirective, + CustomRippleClickAnimationDirective, FormGeneralErrorsComponent, SpinnerComponent, NoContentMessageAndIconComponent, @@ -133,7 +153,15 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer ErrorMsgComponent, DynamicInputsComponent, DynamicInputLabelPipe, - InstantiationTemplatesModalComponent + InstantiationTemplatesModalComponent, + ModalComponent, + ModalCloseButtonComponent, + CustomButtonComponent, + CustomModalButtonComponent, + LoaderComponent, + SvgIconComponent, + TooltipTemplateComponent, + UploadFilesLinkComponent ], exports: [ PopoverComponent, @@ -142,7 +170,9 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer FormControlErrorComponent, DropdownFormControlComponent, InputPreventionPatternDirective, + CustomRippleClickAnimationDirective, ClickOutsideDirective, + TooltipDirective, FormGeneralErrorsComponent, SpinnerComponent, NoContentMessageAndIconComponent, @@ -165,18 +195,29 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer ErrorMsgComponent, SvgComponent, DynamicInputsComponent, - DynamicInputLabelPipe + DynamicInputLabelPipe, + ModalComponent, + ModalCloseButtonComponent, + CustomButtonComponent, + CustomModalButtonComponent, + LoaderComponent, + SvgIconComponent, + TooltipTemplateComponent, + UploadFilesLinkComponent ], entryComponents : [ GenericFormPopupComponent, SearchElementsModalComponent, - InstantiationTemplatesModalComponent + InstantiationTemplatesModalComponent, + DuplicateVnfComponent, + ModalComponent ], providers: [ ServiceInfoService, MessageBoxService, - SdcUiServices.ModalService, - SdcUiServices.LoaderService, + CreateDynamicComponentService, + ModalService, + LoaderService, HttpInterceptorService, IframeService, DefaultDataGeneratorService, @@ -212,7 +253,9 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer SearchFilterPipe, ModelInformationService, MultiselectFormControlService, - InstantiationTemplatesModalService + InstantiationTemplatesModalService, + LoaderService, + MessageModal ] }) export class SharedModule { diff --git a/vid-webpack-master/src/app/shared/store/module.ts b/vid-webpack-master/src/app/shared/store/module.ts index 5a81f36ec..5a81f36ec 100644..100755 --- a/vid-webpack-master/src/app/shared/store/module.ts +++ b/vid-webpack-master/src/app/shared/store/module.ts diff --git a/vid-webpack-master/src/app/shared/utils/constants.ts b/vid-webpack-master/src/app/shared/utils/constants.ts index da717c8f4..01466f113 100644 --- a/vid-webpack-master/src/app/shared/utils/constants.ts +++ b/vid-webpack-master/src/app/shared/utils/constants.ts @@ -97,6 +97,7 @@ export module Constants { public static SERVICE_MODEL_ID = 'serviceModelId'; public static SERVICES_RETRY_TOPOLOGY = '../../asyncInstantiation/bulkForRetry'; public static INSTANTIATION_TEMPLATE_TOPOLOGY = '../../instantiationTemplates/templateTopology'; + public static PRE_LOAD = '../../preload'; public static CONFIGURATION_PATH = '../../get_property/{name}/defaultvalue'; public static SERVICES_JOB_AUDIT_PATH = '/auditStatus'; public static SERVICES_PROBE_PATH = "../../probe"; |