Repository: metron Updated Branches: refs/heads/master d5afb7284 -> bbfe29a97
METRON-1083 Add filters using faceted search capabilities of metron-rest-api (iraghumitra via james-sirota) closes apache/metron#710 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/bbfe29a9 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/bbfe29a9 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/bbfe29a9 Branch: refs/heads/master Commit: bbfe29a9792813f5aedfaa6b6f1d2437f6961333 Parents: d5afb72 Author: iraghumitra <[email protected]> Authored: Fri Oct 13 13:56:14 2017 -0700 Committer: jsirota <[email protected]> Committed: Fri Oct 13 13:56:14 2017 -0700 ---------------------------------------------------------------------- .../alert-filters/alert-filters.e2e-spec.ts | 111 +++++++++++++++++++ .../alert-filters/alert-filters.po.ts | 68 ++++++++++++ .../e2e/alerts-list/alerts-list.po.ts | 4 +- .../configure-table/configure-table.e2e-spec.ts | 4 +- .../save-search/save-search.e2e-spec.ts | 16 +-- .../metron-alerts/protractor.conf.js | 1 + .../metron-alerts/src/_variables.scss | 1 + .../alert-filters/alert-filters.component.html | 23 ++++ .../alert-filters/alert-filters.component.scss | 32 ++++++ .../alert-filters.component.spec.ts | 25 +++++ .../alert-filters/alert-filters.component.ts | 53 +++++++++ .../alerts-list/alerts-list.component.html | 11 +- .../alerts/alerts-list/alerts-list.component.ts | 4 + .../alerts/alerts-list/alerts-list.module.ts | 3 +- .../saved-searches.component.html | 4 +- .../metron-alerts/src/app/model/facets.ts | 23 ++++ .../src/app/model/search-request.ts | 2 + .../src/app/model/search-response.ts | 2 + .../src/app/service/search.service.ts | 1 - .../shared/collapse/collapse-component-data.ts | 1 + .../app/shared/collapse/collapse.component.html | 14 +-- .../app/shared/collapse/collapse.component.scss | 35 ++++-- .../app/shared/collapse/collapse.component.ts | 3 +- .../metron-alerts/src/app/utils/constants.ts | 1 + 24 files changed, 408 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.e2e-spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.e2e-spec.ts b/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.e2e-spec.ts new file mode 100644 index 0000000..11b8ae3 --- /dev/null +++ b/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.e2e-spec.ts @@ -0,0 +1,111 @@ +/// <reference path="../../matchers/custom-matchers.d.ts"/> +/** + * 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 {customMatchers} from '../../matchers/custom-matchers'; +import {LoginPage} from '../../login/login.po'; +import {AlertFacetsPage} from './alert-filters.po'; +import {loadTestData, deleteTestData} from '../../utils/e2e_util'; + +describe('metron-alerts facets', function() { + let page: AlertFacetsPage; + let loginPage: LoginPage; + + beforeAll(() => { + loadTestData(); + loginPage = new LoginPage(); + loginPage.login(); + }); + + afterAll(() => { + loginPage.logout(); + deleteTestData(); + }); + + beforeEach(() => { + page = new AlertFacetsPage(); + jasmine.addMatchers(customMatchers); + }); + + it('should display facets data', () => { + let facetValues = [ 'enrichm...:country 3', 'host 9', 'ip_dst_addr 8', 'ip_src_addr 2', 'source:type 1' ]; + + page.navgateToAlertList(); + expect(page.getFacetsTitle()).toEqualBcoz(['Filters'], 'for Title as Filters'); + expect(page.getFacetsValues()).toEqual(facetValues, 'for Facet values'); + }); + + it('should expand all facets', () => { + expect(page.getFacetState(0)).toEqualBcoz('collapse', 'for first facet'); + expect(page.getFacetState(1)).toEqualBcoz('collapse', 'for second facet'); + expect(page.getFacetState(2)).toEqualBcoz('collapse', 'for third facet'); + expect(page.getFacetState(3)).toEqualBcoz('collapse', 'for fourth facet'); + expect(page.getFacetState(4)).toEqualBcoz('collapse', 'for fifth facet'); + + page.toggleFacetState(0); + page.toggleFacetState(1); + page.toggleFacetState(2); + page.toggleFacetState(3); + page.toggleFacetState(4); + + expect(page.getFacetState(0)).toEqualBcoz('collapse show', 'for first facet'); + expect(page.getFacetState(1)).toEqualBcoz('collapse show', 'for second facet'); + expect(page.getFacetState(2)).toEqualBcoz('collapse show', 'for third facet'); + expect(page.getFacetState(3)).toEqualBcoz('collapse show', 'for fourth facet'); + expect(page.getFacetState(4)).toEqualBcoz('collapse show', 'for fifth facet'); + }); + + it('should have all facet values', () => { + let hostMap = { + 'comarks...rity.com': '9' , + '7oqnsnz...ysun.com': '44' , + 'node1': '36' , + '62.75.195.236': '18' , + 'runlove.us': '13' , + 'ip-addr.es': '2' , + 'ubb67.3...grams.in': '1' , + 'r03afd2...grams.in': '3' , + 'va872g....grams.in': '1' + }; + + expect(page.getFacetValues(0)).toEqualBcoz({ US: '22', RU: '44', FR: '25' }, 'for enrichment facet'); + expect(page.getFacetValues(1)).toEqual(hostMap, 'for host facet'); + expect(page.getFacetValues(4)).toEqual({ alerts_ui_e2e: '169' }, 'for source:type facet'); + }); + + it('should collapse all facets', () => { + expect(page.getFacetState(0)).toEqualBcoz('collapse show', 'for first facet'); + expect(page.getFacetState(1)).toEqualBcoz('collapse show', 'for second facet'); + expect(page.getFacetState(2)).toEqualBcoz('collapse show', 'for third facet'); + expect(page.getFacetState(3)).toEqualBcoz('collapse show', 'for fourth facet'); + expect(page.getFacetState(4)).toEqualBcoz('collapse show', 'for fifth facet'); + + page.toggleFacetState(0); + page.toggleFacetState(1); + page.toggleFacetState(2); + page.toggleFacetState(3); + page.toggleFacetState(4); + + expect(page.getFacetState(0)).toEqualBcoz('collapse', 'for first facet'); + expect(page.getFacetState(1)).toEqualBcoz('collapse', 'for second facet'); + expect(page.getFacetState(2)).toEqualBcoz('collapse', 'for third facet'); + expect(page.getFacetState(3)).toEqualBcoz('collapse', 'for fourth facet'); + expect(page.getFacetState(4)).toEqualBcoz('collapse', 'for fifth facet'); + }); +}); + http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.po.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.po.ts b/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.po.ts new file mode 100644 index 0000000..7d675e5 --- /dev/null +++ b/metron-interface/metron-alerts/e2e/alerts-list/alert-filters/alert-filters.po.ts @@ -0,0 +1,68 @@ +/** + * 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 {browser, element, by} from 'protractor'; +import {waitForElementPresence} from '../../utils/e2e_util'; + +export class AlertFacetsPage { + + private sleepTime = 500; + + navgateToAlertList() { + browser.waitForAngularEnabled(false); + return browser.get('/alerts-list'); + } + + getFacetsTitle() { + return waitForElementPresence(element.all(by.css('app-alert-filters metron-collapse'))).then(() => { + return element.all(by.css('app-alert-filters .title')).getText(); + }); + } + + getFacetsValues() { + return element.all(by.css('app-alert-filters metron-collapse')).getText(); + } + + getFacetState(id: number) { + browser.sleep(this.sleepTime); + let collpaseElement = element.all(by.css('metron-collapse')).get(id); + browser.actions().mouseMove(collpaseElement).perform(); + return collpaseElement.element(by.css('div.collapse')).getAttribute('class'); + } + + toggleFacetState(id: number) { + browser.sleep(this.sleepTime); + let collpaseElement = element.all(by.css('metron-collapse')).get(id); + browser.actions().mouseMove(collpaseElement).perform(); + return collpaseElement.element(by.css('a')).click(); + } + + getFacetValues(id: number) { + let collapsableElement = element.all(by.css('metron-collapse')).get(id); + return collapsableElement.element(by.css('.list-group')).getText().then(text => { + let facetMap = {}; + let facetValues = text.split('\n'); + for (let i = 0; i < facetValues.length; i = i + 2) { + facetMap[facetValues[i]] = facetValues[i + 1]; + } + return facetMap; + }); + } + +} + http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.po.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.po.ts b/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.po.ts index 982a79b..8e09f85 100644 --- a/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.po.ts +++ b/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.po.ts @@ -187,7 +187,7 @@ export class MetronAlertsPage { getRecentSearchOptions() { browser.sleep(1000); let map = {}; - let recentSearches = element.all(by.css('metron-collapse')).get(0); + let recentSearches = element.all(by.css('app-saved-searches metron-collapse')).get(0); return recentSearches.all(by.css('a')).getText().then(title => { return recentSearches.all(by.css('.collapse.show')).getText().then(values => { map[title] = values; @@ -199,7 +199,7 @@ export class MetronAlertsPage { getSavedSearchOptions() { browser.sleep(1000); let map = {}; - let recentSearches = element.all(by.css('metron-collapse')).get(1); + let recentSearches = element.all(by.css('app-saved-searches metron-collapse')).get(1); return recentSearches.all(by.css('a')).getText().then(title => { return recentSearches.all(by.css('.collapse.show')).getText().then(values => { map[title] = values; http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts b/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts index 284255f..0834960 100644 --- a/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts +++ b/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts @@ -51,10 +51,10 @@ describe('metron-alerts configure table', function() { page.navigateTo(); page.clickConfigureTable(); - expect(page.getSelectedColumnNames()).toEqual(colNamesColumnConfig, 'for default selected column names'); + expect(page.getSelectedColumnNames()).toEqualBcoz(colNamesColumnConfig, 'for default selected column names'); page.toggleSelectCol('id'); page.toggleSelectCol('guid', 'method'); - expect(page.getSelectedColumnNames()).toEqual(newColNamesColumnConfig, 'for guid added to selected column names'); + expect(page.getSelectedColumnNames()).toEqualBcoz(newColNamesColumnConfig, 'for guid added to selected column names'); page.saveConfigureColumns(); }); http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts b/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts index 91bb81a..b606284 100644 --- a/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts +++ b/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts @@ -47,8 +47,8 @@ describe('metron-alerts Search', function() { page.clickSavedSearch(); expect(page.getSavedSearchTitle()).toEqualBcoz('Searches', 'for saved searches title'); - expect(page.getRecentSearchOptions()).toEqual({ 'Recent Searches': [ 'No Recent Searches yet' ] }, 'for recent search options'); - expect(page.getSavedSearchOptions()).toEqual({ 'Saved Searches': [ 'No Saved Searches yet' ] }, 'for saved search options'); + expect(page.getRecentSearchOptions()).toEqualBcoz({ 'Recent Searches': [ 'No Recent Searches' ] }, 'for recent search options'); + expect(page.getSavedSearchOptions()).toEqualBcoz({ 'Saved Searches': [ 'No Saved Searches' ] }, 'for saved search options'); page.clickCloseSavedSearch(); }); @@ -56,22 +56,22 @@ describe('metron-alerts Search', function() { it('should have all save search controls and they save search should be working', () => { page.saveSearch('e2e-1'); page.clickSavedSearch(); - expect(page.getSavedSearchOptions()).toEqual({ 'Saved Searches': [ 'e2e-1' ] }, 'for saved search options e2e-1'); + expect(page.getSavedSearchOptions()).toEqualBcoz({ 'Saved Searches': [ 'e2e-1' ] }, 'for saved search options e2e-1'); page.clickCloseSavedSearch(); }); it('should populate search items when selected on table', () => { page.clickTableText('US'); - expect(page.getSearchText()).toEqual('enrichments:geo:ip_dst_addr:country:US', 'for search text ip_dst_addr_country US'); + expect(page.getSearchText()).toEqualBcoz('enrichments:geo:ip_dst_addr:country:US', 'for search text ip_dst_addr_country US'); page.clickClearSearch(); - expect(page.getSearchText()).toEqual('*', 'for clear search'); + expect(page.getSearchText()).toEqualBcoz('*', 'for clear search'); }); it('should delete search items from search box', () => { page.clickTableText('US'); - expect(page.getSearchText()).toEqual('enrichments:geo:ip_dst_addr:country:US', 'for search text ip_dst_addr_country US'); + expect(page.getSearchText()).toEqualBcoz('enrichments:geo:ip_dst_addr:country:US', 'for search text ip_dst_addr_country US'); page.clickRemoveSearchChip(); - expect(page.getSearchText()).toEqual('*', 'for search chip remove'); + expect(page.getSearchText()).toEqualBcoz('*', 'for search chip remove'); }); it('should delete first search items from search box having multiple search fields', () => { @@ -81,7 +81,7 @@ describe('metron-alerts Search', function() { page.clickRemoveSearchChip(); expect(page.getSearchText()).toEqual('source:type:alerts_ui_e2e', 'for search text alerts_ui_e2e after US is removed'); page.clickRemoveSearchChip(); - expect(page.getSearchText()).toEqual('*', 'for search chip remove for two search texts'); + expect(page.getSearchText()).toEqualBcoz('*', 'for search chip remove for two search texts'); }); it('manually entering search queries to search box and pressing enter key should search', () => { http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/protractor.conf.js ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/protractor.conf.js b/metron-interface/metron-alerts/protractor.conf.js index 6a82e9c..fe0fec0 100644 --- a/metron-interface/metron-alerts/protractor.conf.js +++ b/metron-interface/metron-alerts/protractor.conf.js @@ -29,6 +29,7 @@ exports.config = { './e2e/alerts-list/alerts-list.e2e-spec.ts', './e2e/alerts-list/configure-table/configure-table.e2e-spec.ts', './e2e/alerts-list/save-search/save-search.e2e-spec.ts', + './e2e/alerts-list/alert-filters/alert-filters.e2e-spec.ts', './e2e/alerts-list/alert-status/alerts-list-status.e2e-spec.ts', './e2e/alert-details/alert-status/alert-details-status.e2e-spec.ts' ], http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/_variables.scss ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/_variables.scss b/metron-interface/metron-alerts/src/_variables.scss index 1a5fa86..2705ff1 100644 --- a/metron-interface/metron-alerts/src/_variables.scss +++ b/metron-interface/metron-alerts/src/_variables.scss @@ -64,6 +64,7 @@ $breaker-bay: #669AAA; $gray: #909090; $silver-chalice: #B2B2B2; $silver-chalice-2: #A2A2A2; +$silver-chalice-3: #B0B0B0; $dusty-grey: #999999; $dusty-grey-1: #9B9A9A; $outer-space: #2D3A3F; http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.html ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.html b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.html new file mode 100644 index 0000000..ea0fff2 --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.html @@ -0,0 +1,23 @@ +<!-- + 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 class="w-100 h-100 filter-container"> + <div class="title"> Filters</div> + <div class="facets"> + <metron-collapse *ngFor="let facet of data" [data]="facet" [countOption]="true" + [titleSeperator]="false" [strLength]="15" [fontSize]="12" + (onSelect)="onFacetFilterSelect($event)"> + </metron-collapse> + </div> + +</div> http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.scss ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.scss b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.scss new file mode 100644 index 0000000..d8da7b4 --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.scss @@ -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. + */ +@import "../../../../variables"; + +.filter-container { + background: $mine-shaft; + + .title { + font-size: 15px; + padding: 15px 0px 0px 15px; + font-family: 'Roboto-Regular'; + } + + .facets { + padding: 0px 20px; + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.spec.ts new file mode 100644 index 0000000..54fa4bf --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertFiltersComponent } from './alert-filters.component'; + +describe('AlertFiltersComponent', () => { + let component: AlertFiltersComponent; + let fixture: ComponentFixture<AlertFiltersComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AlertFiltersComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AlertFiltersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.ts new file mode 100644 index 0000000..2a78ecd --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alert-filters/alert-filters.component.ts @@ -0,0 +1,53 @@ +import {Component, OnChanges, Input, SimpleChanges, EventEmitter, Output} from '@angular/core'; +import {Facets} from '../../../model/facets'; +import { + CollapseComponentData, + CollapseComponentDataItems +} from '../../../shared/collapse/collapse-component-data'; + +@Component({ + selector: 'app-alert-filters', + templateUrl: './alert-filters.component.html', + styleUrls: ['./alert-filters.component.scss'] +}) +export class AlertFiltersComponent implements OnChanges { + + facetMap = new Map<string, CollapseComponentData>(); + data: CollapseComponentData[] = []; + @Input() facets: Facets = new Facets(); + @Output() facetFilterChange = new EventEmitter<any>(); + + ngOnChanges(changes: SimpleChanges) { + if (changes && changes['facets'] && this.facets) { + this.prepareData(); + } + } + + prepareData() { + this.data.map(collapsableData => collapsableData.groupItems = []); + + for (let key of Object.keys(this.facets)) { + let facet = this.facets[key]; + let facetItems: CollapseComponentDataItems[] = []; + + for (let facetVal of Object.keys(facet)) { + facetItems.push(new CollapseComponentDataItems(facetVal, facet[facetVal])); + } + + let collapseComponentData = this.data.find(collapsableData => collapsableData.groupName === key); + if (!collapseComponentData) { + collapseComponentData = new CollapseComponentData(); + collapseComponentData.groupName = key; + collapseComponentData.collapsed = true; + this.data.push(collapseComponentData); + this.data = this.data.sort((obj1, obj2) => obj1.groupName.localeCompare(obj2.groupName)); + } + + collapseComponentData.groupItems = facetItems; + } + } + + onFacetFilterSelect($event) { + this.facetFilterChange.emit($event); + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html ---------------------------------------------------------------------- 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 856a3a3..1183223 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 @@ -62,9 +62,12 @@ </div> </div> -<div class="container-fluid nav-content"> +<div class="container-fluid no-gutters"> <div class="row"> - <div class="col-sm-12 pl-0"> + <div class="px-0" style="width: 200px;max-width: 200px;"> + <app-alert-filters [facets]="searchResponse.facetCounts" (facetFilterChange)="onAddFacetFilter($event)"> </app-alert-filters> + </div> + <div class="col"> <app-table-view #dataViewComponent [alerts]="alerts" [queryBuilder]="queryBuilder" @@ -76,7 +79,9 @@ (onRefreshData)="onRefreshData($event)" (onShowDetails)="showDetails($event)" (onShowConfigureTable)="showConfigureTable()" - (onSelectedAlertsChange)="onSelectedAlertsChange($event)"></app-table-view> + (onSelectedAlertsChange)="onSelectedAlertsChange($event)"> + + </app-table-view> </div> </div> </div> http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts index a3ba5ef..189c9ba 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 @@ -172,6 +172,10 @@ export class AlertsListComponent implements OnInit, OnDestroy { return false; } + onAddFacetFilter($event) { + this.onAddFilter(new Filter($event.name, $event.key)); + } + onRefreshData($event) { this.search($event); } http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts index c1025f0..8ee194e 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts @@ -26,13 +26,14 @@ import {ListGroupModule} from '../../shared/list-group/list-grup.module'; import {CollapseModule} from '../../shared/collapse/collapse.module'; import {MetronTablePaginationModule} from '../../shared/metron-table/metron-table-pagination/metron-table-pagination.module'; import {ConfigureRowsModule} from '../configure-rows/configure-rows.module'; +import {AlertFiltersComponent} from './alert-filters/alert-filters.component'; import {TableViewComponent} from './table-view/table-view.component'; @NgModule({ imports: [routing, SharedModule, ConfigureRowsModule, MetronSorterModule, MetronTablePaginationModule, ListGroupModule, CollapseModule], exports: [AlertsListComponent], - declarations: [AlertsListComponent, TableViewComponent], + declarations: [AlertsListComponent, TableViewComponent, AlertFiltersComponent], providers: [SearchService] }) export class AlertsListModule { http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.html ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.html b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.html index 925da9a..6311817 100644 --- a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.html +++ b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.html @@ -21,9 +21,9 @@ </div> <div> - <metron-collapse [data]="recentSearches" [fontSize]="15" [titleSeperator]="true" [show]="true" + <metron-collapse [data]="recentSearches" [fontSize]="15" [titleSeperator]="true" (onSelect)="onSaveRecentSearchSelect($event)" (onDelete)="deleteRecentSearch($event)"> </metron-collapse> - <metron-collapse [data]="savedSearches" [fontSize]="15" [titleSeperator]="true" [deleteOption]="true" [show]="true" + <metron-collapse [data]="savedSearches" [fontSize]="15" [titleSeperator]="true" [deleteOption]="true" (onSelect)="onSaveSearchSelect($event)" (onDelete)="deleteSearch($event)"> </metron-collapse> </div> </div> http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/model/facets.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/model/facets.ts b/metron-interface/metron-alerts/src/app/model/facets.ts new file mode 100644 index 0000000..a34ddda --- /dev/null +++ b/metron-interface/metron-alerts/src/app/model/facets.ts @@ -0,0 +1,23 @@ +/** + * 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 Facets { + [key: string]: { + [key: string]: number + } +} + http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/model/search-request.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/model/search-request.ts b/metron-interface/metron-alerts/src/app/model/search-request.ts index a37bd8d..3992ced 100644 --- a/metron-interface/metron-alerts/src/app/model/search-request.ts +++ b/metron-interface/metron-alerts/src/app/model/search-request.ts @@ -1,4 +1,5 @@ import {SortField} from './sort-field'; +import {DEFAULT_FACETS} from '../utils/constants'; import {INDEXES} from '../utils/constants'; /** * Licensed to the Apache Software Foundation (ASF) under one @@ -24,4 +25,5 @@ export class SearchRequest { query: string; size: number; sort: SortField[]; + facetFields: string[] = DEFAULT_FACETS; } http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/model/search-response.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/model/search-response.ts b/metron-interface/metron-alerts/src/app/model/search-response.ts index c3fea27..7fac1f2 100644 --- a/metron-interface/metron-alerts/src/app/model/search-response.ts +++ b/metron-interface/metron-alerts/src/app/model/search-response.ts @@ -16,8 +16,10 @@ * limitations under the License. */ import {Alert} from './alert'; +import {Facets} from './facets'; export class SearchResponse { total = 0; results: Alert[] = []; + facetCounts: Facets; } http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/service/search.service.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/search.service.ts b/metron-interface/metron-alerts/src/app/service/search.service.ts index d8842b8..0e48f6e 100644 --- a/metron-interface/metron-alerts/src/app/service/search.service.ts +++ b/metron-interface/metron-alerts/src/app/service/search.service.ts @@ -60,7 +60,6 @@ export class SearchService { public getAlert(sourceType: string, alertId: string): Observable<AlertSource> { let url = '/api/v1/search/findOne'; let requestSchema = { guid: alertId, sensorType: sourceType}; - return this.http.post(url, requestSchema, new RequestOptions({headers: new Headers(this.defaultHeaders)})) .map(HttpUtil.extractData) .catch(HttpUtil.handleError) http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/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 index cff81af..ce7f56c 100644 --- 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 @@ -29,4 +29,5 @@ export class CollapseComponentDataItems { export class CollapseComponentData { groupName: string; groupItems: CollapseComponentDataItems[] = []; + collapsed = false; } http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/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 index aaca91a..c83007c 100644 --- a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html +++ b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.html @@ -11,20 +11,20 @@ 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 [attr.href]="'#' + uniqueId" data-toggle="collapse" aria-expanded="false" [attr.aria-controls]="uniqueId" class="pr-2 collapsed" + [ngClass]="{'font-size-12' : fontSize === 12, 'font-size-15' : fontSize === 15, 'border-bottom' : titleSeperator=== true}"> + {{ data.groupName | columnNameTranslate | centerEllipses: strLength }} <span *ngIf="countOption" class="group-items-count"> {{ data.groupItems.length }} </span> </a> -<div class="collapse" [attr.id]="uniqueId" [ngClass]="{'show': show === true}"> +<div class="collapse" [attr.id]="uniqueId" [ngClass]="{'show': data.collapsed === false}"> <div *ngIf="data.groupItems.length === 0" class="container-fluid no-data-text"> - <i> {{ 'No ' + data.groupName + ' yet'}} </i> + <i> {{ 'No ' + data.groupName | centerEllipses: strLength }} </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" + [ngClass]="{'font-size-12' : fontSize === 12, '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="countOption" class="count"> {{ groupItem.count }} </span> <span *ngIf="deleteOption" class="delete" (click)="onDeleteClick($event, groupItem.name)"> </span> </li> </ul> http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/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 index 2208c37..c57711f 100644 --- a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss +++ b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.scss @@ -17,12 +17,23 @@ */ @import "../../../variables.scss"; -.font-size-14 { - font-size: 14px; +.font-size-12 { + font-size: 12px; + font-family: 'Roboto'; + + +.collapse .list-group { + padding-top: 0px; + padding-bottom: 0px; + } + + +.collapse .list-group-item, +.collapsing .list-group-item { + padding: 2px 10px; + } } .font-size-15 { font-size: 15px; + font-family: 'Roboto-Regular'; } .border-bottom { @@ -36,29 +47,33 @@ a { display: block; margin: 5px 0px; text-decoration: none; - color: $silver; + color: $silver-chalice-3; &::after { font-family: "FontAwesome"; font-style: normal; - font-size: 14px; + font-size: 16px; content: '\f106'; float: right; color: $dove-grey; + line-height: 1; } } a.collapsed::after { font-family: "FontAwesome"; font-style: normal; - font-size: 14px; + font-size: 16px; content: '\f107'; float: right; color: $dove-grey; + line-height: 1; } -.list-group { - padding: 10px 0px; +.group-items-count { + color: $dusty-grey; + font-size: 13px; + padding-left: 10px; } .list-group-item { @@ -79,7 +94,13 @@ a.collapsed::after { } } +.count { + font-size: 12px; + color: $dusty-grey; +} + .list-group-item:hover { + border-radius: 2px; background: $outer-space; .delete { http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/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 index 98947d3..4d609df 100644 --- a/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts +++ b/metron-interface/metron-alerts/src/app/shared/collapse/collapse.component.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; + import 'bootstrap'; import {CollapseComponentData} from './collapse-component-data'; @@ -33,7 +34,7 @@ export class CollapseComponent implements OnInit { @Input() fontSize = 14; @Input() titleSeperator = false; @Input() deleteOption = false; - @Input() show = false; + @Input() countOption = false; @Input() strLength = 30; @Output() onSelect = new EventEmitter<{name: string, key: string}>(); http://git-wip-us.apache.org/repos/asf/metron/blob/bbfe29a9/metron-interface/metron-alerts/src/app/utils/constants.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/utils/constants.ts b/metron-interface/metron-alerts/src/app/utils/constants.ts index a738a1d..6435b93 100644 --- a/metron-interface/metron-alerts/src/app/utils/constants.ts +++ b/metron-interface/metron-alerts/src/app/utils/constants.ts @@ -21,4 +21,5 @@ export const ALERTS_SAVED_SEARCH = 'metron-alerts-saved-search'; export const ALERTS_TABLE_METADATA = 'metron-alerts-table-metadata'; export const ALERTS_COLUMN_NAMES = 'metron-alerts-column-names'; +export let DEFAULT_FACETS = ['source:type', 'ip_src_addr', 'ip_dst_addr', 'host', 'enrichments:geo:ip_dst_addr:country']; export let INDEXES = ['websphere', 'snort', 'asa', 'bro', 'yaf'];
