summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts110
-rw-r--r--vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json3
-rw-r--r--vid-webpack-master/package.json1
-rw-r--r--vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts45
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html21
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts98
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html161
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss192
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts55
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts133
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts15
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts51
-rw-r--r--vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts2
-rw-r--r--vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts37
-rw-r--r--vid-webpack-master/src/app/shared/shared.module.ts11
15 files changed, 855 insertions, 80 deletions
diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts
new file mode 100644
index 000000000..b862e568d
--- /dev/null
+++ b/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts
@@ -0,0 +1,110 @@
+///<reference path="../../../node_modules/cypress/types/index.d.ts"/>
+describe('Template', () => {
+
+ beforeEach(() => {
+ cy.clearSessionStorage();
+ cy.setReduxState();
+ cy.preventErrorsOnLoading();
+ cy.initAAIMock();
+ cy.initVidMock();
+ cy.login();
+ });
+
+ afterEach(() => {
+ cy.screenshot();
+ });
+
+ it('when open service popup should show template button', function () {
+ cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then((flags) => {
+ cy.server()
+ .route({
+ method: 'GET',
+ delay: 0,
+ status: 200,
+ url: Cypress.config('baseUrl') + "/flags**",
+ response: {
+ "FLAG_VF_MODULE_RESUME_STATUS_CREATE": false,
+ "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP": true
+ }
+ }).as('initFlags');
+ });
+
+ const asyncInstantiation = [
+ {
+ "id": 8,
+ "created": 1525075968000,
+ "modified": 1525075971000,
+ "action": "INSTANTIATE",
+ "createdId": null,
+ "modifiedId": null,
+ "rowNum": null,
+ "auditUserId": null,
+ "auditTrail": null,
+ "jobId": "5c2cd8e5-27d0-42e3-85a1-85db5eaba459",
+ "templateId": "d42ba7c8-9e19-4e34-ae2c-d8af3f24498e",
+ "userId": "16807000",
+ "aLaCarte": false,
+ "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d9c",
+ "jobStatus": "FAILED",
+ "statusModifiedDate": 1525075968000,
+ "hidden": false,
+ "pause": false,
+ "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc",
+ "owningEntityName": "WayneHolland",
+ "project": "WATKINS",
+ "aicZoneId": "NFT1",
+ "aicZoneName": "NFTJSSSS-NFT1",
+ "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054",
+ "tenantName": "AIN Web Tool-15-D-testalexandria",
+ "regionId": "hvf6",
+ "regionName": null,
+ "serviceType": "TYLER SILVIA",
+ "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89",
+ "serviceInstanceId": null,
+ "serviceInstanceName": "nWUfl instance name_002",
+ "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
+ "serviceModelName": "action-data",
+ "serviceModelVersion": "1.0",
+ "createdBulkDate": 1525075968000,
+ "isRetryEnabled": true
+ }
+ ];
+
+ cy.route(Cypress.config('baseUrl') + "/asyncInstantiation**", asyncInstantiation);
+
+ cy.openIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true');
+ cy.getElementByDataTestsId('templateButton').contains('Template')
+ .getElementByDataTestsId('templateButton').click({force: true}) // Open template Modal
+ .getElementByDataTestsId('template-modal-title').contains('Templates') // Check Modal header
+ .getElementByDataTestsId('description-part-1').contains('The following list presents previous instantiations done for this model in this version.')
+ .getElementByDataTestsId('description-part-2').contains('You may use one of them as a baseline for your instantiation or start from scratch.')
+ .getElementByDataTestsId('description-part-3').contains('Once you selecting one allows you to change the data before start instantiating.')
+
+
+ //check table headers
+ cy.get(`#header-userId`).contains('User ID');
+ cy.get(`#header-createDate`).contains('Date');
+ cy.get(`#header-instanceName`).contains('Instance Name');
+ cy.get(`#header-instantiationStatus`).contains('Instantiation Status');
+ cy.get(`#header-region`).contains('Region');
+ cy.get(`#header-tenant`).contains('Tenant');
+ cy.get(`#header-aicZone`).contains('AIC Zone');
+
+ // check table body row
+ cy.getElementByDataTestsId(`userId-${asyncInstantiation[0].jobId}`).contains('16807000');
+ cy.getElementByDataTestsId(`createDate-${asyncInstantiation[0].jobId}`).contains('2018-04-30 11:12:48');
+ cy.getElementByDataTestsId(`instanceName-${asyncInstantiation[0].jobId}`).contains('nWUfl instance name_002');
+ cy.getElementByDataTestsId(`instantiationStatus-${asyncInstantiation[0].jobId}`).contains('FAILED');
+ cy.getElementByDataTestsId(`region-${asyncInstantiation[0].jobId}`).contains('hvf6 (WAYNEHOLLAND)');
+ cy.getElementByDataTestsId(`tenant-${asyncInstantiation[0].jobId}`).contains('AIN Web Tool-15-D-testalexandria');
+ cy.getElementByDataTestsId(`aicZone-${asyncInstantiation[0].jobId}`).contains('NFTJSSSS-NFT1');
+
+
+ //check load button is disabled
+ cy.getElementByDataTestsId('LoadTemplateButton').should('be.disabled')
+ cy.getElementByDataTestsId('row-5c2cd8e5-27d0-42e3-85a1-85db5eaba459').click();
+ cy.getElementByDataTestsId('LoadTemplateButton').should('not.be.disabled')
+
+ });
+});
+
diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json
index b829361af..0f5e15298 100644
--- a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json
+++ b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json
@@ -19,5 +19,6 @@
"FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE": false,
"FLAG_2002_VNF_PLATFORM_MULTI_SELECT" : false,
"FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS": true,
- "FLAG_2004_INSTANTIATION_STATUS_FILTER": true
+ "FLAG_2004_INSTANTIATION_STATUS_FILTER": true,
+ "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP" : false
}
diff --git a/vid-webpack-master/package.json b/vid-webpack-master/package.json
index f76ab8745..f2f913612 100644
--- a/vid-webpack-master/package.json
+++ b/vid-webpack-master/package.json
@@ -56,6 +56,7 @@
"install": "0.12.2",
"jest-image-snapshot": "2.8.1",
"jest-preset-angular": "6.0.2",
+ "moment": "^2.24.0",
"ng-multiselect-dropdown": "0.1.3",
"ng2-bootstrap-modal": "1.0.1",
"ngx-bootstrap": "^2.0.2",
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 07f4d481b..a7b8ac744 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
@@ -3,18 +3,20 @@ import {HighlightPipe} from "../../pipes/highlight/highlight-filter.pipe";
import * as _ from 'lodash';
@Component({
- selector : 'custom-ellipsis',
+ selector: 'custom-ellipsis',
template: `
<span
- sdc-tooltip
- class="ellipsis"
- id="{{id}}"
- [innerHtml]="displayValue | safe : 'html'"
- [ngClass]="{'breakWord' : breakWord == true}"
- [tooltip-text]="value">
+ sdc-tooltip
+ class="ellipsis"
+ [attr.data-tests-id]="dataTestId"
+ id="{{id}}"
+ [innerHtml]="displayValue | safe : 'html'"
+ [ngStyle]="{'white-space' : showDots ? 'nowrap' : 'initial'}"
+ [ngClass]="{'breakWord' : breakWord == true}"
+ [tooltip-text]="value">
</span>`,
- styles : [
- `
+ styles: [
+ `
.ellipsis {
white-space: nowrap;
overflow: hidden;
@@ -23,30 +25,33 @@ import * as _ from 'lodash';
width: 99%;
text-align: left;
}
-
+
.breakWord {
word-wrap: break-word;
white-space: normal;
}
`
],
- providers : [HighlightPipe]
+ providers: [HighlightPipe]
})
-export class EllipsisComponent implements OnChanges{
- @Input() value : string;
- @Input() id : string;
- @Input() hightlight : string;
- @Input() breakWord : boolean = false;
+export class EllipsisComponent implements OnChanges {
+ @Input() value: string;
+ @Input() id: string;
+ @Input() hightlight: string;
+ @Input() breakWord: boolean = false;
+ @Input() dataTestId: string;
+ @Input() showDots: boolean = false;
+
+ displayValue: string;
- displayValue : string;
- constructor(private _highlightPipe : HighlightPipe){
+ constructor(private _highlightPipe: HighlightPipe) {
this.displayValue = this.value;
}
ngOnChanges(changes: SimpleChanges): void {
this.displayValue = this.value;
- if(!_.isNil(this.hightlight)){
- this.displayValue = this._highlightPipe.transform(this.value ,this.hightlight ? this.hightlight : '');
+ if (!_.isNil(this.hightlight)) {
+ this.displayValue = this._highlightPipe.transform(this.value, this.hightlight ? this.hightlight : '');
}
}
}
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 57064f658..5b8dfa9c9 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
@@ -3,14 +3,13 @@
<div class="modal-header">
<button type="button"
class="close"
- (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)" >&times;
+ (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)">&times;
</button>
<span [attr.data-tests-id]="'create-modal-title'"
class="modal-title">{{formPopupDetails?.title}}
</span>
</div>
<div class="modal-body popup-content">
-
<div class="header-left">
<div>MODEL: <span>"{{formPopupDetails?.leftSubTitle}}"</span></div>
</div>
@@ -36,12 +35,14 @@
<model-information [modelInformationItems]="formPopupDetails?.modelInformationItems"></model-information>
</div>
- <div class="instance-form">
+ <div class="instance-form">
<div style="position: relative;height: 100%;overflow: auto;">
- <label id="notification-area" *ngIf="shouldShowNotification() == true" style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all service instances</label>
- <generic-form [formControls]="formPopupDetails?.formControlList"
- [dynamicInputs]="formPopupDetails?.dynamicInputsControlList"
- (onFormChanged)="dynamicForm = $event" ></generic-form>
+ <label id="notification-area" *ngIf="shouldShowNotification() == true"
+ style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all
+ service instances</label>
+ <generic-form [formControls]="formPopupDetails?.formControlList"
+ [dynamicInputs]="formPopupDetails?.dynamicInputsControlList"
+ (onFormChanged)="dynamicForm = $event"></generic-form>
</div>
</div>
@@ -54,6 +55,12 @@
</div>
<div class="col-md-6" style="padding: 15px;padding-right: 35px;">
<button
+ *ngIf="showTemplateBtn"
+ [attr.data-tests-id]="'templateButton'"
+ type="button" class="btn btn-success submit"
+ (click)="openTemplateModal()"
+ ><span>Template</span></button>
+ <button
[attr.data-tests-id]="'cancelButton'"
type="button" class="btn btn-default cancel"
(click)="formPopupDetails.onCancel(formPopupDetails.that, dynamicForm)"><span>Cancel</span></button>
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 d0e2d4b85..cadce7ddb 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
@@ -13,16 +13,17 @@ import {AaiService} from "../../services/aaiService/aai.service";
import {GenericFormPopupService} from "./generic-form-popup.service";
import {FormControlModel} from "../../models/formControlModels/formControl.model";
import {FormGeneralErrorsService} from "../formGeneralErrors/formGeneralErrors.service";
+import {InstantiationTemplatesModalComponent} from "./instantiationTemplatesModal/instantiation.templates.modal.component";
export interface PopupModel {
- type : PopupType;
- uuidData : UUIDData;
- node : ITreeNode;
- isUpdateMode : boolean;
+ type: PopupType;
+ uuidData: UUIDData;
+ node: ITreeNode;
+ isUpdateMode: boolean;
}
-export enum PopupType{
+export enum PopupType {
SERVICE = 'service',
VNF = 'vnf',
NETWORK = 'network',
@@ -33,36 +34,39 @@ export enum PopupType{
@Component({
- selector : 'generic-form-popup',
- templateUrl : 'generic-form-popup.component.html',
- styleUrls : ['generic-form-popup.component.scss']
+ selector: 'generic-form-popup',
+ templateUrl: 'generic-form-popup.component.html',
+ styleUrls: ['generic-form-popup.component.scss']
})
-export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy{
- formPopupDetails : FormPopupDetails = null;
- dynamicForm : FormGroup;
- type : PopupType;
- uuidData : UUIDData;
- isUpdateMode : boolean;
- node : ITreeNode = null;
- hasGeneralApiError : boolean = false;
+export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy {
+ formPopupDetails: FormPopupDetails = null;
+ dynamicForm: FormGroup;
+ type: PopupType;
+ uuidData: UUIDData;
+ showTemplateBtn: boolean = false;
+ isUpdateMode: boolean;
+ node: ITreeNode = null;
+ hasGeneralApiError: boolean = false;
parentElementClassName = 'content';
errorMsg = 'Page contains errors. Please see details next to the relevant fields.';
servicesQty = 1;
quantityOptions = _.range(1, 51)
- constructor(dialogService: DialogService ,
- private _iframeService : IframeService,
+
+ constructor(dialogService: DialogService,
+ private _iframeService: IframeService,
private _store: NgRedux<AppState>,
- private _servicePopupService : ServicePopupService,
- private _activatedRoute : ActivatedRoute,
- private _aaiService : AaiService,
+ private _servicePopupService: ServicePopupService,
+ private _activatedRoute: ActivatedRoute,
+ private _aaiService: AaiService,
+ private _dialogService: DialogService,
private _route: ActivatedRoute,
- private _genericFormPopupService : GenericFormPopupService){
+ private _genericFormPopupService: GenericFormPopupService) {
super(dialogService);
}
- closeDialog(that) : void{
+ closeDialog(that): void {
this._iframeService.removeClassCloseModal(that.parentElementClassName);
this.dialogService.removeDialog(this);
setTimeout(() => {
@@ -70,7 +74,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
}, 15);
}
- shouldShowNotification() : boolean {
+ shouldShowNotification(): boolean {
return this.formPopupDetails && this.formPopupDetails.UUIDData['bulkSize'] > 1
}
@@ -79,17 +83,18 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
.queryParams
.subscribe(params => {
console.log('changed');
- if(params['serviceModelId'] && params['isCreate']=="true"){
- this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId : string)=>{
+ if (params['serviceModelId'] && params['isCreate'] == "true") {
+ this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => {
this.uuidData = <any>{
- bulkSize : 1,
- isMacro : this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro',
- type : PopupType.SERVICE,
+ bulkSize: 1,
+ isMacro: this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro',
+ type: PopupType.SERVICE,
serviceId: serviceModelId,
popupService: this._servicePopupService,
};
+ this.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"];
- this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{
+ this.uuidData.popupService.closeDialogEvent.subscribe((that) => {
this.closeDialog(that);
});
@@ -105,12 +110,12 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
}
});
- FormGeneralErrorsService.checkForErrorTrigger.subscribe(()=>{
+ FormGeneralErrorsService.checkForErrorTrigger.subscribe(() => {
this.hasSomeError(this.formPopupDetails, this.dynamicForm);
});
-
- if(!_.isNil(this.uuidData)){
- this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{
+
+ if (!_.isNil(this.uuidData)) {
+ this.uuidData.popupService.closeDialogEvent.subscribe((that) => {
this.closeDialog(that);
});
@@ -119,28 +124,33 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
}
}
- hasSomeError(formPopupDetails : FormPopupDetails, form : FormGroup) : boolean{
- if(_.isNil(formPopupDetails)) return false;
+ hasSomeError(formPopupDetails: FormPopupDetails, form: FormGroup): boolean {
+ if (_.isNil(formPopupDetails)) return false;
else {
- for(let controlName in form.controls){
- if(form.controls[controlName].errors){
+ for (let controlName in form.controls) {
+ if (form.controls[controlName].errors) {
let error: string[] = Object.keys(form.controls[controlName].errors);
- if(error.length === 1 && error[0] === 'required'){
+ if (error.length === 1 && error[0] === 'required') {
continue;
- }else if(Object.keys(form.controls[controlName].errors).length > 0 ){
+ } else if (Object.keys(form.controls[controlName].errors).length > 0) {
return true;
}
}
}
}
- return formPopupDetails.formControlList.filter((item : FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0
+ return formPopupDetails.formControlList.filter((item: FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0
+ }
+
+
+ openTemplateModal = (): void => {
+ this._dialogService.addDialog(InstantiationTemplatesModalComponent, {});
}
}
-export class UUIDData extends Object{
- type : string;
- popupService : any;
+export class UUIDData extends Object {
+ type: string;
+ popupService: any;
}
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
new file mode 100644
index 000000000..c231c6081
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html
@@ -0,0 +1,161 @@
+<div id="template-popup" class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button"
+ class="close"
+ (click)="closeModal()">&times;
+ </button>
+ <span [attr.data-tests-id]="'template-modal-title'"
+ class="modal-title">Templates
+ </span>
+ </div>
+ <div class="modal-body templateModalBody">
+ <div class="row description-section">
+ <div class="col-md-6">
+ <div [attr.data-tests-id]="'description-part-1'">The following list presents previous instantiations done for
+ this model in this version.
+ </div>
+ <div [attr.data-tests-id]="'description-part-2'">You may use one of them as a baseline for your instantiation
+ or start from scratch.
+ </div>
+ <div [attr.data-tests-id]="'description-part-3'">Once you selecting one allows you to change the data before
+ start instantiating.
+ </div>
+ </div>
+ <div class="col-md-6">
+ <input
+ (keypress)="onFilterKeypress($event)"
+ class="filter-input form-control input-text"
+ placeholder="Filter...">
+ </div>
+
+ </div>
+ <div class="row" style="margin-left: 0;margin-right: 0;padding: 20px;">
+ <table id="member-table" class="table table-bordered" style="table-layout: fixed">
+ <thead class="thead-dark">
+ <tr>
+ <th class="header-title" id="header-userId">User ID</th>
+ <th class="header-title" id="header-createDate" style="width: 21ch;">Date</th>
+ <th class="header-title" id="header-instanceName" style="max-width: 50ch;">Instance Name</th>
+ <th class="header-title" id="header-instantiationStatus">Instantiation Status</th>
+ <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>
+ <tr class="member-table-row"
+ *ngFor="let item of filterTableData;"
+ (click)="selectedJobId = item.jobId"
+ [ngClass]="{'selected' : selectedJobId === item.jobId}"
+ [attr.data-tests-id]="'row-' + item.jobId">
+ <td>
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'userId-' + item.jobId"
+ [id]="item.userId"
+ [value]="item.userId"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td style="width: 21ch;">
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'createDate-' + item.jobId"
+ [id]="item.createDate"
+ [value]="item.createDate"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td style="max-width: 50ch;">
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'instanceName-' + item.jobId"
+ [id]="item.instanceName"
+ [value]="item.instanceName"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'instantiationStatus-' + item.jobId"
+ [id]="item.instantiationStatus"
+ [value]="item.instantiationStatus"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'summary-' + item.jobId"
+ [id]="item.summary"
+ [value]="item.summary"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'region-' + item.jobId"
+ [id]="item.region"
+ [value]="item.region"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'tenant-' + item.jobId"
+ [id]="item.tenant"
+ [value]="item.tenant"
+ [breakWord]="true">
+ </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>
+ </div>
+
+ </div>
+ <div class="modal-footer row" style="padding: 0">
+ <div class="col-md-6">
+ </div>
+ <div class="col-md-6" style="padding: 15px;padding-right: 35px;">
+ <button
+ [disabled]="selectedJobId === null"
+ [attr.data-tests-id]="'LoadTemplateButton'"
+ type="button" class="btn btn-primary submit"
+ (click)="loadTemplate()"><span>Load Template</span>
+ </button>
+ <button
+ [attr.data-tests-id]="'startFromScratchButton'"
+ type="button" class="btn btn-success submit startFromScratchButton"
+ (click)="closeModal()"><span>Start from Scratch</span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss
new file mode 100644
index 000000000..23c950c33
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss
@@ -0,0 +1,192 @@
+$grid-border: 1px #d2d2d2 solid;
+
+#template-popup {
+ color: #191919;
+
+ thead {
+ background: #F8F8F8;
+ }
+ .left-panel {
+ background: #f2f2f2;
+ border-right: $grid-border;
+ }
+
+ .header-common {
+ height: 100%;
+ align-items: center;
+ display: flex;
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+
+ .header-text {
+ padding-left: 30px;
+ @extend .header-common;
+ }
+
+ .header-left {
+ grid-area: header-left;
+ @extend .header-text;
+ @extend .left-panel;
+ border-bottom: $grid-border;
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ }
+ ;
+ }
+
+ .header-right {
+ grid-area: header-right;
+
+ @extend .header-text;
+ }
+
+ .quantity-label {
+ grid-area: quantity-label;
+ @extend .header-common;
+ height: 100%;
+ font-family: OpenSans-Regular;
+ }
+
+ input[type="number"]:hover::-webkit-inner-spin-button {
+ height: 20px;
+ }
+
+ .popup-content {
+ display: grid;
+ grid-template-columns: 400px auto 30px 93px;
+ grid-template-rows: 50px calc(100vh - 180px);
+ grid-template-areas: "header-left header-right quantity-label quantity" "model-information instance-form instance-form instance-form";
+ padding: 0;
+ }
+}
+
+.modal {
+ background-color: #191919;
+ opacity: 0.8;
+}
+
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0;
+}
+
+@media (min-width: 1150px) {
+ .popup-content {
+ grid-template-rows: 30px 680px;
+ }
+}
+
+.modal-content {
+ border-radius: 0;
+ box-shadow: none;
+ border: none;
+ min-height: calc(100vh);
+
+}
+
+.modal-footer {
+ padding: 0;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+
+ .cancel {
+ width: 120px;
+ height: 36px;
+ background: #ffffff;
+ border: 1px solid #009fdb;
+ border-radius: 2px;
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #009fdb;
+ line-height: 16px;
+ }
+ }
+
+ .startFromScratchButton {
+ width: 150px !important;
+ }
+
+ .submit {
+ width: 120px;
+ height: 36px;
+ background: #009fdb;
+ border-radius: 2px;
+ border-color: #009fdb;
+
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #FFFFFF;
+ line-height: 16px;
+ }
+ }
+}
+
+.modal-header {
+ background-color: #009fdb;
+
+ padding-bottom: 13px;
+ padding-top: 13px;
+ padding-left: 29px;
+ padding-right: 21px;
+
+ .close {
+ font-size: 32px;
+ font-weight: 200;
+ color: #d8d8d8;
+ text-shadow: none;
+ filter: none;
+ opacity: 1;
+ }
+
+ .modal-title {
+ font-family: OpenSans-Regular;
+ font-size: 24px;
+ color: #fff;
+ line-height: 34px;
+ }
+}
+
+.modal-body {
+ padding: 0;
+ height: calc(85vh);
+
+ .description-section {
+ padding: 20px;
+ font-size: 20px;
+ }
+
+ .filter-input {
+ float: right;
+ width: 25%;
+ }
+
+
+ td.loadTemplateButton {
+ text-align: center;
+ vertical-align: middle;
+ }
+
+ td {
+ text-align: center;
+ vertical-align: middle;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ .member-table-row:hover {
+ background: #80808033 !important;
+ }
+
+ .member-table-row.selected {
+ background: #009fdbb5 !important;
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts
new file mode 100644
index 000000000..56abe5b4c
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts
@@ -0,0 +1,55 @@
+import {Component, OnDestroy, OnInit} from "@angular/core";
+import {DialogComponent, DialogService} from "ng2-bootstrap-modal";
+import {IframeService} from "../../../utils/iframe.service";
+import {ActivatedRoute} from "@angular/router";
+import {ServiceInfoService} from "../../../server/serviceInfo/serviceInfo.service";
+import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+@Component({
+ selector: 'template-modal',
+ templateUrl: 'instantiation.templates.modal.component.html',
+ styleUrls: ['instantiation.templates.modal.component.scss']
+})
+
+export class InstantiationTemplatesModalComponent extends DialogComponent<string, boolean> implements OnInit, OnDestroy {
+
+ selectedJobId : string = null;
+ templateModalComponentService: InstantiationTemplatesModalService;
+ originalTableData: InstantiationTemplatesRowModel[] = [];
+ filterTableData : InstantiationTemplatesRowModel[] = [];
+
+ constructor(dialogService: DialogService,
+ private _iframeService: IframeService,
+ private _serviceInfoService: ServiceInfoService,
+ private _templateModalComponentService: InstantiationTemplatesModalService,
+ private _route: ActivatedRoute) {
+ super(dialogService);
+ this.templateModalComponentService = _templateModalComponentService;
+ }
+
+ ngOnInit(): void {
+ this._route
+ .queryParams
+ .subscribe(params => {
+ this._serviceInfoService.getServicesJobInfo(true, params['serviceModelId']).subscribe((jobs) => {
+ this.originalTableData = this._templateModalComponentService.convertResponseToUI(jobs);
+ this.filterTableData = this.originalTableData;
+ });
+ });
+ }
+
+ loadTemplate = () => {
+
+ };
+
+
+ onFilterKeypress = (event : KeyboardEvent) => {
+ //event.target.value
+ console.log(event.altKey);
+ };
+
+ closeModal(): void {
+ this.dialogService.removeDialog(this);
+ }
+}
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
new file mode 100644
index 000000000..f3bd9152e
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts
@@ -0,0 +1,133 @@
+import {getTestBed, TestBed} from '@angular/core/testing';
+import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
+import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service";
+import {AaiService} from "../../../services/aaiService/aai.service";
+import {ActivatedRoute} from "@angular/router";
+import {IframeService} from "../../../utils/iframe.service";
+import {NgRedux} from "@angular-redux/store";
+import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+
+class ActivatedRouteMock<T> {
+ queryParams() {
+ return {
+ serviceModelId: '6e59c5de-f052-46fa-aa7e-2fca9d674c44'
+ }
+ }
+}
+
+class MockAppStore {
+
+}
+
+describe('instantiation templates modal service', () => {
+ let injector;
+ let service: InstantiationTemplatesModalService;
+ let httpMock: HttpTestingController;
+ let _aaiService: AaiService;
+ let _activatedRoute: ActivatedRoute;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [InstantiationTemplatesModalService,
+ IframeService,
+ AaiService,
+ FeatureFlagsService,
+ {provide: ActivatedRoute, useClass: ActivatedRouteMock},
+ {provide: NgRedux, useClass: MockAppStore}
+ ]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ service = injector.get(InstantiationTemplatesModalService);
+ httpMock = injector.get(HttpTestingController);
+ _aaiService = injector.get(AaiService);
+ _activatedRoute = injector.get(ActivatedRoute);
+
+ })().then(done).catch(done.fail));
+
+
+ test('service should be defined', () => {
+ expect(service).toBeDefined();
+ });
+
+
+ test('convertResponseToUI - should return table data', () => {
+ const jobs = [{
+ "id": 5,
+ "created": 1524995555000,
+ "modified": 1524995556000,
+ "action": "INSTANTIATE",
+ "createdId": null,
+ "modifiedId": null,
+ "rowNum": null,
+ "auditUserId": null,
+ "auditTrail": null,
+ "jobId": "9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c",
+ "templateId": "ce4ec177-cfc8-483e-8a2c-b7aea53fd740",
+ "userId": "16807000",
+ "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d91",
+ "requestId": null,
+ "jobStatus": "FAILED",
+ "statusModifiedDate": 1524995555000,
+ "hidden": false,
+ "pause": false,
+ "owningEntityId": "aaa1",
+ "owningEntityName": "aaa1",
+ "project": "WATKINS",
+ "aicZoneId": "BAN1",
+ "aicZoneName": "VSDKYUTP-BAN1",
+ "tenantId": "1178612d2b394be4834ad77f567c0af2",
+ "tenantName": "AIN Web Tool-15-D-SSPtestcustome",
+ "regionId": "hvf6",
+ "regionName": null,
+ "serviceType": "TYLER SILVIA",
+ "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89",
+ "serviceInstanceId": null,
+ "serviceInstanceName": 'serviceInstanceName',
+ "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
+ "serviceModelName": "ComplexService",
+ "serviceModelVersion": "1.0",
+ "createdBulkDate": 1524995555000,
+ "isRetryEnabled": false
+ }];
+ const tableRows: InstantiationTemplatesRowModel[] = service.convertResponseToUI(jobs);
+ expect(tableRows).toHaveLength(1);
+ expect(tableRows[0].userId).toEqual('16807000');
+ expect(tableRows[0].createDate).toEqual('2018-04-29 12:52:35');
+ expect(tableRows[0].instanceName).toEqual('serviceInstanceName');
+ 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');
+ });
+
+
+ test('getCloudOwner should remove "-att" from owningEntityName : "att-owner', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({
+ owningEntityName: 'att-owner',
+ regionId: 'regionId'
+ });
+ expect(result.region).toEqual('regionId (OWNER)');
+ });
+
+ test('getCloudOwner should not return owningEntityName if not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({owningEntityName: null, regionId: 'regionId'});
+ expect(result.region).toEqual('regionId');
+ });
+
+ test('getInstanceName should return instance name id exist if not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({serviceInstanceName: 'instanceName'});
+ expect(result.instanceName).toEqual('instanceName');
+ });
+
+ test('getInstanceName should return <Automatically generated> if instance name not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({});
+ expect(result.instanceName).toEqual('<Automatically generated>');
+ });
+
+});
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
new file mode 100644
index 000000000..7126da36a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts
@@ -0,0 +1,15 @@
+import {Injectable} from "@angular/core";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+@Injectable()
+export class InstantiationTemplatesModalService {
+ convertResponseToUI = (jobsResponse: any[]): InstantiationTemplatesRowModel[] => {
+ let tableRows: InstantiationTemplatesRowModel[] = [];
+
+ jobsResponse.forEach((job) => {
+ tableRows.push(new InstantiationTemplatesRowModel(job));
+ });
+
+ return tableRows;
+ };
+}
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
new file mode 100644
index 000000000..08982cc67
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts
@@ -0,0 +1,51 @@
+import * as moment from 'moment';
+import * as _ from 'lodash';
+
+export class InstantiationTemplatesRowModel {
+ readonly jobId: string;
+ readonly userId ?: string;
+ readonly createDate ?: string;
+ readonly instanceName ?: string;
+ readonly instantiationStatus?: string;
+ readonly summary?: string;
+ readonly region?: string;
+ readonly tenant?: string;
+ readonly aicZone?: string;
+
+ constructor(data) {
+ this.jobId = data.jobId;
+ this.userId = !_.isNil(data.created) ? data.userId : null;
+ this.createDate = !_.isNil(data.created) ? moment(data.created).format("YYYY-MM-DD HH:mm:ss") : null;
+ this.instanceName = this.getInstanceName(data.serviceInstanceName);
+ this.instantiationStatus = !_.isNil(data.jobStatus) ? data.jobStatus : null;
+ this.summary = null;
+ this.region = this.getRegion(data.regionId, data.owningEntityName);
+ this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null;
+ this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null;
+
+ }
+
+
+ /**************************************************************************************************
+ return the LCP region and in brackets the cloud owner removing the “att-“ with capital letters.
+ **************************************************************************************************/
+ getCloudOwner = (owningEntityName: string): string => {
+ const splitByAtt: string[] = owningEntityName.split('att-');
+ let owning: string = splitByAtt[splitByAtt.length - 1];
+ return owning.toUpperCase();
+ };
+
+ getRegion = (regionId: string, owningEntityName: string): string => {
+ const convertOwning = !_.isNil(owningEntityName) ? `(${this.getCloudOwner(owningEntityName)})` : '';
+ return `${regionId} ${convertOwning}`.trim();
+ };
+
+
+ getInstanceName = (instanceName?: string): string => {
+ if (_.isNil(instanceName)) {
+ return '<Automatically generated>';
+ }
+ return instanceName;
+ }
+}
+
diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts
index cbf7324ac..2567cbf27 100644
--- a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts
+++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts
@@ -5,7 +5,7 @@ describe('Search filter pipe', () => {
const items= [{'id':1, 'name': 'aaa'},
{'id':12, 'name': 'bbb', 'children':{'first': 155, 'second': 2, 'third': 3}},
- {'id':3, 'name': 'ccc', 'children':{'first': 1, 'BbB': '3', 'third': 3}},
+ {'id':3, 'name': 'ccc', 'children':{'first': 1, 'BbB': 'BbB', 'third': 3}},
{'id':4, 'name': 'aad', 'children':{'first': 1, 'second': 2, 'third': 3}}];
test('should return items contains substring bb', () => {
diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts
index 725eacb53..6e5cfc667 100644
--- a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts
+++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts
@@ -1,14 +1,43 @@
import {Pipe, PipeTransform} from '@angular/core';
+import * as _ from 'lodash';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
transform(items: Object[], searchText: string): any[] {
- if(!items) return [];
- if(!searchText) return items;
- return items.filter( item => {
- return JSON.stringify(item).toLowerCase().includes(searchText.toLowerCase());
+ if (!items) return [];
+ if (!searchText) return items;
+ return items.filter((item: object) => {
+
+ const deepFlatObject = this.flatten(item);
+
+ const values = _.values(deepFlatObject).map((item: string) => {
+ return item.toString().toLowerCase()
+ });
+
+ return _.some(values, _.method('includes', searchText.toLowerCase()));
});
}
+
+ flatten = object => {
+ return Object.assign(
+ {},
+ ...(function _flatten(objectBit, path = '') {
+ //spread the result into our return object
+ if(objectBit === null) return [];
+ return [].concat(
+ //concat everything into one level
+
+ ...Object.keys(objectBit).map(
+ //iterate over object
+ key =>
+ typeof objectBit[key] === 'object' //check if there is a nested object
+ ? _flatten(objectBit[key], `${path}/${key}`) //call itself if there is
+ : { [`${path}/${key}`]: objectBit[key] } //append object with it’s path as key
+ )
+ );
+ })(object)
+ );
+ };
}
diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts
index a8b45c99a..273dff472 100644
--- a/vid-webpack-master/src/app/shared/shared.module.ts
+++ b/vid-webpack-master/src/app/shared/shared.module.ts
@@ -74,6 +74,8 @@ import {DynamicInputsComponent} from "./components/dynamic-inputs/dynamic-inputs
import {DynamicInputLabelPipe} from "./pipes/dynamicInputLabel/dynamic-input-label.pipe";
import {ModelInformationService} from "./components/model-information/model-information.service";
import {MultiselectFormControlService} from "./components/formControls/component/multiselect/multiselect.formControl.service";
+import {InstantiationTemplatesModalComponent} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component";
+import {InstantiationTemplatesModalService} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service";
import {SearchFilterPipe} from "./pipes/searchFilter/search-filter.pipe";
import {RecreateResolver} from "./resolvers/recreate/recreate.resolver";
import {InstantiationTemplatesService} from "./services/templateService/instantiationTemplates.service";
@@ -129,7 +131,8 @@ import {InstantiationTemplatesService} from "./services/templateService/instanti
SvgComponent,
ErrorMsgComponent,
DynamicInputsComponent,
- DynamicInputLabelPipe
+ DynamicInputLabelPipe,
+ InstantiationTemplatesModalComponent
],
exports: [
PopoverComponent,
@@ -165,7 +168,8 @@ import {InstantiationTemplatesService} from "./services/templateService/instanti
],
entryComponents : [
GenericFormPopupComponent,
- SearchElementsModalComponent
+ SearchElementsModalComponent,
+ InstantiationTemplatesModalComponent
],
providers: [
ServiceInfoService,
@@ -205,7 +209,8 @@ import {InstantiationTemplatesService} from "./services/templateService/instanti
DataFilterPipe,
SearchFilterPipe,
ModelInformationService,
- MultiselectFormControlService
+ MultiselectFormControlService,
+ InstantiationTemplatesModalService
]
})
export class SharedModule {