http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/column-names.service.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/column-names.service.ts 
b/metron-interface/metron-alerts/src/app/service/column-names.service.ts
new file mode 100644
index 0000000..e289ca2
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/column-names.service.ts
@@ -0,0 +1,71 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Http} from '@angular/http';
+
+import {ColumnNames} from '../model/column-names';
+import {DataSource} from './data-source';
+
+@Injectable()
+export class ColumnNamesService {
+
+  static columnNameToDisplayValueMap = {};
+  static columnDisplayValueToNameMap = {};
+
+  public static getColumnDisplayValue(key: string) {
+    if (!key) {
+      return '';
+    }
+
+    let displayValue = ColumnNamesService.columnNameToDisplayValueMap[key];
+
+    return displayValue ? displayValue : key;
+  }
+
+  public static getColumnDisplayKey(key: string) {
+    if (!key) {
+      return key;
+    }
+
+    let name = ColumnNamesService.columnDisplayValueToNameMap[key];
+
+    return (!name || name.length === 0) ? key : name;
+  }
+
+  public static toMap(columnNames: ColumnNames[]) {
+    ColumnNamesService.columnNameToDisplayValueMap = {};
+    ColumnNamesService.columnDisplayValueToNameMap = {};
+
+    columnNames.forEach(columnName => {
+      ColumnNamesService.columnNameToDisplayValueMap[columnName.key] = 
columnName.displayValue;
+      ColumnNamesService.columnDisplayValueToNameMap[columnName.displayValue] 
= columnName.key;
+    });
+  }
+
+  constructor(private http: Http,
+              private dataSource: DataSource) {}
+
+  list(): Promise<ColumnNames[]> {
+    return this.dataSource.getAlertTableColumnNames().toPromise();
+  }
+
+  save(columns: ColumnNames[]): Observable<{}> {
+    return this.dataSource.saveAlertTableColumnNames(columns);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/configure-table.service.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/configure-table.service.ts 
b/metron-interface/metron-alerts/src/app/service/configure-table.service.ts
new file mode 100644
index 0000000..5c8f49d
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/configure-table.service.ts
@@ -0,0 +1,50 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Http} from '@angular/http';
+import {Subject} from 'rxjs/Subject';
+import {ColumnMetadata} from '../model/column-metadata';
+import {TableMetadata} from '../model/table-metadata';
+import {DataSource} from './data-source';
+
+@Injectable()
+export class ConfigureTableService {
+
+  private tableChangedSource = new Subject<string>();
+  tableChanged$ = this.tableChangedSource.asObservable();
+
+  constructor(private http: Http,
+              private dataSource: DataSource) {}
+
+  fireTableChanged() {
+    this.tableChangedSource.next('table changed');
+  }
+
+  getTableMetadata(): Observable<TableMetadata> {
+    return this.dataSource.getAlertTableSettings();
+  }
+
+  saveColumnMetaData(columns: ColumnMetadata[]): Observable<{}> {
+    return this.dataSource.saveColumnMetaDataInAlertTableSettings(columns);
+  }
+
+  saveTableMetaData(tableMetadata: TableMetadata): Observable<TableMetadata> {
+    return this.dataSource.saveAlertTableSettings(tableMetadata);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/data-source.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/data-source.ts 
b/metron-interface/metron-alerts/src/app/service/data-source.ts
new file mode 100644
index 0000000..242fa3a
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/data-source.ts
@@ -0,0 +1,62 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Injectable} from '@angular/core';
+import {Http} from '@angular/http';
+
+import {Alert} from '../model/alert';
+import {ColumnMetadata} from '../model/column-metadata';
+import {ColumnNames} from '../model/column-names';
+import {TableMetadata} from '../model/table-metadata';
+import {SaveSearch} from '../model/save-search';
+import {AlertsSearchResponse} from '../model/alerts-search-response';
+import {SearchRequest} from '../model/search-request';
+
+@Injectable()
+export abstract class DataSource {
+  defaultHeaders: {'Content-Type': 'application/json', 'X-Requested-With': 
'XMLHttpRequest'};
+
+  constructor(protected http: Http) {}
+
+  // Calls to fetch alerts
+  abstract getAlerts(searchRequest: SearchRequest): 
Observable<AlertsSearchResponse>
+  abstract getAlert(index: string, type: string, alertId: string): 
Observable<Alert>
+  abstract updateAlertState(request: any): Observable<{}>
+
+  // Calls to fetch default alert table column names and all the field names 
across all indexes
+  abstract getDefaultAlertTableColumnNames(): Observable<ColumnMetadata[]>
+  abstract getAllFieldNames(): Observable<ColumnMetadata[]>
+
+  // Calls to rename field names and to fetch the renamed field names
+  abstract getAlertTableColumnNames(): Observable<ColumnNames[]>
+  abstract saveAlertTableColumnNames(columns: ColumnNames[]): Observable<{}>
+
+  // Calls to fetch and save alerts table settings like refresh interval, page 
size, default selected table column names
+  abstract getAlertTableSettings(): Observable<TableMetadata>
+  abstract saveColumnMetaDataInAlertTableSettings(columns: ColumnMetadata[]): 
Observable<{}>
+  abstract saveAlertTableSettings(tableMetadata): Observable<TableMetadata>
+
+  // Calls to save search, last 10 searches, saved searches
+  abstract deleteRecentSearch(saveSearch: SaveSearch): Observable<{}>
+  abstract deleteSavedSearch(saveSearch: SaveSearch): Observable<{}>
+  abstract listRecentSearches(): Observable<SaveSearch[]>
+  abstract listSavedSearches(): Observable<SaveSearch[]>
+  abstract saveRecentSearch(saveSearch: SaveSearch): Observable<{}>
+  abstract saveSearch(saveSearch: SaveSearch): Observable<{}>
+  abstract updateSearch(saveSearch: SaveSearch): Observable<{}>
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
 
b/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
new file mode 100644
index 0000000..0cd2bce
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
@@ -0,0 +1,294 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Headers, RequestOptions} from '@angular/http';
+
+import {HttpUtil} from '../utils/httpUtil';
+import {DataSource} from './data-source';
+import {Alert} from '../model/alert';
+import {ColumnMetadata} from '../model/column-metadata';
+import {ElasticsearchUtils} from '../utils/elasticsearch-utils';
+import {
+  ALERTS_COLUMN_NAMES, ALERTS_TABLE_METADATA, ALERTS_RECENT_SEARCH,
+  ALERTS_SAVED_SEARCH, NUM_SAVED_SEARCH
+} from '../utils/constants';
+import {ColumnNames} from '../model/column-names';
+import {ColumnNamesService} from './column-names.service';
+import {TableMetadata} from '../model/table-metadata';
+import {SaveSearch} from '../model/save-search';
+import {AlertsSearchResponse} from '../model/alerts-search-response';
+import {SearchRequest} from '../model/search-request';
+
+export class ElasticSearchLocalstorageImpl extends DataSource {
+
+  private defaultColumnMetadata = [
+    new ColumnMetadata('_id', 'string'),
+    new ColumnMetadata('timestamp', 'date'),
+    new ColumnMetadata('source:type', 'string'),
+    new ColumnMetadata('ip_src_addr', 'ip'),
+    new ColumnMetadata('enrichments:geo:ip_dst_addr:country', 'string'),
+    new ColumnMetadata('ip_dst_addr', 'ip'),
+    new ColumnMetadata('host', 'string'),
+    new ColumnMetadata('alert_status', 'string')
+  ];
+
+  getAlerts(searchRequest: SearchRequest): Observable<AlertsSearchResponse> {
+    let url = '/search/*' + ElasticsearchUtils.excludeIndexName + '/_search';
+    let request: any  = JSON.parse(JSON.stringify(searchRequest));
+    request.query = { query_string: { query: searchRequest.query } };
+
+    return this.http.post(url, request, new RequestOptions({headers: new 
Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractData)
+      .map(ElasticsearchUtils.extractAlertsData)
+      .catch(HttpUtil.handleError)
+      .onErrorResumeNext();
+  }
+
+  getAlert(index: string, type: string, alertId: string): Observable<Alert> {
+    return this.http.get('/search/' + index + '/' + type + '/' + alertId, new 
RequestOptions({headers: new Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractData);
+  }
+
+  updateAlertState(request: any) {
+    return this.http.post('/search/_bulk', request, new 
RequestOptions({headers: new Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractData)
+      .catch(HttpUtil.handleError);
+  }
+
+  getDefaultAlertTableColumnNames(): Observable<ColumnMetadata[]> {
+    return Observable.create(observer => {
+      observer.next(JSON.parse(JSON.stringify(this.defaultColumnMetadata)));
+      observer.complete();
+    });
+  }
+
+  getAllFieldNames(): Observable<ColumnMetadata[]> {
+    let url = '_cluster/state';
+    return this.http.get(url, new RequestOptions({headers: new 
Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractData)
+      .map(ElasticsearchUtils.extractColumnNameData)
+      .catch(HttpUtil.handleError);
+  }
+
+  getAlertTableColumnNames(): Observable<ColumnNames[]> {
+    return Observable.create(observer => {
+      let columnNames: ColumnNames[];
+      try {
+        columnNames = JSON.parse(localStorage.getItem(ALERTS_COLUMN_NAMES));
+        ColumnNamesService.toMap(columnNames);
+      } catch (e) {}
+
+      columnNames = columnNames || [];
+
+      observer.next(columnNames);
+      observer.complete();
+
+    });
+  }
+
+  saveAlertTableColumnNames(columns: ColumnNames[]): Observable<{}> {
+    return Observable.create(observer => {
+      try {
+        localStorage.setItem(ALERTS_COLUMN_NAMES, JSON.stringify(columns));
+      } catch (e) {}
+      ColumnNamesService.toMap(columns);
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  getAlertTableSettings(): Observable<TableMetadata> {
+    return Observable.create(observer => {
+      let tableMetadata: TableMetadata;
+      try {
+        tableMetadata = 
TableMetadata.fromJSON(JSON.parse(localStorage.getItem(ALERTS_TABLE_METADATA)));
+      } catch (e) {}
+
+      observer.next(tableMetadata);
+      observer.complete();
+
+    });
+  }
+
+  saveColumnMetaDataInAlertTableSettings(columns: ColumnMetadata[]): 
Observable<{}> {
+    return Observable.create(observer => {
+      try {
+        let  tableMetadata = 
TableMetadata.fromJSON(JSON.parse(localStorage.getItem(ALERTS_TABLE_METADATA)));
+        tableMetadata.tableColumns = columns;
+        localStorage.setItem(ALERTS_TABLE_METADATA, 
JSON.stringify(tableMetadata));
+      } catch (e) {}
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  saveAlertTableSettings(tableMetadata): Observable<TableMetadata> {
+    return Observable.create(observer => {
+      try {
+        localStorage.setItem(ALERTS_TABLE_METADATA, 
JSON.stringify(tableMetadata));
+      } catch (e) {}
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  deleteRecentSearch(saveSearch: SaveSearch): Observable<{}> {
+    return Observable.create(observer => {
+      let recentSearches: SaveSearch[] = [];
+      try {
+        recentSearches = 
JSON.parse(localStorage.getItem(ALERTS_RECENT_SEARCH));
+        recentSearches = recentSearches.filter(search => search.name !== 
saveSearch.name);
+      } catch (e) {}
+
+      localStorage.setItem(ALERTS_RECENT_SEARCH, 
JSON.stringify(recentSearches));
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  deleteSavedSearch(saveSearch: SaveSearch): Observable<{}> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_SAVED_SEARCH));
+        savedSearches = savedSearches.filter(search => search.name !== 
saveSearch.name);
+      } catch (e) {}
+
+      localStorage.setItem(ALERTS_SAVED_SEARCH, JSON.stringify(savedSearches));
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  listRecentSearches(): Observable<SaveSearch[]> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_RECENT_SEARCH));
+      } catch (e) {}
+
+      savedSearches = savedSearches || [];
+      savedSearches = savedSearches.map(tSaveSeacrh => 
SaveSearch.fromJSON(tSaveSeacrh));
+
+      observer.next(savedSearches);
+      observer.complete();
+
+    });
+  }
+
+  listSavedSearches(): Observable<SaveSearch[]> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_SAVED_SEARCH));
+      } catch (e) {}
+
+      savedSearches = savedSearches || [];
+      savedSearches = savedSearches.map(tSaveSeacrh => 
SaveSearch.fromJSON(tSaveSeacrh));
+
+      observer.next(savedSearches);
+      observer.complete();
+
+    });
+  }
+
+  saveRecentSearch(saveSearch: SaveSearch): Observable<{}> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      saveSearch.lastAccessed = new Date().getTime();
+
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_RECENT_SEARCH));
+      } catch (e) {}
+
+      savedSearches = savedSearches || [];
+      savedSearches = savedSearches.map(tSaveSeacrh => 
SaveSearch.fromJSON(tSaveSeacrh));
+
+      if (savedSearches.length  === 0) {
+        savedSearches.push(saveSearch);
+      } else {
+        let found = false;
+        for ( let tSaveSearch of savedSearches) {
+          if (saveSearch.name === tSaveSearch.name) {
+            tSaveSearch.lastAccessed = new Date().getTime();
+            found = true;
+            break;
+          }
+        }
+        if (!found ) {
+          if (savedSearches.length < NUM_SAVED_SEARCH) {
+            savedSearches.push(saveSearch);
+          } else {
+            savedSearches.sort((s1, s2) => s1.lastAccessed - 
s2.lastAccessed).shift();
+            savedSearches.push(saveSearch);
+          }
+        }
+      }
+
+      localStorage.setItem(ALERTS_RECENT_SEARCH, 
JSON.stringify(savedSearches));
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  saveSearch(saveSearch: SaveSearch): Observable<{}> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_SAVED_SEARCH));
+      } catch (e) {}
+
+      savedSearches = savedSearches || [];
+      savedSearches.push(saveSearch);
+      localStorage.setItem(ALERTS_SAVED_SEARCH, JSON.stringify(savedSearches));
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+
+  updateSearch(saveSearch: SaveSearch): Observable<{}> {
+    return Observable.create(observer => {
+      let savedSearches: SaveSearch[] = [];
+      try {
+        savedSearches = JSON.parse(localStorage.getItem(ALERTS_SAVED_SEARCH));
+        let savedItem = savedSearches.find(search => search.name === 
saveSearch.name);
+        savedItem.lastAccessed = saveSearch.lastAccessed;
+        savedItem.searchRequest = saveSearch.searchRequest;
+      } catch (e) {}
+
+      localStorage.setItem(ALERTS_SAVED_SEARCH, JSON.stringify(savedSearches));
+
+      observer.next({});
+      observer.complete();
+
+    });
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/save-search.service.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/save-search.service.ts 
b/metron-interface/metron-alerts/src/app/service/save-search.service.ts
new file mode 100644
index 0000000..dba03c2
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/save-search.service.ts
@@ -0,0 +1,75 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Http} from '@angular/http';
+import {Subject} from 'rxjs/Subject';
+import {QueryBuilder} from '../alerts/alerts-list/query-builder';
+import {SaveSearch} from '../model/save-search';
+import {ColumnMetadata} from '../model/column-metadata';
+import {DataSource} from './data-source';
+
+@Injectable()
+export class SaveSearchService {
+
+  queryBuilder: QueryBuilder;
+  tableColumns: ColumnMetadata[];
+
+  private loadSavedSearch = new Subject<SaveSearch>();
+  loadSavedSearch$ = this.loadSavedSearch.asObservable();
+
+  constructor(private http: Http,
+              private dataSource: DataSource) {}
+
+  deleteRecentSearch(saveSearch: SaveSearch): Observable<{}> {
+    return this.dataSource.deleteRecentSearch(saveSearch);
+  }
+
+  deleteSavedSearch(saveSearch: SaveSearch): Observable<{}> {
+    return this.dataSource.deleteSavedSearch(saveSearch);
+  }
+
+  fireLoadSavedSearch(savedSearch: SaveSearch) {
+    this.loadSavedSearch.next(savedSearch);
+  }
+
+  listRecentSearches(): Observable<SaveSearch[]> {
+    return this.dataSource.listRecentSearches();
+  }
+
+  listSavedSearches(): Observable<SaveSearch[]> {
+    return this.dataSource.listSavedSearches();
+  }
+
+  saveAsRecentSearches(saveSearch: SaveSearch): Observable<{}> {
+    return this.dataSource.saveRecentSearch(saveSearch);
+  }
+
+  saveSearch(saveSearch: SaveSearch): Observable<{}> {
+    return this.dataSource.saveSearch(saveSearch);
+  }
+
+  setCurrentQueryBuilderAndTableColumns(queryBuilder: QueryBuilder, 
tableColumns: ColumnMetadata[]) {
+    this.queryBuilder = queryBuilder;
+    this.tableColumns = tableColumns;
+  }
+
+  updateSearch(saveSearch: SaveSearch): Observable<{}> {
+    return this.dataSource.updateSearch(saveSearch);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/service/workflow.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/workflow.service.ts 
b/metron-interface/metron-alerts/src/app/service/workflow.service.ts
new file mode 100644
index 0000000..060769f
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/workflow.service.ts
@@ -0,0 +1,36 @@
+/**
+ * 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 {Observable} from 'rxjs/Rx';
+import {Alert} from '../model/alert';
+import {Http, Headers, RequestOptions} from '@angular/http';
+import {HttpUtil} from '../utils/httpUtil';
+
+@Injectable()
+export class WorkflowService {
+
+  defaultHeaders = {'Content-Type': 'application/json', 'X-Requested-With': 
'XMLHttpRequest'};
+
+  constructor(private http: Http) {
+  }
+
+  public start(alerts: Alert[]): Observable<string> {
+    return this.http.post('/api/v1/workflow', alerts, new 
RequestOptions({headers: new Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractString);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse-component-data.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse-component-data.ts
 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse-component-data.ts
new file mode 100644
index 0000000..cff81af
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse-component-data.ts
@@ -0,0 +1,32 @@
+/**
+ * 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 class CollapseComponentDataItems {
+  name: string;
+  count: number;
+
+  constructor(name: string, count?: number) {
+    this.name = name;
+    this.count = count;
+  }
+}
+
+export class CollapseComponentData {
+  groupName: string;
+  groupItems: CollapseComponentDataItems[] = [];
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html
 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html
new file mode 100644
index 0000000..aaca91a
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html
@@ -0,0 +1,31 @@
+<!--
+  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.
+  -->
+<a [attr.href]="'#' + uniqueId"  data-toggle="collapse"  aria-expanded="true" 
[attr.aria-controls]="uniqueId" class="pr-2"
+   [ngClass]="{'font-size-14' : fontSize === 14, 'font-size-15' : fontSize === 
15, 'border-bottom' : titleSeperator=== true}">
+  {{ data.groupName }}
+</a>
+<div class="collapse" [attr.id]="uniqueId" [ngClass]="{'show': show === true}">
+  <div *ngIf="data.groupItems.length === 0" class="container-fluid 
no-data-text">
+    <i> {{ 'No ' +  data.groupName + ' yet'}} </i>
+  </div>
+  <ul  *ngIf="data.groupItems.length > 0"  class="list-group">
+    <li *ngFor="let groupItem of data.groupItems" class="list-group-item 
justify-content-between anchor"
+        [ngClass]="{'font-size-14' : fontSize === 14, 'font-size-15' : 
fontSize === 15}" [attr.title]="groupItem.name"
+        (click)="onSelectClick(groupItem.name)">
+      {{ groupItem.name | centerEllipses: strLength }}
+      <span *ngIf="data.doc_count" class="badge badge-default badge-pill"> {{ 
groupItem.count }} </span>
+      <span *ngIf="deleteOption" class="delete" (click)="onDeleteClick($event, 
groupItem.name)"> </span>
+    </li>
+  </ul>
+</div>

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss
 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss
new file mode 100644
index 0000000..2208c37
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss
@@ -0,0 +1,92 @@
+/**
+ * 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 "../../../variables.scss";
+
+.font-size-14 {
+  font-size: 14px;
+}
+
+.font-size-15 {
+  font-size: 15px;
+}
+
+.border-bottom {
+  margin-bottom: 0px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid $tundora;
+  color: $silver-chalice-2;
+}
+
+a {
+  display: block;
+  margin: 5px 0px;
+  text-decoration: none;
+  color: $silver;
+
+  &::after {
+    font-family: "FontAwesome";
+    font-style: normal;
+    font-size: 14px;
+    content: '\f106';
+    float: right;
+    color: $dove-grey;
+  }
+}
+
+a.collapsed::after {
+  font-family: "FontAwesome";
+  font-style: normal;
+  font-size: 14px;
+  content: '\f107';
+  float: right;
+  color: $dove-grey;
+}
+
+.list-group {
+  padding: 10px 0px;
+}
+
+.list-group-item {
+  border: none;
+  background: none;
+  color: $curious-blue;
+}
+
+.delete {
+  line-height: 0px;
+  opacity: 0;
+  transition: opacity .35s ease;
+
+  &::before {
+    font-family: "FontAwesome";
+    content: '\f014';
+    color: $dove-grey;
+  }
+}
+
+.list-group-item:hover {
+  background: $outer-space;
+
+  .delete {
+    opacity: 1;
+  }
+}
+
+.no-data-text {
+  font-size: 12px;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.spec.ts
new file mode 100644
index 0000000..f6f32d1
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.spec.ts
@@ -0,0 +1,39 @@
+/**
+ * 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CollapseComponent } from './collapse.component';
+
+describe('CollapseComponent', () => {
+  let component: CollapseComponent;
+  let fixture: ComponentFixture<CollapseComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ CollapseComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CollapseComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts
new file mode 100644
index 0000000..98947d3
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts
@@ -0,0 +1,58 @@
+/**
+ * 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, Input, Output, EventEmitter } from '@angular/core';
+import 'bootstrap';
+import {CollapseComponentData} from './collapse-component-data';
+
+@Component({
+  selector: 'metron-collapse',
+  templateUrl: './collapse.component.html',
+  styleUrls: ['./collapse.component.scss']
+})
+export class CollapseComponent implements OnInit {
+
+  static counter = 0;
+  uniqueId = '';
+
+  @Input() data = new CollapseComponentData();
+  @Input() fontSize = 14;
+  @Input() titleSeperator = false;
+  @Input() deleteOption = false;
+  @Input() show = false;
+  @Input() strLength = 30;
+
+  @Output() onSelect = new EventEmitter<{name: string, key: string}>();
+  @Output() onDelete = new EventEmitter<{name: string, key: string}>();
+
+  constructor() {
+    this.uniqueId = 'CollapseComponent' + '_' + ++CollapseComponent.counter;
+  }
+
+  ngOnInit() {
+  }
+
+  onDeleteClick($event, key: string) {
+    this.onDelete.emit({name: this.data.groupName, key: key});
+    $event.stopPropagation();
+    return false;
+  }
+
+  onSelectClick(key: string) {
+    this.onSelect.emit({name: this.data.groupName, key: key});
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/collapse/collapse.module.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.module.ts 
b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.module.ts
new file mode 100644
index 0000000..79ac01d
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.module.ts
@@ -0,0 +1,30 @@
+/**
+ * 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 {NgModule} from '@angular/core';
+
+import {CollapseComponent}   from './collapse.component';
+import {SharedModule} from '../shared.module';
+
+@NgModule({
+  imports: [SharedModule],
+  exports: [CollapseComponent],
+  declarations: [CollapseComponent],
+  providers: [],
+})
+export class CollapseModule {
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.spec.ts
new file mode 100644
index 0000000..f8debdb
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.spec.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.
+ */
+
+describe('AlertSearchDirective', () => {
+
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.ts
 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.ts
new file mode 100644
index 0000000..fc3d113
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-search.directive.ts
@@ -0,0 +1,208 @@
+/**
+ * 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.
+ */
+/// <reference path="../../../../node_modules/@types/ace/index.d.ts" />
+import {Directive, ElementRef, EventEmitter, AfterViewInit, Output, Input, 
OnChanges, SimpleChanges} from '@angular/core';
+
+declare var ace: any;
+let ACERange = ace.require('ace/range').Range;
+
+@Directive({
+  selector: '[appAceEditor]'
+})
+
+export class AlertSearchDirective implements AfterViewInit, OnChanges {
+  editor: AceAjax.Editor;
+  closeButton: any;
+  mouseEventTimer: number;
+  target: any;
+
+  @Input() text = '';
+  @Output() textChanged = new EventEmitter();
+
+  constructor(private elementRef: ElementRef) {
+    const el = elementRef.nativeElement;
+    el.classList.add('editor');
+
+    ace.config.set('basePath', '/assets/ace');
+
+    this.editor = ace.edit(el);
+    this.editor.$blockScrolling = Infinity;
+    this.editor.renderer.setShowGutter(false);
+    this.editor.renderer.setShowPrintMargin(false);
+    this.editor.renderer.setPadding(10);
+    this.editor.setTheme('ace/theme/monokai');
+    this.editor.container.style.lineHeight = '1.5';
+
+    this.editor.setOptions({
+      minLines: 1,
+      highlightActiveLine: false,
+      maxLines: Infinity,
+      fontSize: '0.75em'
+    });
+
+    this.editor.getSession().setMode('ace/mode/lucene');
+
+    // This is a hack: setScrollMargin is not available in latest ace typings 
but is available in ace
+    let renderer: any = this.editor.renderer;
+    renderer.setScrollMargin(12, 12);
+
+    this.closeButton = document.createElement('i');
+    this.closeButton.classList.add('fa');
+    this.closeButton.classList.add('fa-times');
+    this.editor.on('click', (event) => {
+      if (event.domEvent.target.classList.contains('fa-times')) {
+        let pos = event.getDocumentPosition();
+        let strToDelete = 
this.getTextTillOperator(event.domEvent.target.parentElement);
+
+        let endIndex = pos.column;
+        let startIndex = pos.column - (strToDelete.length + 1);
+        if ( startIndex < 0) {
+          startIndex = 0;
+          endIndex = (strToDelete.length + 1);
+        }
+
+        let range = new ACERange(0, startIndex , 0, endIndex);
+        this.editor.selection.addRange(range);
+        this.editor.removeWordLeft();
+        this.editor.renderer.showCursor();
+        this.textChanged.next(this.editor.getValue());
+      }
+    });
+  }
+
+  private  getTextTillOperator(valueElement) {
+    let str = valueElement ? valueElement.textContent : '';
+
+    let previousSibling = valueElement && valueElement.previousSibling;
+    if (previousSibling && previousSibling.classList && 
previousSibling.classList.contains('ace_keyword')) {
+      str = previousSibling.textContent + str;
+    }
+
+    previousSibling = previousSibling && previousSibling.previousSibling;
+    if (previousSibling && previousSibling.nodeName === '#text') {
+      str = previousSibling.textContent + str;
+    }
+
+    previousSibling = previousSibling && previousSibling.previousSibling;
+    if (previousSibling && previousSibling.classList && 
previousSibling.classList.contains('ace_operator')) {
+      str = previousSibling.textContent + str;
+    } else {
+      str = str + this.getTextTillNextOperator(valueElement);
+    }
+
+    return str;
+  }
+
+  getTextTillNextOperator(valueElement) {
+    let str = '';
+    let nextSibling = valueElement.nextSibling;
+
+    if (nextSibling && nextSibling.nodeName === '#text') {
+      str = str + nextSibling.textContent;
+    }
+
+    nextSibling = nextSibling && nextSibling.nextSibling;
+    if (nextSibling && nextSibling.classList && 
nextSibling.classList.contains('ace_operator')) {
+      str = str + nextSibling.textContent;
+    }
+
+    return str;
+  }
+
+  getSeacrhText(): string {
+    return this.editor.getValue();
+  }
+
+  private handleMouseEvent (callback: Function) {
+    clearTimeout(this.mouseEventTimer);
+    this.mouseEventTimer = setTimeout(() => { callback(); }, 500);
+  }
+
+  private mouseover($event) {
+    if ($event.target.classList.contains('ace_value') ||
+        $event.target.classList.contains('ace_keyword') ||
+        $event.target.classList.contains('fa-times')) {
+      this.handleMouseEvent(() => {
+        this.target = $event.target.classList.contains('fa-times') ? 
$event.target.parentElement : $event.target;
+        if (this.target.classList.contains('ace_value')) {
+          this.target.classList.add('active');
+          if (this.target.previousSibling && 
this.target.previousSibling.classList) {
+            this.target.previousSibling.classList.add('active');
+          }
+          this.target.appendChild(this.closeButton);
+          this.editor.renderer.hideCursor();
+        }
+        if (this.target.classList.contains('ace_keyword') && 
!this.target.classList.contains('ace_operator')) {
+          this.target.classList.add('active');
+          if (this.target.nextSibling && this.target.nextSibling.classList) {
+            this.target.nextSibling.classList.add('active');
+            this.target.nextSibling.appendChild(this.closeButton);
+          }
+          this.editor.renderer.hideCursor();
+        }
+      });
+    }
+  }
+
+  private mouseout($event) {
+    if (this.target) {
+      this.handleMouseEvent(() => {
+        if (this.target.classList.contains('ace_value')) {
+          this.target.classList.remove('active');
+          if (this.target.previousSibling && 
this.target.previousSibling.classList) {
+            this.target.previousSibling.classList.remove('active');
+          }
+          this.target.removeChild(this.closeButton);
+          this.editor.renderer.showCursor();
+        }
+        if (this.target.classList.contains('ace_keyword') && 
!this.target.classList.contains('ace_operator')) {
+          this.target.classList.remove('active');
+          if (this.target.nextSibling && this.target.nextSibling.classList) {
+            this.target.nextSibling.classList.remove('active');
+            this.target.nextSibling.removeChild(this.closeButton);
+          }
+          this.editor.renderer.showCursor();
+        }
+        this.target = null;
+      });
+    }
+  }
+
+  ngAfterViewInit() {
+    this.editor.getSession().setUseWrapMode(true);
+    this.editor.keyBinding.addKeyboardHandler( (data, hashId, keyString, 
keyCode, event) => {
+      if (keyCode === 13) {
+        event.preventDefault();
+        event.stopPropagation();
+        this.textChanged.next(this.editor.getValue());
+        return false;
+      }
+      return true;
+    }, 0);
+    
this.elementRef.nativeElement.querySelector('.ace_content').addEventListener('mouseover',
 this.mouseover.bind(this));
+    
this.elementRef.nativeElement.querySelector('.ace_content').addEventListener('mouseout',
 this.mouseout.bind(this));
+  }
+
+  ngOnChanges(changes: SimpleChanges) {
+    if (changes && changes['text']) {
+      this.editor.setValue(this.text);
+      this.editor.clearSelection();
+      this.editor.focus();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/directives/alert-severity.directive.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/directives/alert-severity.directive.ts
 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-severity.directive.ts
new file mode 100644
index 0000000..c978d62
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/directives/alert-severity.directive.ts
@@ -0,0 +1,53 @@
+/**
+ * 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 { Directive, ElementRef, OnChanges, SimpleChanges, Input, OnInit } from 
'@angular/core';
+
+@Directive({
+  selector: '[appAlertSeverity]'
+})
+export class AlertSeverityDirective implements OnInit, OnChanges {
+
+  @Input() severity: number;
+
+  constructor(private el: ElementRef) { }
+
+  ngOnInit() {
+    this.setBorder(this.severity);
+  }
+
+  ngOnChanges(changes: SimpleChanges) {
+    if (changes['severity'] && changes['severity'].currentValue) {
+      this.setBorder(this.severity);
+    }
+  }
+
+  private setBorder(severity: number) {
+
+    if ( severity > 69 ) {
+      this.el.nativeElement.style.borderLeft = '4px solid #D60A15';
+      this.el.nativeElement.style.paddingLeft = '10px';
+    } else if ( severity > 39 ) {
+      this.el.nativeElement.style.borderLeft = '4px solid #D6711D';
+      this.el.nativeElement.style.paddingLeft = '10px';
+    } else  {
+      this.el.nativeElement.style.borderLeft = '4px solid #AC9B5A';
+      this.el.nativeElement.style.paddingLeft = '10px';
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.spec.ts
new file mode 100644
index 0000000..ec64f24
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.spec.ts
@@ -0,0 +1,25 @@
+/**
+ * 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 { NavContentDirective } from './nav-content.directive';
+
+describe('NavContentDirective', () => {
+  it('should create an instance', () => {
+    const directive = new NavContentDirective();
+    expect(directive).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.ts
 
b/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.ts
new file mode 100644
index 0000000..8bf9ba2
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/directives/nav-content.directive.ts
@@ -0,0 +1,35 @@
+/**
+ * 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 { Directive, ElementRef, OnInit } from '@angular/core';
+
+@Directive({
+  selector: '[appNavContent]'
+})
+export class NavContentDirective implements OnInit {
+
+  constructor(private element: ElementRef) {
+  }
+
+  ngOnInit() {
+    this.applyStyles();
+  }
+  private applyStyles() {
+    this.element.nativeElement.classList = 'nav-content';
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/index.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/index.ts 
b/metron-interface/metron-alerts/src/app/shared/index.ts
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.html
 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.html
new file mode 100644
index 0000000..948153c
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.html
@@ -0,0 +1,19 @@
+<!--
+  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.
+  -->
+<ul class="list-group">
+  <li *ngFor="let item of data; let i = index;" class="list-group-item anchor" 
[ngClass]="{'active': i === 0}">
+    <i *ngIf="item.icon"  [attr.class]="'fa ' + item.icon" 
aria-hidden="true"></i>
+    <span>{{ item.name }} </span>
+  </li>
+</ul>

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.scss
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.scss
 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.scss
new file mode 100644
index 0000000..2a7b65c
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.scss
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+ul {
+  margin: 10px 0px;
+}
+.list-group-item {
+  span {
+    padding-left: 25px;
+  }
+
+  i+span {
+    padding-left: 10px;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.spec.ts
new file mode 100644
index 0000000..f9916e6
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.spec.ts
@@ -0,0 +1,42 @@
+/**
+ * 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ListGroupComponent } from './list-group.component';
+
+describe('ListGroupComponent', () => {
+  let component: ListGroupComponent;
+  let fixture: ComponentFixture<ListGroupComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ListGroupComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ListGroupComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.ts
 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.ts
new file mode 100644
index 0000000..f42f961
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-group.component.ts
@@ -0,0 +1,47 @@
+/**
+ * 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, Input, HostListener, ElementRef } from 
'@angular/core';
+
+export interface ListGroupComponentData {
+  name: string;
+  icon?: string;
+}
+
+@Component({
+  selector: 'metron-list-group',
+  templateUrl: './list-group.component.html',
+  styleUrls: ['./list-group.component.scss']
+})
+export class ListGroupComponent implements OnInit {
+
+  @Input() data: ListGroupComponentData[] = [];
+
+  constructor(private element: ElementRef) { }
+
+  ngOnInit() {
+  }
+
+  @HostListener('click', ['$event']) onClick($event) {
+    
this.element.nativeElement.getElementsByClassName('active')[0].classList.remove('active');
+    if ($event.target.nodeName === 'LI') {
+      $event.target.classList.add('active');
+    } else {
+      $event.target.parentNode.classList.add('active');
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/list-group/list-grup.module.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/list-group/list-grup.module.ts 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-grup.module.ts
new file mode 100644
index 0000000..b1ba2a9
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/list-group/list-grup.module.ts
@@ -0,0 +1,30 @@
+/**
+ * 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 {NgModule} from '@angular/core';
+
+import {ListGroupComponent}   from './list-group.component';
+import {SharedModule} from '../shared.module';
+
+@NgModule({
+  imports: [SharedModule],
+  exports: [ListGroupComponent],
+  declarations: [ListGroupComponent],
+  providers: [],
+})
+export class ListGroupModule {
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/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
new file mode 100644
index 0000000..1b8e2bf
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
@@ -0,0 +1,91 @@
+/**
+ * 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 fade"  data-backdrop="static" >
+                  <div class="modal-dialog modal-sm" role="document">
+                    <div class="modal-content">
+                      <div class="modal-header">
+                        <button type="button" class="close" 
data-dismiss="modal" aria-label="Close"> 
+                            <span aria-hidden="true">&times;</span> 
+                        </button>
+                        <span class="modal-title"><b>` + 
MetronDialogBox.dialogType[type] + `</b></span>
+                      </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/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/index.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/index.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/index.ts
new file mode 100644
index 0000000..dcfa7b0
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/index.ts
@@ -0,0 +1,18 @@
+/**
+ * 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 * from './metron-sorter.component';

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.html
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.html
new file mode 100644
index 0000000..988bec1
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.html
@@ -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.
+  -->
+<a style="cursor: pointer"  class="text-nowrap" (click)="sort()">
+  <ng-content></ng-content>
+  <i class="fa fa-sort" aria-hidden="true" *ngIf="!sortAsc && !sortDesc"></i>
+  <i class="fa fa-sort-asc" aria-hidden="true" *ngIf="sortAsc"></i>
+  <i class="fa fa-sort-desc" aria-hidden="true" *ngIf="sortDesc"></i>
+</a>

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.scss
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.scss
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.scss
new file mode 100644
index 0000000..5d5f1e3
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.scss
@@ -0,0 +1,17 @@
+/**
+ * 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.
+ */

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.spec.ts
new file mode 100644
index 0000000..bec9378
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.spec.ts
@@ -0,0 +1,92 @@
+/**
+ * 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.
+ */
+/* tslint:disable:no-unused-variable */
+// directiveSelectorNameRule
+
+import {MetronSorterComponent} from './metron-sorter.component';
+import {MetronTableDirective} from '../metron-table.directive';
+
+describe('Component: MetronSorter', () => {
+
+  it('should create an instance', () => {
+    let metronTable = new MetronTableDirective();
+    let component = new MetronSorterComponent(metronTable);
+    expect(component).toBeTruthy();
+  });
+
+  it('should set the variables according to sorter', () => {
+    let metronTable = new MetronTableDirective();
+    let sorter1 = new MetronSorterComponent(metronTable);
+    let sorter2 = new MetronSorterComponent(metronTable);
+    let sorter3 = new MetronSorterComponent(metronTable);
+
+    sorter1.sortBy = 'col1';
+    sorter2.sortBy = 'col2';
+    sorter3.sortBy = 'col3';
+
+    sorter1.sort();
+    expect(sorter1.sortAsc).toEqual(true);
+    expect(sorter1.sortDesc).toEqual(false);
+    expect(sorter2.sortAsc).toEqual(false);
+    expect(sorter2.sortDesc).toEqual(false);
+    expect(sorter3.sortAsc).toEqual(false);
+    expect(sorter3.sortDesc).toEqual(false);
+
+    sorter1.sort();
+    expect(sorter1.sortAsc).toEqual(false);
+    expect(sorter1.sortDesc).toEqual(true);
+    expect(sorter2.sortAsc).toEqual(false);
+    expect(sorter2.sortDesc).toEqual(false);
+    expect(sorter3.sortAsc).toEqual(false);
+    expect(sorter3.sortDesc).toEqual(false);
+
+    sorter2.sort();
+    expect(sorter1.sortAsc).toEqual(false);
+    expect(sorter1.sortDesc).toEqual(false);
+    expect(sorter2.sortAsc).toEqual(true);
+    expect(sorter2.sortDesc).toEqual(false);
+    expect(sorter3.sortAsc).toEqual(false);
+    expect(sorter3.sortDesc).toEqual(false);
+
+    sorter2.sort();
+    expect(sorter1.sortAsc).toEqual(false);
+    expect(sorter1.sortDesc).toEqual(false);
+    expect(sorter2.sortAsc).toEqual(false);
+    expect(sorter2.sortDesc).toEqual(true);
+    expect(sorter3.sortAsc).toEqual(false);
+    expect(sorter3.sortDesc).toEqual(false);
+
+    sorter3.sort();
+    expect(sorter1.sortAsc).toEqual(false);
+    expect(sorter1.sortDesc).toEqual(false);
+    expect(sorter2.sortAsc).toEqual(false);
+    expect(sorter2.sortDesc).toEqual(false);
+    expect(sorter3.sortAsc).toEqual(true);
+    expect(sorter3.sortDesc).toEqual(false);
+
+    sorter3.sort();
+    expect(sorter1.sortAsc).toEqual(false);
+    expect(sorter1.sortDesc).toEqual(false);
+    expect(sorter2.sortAsc).toEqual(false);
+    expect(sorter2.sortDesc).toEqual(false);
+    expect(sorter3.sortAsc).toEqual(false);
+    expect(sorter3.sortDesc).toEqual(true);
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.ts
new file mode 100644
index 0000000..4808156
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.component.ts
@@ -0,0 +1,46 @@
+/**
+ * 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, Input } from '@angular/core';
+import {MetronTableDirective, SortEvent} from '../metron-table.directive';
+import {Sort} from '../../../utils/enums';
+
+@Component({
+  selector: 'metron-config-sorter',
+  templateUrl: './metron-sorter.component.html',
+  styleUrls: ['./metron-sorter.component.scss']
+})
+export class MetronSorterComponent {
+
+  @Input() sortBy: string;
+  @Input() type = 'string';
+
+  sortAsc = false;
+  sortDesc = false;
+
+  constructor(private metronTable: MetronTableDirective ) {
+    this.metronTable.onSortColumnChange.subscribe((event: SortEvent) => {
+      this.sortAsc = (event.sortBy === this.sortBy && event.sortOrder === 
Sort.ASC);
+      this.sortDesc = (event.sortBy === this.sortBy && event.sortOrder === 
Sort.DSC);
+    });
+  }
+
+  sort() {
+    let order = this.sortAsc ? Sort.DSC : Sort.ASC;
+    this.metronTable.setSort({sortBy: this.sortBy, sortOrder: order, type: 
this.type});
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.module.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.module.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.module.ts
new file mode 100644
index 0000000..088d120
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-sorter/metron-sorter.module.ts
@@ -0,0 +1,30 @@
+/**
+ * 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 {NgModule} from '@angular/core';
+
+import {MetronSorterComponent}   from './metron-sorter.component';
+import {SharedModule} from '../../shared.module';
+
+@NgModule({
+    imports: [SharedModule],
+    exports: [MetronSorterComponent],
+    declarations: [MetronSorterComponent],
+    providers: [],
+})
+export class MetronSorterModule {
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.html
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.html
new file mode 100644
index 0000000..63609a5
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.html
@@ -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.
+  -->
+<div *ngIf="pagination.total > 0">
+  <i *ngIf="pagination.from > 0" class="fa fa-chevron-left" aria-hidden="true" 
(click)="onPrevious()"></i>
+  <i *ngIf="pagination.from === 0" class="fa fa-chevron-left disabled" 
aria-hidden="true"></i>
+  <span> {{pagination.from + 1}} - {{pagination.total > (pagination.from + 
pagination.size) ? (pagination.from + pagination.size) : pagination.total}} of 
{{ pagination.total }} </span>
+  <i *ngIf="pagination.total - (pagination.from + pagination.size) > 0"  
class="fa fa-chevron-right" aria-hidden="true" (click)="onNext()"></i>
+  <i *ngIf="pagination.total - (pagination.from + pagination.size) <= 0"  
class="fa fa-chevron-right disabled" aria-hidden="true"></i>
+</div>

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.scss
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.scss
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.scss
new file mode 100644
index 0000000..bad1e52
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.scss
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+i {
+  cursor: pointer;
+  margin: 0px 10px;
+}
+
+.disabled {
+  opacity: 0.3;
+  cursor: default;
+}
+
+span {
+  font-size: 14px;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.spec.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.spec.ts
new file mode 100644
index 0000000..3a519b6
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.spec.ts
@@ -0,0 +1,42 @@
+/**
+ * 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MetronTablePaginationComponent } from 
'./metron-table-pagination.component';
+
+describe('MetronTablePaginationComponent', () => {
+  let component: MetronTablePaginationComponent;
+  let fixture: ComponentFixture<MetronTablePaginationComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ MetronTablePaginationComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MetronTablePaginationComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts
new file mode 100644
index 0000000..0aaa217
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts
@@ -0,0 +1,49 @@
+/**
+ * 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, Input, Output, EventEmitter } from '@angular/core';
+import {Pagination} from '../../../model/pagination';
+
+@Component({
+  selector: 'metron-table-pagination',
+  templateUrl: './metron-table-pagination.component.html',
+  styleUrls: ['./metron-table-pagination.component.scss']
+})
+export class MetronTablePaginationComponent  {
+
+  @Output() pageChange = new EventEmitter();
+  pagination = new Pagination();
+
+  @Input()
+  get pagingData() {
+    return this.pagination;
+  }
+
+  set pagingData(val) {
+    this.pagination = val;
+  }
+
+  onPrevious() {
+    this.pagination.from -= this.pagination.size;
+    this.pageChange.emit();
+  }
+
+  onNext() {
+    this.pagination.from  += this.pagination.size;
+    this.pageChange.emit();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/7d554444/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.module.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.module.ts
 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.module.ts
new file mode 100644
index 0000000..27b98dc
--- /dev/null
+++ 
b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.module.ts
@@ -0,0 +1,30 @@
+/**
+ * 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 {NgModule} from '@angular/core';
+
+import {MetronTablePaginationComponent}   from 
'./metron-table-pagination.component';
+import {SharedModule} from '../../shared.module';
+
+@NgModule({
+  imports: [SharedModule],
+  exports: [MetronTablePaginationComponent],
+  declarations: [MetronTablePaginationComponent],
+  providers: [],
+})
+export class MetronTablePaginationModule {
+}

Reply via email to