METRON-2174 [UI] Grouped alerts total can differ from search alerts total (sardell) closes apache/metron#1455
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
index 79f0962..26a38cb 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
@@ -39,7 +39,8 @@
     </div>
     <div class="mrow">
         <div class="col-md-9 px-0">
-            <span class="col-form-label-lg"> Alerts ({{searchResponse.total}}) </span>
+            <span class="col-form-label-lg">Alerts ({{searchResponse.total}}) </span>
+            <div *ngIf="subgroupTotal" data-qe-id="alert-subgroup-total">Alerts in Groups ({{subgroupTotal}})</div>
         </div>
         <div class="col-md-3 px-0">
             <div class="pull-right" style="position: relative; display: block;">
@@ -100,7 +101,8 @@
                            (onAddFilter)="onAddFilter($event)"
                            (onRefreshData)="onRefreshData($event)"
                            (onShowDetails)="showDetails($event)"
-                           (onSelectedAlertsChange)="onSelectedAlertsChange($event)"></app-tree-view>
+                           (onSelectedAlertsChange)="onSelectedAlertsChange($event)"
+                           (treeViewChange)="onTreeViewChange($event)"></app-tree-view>
         </div>
     </div>
   </div>
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts
index fe838b3..e922984 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts
@@ -96,4 +96,15 @@
     expect(component.selectedTimeRange.dateFilterValue.toDate).toBeTruthy();
   });
 
+  it('shows subtotals in view when onTreeViewChange is truthy', () => {
+    component.onTreeViewChange(4);
+    fixture.detectChanges();
+    let subtotal = fixture.nativeElement.querySelector('[data-qe-id="alert-subgroup-total"]');
+    expect(subtotal.textContent).toEqual('Alerts in Groups (4)');
+
+    component.onTreeViewChange(0);
+    fixture.detectChanges();
+    expect(fixture.nativeElement.querySelector('[data-qe-id="alert-subgroup-total"]')).toBeNull();
+  });
+
 });
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 74fa468..7fd69ba 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
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 import {forkJoin as observableForkJoin} from 'rxjs';
-import {Component, OnInit, ViewChild, ElementRef, OnDestroy} from '@angular/core';
+import {Component, OnInit, ViewChild, ElementRef, OnDestroy, ChangeDetectorRef} from '@angular/core';
 import {Router, NavigationStart} from '@angular/router';
 import {Subscription} from 'rxjs';
 
@@ -84,6 +84,7 @@
   globalConfig: {} = {};
   configSubscription: Subscription;
   groups = [];
+  subgroupTotal = 0;
 
   constructor(private router: Router,
               private searchService: SearchService,
@@ -94,7 +95,8 @@
               private saveSearchService: SaveSearchService,
               private metaAlertsService: MetaAlertService,
               private globalConfigService: GlobalConfigService,
-              private dialogService: DialogService) {
+              private dialogService: DialogService,
+              private cdRef : ChangeDetectorRef) {
     router.events.subscribe(event => {
       if (event instanceof NavigationStart && event.url === '/alerts-list') {
         this.selectedAlerts = [];
@@ -520,4 +522,9 @@
   removeAlertChangedListner() {
     this.alertChangedSubscription.unsubscribe();
   }
+
+  onTreeViewChange(subgroupTotal) {
+    this.subgroupTotal = subgroupTotal;
+    this.cdRef.detectChanges();
+  }
 }
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.html b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.html
index cd87cbc..c986710 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.html
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.html
@@ -20,7 +20,7 @@
       </div>
       <div class="mrow top-group" (click)="toggleTopLevelGroup(group)">
         <div class="col-5 text-light severity-padding"> <span class="title"> {{ group.key | centerEllipses:45 }} </span> </div>
-        <div class="col-5 text-light two-line"> <span class="text-dark"> ALERTS </span> <br> <span class="title"> {{ group.total | number }} </span> </div>
+        <div class="col-5 text-light two-line"> <span class=""> ALERTS </span> <br> <span class="title"> {{ group.total | number }} </span> </div>
         <div class="col-1 text-right pr-4">
           <i class="fa fa-link top-group-link" aria-hidden="true" (click)="createMetaAlert($event, group, i)" data-animation="false" data-toggle="tooltip" data-placement="left"  title="Merge Alerts"></i>
         </div>
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 3fc145f..cdea081 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
@@ -79,4 +79,10 @@
   it('should be created', () => {
     expect(component).toBeTruthy();
   });
+
+  it('should emit subgroup total on change', () => {
+    component.treeViewChange.subscribe((num: number) => {
+      expect(num).toBe(0);
+    });
+  })
 });
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 d2c7c8d..f3833d3 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
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { Component, OnInit, OnChanges, SimpleChanges, OnDestroy, Input } from '@angular/core';
+import { Component, OnInit, OnChanges, SimpleChanges, OnDestroy, Input, EventEmitter, Output } from '@angular/core';
 import {Subscription, Observable} from 'rxjs';
 
 import {TableViewComponent} from '../table-view/table-view.component';
@@ -50,6 +50,7 @@
 export class TreeViewComponent extends TableViewComponent implements OnInit, OnChanges, OnDestroy {
 
   @Input() globalConfig: {} = {};
+  @Output() treeViewChange = new EventEmitter<number>();
   groupByFields: string[] = [];
   topGroups: TreeGroupData[] = [];
   groupResponse: GroupResponse = new GroupResponse();
@@ -57,6 +58,7 @@
   alertsChangedSubscription: Subscription;
   configSubscription: Subscription;
   dialogService: DialogService;
+  subgroupTotalAlerts = 0;
 
   constructor(searchService: SearchService,
               updateService: UpdateService,
@@ -169,10 +171,14 @@
     let previousTopGroupKeys = this.topGroups.map(group => group.key);
 
     if (this.topGroups.length === 0 || JSON.stringify(this.groupByFields) !== JSON.stringify(groupByFields) ||
-        JSON.stringify(currentTopGroupKeys) !== JSON.stringify(previousTopGroupKeys)) {
+    JSON.stringify(currentTopGroupKeys) !== JSON.stringify(previousTopGroupKeys)) {
       this.createTopGroups(groupByFields);
     }
 
+    this.subgroupTotalAlerts = this.topGroups.reduce((accumulator, currentValue) => {
+      return accumulator + currentValue.total;
+    }, 0);
+    this.treeViewChange.next(this.subgroupTotalAlerts);
     this.groupByFields = groupByFields;
   }
 
@@ -192,6 +198,7 @@
 
   ngOnDestroy(): void {
     this.removeAlertChangedLister();
+    this.treeViewChange.next(0);
   }
 
   searchGroup(selectedGroup: TreeGroupData, searchRequest: SearchRequest): Subscription {