Skip to content

Commit

Permalink
#1579 WIP: Improve filter capabilities in alert similarity panel
Browse files Browse the repository at this point in the history
  • Loading branch information
nadouani authored and To-om committed Nov 13, 2020
1 parent 3e8dfea commit cedbf8a
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 9 deletions.
89 changes: 85 additions & 4 deletions frontend/app/scripts/components/alert/AlertSimilarCaseListCmp.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,26 @@

self.CaseResolutionStatus = CaseResolutionStatus;

self.similarityFilters = {
fTitle: undefined,
fMatches: undefined

};

self.rateFilters = {
fObservables: undefined,
fIoc: undefined
};

self.matches = [];

self.$onInit = function() {
this.filtering = new FilteringSrv('case', 'alert.dialog.similar-cases', {
version: 'v1',
defaults: {
showFilters: true,
showStats: false,
pageSize: 15,
pageSize: 2,
sort: ['-startDate']
},
defaultFilter: []
Expand All @@ -40,12 +53,23 @@
skipStream: true,
version: 'v1',
loadAll: true,
pageSize: 15,
pageSize: self.filtering.context.pageSize,
operations: [
{'_name': 'getAlert', 'idOrName': this.alertId},
{'_name': 'similarCases'}
{'_name': 'similarCases', 'caseFilter': this.filtering.buildQuery()}
],
onUpdate: function() {}
onUpdate: function(data) {
_.each(data, function(item) {
item.fTitle = item.case.title;
item.fMatches = _.keys(item.observableTypes);
item.fObservables = Math.floor((item.similarObservableCount / item.observableCount) * 100);
item.fIocs = Math.floor((item.similarIocCount / item.iocCount) * 100);
});

self.matches = _.uniq(_.flatten(_.map(data, function(item){
return _.keys(item.observableTypes);
}))).sort();
}
});
};

Expand All @@ -55,6 +79,63 @@
});
};

// Frontend filter methods
this.clearLocalFilters = function() {
self.similarityFilters = {
fTitle: undefined,
fMatches: undefined
};

self.rateFilters = {
fObservables: undefined,
fIoc: undefined
};
};

this.greaterThan = function(prop){
return function(item){
return !self.rateFilters[prop] || item[prop] >= self.rateFilters[prop];
};
};

// Filtering methods
this.toggleFilters = function () {
this.filtering.toggleFilters();
};

this.search = function () {
self.load();
self.filtering.storeContext();
};

this.addFilterValue = function (field, value) {
self.filtering.addFilterValue(field, value);
self.search();
};

/// Clear all filters
this.clearFilters = function () {
self.filtering.clearFilters()
.then(self.search);
};

// Remove a filter
this.removeFilter = function (index) {
self.filtering.removeFilter(index)
.then(self.search);
};

this.filterBy = function(field, value) {
self.filtering.clearFilters()
.then(function(){
self.addFilterValue(field, value);
});
};

this.filterSimilarities = function(data) {
return data;
};


},
controllerAs: '$cmp',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
});

if (angular.isFunction(this.onUpdate)) {
this.onUpdate();
this.onUpdate(this.allValues);
}
} else {
this.update();
Expand Down
5 changes: 4 additions & 1 deletion frontend/app/styles/case-item.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ div.case-item>div.case-observables-list {
width: 450px;
}
div.case-item>div.case-similarity {
width: 200px;
width: 140px;
}
div.case-item>div.case-similarity-match {
width: 150px;
}
div.case-item>div.case-similarity-merge {
width: 150px;
Expand Down
20 changes: 20 additions & 0 deletions frontend/app/styles/filters.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,23 @@
background: #f5f5f5;
}
*/


.similar-case-list .progress {
height: 2px;
opacity: 1;
}

.similar-case-list .has-feedback .form-control {
padding-right: 25px;
}

.similar-case-list .case-item.filter-panel {
padding: 5px 0;
margin-bottom: 5px !important;
border: none !important;
}

.similar-case-list .case-item.filter-panel .form-group {
margin-bottom: 0 !important;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
<div class="similar-case-list">

<div ng-include="'views/components/alert/similarity/toolbar.html'"></div>

<div class="mt-s filter-panel" ng-include="'views/components/alert/similarity/filters.html'" ng-show="$cmp.filtering.context.showFilters"></div>

<div class="row mt-s">
<div class="col-md-12 clearfix">

<filters-preview filters="$cmp.filtering.context.filters"
on-clear-item="$cmp.removeFilter(field)"
on-clear-all="$cmp.clearFilters()"></filters-preview>
</div>
</div>

<div class="row">

<div class="col-md-12" ng-show="$cmp.list.total === 0">
<div class="empty-message">No records</div>
</div>

<div class="col-md-12" ng-show="$cmp.list.total > 0">
<div class="btn-toolbar" role="toolbar">
<!-- <div class="btn-toolbar" role="toolbar">
<div class="btn-group pull-right" role="group">
<page-sizer collection="$cmp.list" sizes="[10, 15, 30, 100]"></page-sizer>
</div>
</div>
</div> -->

<psearch control="$cmp.list"></psearch>

Expand All @@ -19,11 +33,48 @@
<div class="case-date text-bold">Date</div>
<div class="case-similarity text-bold">Observables</div>
<div class="case-similarity text-bold">IOCs</div>
<div class="case-similarity-match text-bold">Matches</div>
<div class="case-similarity-merge text-bold">Action</div>
</div>

<div class="case-item filter-panel">
<div class="case-details text-bold">
<div class="form-group has-feedback has-clear">
<input type="text" class="form-control input-sm" ng-model="$cmp.similarityFilters.fTitle">
<a class="fa fa-times-circle form-control-feedback form-control-clear text-muted" ng-click="$cmp.similarityFilters.fTitle = undefined" style="pointer-events: auto;cursor: pointer;"></a>
</div>
</div>
<div class="case-date text-bold"></div>
<div class="case-similarity text-bold">
<div class="form-group has-feedback has-clear">
<input type="number" class="form-control input-sm" ng-model="$cmp.rateFilters.fObservables">
<a class="fa fa-times-circle form-control-feedback form-control-clear text-muted" ng-click="$cmp.rateFilters.fObservables = undefined" style="pointer-events: auto;cursor: pointer;"></a>
</div>
</div>
<div class="case-similarity text-bold">
<div class="form-group has-feedback has-clear">
<input type="number" class="form-control input-sm" ng-model="$cmp.rateFilters.fIocs">
<a class="fa fa-times-circle form-control-feedback form-control-clear text-muted" ng-click="$cmp.rateFilters.fIocs = undefined" style="pointer-events: auto;cursor: pointer;"></a>
</div>
</div>
<div class="case-similarity-match text-bold">
<div>
<select class="form-control input-sm" ng-model="$cmp.similarityFilters.fMatches"
ng-options="item for item in $cmp.matches">
<option value=""></option>
</select>
</div>
</div>
<div class="case-similarity-merge text-bold">
<div class="text-center">
<a class="btn btn-link btn-clear btn-sm" ng-click="$cmp.clearLocalFilters()"><i class="fa fa-times"></i> Clear Filters</a>
</div>
</div>
</div>


<div class="case-collection" ng-repeat="item in filteredLinks = ($cmp.list.values | filter:$cmp.similarityFilters)">
<!-- <div class="case-collection" ng-repeat="item in filteredLinks = ($cmp.list.allValues | filter:$cmp.filterSimilarities)"> -->
<div class="case-collection" ng-repeat="item in filteredLinks = ($cmp.list.allValues | filter:$cmp.similarityFilters | filter:$cmp.greaterThan('fObservables') | filter:$cmp.greaterThan('fIocs'))">
<div class="case-item" >
<!-- case severity -->
<div class="case-tlp bg-tlp-{{item.case.tlp}}"></div>
Expand Down Expand Up @@ -76,6 +127,11 @@
<em>N/A</em>
</div>
</div>
<div class="case-similarity-match">
<div>
<div ng-repeat="(match, count) in item.observableTypes track by $index">{{match}} ({{count}})</div>
</div>
</div>

<div class="case-similarity-merge text-center">
<button class="btn btn-sm btn-primary" ng-click="$cmp.merge(item.case._id)">Merge in this case</button>
Expand Down
38 changes: 38 additions & 0 deletions frontend/app/views/components/alert/similarity/filters.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<div class="row">
<div class="col-md-12 active-filters">
<h4>Filters</h4>
<form ng-submit="$cmp.search()">
<div class="row mb-xxxs" ng-repeat="filter in $cmp.filtering.context.filters track by $index">
<div class="col-sm-4 col-md-4 col-lg-2">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="$cmp.removeFilter($index)">
<i class="fa fa-times text-danger"></i>
</button>
</span>
<select class="form-control" ng-model="filter.field"
ng-options="item.name as item.name for (key, item) in $cmp.filtering.attributes"
ng-change="$cmp.filtering.setFilterField(filter, config.entity)"></select>
</div>
</div>
<div class="col-sm-8 col-md-8 col-lg-6">
<filter-editor metadata="$cmp.filtering.metadata" filter="filter" entity="$cmp.filtering.entity"></filter-editor>
</div>
</div>
<div class="mv-xs row">
<div class="col-sm-12 col-md-12 col-lg-8">
<a href class="btn btn-sm btn-link btn-clear" ng-click="$cmp.filtering.addFilter()">
<i class="fa fa-plus"></i> Add a filter
</a>
<a href class="btn btn-sm btn-danger" ng-click="$cmp.clearFilters()" ng-if="$cmp.filtering.context.filters.length > 0">
<i class="fa fa-times"></i> Clear
</a>
<button href class="btn btn-sm btn-primary pull-right" type="submit" ng-if="$cmp.filtering.context.filters.length > 0">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
</form>

</div>
</div>
39 changes: 39 additions & 0 deletions frontend/app/views/components/alert/similarity/toolbar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<div class="row">
<div class="col-md-12">
<div class="btn-toolbar" role="toolbar">

<div class="btn-group" uib-dropdown>
<button class="btn btn-primary btn-sm dropdown-toggle" uib-dropdown-toggle type="button">
<i class="fa fa-filter"></i>
Quick Filters
<span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu>
<li>
<a ng-click="$cmp.filterBy('status', 'Open')"><i class="fa fa-folder-open-o"></i> Open cases</a>
</li>
<li>
<a ng-click="$cmp.filterBy('status', 'Resolved')"><i class="fa fa-folder-o"></i> Closed cases</a>
</li>
<li class="divider"></li>
<li>
<a ng-click="$cmp.filterBy('resolutionStatus', 'TruePositive')"><i class="fa fa-exclamation-circle"></i> Closed - True Positive</a>
</li>
<li>
<a ng-click="$cmp.filterBy('resolutionStatus', 'Indeterminate')"><i class="fa fa-question-circle-o "></i> Closed - Indeterminate</a>
</li>
</ul>
</div>

<div class="btn-group pull-right" role="group">
<page-sizer collection="$cmp.list" sizes="[1, 2, 3, 10, 15, 30, 100]"></page-sizer>
</div>

<div class="btn-group pull-right" role="group">
<button class="btn btn-sm" ng-class="{true: 'btn-primary', false:'btn-default'}[$cmp.filtering.context.showFilters]" type="button" ng-click="$cmp.toggleFilters()">
<i class="fa fa-search"></i> Filters
</button>
</div>
</div>
</div>
</div>

0 comments on commit cedbf8a

Please sign in to comment.