You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by rm...@apache.org on 2018/10/25 12:59:59 UTC

metron git commit: METRON-1830 Re-implement Alerts dialog box without jQuery (sardell via merrimanr) closes apache/metron#1240

Repository: metron
Updated Branches:
  refs/heads/master 0e037edad -> eee996302


METRON-1830 Re-implement Alerts dialog box without jQuery (sardell via merrimanr) closes apache/metron#1240


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/eee99630
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/eee99630
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/eee99630

Branch: refs/heads/master
Commit: eee99630270e08412e589b99afafbb2246f88af5
Parents: 0e037ed
Author: sardell <sa...@hortonworks.com>
Authored: Thu Oct 25 07:59:44 2018 -0500
Committer: rmerriman <me...@gmail.com>
Committed: Thu Oct 25 07:59:44 2018 -0500

----------------------------------------------------------------------
 .../alert-details/alert-details.component.ts    |  10 +-
 .../alerts/alerts-list/alerts-list.component.ts |   9 +-
 .../table-view/table-view.component.spec.ts     |   4 +-
 .../table-view/table-view.component.ts          |  49 ++++---
 .../tree-view/tree-view.component.spec.ts       |   4 +-
 .../tree-view/tree-view.component.ts            |  20 +--
 .../alerts/meta-alerts/meta-alerts.component.ts |   2 -
 .../save-search/save-search.component.spec.ts   |   4 +-
 .../alerts/save-search/save-search.component.ts |  12 +-
 .../saved-searches.component.spec.ts            |   5 +-
 .../saved-searches/saved-searches.component.ts  |  41 ++++--
 .../metron-alerts/src/app/app.component.html    |   1 +
 .../metron-alerts/src/app/app.component.spec.ts |   4 +
 .../metron-alerts/src/app/app.module.ts         |  12 +-
 .../src/app/model/confirmation-type.ts          |  21 +++
 .../metron-alerts/src/app/model/dialog-type.ts  |  21 +++
 .../src/app/service/dialog.service.spec.ts      |  78 ++++++++++++
 .../src/app/service/dialog.service.ts           |  55 ++++++++
 .../src/app/shared/metron-dialog-box.ts         |  91 -------------
 .../metron-dialog/metron-dialog.component.html  |  40 ++++++
 .../metron-dialog/metron-dialog.component.scss  |  20 +++
 .../metron-dialog.component.spec.ts             | 127 +++++++++++++++++++
 .../metron-dialog/metron-dialog.component.ts    |  66 ++++++++++
 23 files changed, 529 insertions(+), 167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
index 0693457..4c0b18b 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
@@ -29,10 +29,11 @@ import {PatchRequest} from '../../model/patch-request';
 import {Patch} from '../../model/patch';
 import {AlertComment} from './alert-comment';
 import {AuthenticationService} from '../../service/authentication.service';
-import {MetronDialogBox} from '../../shared/metron-dialog-box';
 import {CommentAddRemoveRequest} from "../../model/comment-add-remove-request";
 import {META_ALERTS_SENSOR_TYPE} from '../../utils/constants';
 import {GlobalConfigService} from '../../service/global-config.service';
+import { DialogService } from 'app/service/dialog.service';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 export enum AlertState {
   NEW, OPEN, ESCALATE, DISMISS, RESOLVE
@@ -83,7 +84,7 @@ export class AlertDetailsComponent implements OnInit {
               private updateService: UpdateService,
               private alertsService: AlertsService,
               private authenticationService: AuthenticationService,
-              private metronDialogBox: MetronDialogBox,
+              private dialogService: DialogService,
               globalConfigService: GlobalConfigService) {
     this.globalConfigService = globalConfigService;
   }
@@ -249,8 +250,8 @@ export class AlertDetailsComponent implements OnInit {
       commentText += ' \'' + this.alertCommentsWrapper[index].alertComment.comment + '\'';
     }
 
-    this.metronDialogBox.showConfirmationMessage(commentText).subscribe(response => {
-      if (response) {
+    const confirmedSubscription = this.dialogService.launchDialog(commentText).subscribe(action => {
+      if (action === ConfirmationType.Confirmed) {
         let deletedCommentWrapper = this.alertCommentsWrapper.splice(index, 1)[0];
         let commentRequest = new CommentAddRemoveRequest();
         commentRequest.guid = this.alertSource.guid;
@@ -268,6 +269,7 @@ export class AlertDetailsComponent implements OnInit {
               this.alertCommentsWrapper.sort((a, b) => b.alertComment.timestamp - a.alertComment.timestamp);
             });
       }
+      confirmedSubscription.unsubscribe();
     });
   }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
index d5b3c8b..fcc129f 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
@@ -33,7 +33,6 @@ import {SaveSearchService} from '../../service/save-search.service';
 import {RefreshInterval} from '../configure-rows/configure-rows-enums';
 import {SaveSearch} from '../../model/save-search';
 import {TableMetadata} from '../../model/table-metadata';
-import {MetronDialogBox, DialogType} from '../../shared/metron-dialog-box';
 import {AlertSearchDirective} from '../../shared/directives/alert-search.directive';
 import {SearchResponse} from '../../model/search-response';
 import {ElasticsearchUtils} from '../../utils/elasticsearch-utils';
@@ -45,6 +44,8 @@ import {META_ALERTS_SENSOR_TYPE} from '../../utils/constants';
 import {MetaAlertService} from '../../service/meta-alert.service';
 import {Facets} from '../../model/facets';
 import { GlobalConfigService } from '../../service/global-config.service';
+import { DialogService } from 'app/service/dialog.service';
+import { DialogType } from 'app/model/dialog-type';
 
 @Component({
   selector: 'app-alerts-list',
@@ -88,9 +89,9 @@ export class AlertsListComponent implements OnInit, OnDestroy {
               private alertsService: AlertsService,
               private clusterMetaDataService: ClusterMetaDataService,
               private saveSearchService: SaveSearchService,
-              private metronDialogBox: MetronDialogBox,
               private metaAlertsService: MetaAlertService,
-              private globalConfigService: GlobalConfigService) {
+              private globalConfigService: GlobalConfigService,
+              private dialogService: DialogService) {
     router.events.subscribe(event => {
       if (event instanceof NavigationStart && event.url === '/alerts-list') {
         this.selectedAlerts = [];
@@ -339,7 +340,7 @@ export class AlertsListComponent implements OnInit, OnDestroy {
       this.setData(results);
     }, error => {
       this.setData(new SearchResponse());
-      this.metronDialogBox.showConfirmationMessage(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error);
+      this.dialogService.launchDialog(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error);
     });
 
     this.tryStartPolling();

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.spec.ts
index 73dde50..2d7af57 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.spec.ts
@@ -26,11 +26,11 @@ import { MetronSorterComponent } from '../../../shared/metron-table/metron-sorte
 import { CenterEllipsesPipe } from '../../../shared/pipes/center-ellipses.pipe';
 import { ColumnNameTranslatePipe } from '../../../shared/pipes/column-name-translate.pipe';
 import { AlertSeverityDirective } from '../../../shared/directives/alert-severity.directive';
-import { MetronDialogBox } from '../../../shared/metron-dialog-box';
 import { SearchService } from '../../../service/search.service';
 import { UpdateService } from '../../../service/update.service';
 import { GlobalConfigService } from '../../../service/global-config.service';
 import { MetaAlertService } from '../../../service/meta-alert.service';
+import { DialogService } from 'app/service/dialog.service';
 
 @Component({selector: 'metron-table-pagination', template: ''})
 class MetronTablePaginationComponent {
@@ -50,7 +50,7 @@ describe('TableViewComponent', () => {
         UpdateService,
         GlobalConfigService,
         MetaAlertService,
-        MetronDialogBox,
+        DialogService
       ],
       declarations: [
         MetronTableDirective,

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts
index fd05b69..fd47b67 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts
@@ -24,7 +24,6 @@ import {SortEvent} from '../../../shared/metron-table/metron-table.directive';
 import {ColumnMetadata} from '../../../model/column-metadata';
 import {Alert} from '../../../model/alert';
 import {SearchService} from '../../../service/search.service';
-import {MetronDialogBox} from '../../../shared/metron-dialog-box';
 import {QueryBuilder} from '../query-builder';
 import {Sort} from '../../../utils/enums';
 import {Filter} from '../../../model/filter';
@@ -34,6 +33,8 @@ import {MetaAlertService} from '../../../service/meta-alert.service';
 import {MetaAlertAddRemoveRequest} from '../../../model/meta-alert-add-remove-request';
 import {GetRequest} from '../../../model/get-request';
 import { GlobalConfigService } from '../../../service/global-config.service';
+import { DialogService } from '../../../service/dialog.service';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 export enum MetronAlertDisplayState {
   COLLAPSE, EXPAND
@@ -47,15 +48,10 @@ export enum MetronAlertDisplayState {
 
 export class TableViewComponent implements OnInit, OnChanges, OnDestroy {
 
-  searchService: SearchService;
-  updateService: UpdateService;
   isStatusFieldPresent = false;
-  metronDialogBox: MetronDialogBox;
-  metaAlertService: MetaAlertService;
   metaAlertsDisplayState: {[key: string]: MetronAlertDisplayState} = {};
   metronAlertDisplayState = MetronAlertDisplayState;
   globalConfig: {} = {};
-  globalConfigService: GlobalConfigService;
   configSubscription: Subscription;
 
   @Input() alerts: Alert[] = [];
@@ -71,16 +67,11 @@ export class TableViewComponent implements OnInit, OnChanges, OnDestroy {
   @Output() onShowConfigureTable = new EventEmitter<Alert>();
   @Output() onSelectedAlertsChange = new EventEmitter< Alert[]>();
 
-  constructor(searchService: SearchService,
-              metronDialogBox: MetronDialogBox,
-              updateService: UpdateService,
-              metaAlertService: MetaAlertService,
-              globalConfigService: GlobalConfigService) {
-    this.searchService = searchService;
-    this.metronDialogBox = metronDialogBox;
-    this.updateService = updateService;
-    this.metaAlertService = metaAlertService;
-    this.globalConfigService = globalConfigService;
+  constructor(public searchService: SearchService,
+              public updateService: UpdateService,
+              public metaAlertService: MetaAlertService,
+              public globalConfigService: GlobalConfigService,
+              public dialogService: DialogService) {
   }
 
   ngOnInit() {
@@ -259,20 +250,26 @@ export class TableViewComponent implements OnInit, OnChanges, OnDestroy {
   }
 
   deleteOneAlertFromMetaAlert($event, alert: Alert, metaAlertIndex: number) {
-    this.metronDialogBox.showConfirmationMessage('Do you wish to remove the alert from the meta alert?').subscribe(response => {
-      if (response) {
-        this.doDeleteOneAlertFromMetaAlert(alert, metaAlertIndex);
-      }
-    });
+    const confirmedSubscription = this.dialogService
+      .launchDialog('Do you wish to remove the alert from the meta alert?')
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteOneAlertFromMetaAlert(alert, metaAlertIndex);
+        }
+        confirmedSubscription.unsubscribe();
+      });
     $event.stopPropagation();
   }
 
   deleteMetaAlert($event, alert: Alert) {
-    this.metronDialogBox.showConfirmationMessage('Do you wish to remove all the alerts from meta alert?').subscribe(response => {
-      if (response) {
-        this.doDeleteMetaAlert(alert);
-      }
-    });
+    const confirmedSubscription = this.dialogService
+      .launchDialog('Do you wish to remove all the alerts from meta alert?')
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteMetaAlert(alert);
+        }
+        confirmedSubscription.unsubscribe();
+      });
     $event.stopPropagation();
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.spec.ts
index 9716c53..fda2b78 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.spec.ts
@@ -28,10 +28,10 @@ import { ColumnNameTranslatePipe } from '../../../shared/pipes/column-name-trans
 import { AlertSeverityDirective } from '../../../shared/directives/alert-severity.directive';
 import { MetronTablePaginationComponent } from '../../../shared/metron-table/metron-table-pagination/metron-table-pagination.component';
 import { SearchService } from '../../../service/search.service';
-import { MetronDialogBox } from '../../../shared/metron-dialog-box';
 import { UpdateService } from '../../../service/update.service';
 import { GlobalConfigService } from '../../../service/global-config.service';
 import { MetaAlertService } from '../../../service/meta-alert.service';
+import { DialogService } from 'app/service/dialog.service';
 
 describe('TreeViewComponent', () => {
   let component: TreeViewComponent;
@@ -45,7 +45,7 @@ describe('TreeViewComponent', () => {
         UpdateService,
         GlobalConfigService,
         MetaAlertService,
-        MetronDialogBox,
+        DialogService
       ],
       declarations: [
         MetronTableDirective,

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
index ab168aa..ab1d4eb 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
@@ -27,7 +27,6 @@ import {GroupResponse} from '../../../model/group-response';
 import {GroupResult} from '../../../model/group-result';
 import {SortField} from '../../../model/sort-field';
 import {Sort} from '../../../utils/enums';
-import {MetronDialogBox, DialogType} from '../../../shared/metron-dialog-box';
 import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
 import {SearchRequest} from '../../../model/search-request';
 import {MetaAlertCreateRequest} from '../../../model/meta-alert-create-request';
@@ -37,6 +36,9 @@ import {UpdateService} from '../../../service/update.service';
 import {PatchRequest} from '../../../model/patch-request';
 import {GetRequest} from '../../../model/get-request';
 import { GlobalConfigService } from '../../../service/global-config.service';
+import { DialogService } from '../../../service/dialog.service';
+import { DialogType } from 'app/model/dialog-type';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 @Component({
   selector: 'app-tree-view',
@@ -53,13 +55,14 @@ export class TreeViewComponent extends TableViewComponent implements OnInit, OnC
   treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
   alertsChangedSubscription: Subscription;
   configSubscription: Subscription;
+  dialogService: DialogService
 
   constructor(searchService: SearchService,
-              metronDialogBox: MetronDialogBox,
               updateService: UpdateService,
               metaAlertService: MetaAlertService,
-              globalConfigService: GlobalConfigService) {
-    super(searchService, metronDialogBox, updateService, metaAlertService, globalConfigService);
+              globalConfigService: GlobalConfigService,
+              dialogService: DialogService) {
+    super(searchService, updateService, metaAlertService, globalConfigService, dialogService);
   }
 
   addAlertChangedListner() {
@@ -194,7 +197,7 @@ export class TreeViewComponent extends TableViewComponent implements OnInit, OnC
     return this.searchService.search(searchRequest).subscribe(results => {
       this.setData(selectedGroup, results);
     }, error => {
-      this.metronDialogBox.showConfirmationMessage(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error);
+      this.dialogService.launchDialog(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error);
     });
   }
 
@@ -358,7 +361,7 @@ export class TreeViewComponent extends TableViewComponent implements OnInit, OnC
   canCreateMetaAlert(count: number) {
     if (count > MAX_ALERTS_IN_META_ALERTS) {
       let errorMessage = 'Meta Alert cannot have more than ' + MAX_ALERTS_IN_META_ALERTS +' alerts within it';
-      this.metronDialogBox.showConfirmationMessage(errorMessage, DialogType.Error).subscribe((response) => {});
+      this.dialogService.launchDialog(errorMessage, DialogType.Error);
       return false;
     }
     return true;
@@ -421,10 +424,11 @@ export class TreeViewComponent extends TableViewComponent implements OnInit, OnC
     if (this.canCreateMetaAlert(group.total)) {
       let confirmationMsg = 'Do you wish to create a meta alert with ' +
                             (group.total === 1 ? ' alert' : group.total + ' selected alerts') + '?';
-      this.metronDialogBox.showConfirmationMessage(confirmationMsg).subscribe((response) => {
-        if (response) {
+      const confirmedSubscription = this.dialogService.launchDialog(confirmationMsg).subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
           this.doCreateMetaAlert(group, index);
         }
+        confirmedSubscription.unsubscribe();
       });
     }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/meta-alerts/meta-alerts.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/meta-alerts/meta-alerts.component.ts b/metron-interface/metron-alerts/src/app/alerts/meta-alerts/meta-alerts.component.ts
index bcead06..7031a08 100644
--- a/metron-interface/metron-alerts/src/app/alerts/meta-alerts/meta-alerts.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/meta-alerts/meta-alerts.component.ts
@@ -26,7 +26,6 @@ import {SearchService} from '../../service/search.service';
 import {SearchResponse} from '../../model/search-response';
 import {SortField} from '../../model/sort-field';
 import { META_ALERTS_SENSOR_TYPE } from '../../utils/constants';
-import {MetronDialogBox} from '../../shared/metron-dialog-box';
 import {MetaAlertAddRemoveRequest} from '../../model/meta-alert-add-remove-request';
 import {GetRequest} from '../../model/get-request';
 import { GlobalConfigService } from '../../service/global-config.service';
@@ -47,7 +46,6 @@ export class MetaAlertsComponent implements OnInit, OnDestroy {
               private metaAlertService: MetaAlertService,
               private updateService: UpdateService,
               private searchService: SearchService,
-              private metronDialogBox: MetronDialogBox,
               private globalConfigService: GlobalConfigService) {
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.spec.ts
index b47caca..d230b02 100644
--- a/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.spec.ts
@@ -21,7 +21,7 @@ import { SaveSearchComponent } from './save-search.component';
 import { FormsModule } from '@angular/forms';
 import { Router } from '@angular/router';
 import { SaveSearchService } from '../../service/save-search.service';
-import { MetronDialogBox } from '../../shared/metron-dialog-box';
+import { DialogService } from 'app/service/dialog.service';
 
 describe('SaveSearchComponent', () => {
   let component: SaveSearchComponent;
@@ -33,7 +33,7 @@ describe('SaveSearchComponent', () => {
         FormsModule
       ],
       providers: [
-        MetronDialogBox,
+        DialogService,
         { provide: Router, useValue: {} },
         { provide: SaveSearchService, useValue: {} }
       ],

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.ts b/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.ts
index b27da3a..276cb9b 100644
--- a/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/save-search/save-search.component.ts
@@ -20,7 +20,8 @@ import {Router} from '@angular/router';
 
 import {SaveSearchService} from '../../service/save-search.service';
 import {SaveSearch} from '../../model/save-search';
-import {MetronDialogBox} from '../../shared/metron-dialog-box';
+import { DialogService } from 'app/service/dialog.service';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 @Component({
   selector: 'app-save-search',
@@ -33,7 +34,7 @@ export class SaveSearchComponent implements OnInit {
 
   constructor(private router: Router,
               private saveSearchService: SaveSearchService,
-              private metronDialogBox: MetronDialogBox) {
+              private dialogService: DialogService) {
   }
 
   goBack() {
@@ -49,7 +50,7 @@ export class SaveSearchComponent implements OnInit {
     this.saveSearch.tableColumns = this.saveSearchService.tableColumns;
     this.saveSearch.filters = this.saveSearchService.queryBuilder.filters;
     this.saveSearch.searchRequest.query = '';
-    
+
     this.saveSearchService.saveSearch(this.saveSearch).subscribe(() => {
       this.goBack();
     }, error => {
@@ -68,11 +69,12 @@ export class SaveSearchComponent implements OnInit {
 
   update() {
     let message = 'A Search with the name \'' + this.saveSearch.name + '\' already exist do you wish to override it?';
-    this.metronDialogBox.showConfirmationMessage(message).subscribe(result => {
-      if (result) {
+    const confirmedSubscription = this.dialogService.launchDialog(message).subscribe(action => {
+      if (action === ConfirmationType.Confirmed) {
         this.saveSearch.searchRequest = this.saveSearchService.queryBuilder.searchRequest;
         this.saveSearchService.updateSearch(this.saveSearch).subscribe(() => { this.goBack(); }, error => {});
       }
+      confirmedSubscription.unsubscribe();
     });
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
index 899a2b1..a953b32 100644
--- a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { Component, Input } from '@angular/core';
 
 import { SavedSearchesComponent } from './saved-searches.component';
 import { CollapseComponent } from '../../shared/collapse/collapse.component';
@@ -24,8 +23,8 @@ import { CenterEllipsesPipe } from '../../shared/pipes/center-ellipses.pipe';
 import { ColumnNameTranslatePipe } from '../../shared/pipes/column-name-translate.pipe';
 import { Router } from '@angular/router';
 import { SaveSearchService } from '../../service/save-search.service';
-import { MetronDialogBox } from '../../shared/metron-dialog-box';
 import { of } from 'rxjs';
+import { DialogService } from 'app/service/dialog.service';
 
 
 describe('SavedSearchesComponent', () => {
@@ -40,7 +39,7 @@ describe('SavedSearchesComponent', () => {
           listSavedSearches: jasmine.createSpy('listSavedSearches').and.returnValue(of([])),
           listRecentSearches: jasmine.createSpy('listRecentSearches').and.returnValue(of([])),
         } },
-        MetronDialogBox
+        DialogService
       ],
       declarations: [
         SavedSearchesComponent,

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
index 2204179..ab182c0 100644
--- a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
@@ -22,9 +22,10 @@ import {forkJoin as observableForkJoin} from 'rxjs';
 
 import {SaveSearchService} from '../../service/save-search.service';
 import {SaveSearch} from '../../model/save-search';
-import {MetronDialogBox} from '../../shared/metron-dialog-box';
 import {NUM_SAVED_SEARCH} from '../../utils/constants';
 import {CollapseComponentData, CollapseComponentDataItems} from '../../shared/collapse/collapse-component-data';
+import { DialogService } from 'app/service/dialog.service';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 @Component({
   selector: 'app-saved-searches',
@@ -39,7 +40,7 @@ export class SavedSearchesComponent implements OnInit {
   recentSearches: CollapseComponentData = new CollapseComponentData();
   constructor(private router: Router,
               private saveSearchService: SaveSearchService,
-              private metronDialog: MetronDialogBox) {
+              private dialogService: DialogService) {
   }
 
   doDeleteRecentSearch(selectedSearch: SaveSearch) {
@@ -61,21 +62,33 @@ export class SavedSearchesComponent implements OnInit {
   }
 
   deleteRecentSearch($event) {
-    let selectedSearch = this.recentSearcheObj.find(savedSearch => savedSearch.name === $event.key);
-    this.metronDialog.showConfirmationMessage('Do you wish to delete recent search ' + selectedSearch.name).subscribe((result: boolean) => {
-      if (result) {
-        this.doDeleteRecentSearch(selectedSearch);
-      }
-    });
+    let selectedSearch = this.recentSearcheObj.find(
+      savedSearch => savedSearch.name === $event.key
+    );
+    const confirmedSubscription = this.dialogService
+      .launchDialog(
+        'Do you wish to delete recent search ' + selectedSearch.name
+      )
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteRecentSearch(selectedSearch);
+        }
+        confirmedSubscription.unsubscribe();
+      });
   }
 
   deleteSearch($event) {
-    let selectedSearch = this.searches.find(savedSearch => savedSearch.name === $event.key);
-    this.metronDialog.showConfirmationMessage('Do you wish to delete saved search ' + selectedSearch.name).subscribe((result: boolean) => {
-      if (result) {
-        this.doDeleteSearch(selectedSearch);
-      }
-    });
+    let selectedSearch = this.searches.find(
+      savedSearch => savedSearch.name === $event.key
+    );
+    const confirmedSubscription = this.dialogService
+      .launchDialog('Do you wish to delete saved search ' + selectedSearch.name)
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteSearch(selectedSearch);
+        }
+        confirmedSubscription.unsubscribe();
+      });
   }
 
   ngOnInit() {

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/app.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.html b/metron-interface/metron-alerts/src/app/app.component.html
index c3a5d3c..d94a6d7 100644
--- a/metron-interface/metron-alerts/src/app/app.component.html
+++ b/metron-interface/metron-alerts/src/app/app.component.html
@@ -30,6 +30,7 @@
         <router-outlet></router-outlet>
     </div>
     <router-outlet name="dialog" ></router-outlet>
+    <app-metron-dialog></app-metron-dialog>
 </div>
 
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/app.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.spec.ts b/metron-interface/metron-alerts/src/app/app.component.spec.ts
index ce38c22..1485904 100644
--- a/metron-interface/metron-alerts/src/app/app.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/app.component.spec.ts
@@ -21,6 +21,8 @@ import { AppComponent } from './app.component';
 import { Component } from '@angular/core';
 import { AuthenticationService } from './service/authentication.service';
 import { of } from 'rxjs';
+import { DialogService } from './service/dialog.service';
+import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
 
 @Component({ selector: 'router-outlet', template: '' })
 class RouterOutletStubComponent {}
@@ -32,10 +34,12 @@ describe('AppComponent', () => {
   beforeEach(async(() => {
     TestBed.configureTestingModule({
       providers: [
+        DialogService,
         { provide: AuthenticationService, useValue: { onLoginEvent: of(true) } }
       ],
       declarations: [
         AppComponent,
+        MetronDialogComponent,
         RouterOutletStubComponent,
       ],
     }).compileComponents();

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.module.ts b/metron-interface/metron-alerts/src/app/app.module.ts
index 44e2650..a605b80 100644
--- a/metron-interface/metron-alerts/src/app/app.module.ts
+++ b/metron-interface/metron-alerts/src/app/app.module.ts
@@ -31,7 +31,6 @@ import {ConfigureTableService} from './service/configure-table.service';
 import {SaveSearchModule} from './alerts/save-search/save-search.module';
 import {SaveSearchService} from './service/save-search.service';
 import {SavedSearchesModule} from './alerts/saved-searches/saved-searches.module';
-import {MetronDialogBox} from './shared/metron-dialog-box';
 import {ConfigureRowsModule} from './alerts/configure-rows/configure-rows.module';
 import {SwitchModule} from './shared/switch/switch.module';
 import {ColumnNamesService} from './service/column-names.service';
@@ -47,6 +46,9 @@ import {MetaAlertsModule} from './alerts/meta-alerts/meta-alerts.module';
 import {SearchService} from './service/search.service';
 import { GlobalConfigService } from './service/global-config.service';
 import { DefaultHeadersInterceptor } from './http-interceptors/default-headers.interceptor';
+import { DialogService } from './service/dialog.service';
+import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
+
 
 
 import {PcapModule} from './pcap/pcap.module';
@@ -57,7 +59,8 @@ export function initConfig(config: ColumnNamesService) {
 
 @NgModule({
   declarations: [
-    AppComponent
+    AppComponent,
+    MetronDialogComponent
   ],
   imports: [
     BrowserModule,
@@ -84,11 +87,12 @@ export function initConfig(config: ColumnNamesService) {
               ConfigureTableService,
               SearchService,
               SaveSearchService,
-              MetronDialogBox,
               ColumnNamesService,
               UpdateService,
               MetaAlertService,
-              GlobalConfigService],
+              GlobalConfigService,
+              DialogService,
+            ],
   bootstrap: [AppComponent]
 })
 

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/confirmation-type.ts b/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
new file mode 100644
index 0000000..5441a9e
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export enum ConfirmationType {
+  Confirmed = 'Confirmed',
+  Rejected = 'Rejected'
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/model/dialog-type.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/dialog-type.ts b/metron-interface/metron-alerts/src/app/model/dialog-type.ts
new file mode 100644
index 0000000..0cd398e
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/dialog-type.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export enum DialogType {
+  Confirmation,
+  Error
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts b/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
new file mode 100644
index 0000000..521d74c
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { TestBed, inject } from '@angular/core/testing';
+
+import {
+  DialogService,
+  DialogParams
+} from './dialog.service';
+import { DialogType } from '../model/dialog-type';
+import { ConfirmationType } from '../model/confirmation-type';
+
+describe('DialogService', () => {
+  let dialogService: DialogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [DialogService]
+    });
+    dialogService = TestBed.get(DialogService);
+  });
+
+  it('should be created', inject([DialogService], (service: DialogService) => {
+    expect(service).toBeTruthy();
+  }));
+
+  describe('confirm()', () => {
+
+    it('should emit a message with the correct params', () => {
+      const messageSpy = spyOn(dialogService.message, 'next');
+      const testMessage = 'this is a test';
+      let messageEmit: DialogParams = {
+        message: testMessage,
+        show: true,
+        dialogType: DialogType.Confirmation
+      };
+
+      dialogService.launchDialog(testMessage);
+      expect(messageSpy).toHaveBeenCalledWith(messageEmit);
+
+      messageEmit.dialogType = DialogType.Error;
+      dialogService.launchDialog(testMessage, DialogType.Error);
+    });
+
+  });
+
+  describe('cancel()', () => {
+    it('should emit ConfirmationType.Rejected', () => {
+      const messageSpy = spyOn(dialogService.confirmed, 'next');
+
+      dialogService.cancel();
+      expect(messageSpy).toHaveBeenCalledWith(ConfirmationType.Rejected);
+    });
+  });
+
+  describe('approve()', () => {
+    it('should emit ConfirmationType.Confirmed', () => {
+      const messageSpy = spyOn(dialogService.confirmed, 'next');
+
+      dialogService.approve();
+      expect(messageSpy).toHaveBeenCalledWith(ConfirmationType.Confirmed);
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/service/dialog.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/dialog.service.ts b/metron-interface/metron-alerts/src/app/service/dialog.service.ts
new file mode 100644
index 0000000..ad758a0
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/dialog.service.ts
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Subject } from 'rxjs';
+import { ConfirmationType } from '../model/confirmation-type';
+import { DialogType } from '../model/dialog-type';
+
+@Injectable({
+  providedIn: 'root'
+})
+
+export class DialogParams {
+  show = false;
+  message = '';
+  dialogType = DialogType.Confirmation;
+}
+
+export class DialogService {
+  message = new BehaviorSubject<DialogParams>(new DialogParams());
+  confirmed = new Subject<ConfirmationType>();
+
+  constructor() {}
+
+  launchDialog(message: string, dialogType = DialogType.Confirmation): Subject<ConfirmationType> {
+    this.message.next({
+      message: message,
+      show: true,
+      dialogType: dialogType
+    });
+    return this.confirmed;
+  }
+
+  approve() {
+    this.confirmed.next(ConfirmationType.Confirmed);
+  }
+
+  cancel() {
+    this.confirmed.next(ConfirmationType.Rejected);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
deleted file mode 100644
index aaa2791..0000000
--- a/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {EventEmitter}     from '@angular/core';
-
-declare var $;
-
-export enum DialogType {
-  Confirmation, Error
-};
-
-export class MetronDialogBox {
-  private static dialogType = DialogType;
-
-  private getCancelButton(type: DialogType): string {
-    if (type === DialogType.Confirmation) {
-      return `<button type="button" class="btn btn-mine_shaft_2" data-dismiss="modal">Cancel</button>`;
-    }
-
-    return '';
-  }
-
-  private createDialogBox(message: string, type: DialogType) {
-    let cancelButtonHTML = this.getCancelButton(type);
-    let html = `<div class="metron-dialog modal"  data-backdrop="static" >
-                  <div class="modal-dialog modal-sm" role="document">
-                    <div class="modal-content">
-                      <div class="modal-header">
-                        <span class="modal-title"><b>` + MetronDialogBox.dialogType[type] + `</b></span>
-                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"> 
-                            <span aria-hidden="true">&times;</span> 
-                        </button>
-                      </div>
-                      <div class="modal-body">
-                        <p>` +  message + `</p>
-                      </div>
-                      <div class="modal-footer">
-                        <button type="button" class="btn btn-all_ports">OK</button>`
-                        + cancelButtonHTML +
-                      `</div>
-                    </div>
-                  </div>
-                </div>`;
-
-    let element = document.createElement('div');
-    element.innerHTML = html;
-
-    document.body.appendChild(element);
-
-    return element;
-  }
-
-  public showConfirmationMessage(message: string, dialogType = DialogType.Confirmation): EventEmitter<boolean> {
-    message = message.replace(/\n/g, '<br>');
-    let eventEmitter = new EventEmitter<boolean>();
-    let element = this.createDialogBox(message, dialogType);
-
-    $(element).find('.metron-dialog').modal('show');
-
-    $(element).find('.btn-all_ports').on('click', function (e) {
-      $(element).find('.metron-dialog').modal('hide');
-      eventEmitter.emit(true);
-    });
-
-    $(element).find('.btn-mine_shaft_2').on('click', function (e) {
-      $(element).find('.metron-dialog').modal('hide');
-      eventEmitter.emit(false);
-    });
-
-    $(element).find('.metron-dialog').on('hidden.bs.modal', function (e) {
-      $(element).remove();
-    });
-
-    return eventEmitter;
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
new file mode 100644
index 0000000..0308e97
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
@@ -0,0 +1,40 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<div>
+  <div *ngIf="showModal" class="metron-dialog modal show" [class.block]="showModal" data-backdrop="static" data-qe-id="modal">
+    <div class="modal-dialog modal-sm" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <span class="modal-title" data-qe-id="modal-title"><b>{{ dialogType }}</b></span>
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+            <span aria-hidden="true" (click)="cancel()">&times;</span>
+          </button>
+        </div>
+        <div class="modal-body">
+          <p data-qe-id="modal-message">{{ message }}</p>
+        </div>
+        <div class="modal-footer">
+          <button *ngIf="dialogType === 'Error'" type="button" class="btn btn-all_ports" (click)="cancel()" data-qe-id="modal-error-cancel">OK</button>
+          <button *ngIf="dialogType !== 'Error'" type="button" class="btn btn-all_ports" (click)="confirm()" data-qe-id="modal-confirm">OK</button>
+          <button *ngIf="dialogType !== 'Error'" type="button" class="btn btn-mine_shaft_2" data-dismiss="modal" (click)="cancel()" data-qe-id="modal-cancel">Cancel</button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="modal-backdrop show" *ngIf="showModal"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
new file mode 100644
index 0000000..675242b
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ .block {
+    display: block;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
new file mode 100644
index 0000000..c5540a6
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MetronDialogComponent } from './metron-dialog.component';
+import { DialogService } from 'app/service/dialog.service';
+import { DialogType } from 'app/model/dialog-type';
+
+describe('MetronDialogComponent', () => {
+  let component: MetronDialogComponent;
+  let fixture: ComponentFixture<MetronDialogComponent>;
+  let dialogService: DialogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [MetronDialogComponent],
+      providers: [DialogService]
+    });
+    fixture = TestBed.createComponent(MetronDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+    dialogService = TestBed.get(DialogService);
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should show when showModal is true', () => {
+    component.showModal = false;
+    fixture.detectChanges();
+    let modal = fixture.nativeElement.querySelector('[data-qe-id="modal"]');
+    expect(modal).toBeNull();
+
+    component.showModal = true;
+    fixture.detectChanges();
+    modal = fixture.nativeElement.querySelector('[data-qe-id="modal"]');
+    expect(modal).toBeTruthy();
+  });
+
+  it('should display the passed message', () => {
+    const testMessage = 'This is a confirmation message';
+    dialogService.launchDialog(testMessage);
+    fixture.detectChanges();
+    const modalMessage = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-message"]'
+    );
+    expect(modalMessage.textContent).toBe(testMessage);
+  });
+
+  it('should display the correct title based on the dialog type', () => {
+    dialogService.launchDialog('');
+    fixture.detectChanges();
+    let modalTitle = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-title"]'
+    );
+    expect(modalTitle.textContent).toBe('Confirmation');
+
+    dialogService.launchDialog('', DialogType.Error);
+    fixture.detectChanges();
+    modalTitle = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-title"]'
+    );
+    expect(modalTitle.textContent).toBe('Error');
+  });
+
+  it('should execute cancel() when the cancel button is clicked', () => {
+    dialogService.launchDialog('');
+    const cancelSpy = spyOn(component, 'cancel').and.callThrough();
+    fixture.detectChanges();
+
+    const cancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-cancel"]'
+    );
+    cancelButton.click();
+    expect(cancelSpy).toHaveBeenCalled();
+    expect(component.showModal).toBe(false);
+  });
+
+  it('should execute confirm() when the ok button is clicked', () => {
+    dialogService.launchDialog('');
+    const confirmSpy = spyOn(component, 'confirm').and.callThrough();
+    fixture.detectChanges();
+
+    const confirmButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-confirm"]'
+    );
+    confirmButton.click();
+    expect(confirmSpy).toHaveBeenCalled();
+    expect(component.showModal).toBe(false);
+  });
+
+  it('should only display a cancel() button when the dialog type is Error', () => {
+    dialogService.launchDialog('', DialogType.Error);
+    fixture.detectChanges();
+
+    const errorCancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-error-cancel"]'
+    );
+    expect(errorCancelButton).toBeTruthy();
+
+    const confirmCancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-cancel"]'
+    );
+    expect(confirmCancelButton).toBeNull();
+
+    const confirmApproveButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-confirm"]'
+    );
+    expect(confirmApproveButton).toBeNull();
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/eee99630/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
new file mode 100644
index 0000000..7ba71e5
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+  Component,
+  OnInit,
+  OnDestroy
+} from '@angular/core';
+import { DialogService } from '../../service/dialog.service';
+import { Subscription } from 'rxjs';
+
+export enum DialogType {
+  Confirmation,
+  Error
+}
+
+@Component({
+  selector: 'app-metron-dialog',
+  templateUrl: './metron-dialog.component.html',
+  styleUrls: ['./metron-dialog.component.scss']
+})
+export class MetronDialogComponent implements OnInit, OnDestroy {
+  public message: string;
+  public showModal = false;
+  public dialogType: string;
+  private subscription: Subscription;
+
+  constructor(private dialogService: DialogService) {}
+
+  ngOnInit(): void {
+    this.subscription = this.dialogService.message.subscribe(r => {
+      this.showModal = r.show;
+      this.message = r.message;
+      this.dialogType = DialogType[r.dialogType];
+    });
+
+  }
+
+  confirm(): void {
+    this.dialogService.approve();
+    this.showModal = false;
+  }
+
+  cancel(): void {
+    this.dialogService.cancel();
+    this.showModal = false;
+  }
+
+  ngOnDestroy() {
+    this.subscription.unsubscribe();
+  }
+}