Skip to content

Commit

Permalink
#110 Add responders list section to the UI
Browse files Browse the repository at this point in the history
  • Loading branch information
nadouani committed Jul 9, 2018
1 parent c7d9c9a commit 9e2d412
Show file tree
Hide file tree
Showing 8 changed files with 486 additions and 1 deletion.
6 changes: 6 additions & 0 deletions www/src/app/components/header/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
<strong>Analyzers</strong>
</a>
</li>
<li ui-sref-active="active" require-roles="orgadmin,analyze">
<a ui-sref="main.responders">
<i class="fa fa-forward"></i>
<strong>Responders</strong>
</a>
</li>
<li ui-sref-active="active" require-roles="orgadmin">
<a ui-sref="main.organization({id: $ctrl.main.currentUser.organization})">
<i class="fa fa-file-text"></i>
Expand Down
4 changes: 3 additions & 1 deletion www/src/app/index.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import indexComponents from './index.components';
import mainModule from './pages/main/main.module';
import loginModule from './pages/login/login.module';
import analyzersModule from './pages/analyzers/analyzers.module';
import respondersModule from './pages/responders/responders.module';
import jobsModule from './pages/jobs/jobs.module';
import settingsModule from './pages/settings/settings.module';

Expand Down Expand Up @@ -46,11 +47,12 @@ const App = angular.module('cortex', [
loginModule.name,
maintenanceModule.name,
analyzersModule.name,
respondersModule.name,
jobsModule.name,
adminModule.name,
settingsModule.name
]);

App.config(config).run(run);

export default App;
export default App;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

export default class ResponderListController {
constructor($state, ResponderService, NotificationService) {
'ngInject';

this.$state = $state;
this.ResponderService = ResponderService;
this.NotificationService = NotificationService;
}

// run(analyzer, dataType) {
// analyzer.active = true;
// this.ResponderService.openRunModal([analyzer], {
// dataType: dataType
// })
// .then(responses => {
// this.$state.go('main.jobs');

// responses.forEach(resp => {
// this.NotificationService.success(
// `${resp.data.analyzerName} started successfully on ${resp.data
// .data || resp.data.attachment.name}`
// );
// });
// })
// .catch(err => {
// if (!_.isString(err)) {
// this.NotificationService.error(
// err.data.message ||
// `An error occurred: ${err.statusText}` ||
// 'An unexpected error occurred'
// );
// }
// });
// }
}
32 changes: 32 additions & 0 deletions www/src/app/pages/responders/components/responders.list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<section>
<div class="row mv-s" ng-if="$ctrl.responders.length === 0">
<div class="col-md-12">
<div class="empty-message">No responders found.</div>
</div>
</div>

<div class="row mv-s" ng-if="$ctrl.responders.length > 0">
<div class="col-sm-12 flex-table">
<div class="flex-row media" ng-repeat="responder in $ctrl.responders track by responder.id">
<div class="flex-col flex-1">
<h4 class="media-heading">
<span class="text-primary mr-m">{{responder.name}}</span>
<small class="mr-xxs">
<strong>Version:</strong> {{responder.version}}</small>
<small class="mr-xxs" ng-if="responder.author">
<strong>Author:</strong> {{responder.author}}</small>
<small class="mr-xxs" ng-if="responder.license">
<strong>License:</strong> {{responder.license}}</small>
</h4>
<div class="mt-xs text-muted">
{{responder.description}}
</div>
<div class="mt-xs mb-xxxs">
<strong>Applies to:</strong>
<span class="datatype clickable label label-primary" ng-repeat="type in responder.dataTypeList">{{type}}</span>&nbsp;
</div>
</div>
</div>
</div>
</div>
</section>
109 changes: 109 additions & 0 deletions www/src/app/pages/responders/responders.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use strict';

import _ from 'lodash/core';

import PageController from '../../core/controllers/PageController';

export default class RespondersController extends PageController {
constructor(
$log,
SearchService,
ResponderService,
NotificationService,
localStorageService
) {
'ngInject';

super('responders-page');

this.$log = $log;
this.ResponderService = ResponderService;
this.NotificationService = NotificationService;
this.localStorageService = localStorageService;
this.SearchService = SearchService;

this.pagination = {
current: 1,
total: 0
};

this.state = this.localStorageService.get('responders-page') || {
filters: {
search: null,
dataType: []
},
pagination: {
pageSize: 50,
current: 1
}
};

this.filters = this.state.filters;
this.pagination = this.state.pagination;
}

$onInit() {
this.load(1);
}

buildQuery() {
let criteria = [];

if (!_.isEmpty(this.filters.search)) {
criteria.push({
_or: [{
_like: {
_field: 'description',
_value: this.filters.search
}
},
{
_like: {
_field: 'name',
_value: this.filters.search
}
}
]
});
}

if (!_.isEmpty(this.filters.dataType)) {
criteria.push({
_in: {
_field: 'dataTypeList',
_values: this.filters.dataType
}
});
}

return _.isEmpty(criteria) ? {} :
criteria.length === 1 ?
criteria[0] : {
_and: criteria
};
}

load(page) {
if (page) {
this.pagination.current = page;
}

this.state.filters = this.filters;
this.state.pagination = {
pageSize: this.pagination.pageSize
};
this.localStorageService.set('responders-page', this.state);

this.SearchService.configure({
objectType: 'responder',
filter: this.buildQuery(),
range: this.buildRange(),
sort: '+name'
})
.search()
.then(response => {
this.responders = response.data;
this.pagination.total = parseInt(response.headers('x-total')) || 0;
});
}
}
55 changes: 55 additions & 0 deletions www/src/app/pages/responders/responders.module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

import RepondersController from './responders.controller';
import tpl from './responders.page.html';

import RespondersListController from './components/responders.list.controller';
import respondersListTpl from './components/responders.list.html';

import responderService from './responders.service.js';

//import './analyzers.page.scss';

const respondersModule = angular
.module('responders-module', ['ui.router'])
.config(($stateProvider, Roles) => {
'ngInject';

$stateProvider.state('main.responders', {
url: 'responders',
component: 'respondersPage',
resolve: {
datatypes: ($q, ResponderService) => {
let defer = $q.defer();

ResponderService.list()
.then(() => {
defer.resolve(ResponderService.getTypes());
})
.catch(err => defer.reject(err));

return defer.promise;
}
},
data: {
allow: [Roles.SUPERADMIN, Roles.ORGADMIN, Roles.ANALYZE]
}
});
})
.component('respondersPage', {
controller: RepondersController,
templateUrl: tpl,
bindings: {
datatypes: '<'
}
})
.component('respondersList', {
controller: RespondersListController,
templateUrl: respondersListTpl,
bindings: {
responders: '<'
}
})
.service('ResponderService', responderService);

export default respondersModule;
42 changes: 42 additions & 0 deletions www/src/app/pages/responders/responders.page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<section class="content-header">
<h1>Responders ({{$ctrl.pagination.total}})</h1>
</section>

<section class="responders-page content">
<div class="box box-primary paginable-page">
<div class="box-header">
<form ng-submit="$ctrl.applyFilters()">
<div class="table-toolbar">
<label class="form-control pull-left">Data Types</label>

<multiselect class="pull-left mr-xs" ng-model="$ctrl.filters.dataType" options="$ctrl.datatypes" placeholder="Select" show-select-all="true"
show-unselect-all="true" classes-btn="($ctrl.filters.dataType.length > 0) ? 'btn-block btn-primary' : 'btn-default btn-block'">
</multiselect>

<label class="form-control pull-left">Responder</label>
<input type="text" class="form-control pull-left mr-xs" placeholder="Search for responder description" ng-model="$ctrl.filters.search">
<button class="pull-left btn btn-primary" type="submit">Search</button>
<button class="pull-left btn btn-clear text-danger ml-xxxs" type="button" ng-click="$ctrl.clearFilters()">
<i class="fa fa-times-circle"></i> Clear</button>

<select class="ml-xxxs form-control pull-right" ng-model="$ctrl.pagination.pageSize" ng-change="$ctrl.load()" ng-options="v as (v + ' / page') for v in [10, 50, 100, 1000]"></select>
<ul class="pull-right" ng-show="$ctrl.pagination.total > $ctrl.pagination.pageSize" uib-pagination total-items="$ctrl.pagination.total"
ng-change="$ctrl.load()" ng-model="$ctrl.pagination.current" boundary-links="true" items-per-page="$ctrl.pagination.pageSize"
previous-text="&lsaquo;" next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;" max-size="3" rotate="false"></ul>
</div>
</form>
</div>
<div class="box-body">
<responders-list responders="$ctrl.responders" on-delete="$ctrl.load(1)"></responders-list>
</div>
<div class="box-footer clearfix">
<div class="box-tools btn-toolbar pull-right">
<ul ng-show="$ctrl.pagination.total > $ctrl.pagination.pageSize" uib-pagination total-items="$ctrl.pagination.total" ng-change="$ctrl.load()"
ng-model="$ctrl.pagination.current" boundary-links="true" items-per-page="$ctrl.pagination.pageSize" previous-text="&lsaquo;"
next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;" max-size="3" rotate="false"></ul>
<select class="ml-xs form-control pull-right " ng-model="$ctrl.pagination.pageSize" ng-change="$ctrl.load()" ng-options="v as (v + ' / page') for v in [10, 50, 100, 1000]"></select>
</div>
</div>
</div>
</section>

Loading

0 comments on commit 9e2d412

Please sign in to comment.