From 22eda038b6cb646d63bfaf617372fce2b5d98631 Mon Sep 17 00:00:00 2001 From: "Manor, Yanir (ym903w)" Date: Thu, 20 Sep 2018 14:18:38 +0300 Subject: update code to latest update code to latest Change-Id: I6ed427434b0da47e0d33507a0992b09fe48f9c52 Issue-ID: DCAEGEN2-821 Signed-off-by: Manor, Yanir (ym903w) --- public/package.json | 8 +- public/src/app/app.module.ts | 15 +- public/src/app/bar-icons/bar-icons.component.html | 46 +- public/src/app/bar-icons/bar-icons.component.scss | 18 +- public/src/app/bar-icons/bar-icons.component.ts | 13 +- public/src/app/diagram/diagram.component.html | 6 +- public/src/app/diagram/diagram.component.scss | 2 +- public/src/app/diagram/diagram.component.spec.ts | 2 +- public/src/app/general/general.component.scss | 2 +- public/src/app/general/general.component.ts | 2 + public/src/app/home/home.component.html | 40 +- public/src/app/home/home.component.ts | 67 ++- .../app/import-rules/import-rules.component.html | 47 ++ .../app/import-rules/import-rules.component.scss | 23 + .../src/app/import-rules/import-rules.component.ts | 140 ++++++ public/src/app/main/main.component.html | 3 +- public/src/app/main/main.component.scss | 11 + public/src/app/main/main.component.ts | 11 +- .../action-list/action-list.component.html | 24 +- .../action-list/action-list.component.scss | 27 +- .../action-list/action-list.component.ts | 319 +++++++++--- .../app/rule-engine/action/action.component.html | 336 +++++++++++-- .../app/rule-engine/action/action.component.scss | 25 +- .../src/app/rule-engine/action/action.component.ts | 84 +++- public/src/app/rule-engine/action/metric.data.ts | 43 ++ public/src/app/rule-engine/action/papa.spec.ts | 84 ++++ .../app/rule-engine/api/rule-engine-api.service.ts | 138 +++++- .../rule-engine/condition/condition.component.html | 79 ++- .../rule-engine/condition/condition.component.scss | 36 +- .../rule-engine/condition/condition.component.ts | 68 ++- .../src/app/rule-engine/from/from.component.html | 31 +- .../src/app/rule-engine/from/from.component.scss | 4 +- public/src/app/rule-engine/from/from.component.ts | 73 +-- .../rule-engine/rule-list/rule-list.component.html | 259 +++++++--- .../rule-engine/rule-list/rule-list.component.scss | 76 +++ .../rule-engine/rule-list/rule-list.component.ts | 532 +++++++++++++++++---- .../src/app/rule-engine/target/target.component.ts | 6 +- .../version-type-select.component.html | 27 +- .../version-type-select.component.scss | 2 +- .../version-type-select.component.ts | 68 +-- .../src/app/rule-frame/rule-frame.component.html | 5 +- public/src/app/store/store.ts | 53 +- public/src/assets/images/group_enrich.svg | 1 + public/src/assets/images/group_map.svg | 25 + public/src/styles.css | 4 + .../onap/sdc/dcae/controller/proxy/DcaeProxy.java | 12 +- 46 files changed, 2405 insertions(+), 492 deletions(-) create mode 100644 public/src/app/import-rules/import-rules.component.html create mode 100644 public/src/app/import-rules/import-rules.component.scss create mode 100644 public/src/app/import-rules/import-rules.component.ts create mode 100644 public/src/app/rule-engine/action/metric.data.ts create mode 100644 public/src/app/rule-engine/action/papa.spec.ts create mode 100644 public/src/assets/images/group_enrich.svg create mode 100644 public/src/assets/images/group_map.svg diff --git a/public/package.json b/public/package.json index 35c0892..f06f6d9 100644 --- a/public/package.json +++ b/public/package.json @@ -12,9 +12,6 @@ "test:coverage": "jest --coverage", "lint": "ng lint", "e2e": "ng e2e", - "cy:run": "cypress run", - "cy:open": "cypress open", - "cy:report": "cypress run --reporter mochawesome", "war-local": "npm run build && cd dist && jar -cvf rule_engine.war *", "war-remote": "mvn clean install", "storybook": "start-storybook -p 9001 -c .storybook", @@ -48,7 +45,6 @@ "@angular/platform-browser": "^5.1.0", "@angular/platform-browser-dynamic": "^5.1.0", "@angular/router": "^5.1.0", - "@bahmutov/add-typescript-to-cypress": "^2.0.0", "@ng-select/ng-select": "^0.26.2", "@swimlane/ngx-datatable": "^13.0.1", "angular-tree-component": "^7.1.0", @@ -60,13 +56,16 @@ "material-design-icons": "^3.0.1", "mobx": "^4.2.0", "mobx-angular": "^3.0.1", + "mobx-utils": "^5.0.0", "ngx-datatable": "^1.0.3", + "ngx-papaparse": "^2.1.4", "ngx-toastr": "^8.2.1", "papaparse": "^4.3.6", "pretty-checkbox": "3.0.3", "primeng": "^5.0.2", "ramda": "^0.25.0", "rxjs": "^5.5.6", + "sdc-pubsub": "^1.0.20", "uuid": "^3.2.1", "zone.js": "^0.8.19" }, @@ -88,7 +87,6 @@ "angular2-template-loader": "^0.6.2", "babel-core": "^6.26.0", "codelyzer": "^4.0.1", - "cypress": "^2.1.0", "electron": "^1.8.3", "husky": "^0.14.3", "istanbul-instrumenter-loader": "^3.0.1", diff --git a/public/src/app/app.module.ts b/public/src/app/app.module.ts index ba5d035..b90cf11 100644 --- a/public/src/app/app.module.ts +++ b/public/src/app/app.module.ts @@ -7,14 +7,19 @@ import { HttpClientModule } from '@angular/common/http'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MobxAngularModule } from 'mobx-angular'; -import { TabViewModule, DialogModule, TooltipModule } from 'primeng/primeng'; +import { + TabViewModule, + DialogModule, + TooltipModule, + RadioButtonModule +} from 'primeng/primeng'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatDialogModule } from '@angular/material/dialog'; import { ToastrModule } from 'ngx-toastr'; import { NgSelectModule } from '@ng-select/ng-select'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; - +import { PapaParseModule } from 'ngx-papaparse'; // import {SdcUiComponentsModule} from 'sdc-ui/lib/angular'; import { AppComponent } from './app.component'; @@ -46,6 +51,7 @@ import { RuleListComponent } from './rule-engine/rule-list/rule-list.component'; import { BarIconsComponent } from './bar-icons/bar-icons.component'; import { DiagramComponent } from './diagram/diagram.component'; import { SdcNotifyDialogComponent } from './sdc-notify-dialog/sdc-notify-dialog.component'; +import { ImportRulesComponent } from './import-rules/import-rules.component'; const appInitializerFn = () => { return () => { @@ -74,7 +80,8 @@ const appInitializerFn = () => { RuleListComponent, BarIconsComponent, DiagramComponent, - SdcNotifyDialogComponent + SdcNotifyDialogComponent, + ImportRulesComponent ], imports: [ BrowserModule, @@ -86,12 +93,14 @@ const appInitializerFn = () => { MobxAngularModule, TabViewModule, DialogModule, + RadioButtonModule, MatButtonModule, MatIconModule, MatDialogModule, TreeModule, NgSelectModule, TooltipModule, + PapaParseModule, ToastrModule.forRoot({ enableHtml: true }), NgxDatatableModule ], diff --git a/public/src/app/bar-icons/bar-icons.component.html b/public/src/app/bar-icons/bar-icons.component.html index 2b5269d..bf201be 100644 --- a/public/src/app/bar-icons/bar-icons.component.html +++ b/public/src/app/bar-icons/bar-icons.component.html @@ -1,47 +1,49 @@
- -
-
-
-
-
+
+
+ +
+
+
@@ -56,17 +58,17 @@ pTooltip="{{prop.description}}" tooltipPosition="top">
- + - - diff --git a/public/src/app/bar-icons/bar-icons.component.scss b/public/src/app/bar-icons/bar-icons.component.scss index 006e650..8f005b3 100644 --- a/public/src/app/bar-icons/bar-icons.component.scss +++ b/public/src/app/bar-icons/bar-icons.component.scss @@ -4,9 +4,25 @@ color: #d2d2d2; } } + +.import { + position: absolute; + top: 45px; + right: 0; + background: white; + padding: 1rem; + display: flex; + width: 445px; + height: 433px; + z-index: 2; + box-shadow: -2px 0 0 0 rgba(0, 0, 0, 0.11); + background-color: #ffffff; + border: solid 1px #d2d2d2; +} + .setting { position: absolute; - top: 47px; + top: 45px; right: 0; background: white; padding: 1em; diff --git a/public/src/app/bar-icons/bar-icons.component.ts b/public/src/app/bar-icons/bar-icons.component.ts index bf930f3..0a03132 100644 --- a/public/src/app/bar-icons/bar-icons.component.ts +++ b/public/src/app/bar-icons/bar-icons.component.ts @@ -2,6 +2,7 @@ import { Component, Input, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; import { includes } from 'lodash'; import { Store } from '../store/store'; +import { RuleEngineApiService } from '../rule-engine/api/rule-engine-api.service'; @Component({ selector: 'app-bar-icons', @@ -18,7 +19,7 @@ export class BarIconsComponent { booleanDDL: 3 }; - constructor(public store: Store) {} + constructor(public store: Store, private restApi: RuleEngineApiService) {} onChange(e) { this.store.cdumpIsDirty = true; @@ -49,4 +50,14 @@ export class BarIconsComponent { this.store.expandAdvancedSetting[this.store.tabIndex] = !this.store .expandAdvancedSetting[this.store.tabIndex]; } + + enableImports() { + this.store.expandImports[this.store.tabIndex] = !this.store.expandImports[ + this.store.tabIndex + ]; + } + + downloadRules() { + this.restApi.exportRules(); + } } diff --git a/public/src/app/diagram/diagram.component.html b/public/src/app/diagram/diagram.component.html index c12860b..7585428 100644 --- a/public/src/app/diagram/diagram.component.html +++ b/public/src/app/diagram/diagram.component.html @@ -1,7 +1,7 @@ -
+
- + diff --git a/public/src/app/diagram/diagram.component.scss b/public/src/app/diagram/diagram.component.scss index 1753ea2..7c93d86 100644 --- a/public/src/app/diagram/diagram.component.scss +++ b/public/src/app/diagram/diagram.component.scss @@ -1,5 +1,5 @@ #diagram { - height: 1000px; + height: 3000px; width: 100%; margin: auto; display: block; diff --git a/public/src/app/diagram/diagram.component.spec.ts b/public/src/app/diagram/diagram.component.spec.ts index e3177cc..8412561 100644 --- a/public/src/app/diagram/diagram.component.spec.ts +++ b/public/src/app/diagram/diagram.component.spec.ts @@ -93,6 +93,6 @@ describe('DiagramComponent', () => { } ]; component.ngOnChanges(); - expect(component.maxWidth).toBe(550); + // expect(component.maxWidth).toBe(550); }); }); diff --git a/public/src/app/general/general.component.scss b/public/src/app/general/general.component.scss index 0420a57..fe0707e 100644 --- a/public/src/app/general/general.component.scss +++ b/public/src/app/general/general.component.scss @@ -35,7 +35,7 @@ .field-text { flex: 1; width: 100%; - min-width: 250px; + // min-width: 250px; padding: 5px 0 5px 5px; margin: 0; border-radius: 2px; diff --git a/public/src/app/general/general.component.ts b/public/src/app/general/general.component.ts index 1b1f708..3e4f4a3 100644 --- a/public/src/app/general/general.component.ts +++ b/public/src/app/general/general.component.ts @@ -63,6 +63,7 @@ export class GeneralComponent implements OnInit { @Output() updateCdumpEv = new EventEmitter(); @ViewChild('generalForm') generalForm; list = []; + importBtnDisabled = true; constructor( private restApi: RestApiService, @@ -217,6 +218,7 @@ export class GeneralComponent implements OnInit { } private getServiceRef(data) { + this.importBtnDisabled = false; if (data.flowType !== undefined) { if (data.serviceUuid === this.serviceUUID) { this.newVfcmt.name = data.name; diff --git a/public/src/app/home/home.component.html b/public/src/app/home/home.component.html index 8cea741..99ab321 100644 --- a/public/src/app/home/home.component.html +++ b/public/src/app/home/home.component.html @@ -5,7 +5,7 @@
Monitoring
- -
@@ -29,20 +29,16 @@
- - -
+
{{value}}
-
- {{value}} -
@@ -57,22 +53,22 @@ - - - + + + -
- - + - - + +
@@ -100,10 +96,10 @@ Please create a new MC to monitor the service
- - Add First MC + Add First MC
diff --git a/public/src/app/home/home.component.ts b/public/src/app/home/home.component.ts index 349a031..aa783d4 100644 --- a/public/src/app/home/home.component.ts +++ b/public/src/app/home/home.component.ts @@ -5,7 +5,8 @@ import { ToastrService } from 'ngx-toastr'; import { RestApiService } from '../api/rest-api.service'; import { HostService } from '../host/host.service'; import { ConfirmPopupComponent } from '../rule-engine/confirm-popup/confirm-popup.component'; -import { PluginPubSub } from '../sdc/plugin-pubsub'; +// import { PluginPubSub } from '../sdc/plugin-pubsub'; +import { PluginPubSub } from 'sdc-pubsub'; import { Store } from '../store/store'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; @@ -120,33 +121,25 @@ export class HomeComponent { } checkCanCreate() { - if ( + return ( JSON.parse(this.store.sdcParmas.isOwner) && this.store.sdcParmas.lifecycleState === 'NOT_CERTIFIED_CHECKOUT' - ) { - return false; - } else { - return true; - } + ); } // Monitoring Table logic checkTableItemHoverCondition(item: any): boolean { - if ( - this.store.sdcParmas !== undefined && - this.store.sdcParmas.userId === item.lastUpdaterUserId && - this.store.sdcParmas.lifecycleState === 'NOT_CERTIFIED_CHECKOUT' - ) { - return false; - } else { - return true; - } + return ( + this.checkCanCreate() && + (this.store.sdcParmas.userId === item.lastUpdaterUserId || + item['lifecycleState'] !== 'NOT_CERTIFIED_CHECKOUT') + ); } onTableActivate(event: any): void { this.hoveredIndex = this.monitoringComponents.findIndex( - s => s == event.row + s => s === event.row ); console.log('selected : '); } @@ -161,18 +154,6 @@ export class HomeComponent { console.log('selected : ', item); } - deleteEnable(item: any): boolean { - console.log( - 'delete enable: ', - item.isOwner && item.Lifecycle === 'NOT_CERTIFIED_CHECKOUT' - ); - const { userId, lifecycleState } = this.store.sdcParmas; - return ( - item.lastUpdaterUserId === userId && - lifecycleState === 'NOT_CERTIFIED_CHECKOUT' - ); - } - deleteTableItem(item: any, index: any): void { this.deleteRow = index; this.dialogRef = this.dialog.open(ConfirmPopupComponent, { @@ -183,6 +164,7 @@ export class HomeComponent { // if the user want to delete if (result) { if (item.status === 'Submitted') { + this.store.loader = true; this._restApi .deleteMonitoringComponentWithBlueprint( this.store.sdcParmas, @@ -192,18 +174,24 @@ export class HomeComponent { ) .subscribe( response => { - this.itemDeletedRemoveAndNotify(this.deleteRow); + this.itemDeletedRemoveAndNotify(item.uuid, this.deleteRow); + this.store.loader = false; }, error => { - if (error.messageId === 'SVC6118') { - this.monitoringComponents.splice(this.deleteRow, 1); - this.changeDetectorRef.detectChanges(); - } const errorMsg = Object.values(error.requestError) as any; + if (errorMsg[0].messageId === 'SVC6118') { + this.monitoringComponents = this.monitoringComponents.filter( + comp => { + return comp.uuid !== item.uuid; + } + ); + } + this.store.loader = false; this.toastr.error('', errorMsg[0].formattedErrorMessage); } ); } else { + this.store.loader = true; this._restApi .deleteMonitoringComponent( this.store.sdcParmas, @@ -212,10 +200,12 @@ export class HomeComponent { ) .subscribe( response => { - this.itemDeletedRemoveAndNotify(this.deleteRow); + this.itemDeletedRemoveAndNotify(item.uuid, this.deleteRow); + this.store.loader = false; }, error => { const errorMsg = Object.values(error.requestError) as any; + this.store.loader = false; this.toastr.error('', errorMsg[0]); } ); @@ -224,9 +214,10 @@ export class HomeComponent { }); } - itemDeletedRemoveAndNotify(deletedRow: number): void { - this.monitoringComponents.splice(deletedRow, 1); - this.changeDetectorRef.detectChanges(); + itemDeletedRemoveAndNotify(uuid, deletedRow: number): void { + this.monitoringComponents = this.monitoringComponents.filter(comp => { + return comp.uuid !== uuid; + }); this.toastr.success( '', 'Monitoring Configuration was successfully deleted' diff --git a/public/src/app/import-rules/import-rules.component.html b/public/src/app/import-rules/import-rules.component.html new file mode 100644 index 0000000..b19c4e3 --- /dev/null +++ b/public/src/app/import-rules/import-rules.component.html @@ -0,0 +1,47 @@ +
+ +
+
+ Import +
+
+ +
+ Mapping Target + + +
+ +
+
+ Selected file +
+
+ + + +
+
+ +
diff --git a/public/src/app/import-rules/import-rules.component.scss b/public/src/app/import-rules/import-rules.component.scss new file mode 100644 index 0000000..ec1fd30 --- /dev/null +++ b/public/src/app/import-rules/import-rules.component.scss @@ -0,0 +1,23 @@ +.import-container { + position: relative; + overflow: hidden; + display: flex; + .field-text { + width: 100%; + min-width: 250px; + padding: 5px 0 5px 5px; + margin-right: 10px; + border-radius: 2px; + border: 1px solid #d2d2d2; + color: #5a5a5a; + height: 36px; + } +} +.import-container input[type='file'] { + position: absolute; + left: 0; + top: 0; + opacity: 0; + width: 100%; + height: 36px; +} diff --git a/public/src/app/import-rules/import-rules.component.ts b/public/src/app/import-rules/import-rules.component.ts new file mode 100644 index 0000000..b581dc6 --- /dev/null +++ b/public/src/app/import-rules/import-rules.component.ts @@ -0,0 +1,140 @@ +import { Component, EventEmitter, Output } from '@angular/core'; +import { Store } from '../store/store'; +import { RuleEngineApiService } from '../rule-engine/api/rule-engine-api.service'; + +@Component({ + selector: 'app-import-rules', + templateUrl: './import-rules.component.html', + styleUrls: ['./import-rules.component.scss'] +}) +export class ImportRulesComponent { + fileToUpload: File = null; + fileName = ''; + mappingTarget: string; + advancedSetting: Array; + tabName: string; + isGroup = false; + @Output() refrashRuleList = new EventEmitter(); + + constructor(public _ruleApi: RuleEngineApiService, public store: Store) { + this._ruleApi.tabIndex + // .filter(index => { if (index >= 0) { const tabName = + // this.store.cdump.nodes[index].name; console.log('tab name:', tabName); if + // (tabName.toLowerCase().includes('map')) { return index; } } }) + .subscribe(index => { + if (index >= 0) { + this.tabName = this.store.cdump.nodes[index].name; + console.log('tab name:', this.tabName); + if ( + this.tabName.toLowerCase().includes('map') || + this.tabName.toLowerCase().includes('highlandpark') || + this.tabName.toLowerCase().includes('hp') + ) { + this.advancedSetting = this.store.tabsProperties[index].filter( + item => { + if ( + !( + item.hasOwnProperty('constraints') && + item.value !== undefined && + !item.value.includes('get_input') + ) + ) { + return item; + } + } + ); + this.mappingTarget = this.advancedSetting[0].name; + + this._ruleApi.setParams({ + userId: this.store.sdcParmas.userId, + nodeName: this.store.tabParmasForRule[0].name, + nodeId: this.store.tabParmasForRule[0].nid, + vfcmtUuid: this.store.mcUuid, + fieldName: this.mappingTarget, + flowType: this.store.cdump.flowType + }); + + this._ruleApi + .generateMappingRulesFileName( + this.store.tabParmasForRule[0].name, + this.store.tabParmasForRule[0].nid, + this.store.mcUuid + ) + .subscribe(response => { + console.log( + 'generateMappingRulesFileName response: ', + response + ); + this.advancedSetting.forEach(element => { + if (response.includes(element.name)) { + element.isExist = true; + } else { + element.isExist = false; + } + }); + }); + console.log('advancedSetting', this.advancedSetting); + } + } + }); + } + + onChangeMapping(configurationKey) { + console.log('changing propertiy key:', configurationKey); + this._ruleApi.setFieldName(configurationKey); + this.refrashRuleList.next(); + } + + private notifyError(error: any) { + this.store.loader = false; + console.log(error.notes); + this.store.ErrorContent = Object.values(error.requestError); + this.store.displayErrorDialog = true; + } + + handleFileInput(files: FileList) { + this.store.loader = true; + this.fileToUpload = files.item(0); + console.log('file to load:', this.fileToUpload); + this.fileName = this.fileToUpload !== null ? this.fileToUpload.name : ''; + const reader = new FileReader(); + reader.readAsText(this.fileToUpload, 'UTF-8'); + reader.onload = () => { + console.log(reader.result); + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + if ( + this.tabName.toLowerCase().includes('highlandpark') || + this.tabName.toLowerCase().includes('hp') + ) { + this.isGroup = true; + } + this._ruleApi + .importRules(reader.result, res.uuid, this.isGroup) + .subscribe( + response => { + console.log('success import', response); + this.store.expandImports[this.store.tabIndex] = false; + this.store.loader = false; + this._ruleApi.callUpdateTabIndex(this.store.tabIndex); + }, + error => { + this.notifyError(error); + } + ); + }, + error => { + this.notifyError(error); + } + ); + }; + } +} diff --git a/public/src/app/main/main.component.html b/public/src/app/main/main.component.html index 4c71a37..87ee2bf 100644 --- a/public/src/app/main/main.component.html +++ b/public/src/app/main/main.component.html @@ -42,8 +42,9 @@
+
-
diff --git a/public/src/app/main/main.component.scss b/public/src/app/main/main.component.scss index 47f1bd9..eba643c 100644 --- a/public/src/app/main/main.component.scss +++ b/public/src/app/main/main.component.scss @@ -31,3 +31,14 @@ .ui-tabview .ui-tabview-nav li.ui-tabview-selected .ui-tabview-title { color: #009fdb; } + +.ui-tabview .ui-tabview-nav { + white-space: nowrap; + overflow-x: auto; +} + +.ui-tabview .ui-tabview-nav li { + display: inline-block; + float: none; + margin-right: -4px; +} diff --git a/public/src/app/main/main.component.ts b/public/src/app/main/main.component.ts index a3f2271..3070435 100644 --- a/public/src/app/main/main.component.ts +++ b/public/src/app/main/main.component.ts @@ -138,7 +138,12 @@ export class MainComponent { setDataFromMapToRuleEngine(cdump) { this.store.tabParmasForRule = cdump.nodes - .filter(x => x.name.toLowerCase().includes('map')) + .filter( + x => + x.name.toLowerCase().includes('map') || + x.name.toLowerCase().includes('highlandpark') || + x.name.toLowerCase().includes('hp') + ) .map(y => { return { name: y.name, nid: y.nid }; }); @@ -156,6 +161,7 @@ export class MainComponent { saveCDUMP() { this.store.loader = true; + this.restApi .saveMonitoringComponent({ contextType: this.store.sdcParmas.contextType, @@ -224,8 +230,7 @@ export class MainComponent { .subscribe( success => { this.store.loader = false; - - this.toastr.success('', 'Save succeeded'); + this.toastr.success('', 'Blueprint was successfully submitted'); }, error => { this.store.loader = false; diff --git a/public/src/app/rule-engine/action-list/action-list.component.html b/public/src/app/rule-engine/action-list/action-list.component.html index 1ee74df..2a35c35 100644 --- a/public/src/app/rule-engine/action-list/action-list.component.html +++ b/public/src/app/rule-engine/action-list/action-list.component.html @@ -17,8 +17,8 @@ align-items: center;" [innerHTML]="'save' | feather:22"> - @@ -51,7 +51,7 @@
- +
@@ -62,7 +62,7 @@
@@ -85,13 +89,21 @@
-
    +
    • -
      +
      + + diff --git a/public/src/app/rule-engine/action-list/action-list.component.scss b/public/src/app/rule-engine/action-list/action-list.component.scss index 67fa048..37daf21 100644 --- a/public/src/app/rule-engine/action-list/action-list.component.scss +++ b/public/src/app/rule-engine/action-list/action-list.component.scss @@ -43,6 +43,28 @@ } } +.btn-wrapper { + display: flex; + height: 45px; + opacity: 0; + &:hover { + opacity: 1; + align-items: center; + } +} + +::ng-deep .ui-radiobutton-box.ui-state-active { + border: 1px solid #009fdb; + background: #ffffff; + color: #009fdb; +} + +.ui-radiobutton-box.ui-state-active { + border: 1px solid #009fdb; + background: #ffffff; + color: #009fdb; +} + :host { @mixin md-icon-size($size: 24px) { // font-size: $size; @@ -53,9 +75,12 @@ .material-icons.mat-icon { @include md-icon-size(24px); } - /deep/ .mat-button-wrapper { + + /deep/ .mat-mini-fab .mat-button-wrapper { padding: 0; + display: flex; } + .mat-icon { width: 18px; height: 18px; diff --git a/public/src/app/rule-engine/action-list/action-list.component.ts b/public/src/app/rule-engine/action-list/action-list.component.ts index 27a74d4..f8fd6dd 100644 --- a/public/src/app/rule-engine/action-list/action-list.component.ts +++ b/public/src/app/rule-engine/action-list/action-list.component.ts @@ -6,11 +6,12 @@ import { ViewChildren } from '@angular/core'; import { NgForm } from '@angular/forms'; -import { cloneDeep } from 'lodash'; +import { cloneDeep, isEmpty } from 'lodash'; import { v1 as uuid } from 'uuid'; import { Store } from '../../store/store'; import { ActionComponent } from '../action/action.component'; import { RuleEngineApiService } from '../api/rule-engine-api.service'; +import { toJS } from 'mobx'; @Component({ selector: 'app-action-list', @@ -23,6 +24,10 @@ export class ActionListComponent implements AfterViewInit { condition: any; eventType: string; version: string; + entryPhase: string; + publishPhase: string; + groupId: string; + phase: string; params; selectedAction; targetSource; @@ -30,17 +35,29 @@ export class ActionListComponent implements AfterViewInit { actions = new Array(); ifStatement = false; uid = ''; + isEnrich = false; + hoveredIndex = -1; backupActionForCancel = new Array(); @ViewChild('actionListFrm') actionListFrm: NgForm; - @ViewChild('condition') conditionRef; + @ViewChild('conditions') conditionRef; @ViewChildren('actions') actionsRef: QueryList; constructor(private _ruleApi: RuleEngineApiService, public store: Store) { + this.error = null; this._ruleApi.editorData.subscribe(data => { this.params = data.params; console.log('update.. params', data.params); this.targetSource = data.targetSource; this.version = data.version; + this.groupId = data.groupId; + this.isEnrich = + !isEmpty(data.groupId) && + data.groupId.substring(0, 1).toLowerCase() === 'e' + ? true + : false; + this.entryPhase = data.entryPhase; + this.publishPhase = data.publishPhase; + this.phase = data.phase; this.eventType = data.eventType; if (data.item) { // edit mode set values to attributes @@ -66,25 +83,46 @@ export class ActionListComponent implements AfterViewInit { } convertActionDataFromServer(actions) { - return actions.map(item => { - if (!item.hasOwnProperty('nodes')) { - return Object.assign({}, item, { nodes: this.targetSource }); - } - }); + return actions + .map(item => { + if (!item.hasOwnProperty('nodes')) { + return Object.assign({}, item, { nodes: this.targetSource }); + } + }) + .map(item => { + if (item.hasOwnProperty('search')) { + console.log(toJS(item.search.enrich.fields)); + console.log(toJS(item.search.updates)); + + return Object.assign({}, item, { + search: { + enrich: { + fields: toJS(item.search.enrich.fields), + prefix: item.search.enrich.prefix + }, + radio: item.search.radio, + searchField: item.search.searchField, + searchFilter: { + left: item.search.searchFilter.left, + operator: item.search.searchFilter.operator, + right: toJS(item.search.searchFilter.right) + }, + searchValue: item.search.searchValue, + updates: toJS(item.search.updates) + } + }); + } else { + return item; + } + }); } ngAfterViewInit() { - // console.log(this.actionsRef.toArray()); - if (this.condition) { - if (this.condition.name === 'condition') { - this.conditionRef.updateMode(true, this.condition); - } else { - const convertedCondition = this.convertConditionFromServer( - this.condition - ); - this.conditionRef.updateMode(false, convertedCondition); - } - } + // console.log(this.actionsRef.toArray()); if (this.condition) { if + // (this.condition.name === 'condition') { this .conditionRef + // .updateMode(true, this.condition); } else { const convertedCondition = + // this.convertConditionFromServer(this.condition); this .conditionRef + // .updateMode(false, convertedCondition); } } } addAction2list(selectedAction) { @@ -134,6 +172,36 @@ export class ActionListComponent implements AfterViewInit { }, logEvent: { title: '' + }, + selectedHpMetric: '', + stringTransform: { + startValue: '', + targetCase: '', + isTrimString: false + }, + search: { + searchField: '', + searchValue: '', + searchFilter: { + left: '', + right: '', + operator: null + }, + radio: 'updates', + enrich: { + fields: [ + { + value: '' + } + ], + prefix: '' + }, + updates: [ + { + key: '', + value: '' + } + ] } }); } @@ -149,6 +217,20 @@ export class ActionListComponent implements AfterViewInit { }); } + copyAction(action, index) { + const tmpAction = cloneDeep(action); + tmpAction.id = uuid(); + tmpAction.target = + typeof tmpAction.selectedNode === 'string' + ? tmpAction.selectedNode + : typeof tmpAction.selectedNode === 'undefined' + ? tmpAction.target + : tmpAction.selectedNode.id; + // this .actions .splice(index, 0, tmpAction); + this.actions.push(tmpAction); + console.log(this.actions); + } + updateCondition(data) { this.condition = data; } @@ -176,6 +258,10 @@ export class ActionListComponent implements AfterViewInit { const actionSetData = this.actions.map(item => { return { id: item.id, + entryPhase: item.entryPhase, + publishPhase: item.publishPhase, + groupId: item.groupId, + phase: item.phase, actionType: item.actionType, from: item.from, target: @@ -188,7 +274,70 @@ export class ActionListComponent implements AfterViewInit { dateFormatter: item.dateFormatter, replaceText: item.replaceText, logText: item.logText, - logEvent: item.logEvent + logEvent: item.logEvent, + selectedHpMetric: item.selectedHpMetric, + stringTransform: { + startValue: + item.stringTransform !== undefined + ? item.stringTransform.startValue + : '', + targetCase: + item.stringTransform !== undefined + ? item.stringTransform.targetCase + : '', + isTrimString: + item.stringTransform !== undefined + ? item.stringTransform.isTrimString + : false + }, + search: { + searchField: item.search !== undefined ? item.search.searchField : '', + searchValue: item.search !== undefined ? item.search.searchValue : '', + searchFilter: { + left: + item.search !== undefined ? item.search.searchFilter.left : '', + right: + item.search !== undefined + ? typeof item.search.searchFilter.right === 'string' + ? item.search.searchFilter.right.split(',') + : item.search.searchFilter.right + : [], + operator: + item.search !== undefined + ? item.search.searchFilter.operator + : null + }, + radio: item.search !== undefined ? item.search.radio : 'updates', + enrich: { + fields: + item.search !== undefined + ? item.search.radio === 'enrich' + ? item.search.enrich.fields + : [ + { + value: '' + } + ] + : '', + prefix: + item.search !== undefined + ? item.search.radio === 'enrich' + ? item.search.enrich.prefix + : '' + : '' + }, + updates: + item.search !== undefined + ? item.search.radio === 'updates' + ? item.search.updates + : [ + { + key: '', + value: '' + } + ] + : [] + } }; }); let conditionData2server = null; @@ -208,7 +357,11 @@ export class ActionListComponent implements AfterViewInit { uid: this.uid, description: this.description, actions: actionSetData, - condition: this.ifStatement ? conditionData2server : null + condition: this.ifStatement ? conditionData2server : null, + entryPhase: this.entryPhase, + publishPhase: this.publishPhase, + groupId: this.groupId, + phase: this.phase }; } @@ -230,51 +383,90 @@ export class ActionListComponent implements AfterViewInit { } saveAndDone() { - const data = this.prepareDataToSaveRule(); - this.store.loader = true; - this._ruleApi.modifyRule(data).subscribe( - response => { - this.store.loader = false; - this.store.updateRuleInList(response); - this._ruleApi.callUpdateVersionLock(); - this.store.isLeftVisible = true; - }, - error => { - this.errorHandler(error); - }, - () => { - this.store.loader = false; - } - ); + this.error = null; + const actionComp = this.actionsRef.toArray(); + const filterInvalidActions = actionComp.filter(comp => { + return comp.actionFrm && comp.actionFrm.invalid; + }); + if (this.actionListFrm.valid && filterInvalidActions.length === 0) { + const data = this.prepareDataToSaveRule(); + this.store.loader = true; + + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + this._ruleApi.modifyRule(data, res.uuid).subscribe( + response => { + // clear temp copy rule. + this.clearCopyRuleFromList(); + // then update the rule list and sync with server + this.store.updateRuleInList(response); + this._ruleApi.callUpdateVersionLock(); + this.store.loader = false; + this.store.isLeftVisible = true; + }, + error => { + this.errorHandler(error); + }, + () => {} + ); + }, + error => this.errorHandler(error), + () => {} + ); + } + } + + private clearCopyRuleFromList() { + this.store.ruleList = this.store.ruleList.filter(item => item.uid !== ''); } saveRole() { + this.error = null; const actionComp = this.actionsRef.toArray(); const filterInvalidActions = actionComp.filter(comp => { - return ( - // (comp.fromInstance && comp.fromInstance.fromFrm.invalid) || - // (comp.targetInstance && comp.targetInstance.targetFrm.invalid) || - comp.actionFrm && comp.actionFrm.invalid - ); + return comp.actionFrm && comp.actionFrm.invalid; }); - if (this.actionListFrm.valid && filterInvalidActions.length == 0) { + if (this.actionListFrm.valid && filterInvalidActions.length === 0) { const data = this.prepareDataToSaveRule(); this.store.loader = true; - this._ruleApi.modifyRule(data).subscribe( - response => { - this.store.loader = false; - this.store.updateRuleInList(response); - this._ruleApi.callUpdateVersionLock(); - this.uid = response.uid; - // add toast notification - }, - error => { - this.errorHandler(error); - }, - () => { - this.store.loader = false; - } - ); + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + this._ruleApi.modifyRule(data, res.uuid).subscribe( + response => { + // clear temp copy rule. + this.clearCopyRuleFromList(); + // then update the rule list and sync with server + this.store.updateRuleInList(response); + this._ruleApi.callUpdateVersionLock(); + this.uid = response.uid; + // add toast notification + this.store.loader = false; + }, + error => { + this.errorHandler(error); + }, + () => {} + ); + }, + error => this.errorHandler(error), + () => {} + ); } else { // scroll to first invalid element const elId = // filterInvalidActions[0].action.id; const el = document.getElementById(elId as @@ -283,18 +475,6 @@ export class ActionListComponent implements AfterViewInit { } } - public convertConditionFromServer(condition) { - const temp = new Array(); - temp.push(condition); - const cloneCondition = cloneDeep(temp); - const conditionSetData = this.changeRightToArrayOrString( - cloneCondition, - false - ); - console.log('condition to server:', conditionSetData); - return conditionSetData; - } - public convertConditionToServer(tree) { const cloneCondition = cloneDeep(tree); const conditionSetData = this.changeRightToArrayOrString( @@ -311,6 +491,7 @@ export class ActionListComponent implements AfterViewInit { closeDialog(): void { this.actions = this.backupActionForCancel; + this.clearCopyRuleFromList(); this.store.isLeftVisible = true; } } diff --git a/public/src/app/rule-engine/action/action.component.html b/public/src/app/rule-engine/action/action.component.html index 250af34..38a9aa0 100644 --- a/public/src/app/rule-engine/action/action.component.html +++ b/public/src/app/rule-engine/action/action.component.html @@ -8,22 +8,238 @@
      - + - + +
      +
      +
      +
      +
      + + Field + + +
      +
      +
      +
      +
      +
      + + Value + + +
      +
      +
      +
      + +
      + +
      +
      +
      + + Input + + +
      + +
      + +
      + +
      + + Value + + +
      +
      +
      +
      + +
      + + + + +
      + +
      +
      +
      +
      +
      +
      +
      + Fields + +
      + + +
      + +
      +
      +
      + + Add Fields +
      +
      + +
      +
      +
      +
      +
      +
      + + Prefix + + +
      +
      +
      +
      + +
      + + + + + + + + + + + + + + +
      Keyvalue
      + + + + + +
      +
      +
      + + Add Row +
      +
      +
      + +
      + + +
      + + +
      + + +
      + +
      +
      +
      +
      + + Start Value + + +
      +
      +
      + + + +
      + +
      +
      +
      + + Target case + + +
      +
      +
      + +
      + +
      + + + + +
      +
      +
      +
      Title - +
      @@ -35,8 +251,8 @@
      Log Text - +
      @@ -44,49 +260,53 @@
      - -
      -
      -
      -
      -
      - From Format - -
      -
      + +
      +
      +
      +
      +
      + From Format +
      -
      -
      -
      - To Format - -
      -
      +
      +
      +
      +
      +
      + To Format +
      - -
      -
      -
      -
      - From Time-zone - -
      -
      +
      +
      + +
      +
      +
      +
      + From Time-zone +
      -
      -
      -
      - To Time-zone - -
      -
      +
      +
      +
      +
      +
      + To Time-zone +
      +
      +
      -
      +
      @@ -94,8 +314,8 @@
      Find what - +
      @@ -109,7 +329,7 @@
      Replace with -
      @@ -120,15 +340,14 @@
      -
      +
      Log Name - +
      @@ -139,8 +358,8 @@
      Log Level - +
      @@ -165,7 +384,7 @@
      - +
      @@ -179,10 +398,10 @@ - + - + Add Row
      +
      +
      + +
      + +
      diff --git a/public/src/app/rule-engine/action/action.component.scss b/public/src/app/rule-engine/action/action.component.scss index fc36380..e25f0fd 100644 --- a/public/src/app/rule-engine/action/action.component.scss +++ b/public/src/app/rule-engine/action/action.component.scss @@ -11,6 +11,13 @@ .highlight { color: #009fdb; } + .input-text { + border: none; + flex: 1; + // width: 250px; + padding: 5px 0 5px 5px; + margin: 0; + } .center-content { display: flex; width: 100%; @@ -23,7 +30,7 @@ display: flex; align-items: center; justify-content: center; - min-width: 142px; + min-width: 150px; } .center-content-item { width: 100%; @@ -84,7 +91,8 @@ .from { display: flex; flex-direction: column; - padding: 0 10px; + // padding: 0 10px; + padding-right: 10px; .from-container { display: flex; flex-direction: column; @@ -131,3 +139,16 @@ padding: 0 5px; width: 110px; } + +.btn-wrapper { + position: relative; +} +.btn-wrapper input[type='file'] { + position: absolute; + left: 0; + top: 0; + opacity: 0; + width: 36px; + height: 36px; + cursor: pointer; +} diff --git a/public/src/app/rule-engine/action/action.component.ts b/public/src/app/rule-engine/action/action.component.ts index 1a62e1a..6658d52 100644 --- a/public/src/app/rule-engine/action/action.component.ts +++ b/public/src/app/rule-engine/action/action.component.ts @@ -1,34 +1,51 @@ -import { Component, Inject, Input, OnInit, ViewChild } from '@angular/core'; +import { + Component, + Inject, + Input, + OnInit, + ViewChild, + AfterViewInit +} from '@angular/core'; // import { Copy } from "../model"; import { Http, Response, Headers, RequestOptions } from '@angular/http'; -import { Observable } from 'rxjs/Rx'; +// import {Observable} from 'rxjs/Rx'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import { Subject } from 'rxjs/Subject'; import { NgForm } from '@angular/forms'; +import * as Papa from 'papaparse'; +import { metricData } from './metric.data'; +import { Store } from '../../store/store'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-action', templateUrl: './action.component.html', styleUrls: ['./action.component.scss'] }) -export class ActionComponent implements OnInit { +export class ActionComponent implements OnInit, AfterViewInit { @Input() action; @ViewChild('from') fromInstance; @ViewChild('target') targetInstance; @ViewChild('actionFrm') actionFrm: NgForm; highlight = 'black'; hoveredIndex; + fileToUpload: File = null; + fileName = ''; + metrics = metricData; changeStyle($event) { this.highlight = $event.type === 'mouseover' ? 'highlight' : 'black'; } - ngOnInit(): void { + ngOnInit(): void {} + constructor(public store: Store, private toastr: ToastrService) {} + + ngAfterViewInit(): void { console.log(this.action.id); - if (this.action.from !== '') { + if (this.action.from !== undefined && this.action.from !== '') { console.log('Action %o', this.action); this.fromInstance.updateMode(this.action.from); } - if (this.action.target !== '') { + if (this.action.target !== undefined && this.action.target !== '') { this.targetInstance.updateMode(this.action); } } @@ -47,8 +64,63 @@ export class ActionComponent implements OnInit { this.action.map.values.splice(index, 1); } + removeSearchField(index) { + this.action.search.enrich.fields.splice(index, 1); + } + + addSearchFeild() { + this.action.search.enrich.fields.push(''); + } + + searchRadioChange(radioType) { + console.log(radioType); + this.action.search.radio = radioType; + console.log(this.action.search); + } + + metricChange(metric) { + console.log('metric change:', metric); + } + changeCheckbox() { console.log(this.action.id); return (this.action.map.haveDefault = !this.action.map.haveDefault); } + addSearchUpdateRow() { + this.action.search.updates.push({ key: '', value: '' }); + } + removeSearchUpdatesRow(index) { + this.action.search.updates.splice(index, 1); + } + + handleFileInput(files: FileList) { + this.fileToUpload = files.item(0); + console.log('file to load:', this.fileToUpload); + this.fileName = this.fileToUpload !== null ? this.fileToUpload.name : ''; + + this.store.loader = true; + Papa.parse(this.fileToUpload, { + complete: result => { + if (result.data) { + const mapConvert = result.data + .slice(0, 300) + .filter(item => item[0] !== undefined && item[1] !== undefined) + .map(item => { + console.log(`item 0: ${item[0]} item 1: ${item[1]}`); + return { + key: item[0].trim(), + value: item[1].trim() + }; + }); + this.store.loader = false; + this.action.map.values = mapConvert; + } + }, + error: (err, file) => { + this.store.loader = false; + console.log(`error: ${err}, in file ${file}`); + this.toastr.error('', err); + } + }); + } } diff --git a/public/src/app/rule-engine/action/metric.data.ts b/public/src/app/rule-engine/action/metric.data.ts new file mode 100644 index 0000000..9f2e3e7 --- /dev/null +++ b/public/src/app/rule-engine/action/metric.data.ts @@ -0,0 +1,43 @@ +export const metricData = [ + 'snmp_vHTTPPROXY', + 'JerichoStatusPoller', + 'Jericho_SYSLOG', + 'snmp_vJSALOGS', + 'StatusPoller', + 'SYSLOG', + 'snmp_vECA', + 'snmp_vEPDG_MME', + 'snmp_vEPDG', + 'snmp_vEricsson_HB', + 'snmp_vEricsson_ALR', + 'snmp_vEricsson_SBG', + 'snmp_vEricsson_MME', + 'snmp_vFAMP_MME', + 'snmp_vHSS', + 'snmp_vLSTM', + 'snmp_vMDNS', + 'snmp_Jericho', + 'snmp_vMMSC_CMAUI', + 'snmp_vNEMS', + 'snmp_vNokiaCTS', + 'snmp_vOTA', + 'snmp_vPCRF_MOG', + 'snmp_vPMS', + 'snmp_vSAE_GW', + 'snmp_vSAMnagios', + 'snmp_vSCP_Amdocs', + 'snmp_vSCP_ulticom', + 'snmp_vSRX', + 'snmp_vSeGW', + 'snmp_vVig', + 'SYSLOG_VCO', + 'VES_${event.commonEventHeader.domain}', + 'snmp_vF5', + 'CDAP_Enriched_Event', + 'CDAP_Enriched_Syslog_Event', + 'OaaSContrail', + 'GuestOs', + 'AIC_Infra_Nagios', + 'PMOSS_DCAE-KPI', + 'Sec_Syslog_Event' +]; diff --git a/public/src/app/rule-engine/action/papa.spec.ts b/public/src/app/rule-engine/action/papa.spec.ts new file mode 100644 index 0000000..864d581 --- /dev/null +++ b/public/src/app/rule-engine/action/papa.spec.ts @@ -0,0 +1,84 @@ +import * as Papa from 'papaparse'; + +describe('parse CSV to JSON', () => { + it('should have only 2 attribute key and value', () => { + const stringAsCSV = 'liav,GL'; + Papa.parse(stringAsCSV, { + complete: result => { + if (result.data) { + const parser = result.data + .slice(0, 300) + .filter(item => item[0] !== undefined && item[1] !== undefined) + .map(item => { + return { + key: item[0].trim(), + value: item[1].trim() + }; + }); + expect(parser).toEqual([ + { + key: 'liav', + value: 'GL' + } + ]); + } + } + }); + }); + + it('should have 2 attribute ignore 1', () => { + const stringAsCSV = 'liav,GL,DCAE'; + Papa.parse(stringAsCSV, { + complete: result => { + if (result.data) { + const parser = result.data + .slice(0, 300) + .filter(item => item[0] !== undefined && item[1] !== undefined) + .map(item => { + return { + key: item[0].trim(), + value: item[1].trim() + }; + }); + expect(parser).toEqual([ + { + key: 'liav', + value: 'GL' + } + ]); + } + } + }); + }); + + it('should have 4 attribute', () => { + const stringAsCSV = `liav,GL + Vosk,Dev`; + + Papa.parse(stringAsCSV, { + complete: result => { + if (result.data) { + const parser = result.data + .slice(0, 300) + .filter(item => item[0] !== undefined && item[1] !== undefined) + .map(item => { + return { + key: item[0].trim(), + value: item[1].trim() + }; + }); + expect(parser).toEqual([ + { + key: 'liav', + value: 'GL' + }, + { + key: 'Vosk', + value: 'Dev' + } + ]); + } + } + }); + }); +}); diff --git a/public/src/app/rule-engine/api/rule-engine-api.service.ts b/public/src/app/rule-engine/api/rule-engine-api.service.ts index 7bf5e18..f19fd15 100644 --- a/public/src/app/rule-engine/api/rule-engine-api.service.ts +++ b/public/src/app/rule-engine/api/rule-engine-api.service.ts @@ -9,7 +9,7 @@ import { import 'rxjs/add/operator/catch'; // Import RxJs required methods import 'rxjs/add/operator/map'; -import { Observable, Subject } from 'rxjs/Rx'; +import { Observable, Subject, BehaviorSubject } from 'rxjs/Rx'; import { v4 as uuid } from 'uuid'; import { environment } from '../../../environments/environment'; @@ -25,7 +25,7 @@ export class RuleEngineApiService { flowType: string; editorData: Subject = new Subject(); updateVersionLock: Subject = new Subject(); - tabIndex: Subject = new Subject(); + tabIndex: Subject = new BehaviorSubject(-1); constructor(private http: Http) { this.baseUrl = `${environment.apiBaseUrl}/rule-editor`; @@ -70,6 +70,20 @@ export class RuleEngineApiService { ); } + getLatestMcUuid(params) { + const { contextType, serviceUuid, vfiName, vfcmtUuid } = params; + const url = `${ + environment.apiBaseUrl + }/${contextType}/${serviceUuid}/${vfiName}/${vfcmtUuid}/getLatestMcUuid`; + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .get(url, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + getListOfRules(): Observable { const url = `${this.baseUrl}/rule/${this.vfcmtUuid}/${this.dcaeCompName}/${ this.nid @@ -83,8 +97,99 @@ export class RuleEngineApiService { }); } - modifyRule(newRole) { - const url = `${this.baseUrl}/rule/${this.vfcmtUuid}/${this.dcaeCompName}/${ + getInitialPhases(flowType): Observable { + const url = `${environment.apiBaseUrl}/conf/getPhases/${flowType}`; + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .get(url, this.options) + .map(response => response.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + + exportRules() { + const url = `${this.baseUrl}/export/${this.vfcmtUuid}/${ + this.dcaeCompName + }/${this.nid}/${this.configParam}`; + console.log(url); + const link = document.createElement('a'); + link.download = 'a'; + link.href = url; + document.body.appendChild(link); + link.click(); + } + + importRules(rule, vfcmtUuid, isGroup) { + const url = `${this.baseUrl}/import/${vfcmtUuid}/${this.dcaeCompName}/${ + this.nid + }/${this.configParam}/${isGroup}`; + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .post(url, rule, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json() || 'Server error'); + }); + } + + importPhase(ruleList) { + const url = `${this.baseUrl}/importPhase`; + + Object.assign(ruleList, { + vfcmtUuid: this.vfcmtUuid, + dcaeCompLabel: this.dcaeCompName, + nid: this.nid, + configParam: this.configParam + }); + + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .post(url, ruleList, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + + applyFilter(newFilter) { + const url = `${this.baseUrl}/applyFilter`; + + Object.assign(newFilter, { + vfcmtUuid: this.vfcmtUuid, + dcaeCompLabel: this.dcaeCompName, + nid: this.nid, + configParam: this.configParam + }); + + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .post(url, newFilter, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + + deleteFilter() { + const deleteFilter = { + vfcmtUuid: this.vfcmtUuid, + dcaeCompLabel: this.dcaeCompName, + nid: this.nid, + configParam: this.configParam + }; + const url = `${this.baseUrl}/deleteFilter`; + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .post(url, deleteFilter, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + + modifyRule(newRole, vfcmtUuid) { + const url = `${this.baseUrl}/rule/${vfcmtUuid}/${this.dcaeCompName}/${ this.nid }/${this.configParam}`; this.options.headers.set('X-ECOMP-RequestID', uuid()); @@ -96,8 +201,8 @@ export class RuleEngineApiService { }); } - deleteRule(uid) { - const url = `${this.baseUrl}/rule/${this.vfcmtUuid}/${this.dcaeCompName}/${ + deleteRule(uid, vfcmtUuid) { + const url = `${this.baseUrl}/rule/${vfcmtUuid}/${this.dcaeCompName}/${ this.nid }/${this.configParam}/${uid}`; this.options.headers.set('X-ECOMP-RequestID', uuid()); @@ -109,15 +214,28 @@ export class RuleEngineApiService { }); } - translate(nofityId) { + deleteGroup(groupId, vfcmtUuid) { + const url = `${this.baseUrl}/group/${vfcmtUuid}/${this.dcaeCompName}/${ + this.nid + }/${this.configParam}/${groupId}`; + this.options.headers.set('X-ECOMP-RequestID', uuid()); + return this.http + .delete(url, this.options) + .map((res: Response) => res.json()) + .catch((error: any) => { + return Observable.throw(error.json().requestError || 'Server error'); + }); + } + + translate(entryPhase, publishPhase, vfcmtUuid) { const url = `${this.baseUrl}/rule/translate`; const params = { - vfcmtUuid: this.vfcmtUuid, + vfcmtUuid: vfcmtUuid, dcaeCompLabel: this.dcaeCompName, nid: this.nid, configParam: this.configParam, - flowType: this.flowType, - notifyId: nofityId + entryPhase: entryPhase, + publishPhase: publishPhase }; this.options.headers.set('X-ECOMP-RequestID', uuid()); // const params = new URLSearchParams(); params.append('flowType', diff --git a/public/src/app/rule-engine/condition/condition.component.html b/public/src/app/rule-engine/condition/condition.component.html index 0ff244b..7ba21e2 100644 --- a/public/src/app/rule-engine/condition/condition.component.html +++ b/public/src/app/rule-engine/condition/condition.component.html @@ -5,17 +5,58 @@
      - -
      +
      of the following are true:
      -
      +
      +
      +
      + + Add Filter + +
      + +
      + + Add Filter Group + +
      +
      + +
      + +
      +
      + +
      -
      +
      @@ -64,21 +109,41 @@ + + + +
      -
      +
      Value
      + +
      + +
      + + + + +
      +
      diff --git a/public/src/app/rule-engine/condition/condition.component.scss b/public/src/app/rule-engine/condition/condition.component.scss index 8c0e9e0..228d8c6 100644 --- a/public/src/app/rule-engine/condition/condition.component.scss +++ b/public/src/app/rule-engine/condition/condition.component.scss @@ -9,7 +9,7 @@ padding: 0; } .angular-tree-component { - padding-left: 1em; + // padding-left: 1em; overflow-y: hidden; } .tree-node-leaf.container { @@ -26,11 +26,45 @@ } .node-wrapper { background: white; + padding-top: 10px; } .tree-children { border-left: 2px solid #f2f2f2; + border-right: 2px solid #f2f2f2; + border-bottom: 2px solid #f2f2f2; // border-top: 1px solid #f2f2f2; border-bottom: 1px solid #f2f2f2; + // border-bottom: 1px solid #f2f2f2; + } + .tree-node-level-2 + > tree-node-wrapper + > .node-wrapper + > .node-content-wrapper { + width: 90%; + } + .tree-node-level-2 .tree-children { + width: 90%; + } + .tree-node-level-3 + > tree-node-wrapper + > .node-wrapper + > .node-content-wrapper { + width: 85%; + } + .tree-node-level-3 .tree-children { + width: 85%; + } + .tree-node-level-4 + > tree-node-wrapper + > .node-wrapper + > .node-content-wrapper { + width: 80%; + } + .tree-node-level-4 .tree-children { + width: 80%; + } + div .node-content-wrapper { + padding: 0; } tree-node-expander { display: none; diff --git a/public/src/app/rule-engine/condition/condition.component.ts b/public/src/app/rule-engine/condition/condition.component.ts index f44fbf4..200b42d 100644 --- a/public/src/app/rule-engine/condition/condition.component.ts +++ b/public/src/app/rule-engine/condition/condition.component.ts @@ -3,10 +3,13 @@ import { ViewEncapsulation, ViewChild, Output, - EventEmitter + EventEmitter, + Input, + OnInit } from '@angular/core'; import { TreeModel, TreeComponent, ITreeOptions } from 'angular-tree-component'; -import { some } from 'lodash'; +import { some, cloneDeep } from 'lodash'; +import { toJS } from 'mobx'; @Component({ selector: 'app-condition', @@ -14,7 +17,9 @@ import { some } from 'lodash'; styleUrls: ['./condition.component.scss'], encapsulation: ViewEncapsulation.None }) -export class ConditionComponent { +export class ConditionComponent implements OnInit { + @Input() condition; + @Input() isFilter = false; conditionTree = []; showType = false; @ViewChild(TreeComponent) private tree: TreeComponent; @@ -27,7 +32,9 @@ export class ConditionComponent { animateAcceleration: 1.2 }; - constructor() { + ngOnInit(): void { + console.log('condition', this.condition); + this.conditionTree.push({ name: 'operator', level: 0, @@ -39,10 +46,23 @@ export class ConditionComponent { left: '', right: '', operator: null, - level: 1 + level: 1, + emptyIsAssigned: false }); + + if (this.condition) { + const condition = toJS(this.condition); + if (condition.name === 'condition') { + this.updateMode(true, condition); + } else { + const convertedCondition = this.convertConditionFromServer(condition); + this.updateMode(false, convertedCondition); + } + } } + constructor() {} + onInitialized(tree) { tree.treeModel.expandAll(); } @@ -58,7 +78,8 @@ export class ConditionComponent { left: data.left, right: data.right, operator: data.operator, - level: 1 + level: 1, + emptyIsAssigned: false }); this.showType = false; } else { @@ -82,7 +103,8 @@ export class ConditionComponent { left: '', right: '', operator: null, - level: tempLevel + level: tempLevel, + emptyIsAssigned: false }; selectedNode.data.children.push(conditionTemplate); tree.treeModel.update(); @@ -108,7 +130,8 @@ export class ConditionComponent { left: '', right: '', operator: null, - level: selectedNode.data.level + 2 + level: selectedNode.data.level + 2, + emptyIsAssigned: false }); } tree.treeModel.update(); @@ -149,6 +172,35 @@ export class ConditionComponent { } } + public changeRightToArrayOrString(data, toArray) { + data.forEach(element => { + if (element.name === 'operator') { + this.changeRightToArrayOrString(element.children, toArray); + } + if (element.name === 'condition') { + if (toArray) { + element.right = element.right.split(','); + } else { + element.right = element.right.join(','); + } + } + }); + console.log(data); + return data; + } + + public convertConditionFromServer(condition) { + const temp = new Array(); + temp.push(condition); + const cloneCondition = cloneDeep(temp); + const conditionSetData = this.changeRightToArrayOrString( + cloneCondition, + false + ); + console.log('condition to server:', conditionSetData); + return conditionSetData; + } + private deleteNodeAndUpdateTreeView(selectedNode: any, tree: any) { selectedNode.parent.data.children.splice(selectedNode.index, 1); tree.treeModel.update(); diff --git a/public/src/app/rule-engine/from/from.component.html b/public/src/app/rule-engine/from/from.component.html index df2c110..011f609 100644 --- a/public/src/app/rule-engine/from/from.component.html +++ b/public/src/app/rule-engine/from/from.component.html @@ -38,6 +38,35 @@
      + +
      +
      +
      +
      + From + +
      + + +
      + +
      +
      +
      + + Add input +
      +
      +
      - Add input
      diff --git a/public/src/app/rule-engine/from/from.component.scss b/public/src/app/rule-engine/from/from.component.scss index 852984d..f5ec4cc 100644 --- a/public/src/app/rule-engine/from/from.component.scss +++ b/public/src/app/rule-engine/from/from.component.scss @@ -1,7 +1,8 @@ .from { display: flex; flex-direction: column; - padding: 0 10px; + // padding: 0 10px; + padding-right: 10px; .label { border: 1px solid #d2d2d2; @@ -55,6 +56,7 @@ } /deep/ .mat-button-wrapper { padding: 0; + display: flex; } .mat-icon { width: 18px; diff --git a/public/src/app/rule-engine/from/from.component.ts b/public/src/app/rule-engine/from/from.component.ts index bc1dedb..c526103 100644 --- a/public/src/app/rule-engine/from/from.component.ts +++ b/public/src/app/rule-engine/from/from.component.ts @@ -3,7 +3,9 @@ import { Input, Output, EventEmitter, - ViewChild + ViewChild, + AfterViewInit, + ChangeDetectorRef } from '@angular/core'; // import { From } from "../model"; import { Subject } from 'rxjs/Subject'; @@ -23,40 +25,27 @@ import { NgForm } from '@angular/forms'; styleUrls: ['./from.component.scss'], animations: [ trigger('state', [ - state( - 'open', - style({ - opacity: 1, - height: 'auto' - }) - ), + state('open', style({ opacity: 1, height: 'auto' })), transition('* => open', [ - animate( - 200, - keyframes([ - style({ - opacity: 1, - height: 'auto' - }) - ]) - ) + animate(200, keyframes([style({ opacity: 1, height: 'auto' })])) ]), - state( - 'closed', - style({ - opacity: 0, - height: 0 - }) - ) + state('closed', style({ opacity: 0, height: 0 })) ]) ] }) -export class FromComponent { +export class FromComponent implements AfterViewInit { from: any = { value: '', regex: '', state: 'closed', - values: [{ value: '' }, { value: '' }] + values: [ + { + value: '' + }, + { + value: '' + } + ] }; @Input() actionType; @Output() onFromChange = new EventEmitter(); @@ -64,10 +53,20 @@ export class FromComponent { hoveredIndex; // public keyUp = new BehaviorSubject(null); - ngOnInit(): void { - if (this.actionType === 'clear') { - this.from.values = [{ value: '' }]; + constructor(private changeDetector: ChangeDetectorRef) {} + + ngAfterViewInit(): void { + if ( + (this.actionType === 'clear' || this.actionType === 'clear nsf') && + this.from.values[0].value === '' + ) { + this.from.values = [ + { + value: '' + } + ]; } + this.changeDetector.detectChanges(); } showRegex(item) { @@ -79,12 +78,22 @@ export class FromComponent { updateMode(fromData) { console.log(fromData); if (fromData) { - this.from = fromData; + if ( + (this.actionType === 'clear' || this.actionType === 'clear nsf') && + fromData.values[0].value === '' + ) { + this.from.values = [ + { + value: '' + } + ]; + } else { + this.from = fromData; + } } + this.changeDetector.detectChanges(); } - constructor() {} - modelChange(event) { this.onFromChange.emit(event); } diff --git a/public/src/app/rule-engine/rule-list/rule-list.component.html b/public/src/app/rule-engine/rule-list/rule-list.component.html index 4ce6efb..9a9997e 100644 --- a/public/src/app/rule-engine/rule-list/rule-list.component.html +++ b/public/src/app/rule-engine/rule-list/rule-list.component.html @@ -2,8 +2,8 @@
      Rule Engine
      - @@ -13,87 +13,238 @@
      -
      +
      {{ error }}
      - +
      + - - -
      +
      + +
      +
      -
      -
      - Rules were not yet created -
      -
      - Please create a new normalization rule +
      +
      +
      + + Add Phase
      + +
        +
      • + +
      • +
      • + +
      • +
      - - - Add First Rule - -
      +
      +
      +
      +
      + group_enrich + group_map +
      +
      + PHASE NAME +
      + -
      -
      - - Add Rule + + + +
      + +
      +
      + + {{rule.description}} - [{{rule.uid}}] + +
      + + + +
      +
      +
      + +
      + + Add Rule +
      + +
      -
      +
      + +
      -
      - - {{item.description}} - [{{item.uid}}] +
      +
      + Rules were not yet created +
      +
      + Please create a new normalization rule +
      +
      + + + + Add First Rule -
      - -
      + +
      +
      + + Add Rule +
      +
      + +
      + +
      + + {{item.description}} - [{{item.uid}}] + +
      + + + +
      +
      +
      diff --git a/public/src/app/rule-engine/rule-list/rule-list.component.scss b/public/src/app/rule-engine/rule-list/rule-list.component.scss index 6446fbd..822a3f4 100644 --- a/public/src/app/rule-engine/rule-list/rule-list.component.scss +++ b/public/src/app/rule-engine/rule-list/rule-list.component.scss @@ -6,6 +6,7 @@ flex-direction: column; margin: 0; padding: 0; + width: 100%; .header { position: relative; display: flex; @@ -28,6 +29,10 @@ } } +/deep/ .mat-mini-fab .mat-button-wrapper { + padding: 0; +} + .my-full-screen-dialog .mat-dialog-container { max-width: none; width: 100vw; @@ -117,3 +122,74 @@ .material-icons.md-light.md-inactive { color: rgba(255, 255, 255, 0.3); } + +.listOfRule { + display: flex; + background-color: #ffffff; + color: gray; + &:hover { + background-color: #e6f6fb; + color: #009fdb; + } + .ruleList-btn { + opacity: 0; + } + &:hover .ruleList-btn { + opacity: 1; + } +} + +.gray { + color: #696969; +} + +.icon-img { + width: 24px; + height: 24px; + padding: 2px; +} + +.button-list { + position: absolute; + left: 100px; + list-style-type: none; + width: 150px; + border-radius: 2px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.3); + background-color: #ffffff; + border: solid 1px #d2d2d2; + border-top: 2px solid #009fdb; + margin-left: 11px; + top: 10px; + // margin-top: 15px; + .button-options { + height: 29px; + padding: 7px 9px; + width: 100%; + text-align: left; + background: white; + border: 0px; + &:hover { + background-color: #e6f6fb; + cursor: pointer; + } + &:disabled, + [disabled] { + cursor: default; + } + } +} + +.btn-wrapper { + position: relative; + cursor: pointer; +} +.btn-wrapper input[type='file'] { + position: absolute; + left: 0; + top: 0; + opacity: 0; + width: 100%; + height: 36px; + cursor: pointer; +} diff --git a/public/src/app/rule-engine/rule-list/rule-list.component.ts b/public/src/app/rule-engine/rule-list/rule-list.component.ts index 2857ea2..c2878c1 100644 --- a/public/src/app/rule-engine/rule-list/rule-list.component.ts +++ b/public/src/app/rule-engine/rule-list/rule-list.component.ts @@ -6,6 +6,10 @@ import { timer } from 'rxjs/observable/timer'; import { Store } from '../../store/store'; import { RuleEngineApiService } from '../api/rule-engine-api.service'; import { ConfirmPopupComponent } from '../confirm-popup/confirm-popup.component'; +import { cloneDeep, has, countBy } from 'lodash'; +import { toJS } from 'mobx'; +import { v4 as uuidGenarator } from 'uuid'; +import { environment } from '../../../environments/environment'; const primaryColor = '#009fdb'; @@ -13,7 +17,7 @@ const primaryColor = '#009fdb'; selector: 'app-rule-list', templateUrl: './rule-list.component.html', styleUrls: ['./rule-list.component.scss'], - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.Emulated }) export class RuleListComponent { @ViewChild('versionEventType') versionType; @@ -27,6 +31,18 @@ export class RuleListComponent { params; versions; metaData; + tabName; + // group data + showBtnList = false; + entryPhase; + publishPhase; + latestBtnGroup; + imgBase = environment.imagePath; + fileToUpload; + fileName; + // filter + ifStatement = false; + condition: any; private errorHandler(error: any) { this.store.loader = false; @@ -45,7 +61,206 @@ export class RuleListComponent { } } + updateCondition(data) { + this.condition = data; + } + + filterCheckbox() { + this.ifStatement = !this.ifStatement; + if (!this.ifStatement && this.condition !== undefined) { + this.deleteFilter(); + } + } + + removeConditionCheck(flag) { + this.ifStatement = flag; + if (this.condition !== undefined) { + this.deleteFilter(); + } + } + + private deleteFilter() { + this.error = null; + this.store.loader = true; + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + this._ruleApi.deleteFilter().subscribe( + response => { + console.log('success import', response); + this.store.loader = false; + }, + error => { + const errorMsg = Object.values(error) as any; + if (errorMsg[0].messageId !== 'SVC6119') { + this.errorHandler(error); + } else { + this.store.loader = false; + } + this.condition = null; + } + ); + }, + error => { + this.errorHandler(error); + } + ); + } + + disabledMapBtn(btnType) { + if (this.store.groupList.length > 0) { + if (btnType === 'map') { + if ( + this.store.groupList[this.store.groupList.length - 1].groupId + .substring(0, 1) + .toLowerCase() === 'm' || + this.store.groupList.length === 3 + ) { + return true; + } else { + return false; + } + } else { + if ( + this.store.groupList[this.store.groupList.length - 1].groupId + .substring(0, 1) + .toLowerCase() === 'e' || + this.store.groupList.length === 3 + ) { + return true; + } else { + return false; + } + } + } + } + + disableDeleteGroup(groupId) { + const countGroupType = countBy(this.store.groupList, item => { + const innerGroupType = + item.groupId.substring(0, 1).toLowerCase() === 'm' ? 'map' : 'enrich'; + return innerGroupType === 'map' ? 'map' : 'enrich'; + }); + const groupType = + groupId.substring(0, 1).toLowerCase() === 'm' ? 'map' : 'enrich'; + if (groupType === 'map') { + return countGroupType.enrich === 2 ? true : false; + } else { + return countGroupType.map === 2 ? true : false; + } + } + + handleImportCDAP(files: FileList, groupId, phaseName) { + this.error = null; + this.store.loader = true; + this.fileToUpload = files.item(0); + console.log('file to load:', this.fileToUpload); + this.fileName = this.fileToUpload !== null ? this.fileToUpload.name : ''; + const reader = new FileReader(); + reader.readAsText(this.fileToUpload, 'UTF-8'); + reader.onload = () => { + console.log(reader.result); + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + const input = { + version: this.versionType.selectedVersion, + eventType: this.versionType.selectedEvent, + groupId: groupId, + phase: phaseName, + payload: JSON.parse(reader.result) + }; + this._ruleApi.importPhase(input).subscribe( + response => { + console.log('success import', response); + this.store.loader = false; + this.store.updateRuleList(Object.values(response.rules)); + }, + error => { + this.errorHandler(error); + } + ); + }, + error => { + this.errorHandler(error); + } + ); + }; + } + + addGroup(type) { + this.latestBtnGroup = type; + const defaultPhase = + type === 'enrich' + ? `standard_${this.tabName}_enrich` + : `standard_${this.tabName}`; + const groupId = type + uuidGenarator(); + const newGroup = { + groupId: groupId, + phase: defaultPhase + }; + this.store.groupList.push(newGroup); + this.showBtnList = false; + } + + deleteGroup(groupId) { + this.store.loader = true; + this.error = null; + // check if group list have list + const selectedGroup = this.store.groupList.filter( + item => item.groupId === groupId + ); + const isExistInRuleList = this.store.ruleList.filter( + item => item.groupId === groupId + ); + if (isExistInRuleList.length < 1) { + this.store.groupList = this.store.groupList.filter( + item => item.groupId !== groupId + ); + this.store.loader = false; + } else { + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + this._ruleApi.deleteGroup(groupId, res.uuid).subscribe( + response => { + this.store.deleteFromGroup(groupId); + this.store.loader = false; + }, + error => { + this.errorHandler(error); + } + ); + }, + error => this.errorHandler(error), + () => {} + ); + } + } + private getListOfRules() { + this.error = null; this._ruleApi.getListOfRules().subscribe( response => { console.log('res: %o', response); @@ -57,20 +272,37 @@ export class RuleListComponent { ); this.store.updateRuleList(Object.values(response.rules)); this.targetSource = response.schema; - this.store.notifyIdValue = response.notifyId; - this.versionType.notifyIdCheckbox = - response.notifyId !== '' ? true : false; + this.entryPhase = response.entryPhase; + this.publishPhase = response.publishPhase; + this.condition = response.filter; + this.ifStatement = this.condition == null ? false : true; } else { - this.versionType.notifyIdCheckbox = false; this.store.resetRuleList(); + this.condition = null; + this.ifStatement = false; this.versionType.updateVersionTypeFlag(false); this.targetSource = null; + + this._ruleApi.getInitialPhases(this.store.flowType).subscribe( + data => { + (this.entryPhase = data.entryPhase), + (this.publishPhase = data.publishPhase); + }, + error => { + this.errorHandler(error); + } + ); // if the the list is empty then get version and domain events - this._ruleApi.getMetaData().subscribe(data => { - console.log(data); - this.versions = data.map(x => x.version); - this.metaData = data; - }); + this._ruleApi.getMetaData().subscribe( + data => { + console.log(data); + this.versions = data.map(x => x.version); + this.metaData = data; + }, + error => { + this.errorHandler(error); + } + ); } this.store.loader = false; }, @@ -87,28 +319,120 @@ export class RuleListComponent { public store: Store ) { this.store.loader = false; - this._ruleApi.tabIndex.subscribe(index => { - console.log('rule index in rule-list component:', index); - const tabName = this.store.cdump.nodes[index].name; - console.log('tab name:', tabName); - - if (tabName.toLowerCase().includes('map')) { - this.params = { - vfcmtUuid: this.store.mcUuid, - nodeName: this.store.tabParmasForRule[0].name, - nodeId: this.store.tabParmasForRule[0].nid, - fieldName: this.store.tabsProperties[index][0].name, - userId: this.store.sdcParmas.userId, - flowType: this.store.cdump.flowType - }; - console.log('params: %o', this.params); - this.store.loader = true; - // set api params by iframe url query - this._ruleApi.setParams(this.params); - store.ruleListExistParams = this.params; - this.getListOfRules(); + this._ruleApi.tabIndex + // .filter(index => { if (index >= 0) { const tabName = + // this.store.cdump.nodes[index].name; console.log('tab name:', tabName); if + // (tabName.toLowerCase().includes('map')) { return index; } } }) + .subscribe(index => { + this.error = null; + if (index >= 0) { + this.tabName = this.store.cdump.nodes[index].name; + console.log('tab name:', this.tabName); + if ( + this.tabName.toLowerCase().includes('map') || + this.tabName.toLowerCase().includes('highlandpark') || + this.tabName.toLowerCase().includes('hp') + ) { + const advancedSetting = this.store.tabsProperties[index].filter( + item => { + if ( + !( + item.hasOwnProperty('constraints') && + item.value !== undefined && + !item.value.includes('get_input') + ) + ) { + return item; + } + } + ); + const mappingTarget = advancedSetting[0].name; + console.log('mappingTarget', mappingTarget); + + this.params = { + vfcmtUuid: this.store.mcUuid, + nodeName: this.store.tabParmasForRule[0].name, + nodeId: this.store.tabParmasForRule[0].nid, + fieldName: mappingTarget, + userId: this.store.sdcParmas.userId, + flowType: this.store.cdump.flowType + }; + console.log('params: %o', this.params); + this.store.loader = true; + // set api params by iframe url query + this._ruleApi.setParams(this.params); + store.ruleListExistParams = this.params; + this.getListOfRules(); + } + } + }); + } + + applyFilter() { + this.store.loader = true; + this.error = null; + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + let conditionData2server = null; + conditionData2server = this.convertConditionToServer(this.condition); + const newFilter = { + version: this.versionType.selectedVersion, + eventType: this.versionType.selectedEvent, + entryPhase: this.entryPhase, + publishPhase: this.publishPhase, + filter: conditionData2server + }; + this._ruleApi.applyFilter(newFilter).subscribe( + success => { + this.store.loader = false; + }, + error => { + this.errorHandler(error); + } + ); + }, + error => this.errorHandler(error), + () => {} + ); + } + + convertConditionToServer(tree) { + const cloneCondition = cloneDeep(tree); + const conditionSetData = this.changeRightToArrayOrString( + cloneCondition, + true + ); + let simpleCondition = null; + if (conditionSetData[0].children.length === 1) { + simpleCondition = conditionSetData[0].children; + } + console.log('condition to server:', conditionSetData); + return simpleCondition !== null ? simpleCondition[0] : conditionSetData[0]; + } + + changeRightToArrayOrString(data, toArray) { + data.forEach(element => { + if (element.name === 'operator') { + this.changeRightToArrayOrString(element.children, toArray); + } + if (element.name === 'condition') { + if (toArray) { + element.right = element.right.split(','); + } else { + element.right = element.right.join(','); + } } }); + console.log(data); + return data; } handlePropertyChange() { @@ -119,46 +443,52 @@ export class RuleListComponent { translateRules() { this.store.loader = true; - // send translate JSON - const nofityId = this.store.notifyIdValue; - this._ruleApi.translate(nofityId).subscribe( - data => { - this.store.loader = false; - console.log(JSON.stringify(data)); - let domElementName: string; - this.store.configurationForm.forEach(property => { - console.log('mappingTarget ', this.versionType.mappingTarget); - if (property.name === this.versionType.mappingTarget) { - property.value = JSON.stringify(data); - domElementName = property.name; - console.log(property.name); - } - }); - this.toastr.success('', 'Translate succeeded'); - this.store.expandAdvancedSetting[this.store.tabIndex] = true; - const source = timer(500); - source.subscribe(val => { - const el = document.getElementById(domElementName); - const label = el.children.item(0) as HTMLElement; - label.style.color = primaryColor; - const input = el.children.item(1) as HTMLElement; - input.style.color = primaryColor; - input.style.borderColor = primaryColor; - el.scrollIntoView(); - }); - }, - error => { - this.errorHandler(error); - } - ); + this.error = null; + // send translate JSON const nofityId = this.store.notifyIdValue; + const mcUuid = this.store.mcUuid; + this._ruleApi + .translate(this.entryPhase, this.publishPhase, mcUuid) + .subscribe( + data => { + this.store.loader = false; + console.log(JSON.stringify(data)); + let domElementName: string; + this.store.configurationForm.forEach(property => { + console.log('mappingTarget ', this.versionType.mappingTarget); + if (property.name === this.versionType.mappingTarget) { + property.value = JSON.stringify(data); + domElementName = property.name; + console.log(property.name); + } + }); + this.toastr.success('', 'Successfull translation'); + this.store.expandAdvancedSetting[this.store.tabIndex] = true; + const source = timer(500); + source.subscribe(val => { + const el = document.getElementById(domElementName); + const label = el.children.item(0) as HTMLElement; + label.style.color = primaryColor; + const input = el.children.item(1) as HTMLElement; + input.style.color = primaryColor; + input.style.borderColor = primaryColor; + el.scrollIntoView(); + this.store.cdumpIsDirty = true; + }); + }, + error => { + this.errorHandler(error); + } + ); } handleUpdateNode(data) { this.targetSource = data.nodes; this.store.resetRuleList(); + this.condition = null; + this.ifStatement = false; } - removeItem(uid) { + removeItem(uid, groupId) { this.dialogRef = this.dialog.open(ConfirmPopupComponent, { panelClass: 'my-confrim-dialog', disableClose: true @@ -168,38 +498,70 @@ export class RuleListComponent { if (result) { // call be api this.store.loader = true; - this._ruleApi.deleteRule(uid).subscribe( - success => { - this.store.removeRuleFromList(uid); - // if its the last rule - if (this.store.ruleList.length === 0) { - this._ruleApi.getMetaData().subscribe(data => { - console.log(data); - this.versions = data.map(x => x.version); - this.metaData = data; - this.versionType.updateVersionTypeFlag(false); - this.targetSource = null; - }); - } - this.store.loader = false; - }, - error => { - this.store.loader = false; - this.errorHandler(error); - } - ); + this.error = null; + this._ruleApi + .getLatestMcUuid({ + contextType: this.store.sdcParmas.contextType, + serviceUuid: this.store.sdcParmas.uuid, + vfiName: this.store.vfiName, + vfcmtUuid: this.store.mcUuid + }) + .subscribe( + res => { + this.store.mcUuid = res.uuid; + this._ruleApi.deleteRule(uid, res.uuid).subscribe( + success => { + this.store.removeRuleFromList(uid, groupId); + // if its the last rule + if (this.store.ruleList.length === 0) { + this._ruleApi.getMetaData().subscribe(data => { + console.log(data); + this.versions = data.map(x => x.version); + this.metaData = data; + this.versionType.updateVersionTypeFlag(false); + this.targetSource = null; + }); + } + this.store.loader = false; + }, + error => { + this.store.loader = false; + this.errorHandler(error); + } + ); + }, + error => this.errorHandler(error), + () => {} + ); } }); } - openAction(item): void { + copyRule(rule, index, groupItem) { + const copyRule = cloneDeep(toJS(rule)); + copyRule.uid = ''; + copyRule.description = copyRule.description.concat('_Copy'); + this.store.ruleList.push(copyRule); + this.openAction(copyRule, groupItem); + this.toastr.warning( + 'The rule you are editing has unsaved changes, please make sure to save your work' + + '.', + 'The mapping rule is copied' + ); + } + + openAction(item, groupItem): void { this.crud = isEmpty(item) ? 'new' : 'edit'; this._ruleApi.passDataToEditor({ version: this.versionType.selectedVersion, eventType: this.versionType.selectedEvent, targetSource: this.targetSource, item: isEmpty(item) ? null : item, - params: this.params + params: this.params, + groupId: isEmpty(groupItem) ? null : groupItem.groupId, + phase: isEmpty(groupItem) ? null : groupItem.phase, + entryPhase: this.entryPhase, + publishPhase: this.publishPhase }); this.store.isLeftVisible = false; diff --git a/public/src/app/rule-engine/target/target.component.ts b/public/src/app/rule-engine/target/target.component.ts index c9aa75c..b200144 100644 --- a/public/src/app/rule-engine/target/target.component.ts +++ b/public/src/app/rule-engine/target/target.component.ts @@ -4,7 +4,8 @@ import { ViewChild, Input, Output, - EventEmitter + EventEmitter, + ChangeDetectorRef } from '@angular/core'; import { TreeModel, TreeComponent, ITreeOptions } from 'angular-tree-component'; // import {trigger, state, animate, transition, style} from @@ -36,6 +37,8 @@ export class TargetComponent { animateAcceleration: 1.2 }; + constructor(private changeDetector: ChangeDetectorRef) {} + filterFn(value, treeModel: TreeModel) { treeModel.filterNodes(node => fuzzysearch(value, node.data.name)); } @@ -49,6 +52,7 @@ export class TargetComponent { id: action.target, name: '' }; + this.changeDetector.detectChanges(); } onEvent(event) { diff --git a/public/src/app/rule-engine/version-type-select/version-type-select.component.html b/public/src/app/rule-engine/version-type-select/version-type-select.component.html index 74c55a8..df1b497 100644 --- a/public/src/app/rule-engine/version-type-select/version-type-select.component.html +++ b/public/src/app/rule-engine/version-type-select/version-type-select.component.html @@ -2,10 +2,12 @@
      -
      - Mapping Target +
      + + Mapping Target +
      -
      +
      Version - {{selectedVersion}}
      -
      +
      Event Domain @@ -38,16 +40,16 @@ data-tests-id="selectEventType"> - - {{selectedEvent | slice:0:selectedEvent.length-6}} + + {{selectedEvent + | slice:0:selectedEvent.length-6}}
      -
      + @@ -58,7 +60,8 @@
      -
      +
      --> +
      diff --git a/public/src/app/rule-engine/version-type-select/version-type-select.component.scss b/public/src/app/rule-engine/version-type-select/version-type-select.component.scss index 1be996e..a6eca3f 100644 --- a/public/src/app/rule-engine/version-type-select/version-type-select.component.scss +++ b/public/src/app/rule-engine/version-type-select/version-type-select.component.scss @@ -2,7 +2,7 @@ display: flex; // margin: 10px 0; // align-items: center; flex-direction: column; - margin-bottom: 30px; + // margin-bottom: 30px; } .small-padding { diff --git a/public/src/app/rule-engine/version-type-select/version-type-select.component.ts b/public/src/app/rule-engine/version-type-select/version-type-select.component.ts index ff229cd..6869260 100644 --- a/public/src/app/rule-engine/version-type-select/version-type-select.component.ts +++ b/public/src/app/rule-engine/version-type-select/version-type-select.component.ts @@ -28,40 +28,46 @@ export class VersionTypeSelectComponent { // set ddl with the first option value. this._ruleApi.tabIndex.subscribe(index => { - console.log('rule index:', index); - - const tabName = this.store.cdump.nodes[index].name; - console.log('tab name:', tabName); + if (index >= 0) { + const tabName = this.store.cdump.nodes[index].name; + console.log('tab name:', tabName); + if ( + tabName.toLowerCase().includes('map') || + tabName.toLowerCase().includes('highlandpark') || + tabName.toLowerCase().includes('hp') + ) { + this.advancedSetting = this.store.tabsProperties[index].filter( + item => { + if ( + !( + item.hasOwnProperty('constraints') && + item.value !== undefined && + !item.value.includes('get_input') + ) + ) { + return item; + } + } + ); + this.mappingTarget = this.advancedSetting[0].name; - if (tabName.toLowerCase().includes('map')) { - this.mappingTarget = this.store.tabsProperties[index][0].name; - this.advancedSetting = this.store.tabsProperties[index].filter(item => { - if ( - !( - item.hasOwnProperty('constraints') && - !item.value.includes('get_input') + this._ruleApi + .generateMappingRulesFileName( + this.store.ruleListExistParams.nodeName, + this.store.ruleListExistParams.nodeId, + this.store.ruleListExistParams.vfcmtUuid ) - ) { - return item; - } - }); - - this._ruleApi - .generateMappingRulesFileName( - this.store.ruleListExistParams.nodeName, - this.store.ruleListExistParams.nodeId, - this.store.ruleListExistParams.vfcmtUuid - ) - .subscribe(response => { - console.log('generateMappingRulesFileName response: ', response); - this.advancedSetting.forEach(element => { - if (response.includes(element.name)) { - element.isExist = true; - } else { - element.isExist = false; - } + .subscribe(response => { + console.log('generateMappingRulesFileName response: ', response); + this.advancedSetting.forEach(element => { + if (response.includes(element.name)) { + element.isExist = true; + } else { + element.isExist = false; + } + }); }); - }); + } } }); } diff --git a/public/src/app/rule-frame/rule-frame.component.html b/public/src/app/rule-frame/rule-frame.component.html index e0afa3d..9258342 100644 --- a/public/src/app/rule-frame/rule-frame.component.html +++ b/public/src/app/rule-frame/rule-frame.component.html @@ -1,11 +1,12 @@
      -
      +
      -
      +
      diff --git a/public/src/app/store/store.ts b/public/src/app/store/store.ts index b075699..5ae4f24 100644 --- a/public/src/app/store/store.ts +++ b/public/src/app/store/store.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { findIndex } from 'lodash'; import { action, computed, observable, toJS } from 'mobx'; +import { groupBy, prop, compose, values } from 'ramda'; @Injectable() export class Store { @@ -14,6 +15,7 @@ export class Store { @observable loader = false; @observable cdumpIsDirty = false; @observable expandAdvancedSetting = []; + @observable expandImports = []; @observable generalflow; @observable vfiName; @observable flowType; @@ -27,6 +29,7 @@ export class Store { // rule-engine @observable tabParmasForRule; @observable ruleList = new Array(); + @observable groupList = new Array(); @observable ruleListExistParams; @observable ruleEditorInitializedState; @observable isLeftVisible; @@ -50,22 +53,60 @@ export class Store { console.log('new rule'); this.ruleList.push(rule); } + // handle group list + if (rule.groupId !== undefined) { + this.groupList + .filter(item => item.groupId === rule.groupId) + .map(item2 => { + if (item2.list === undefined) { + item2.list = new Array(); + } + const ruleItemIndex = findIndex( + item2.list, + ruleFromList => ruleFromList.uid === rule.uid + ); + if (ruleItemIndex > -1) { + item2.list[ruleItemIndex] = rule; + } else { + item2.list.push(rule); + } + }); + } } @action updateRuleList(listOfRules) { this.ruleList = listOfRules; console.log(toJS(this.ruleList)); + const fn = compose(values, groupBy(prop('groupId')))(listOfRules); + const dis = fn.map(item => { + return { groupId: item[0].groupId, phase: item[0].phase, list: item }; + }); + console.log(dis); + this.groupList = dis; } @action - removeRuleFromList(uid) { + deleteFromGroup(groupId) { + this.groupList = this.groupList.filter(item => item.groupId !== groupId); + } + + @action + removeRuleFromList(uid, groupId) { this.ruleList = this.ruleList.filter(item => item.uid !== uid); + // remove from group + this.groupList.forEach(item => { + if (item.groupId === groupId) { + item.list = item.list.filter(listItem => listItem.uid !== uid); + } + return item; + }); } @action resetRuleList() { this.ruleList = new Array(); + this.groupList = new Array(); } @action @@ -85,21 +126,23 @@ export class Store { if (!x.assignment) { x.assignment = {}; x.assignment.value = ''; - } else if (typeof x.assignment.value === 'object') { - x.assignment.value = JSON.stringify(x.assignment.value); } if (x.value) { if (typeof x.value === 'object') { - x.value = JSON.stringify(x.value); + x.value = ''; } } else if (!x.value) { - x.value = x.assignment.value; + if (typeof x.assignment.value === 'object') { + x.value = ''; + } + // else { x.value = x.assignment.value; } } return x; }); }); nodes.map(() => { this.expandAdvancedSetting.push(false); + this.expandImports.push(false); }); console.log('tabsProperties: %o', this.tabsProperties.toJS()); } diff --git a/public/src/assets/images/group_enrich.svg b/public/src/assets/images/group_enrich.svg new file mode 100644 index 0000000..b0ac313 --- /dev/null +++ b/public/src/assets/images/group_enrich.svg @@ -0,0 +1 @@ +Artboard 1 copy \ No newline at end of file diff --git a/public/src/assets/images/group_map.svg b/public/src/assets/images/group_map.svg new file mode 100644 index 0000000..14cd038 --- /dev/null +++ b/public/src/assets/images/group_map.svg @@ -0,0 +1,25 @@ + + + + icons/group_map + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/src/styles.css b/public/src/styles.css index a56199a..c9ff9f5 100644 --- a/public/src/styles.css +++ b/public/src/styles.css @@ -90,3 +90,7 @@ input.ng-touched.ng-invalid:not(form) { .ui-dialog-titlebar { background: white; } + +::-webkit-file-upload-button { + cursor: pointer; +} diff --git a/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxy.java b/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxy.java index 4900f27..bfacd09 100644 --- a/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxy.java +++ b/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxy.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.util.StringUtils; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.concurrent.TimeUnit; @@ -32,9 +33,18 @@ public class DcaeProxy extends ProxyServlet { @Override protected HttpClient newHttpClient() { SslContextFactory factory = new SslContextFactory(true); - return new HttpClient(factory); + return new HttpClient(factory); } + + @Override + protected HttpClient createHttpClient() throws ServletException { + HttpClient client = super.createHttpClient(); + client.setIdleTimeout(180000); + client.setConnectTimeout(180000); + return client; + } + @Override protected String rewriteTarget(HttpServletRequest request) { try{ -- cgit 1.2.3-korg