Merge pull request #130 from wazuh/3.0-fix-autocomplete

Fix autocomplete
This commit is contained in:
Javier Castro 2017-12-12 18:08:04 +01:00 committed by GitHub
commit 6e549ffec3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 199 additions and 77 deletions

View File

@ -1,7 +1,7 @@
let app = require('ui/modules').get('app/wazuh', []);
app.controller('agentsController',
function ($scope, $location, $rootScope, Notifier, appState, genericReq, apiReq, AgentsAutoComplete) {
function ($scope, $location, $q, $rootScope, Notifier, appState, genericReq, apiReq, AgentsAutoComplete) {
$rootScope.page = 'agents';
$scope.extensions = appState.getExtensions().extensions;
$scope.agentsAutoComplete = AgentsAutoComplete;
@ -172,6 +172,22 @@ function ($scope, $location, $rootScope, Notifier, appState, genericReq, apiReq,
$location.path('/manager');
};
$scope.analizeAgents = search => {
let deferred = $q.defer();
let promise;
$scope.agentsAutoComplete.filters = [];
promise = $scope.agentsAutoComplete.addFilter('search',search);
promise
.then(() => deferred.resolve($scope.agentsAutoComplete.items))
.catch(error => notify.error(error));
return deferred.promise;
}
//Load
try {
$scope.getAgent();

View File

@ -12,6 +12,19 @@ app
},
};
})
.directive('myEnter', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.myEnter);
});
event.preventDefault();
}
});
};
})
.directive('menuTop',function(){
return{
template:

View File

@ -26,4 +26,21 @@ app
.factory('Agents', agents)
.factory('Logs', logs)
.factory('Rules', rules)
.factory('Decoders', decoders);
.factory('RulesAutoComplete', rules)
.factory('Decoders', decoders)
.factory('DecodersAutoComplete', decoders)
.directive('lazyLoadData', function($compile) {
return {
link: (scope, el, attrs) => {
let now = new Date().getTime();
let rep = angular.element(document.getElementsByClassName('md-virtual-repeat-scroller'));
rep.on('scroll', evt => {
if (rep[0].scrollTop + rep[0].offsetHeight >= rep[0].scrollHeight)
if (new Date().getTime() - now > 100) {
now = new Date().getTime();
scope.$apply(() => scope.$eval(attrs.lazyLoadData));
}
});
}
};
});

View File

@ -1,51 +1,59 @@
let app = require('ui/modules').get('app/wazuh', []);
app.controller('rulesController', function ($scope,$rootScope, Notifier, Rules) {
app.controller('rulesController', function ($scope,$q,$rootScope, Notifier, Rules,RulesAutoComplete) {
$scope.setRulesTab = (tab) => $rootScope.globalsubmenuNavItem2 = tab;
//Initialization
const notify = new Notifier({ location: 'Manager - Rules' });
$scope.loading = true;
$scope.rules = Rules;
$scope.rulesAutoComplete = RulesAutoComplete;
$scope.setRulesTab('rules');
$scope.analizeRules = search => {
let deferred = $q.defer();
let promise;
$scope.rulesAutoComplete.filters = [];
$scope.analizeRules = (search) => {
$scope.autoComplete = [];
if (search !== '') $scope.autoComplete.push({
name: search,
type: 'search'
});
for(let element of $scope.rules.items){
for(let pci of element.pci){
$scope.autoComplete.push({
name: pci,
type: 'pci'
});
}
for(let group of element.groups){
$scope.autoComplete.push({
name: group,
type: 'group'
});
}
$scope.autoComplete.push({
name: element.file,
type: 'file'
});
if(search.startsWith('group:') && search.split('group:')[1].trim()) {
promise = $scope.rulesAutoComplete.addFilter('group',search.split('group:')[1].trim());
} else if(search.startsWith('level:') && search.split('level:')[1].trim()) {
promise = $scope.rulesAutoComplete.addFilter('level',search.split('level:')[1].trim());
} else if(search.startsWith('pci:') && search.split('pci:')[1].trim()) {
promise = $scope.rulesAutoComplete.addFilter('pci',search.split('pci:')[1].trim());
} else if(search.startsWith('file:') && search.split('file:')[1].trim()) {
promise = $scope.rulesAutoComplete.addFilter('file',search.split('file:')[1].trim());
} else {
promise = $scope.rulesAutoComplete.addFilter('search',search);
}
$scope.autoComplete = new Set($scope.autoComplete.map(e => JSON.stringify(e)));
$scope.autoComplete = Array.from($scope.autoComplete).map(e => JSON.parse(e));
promise
.then(() => deferred.resolve($scope.rulesAutoComplete.items))
.catch(error => notify.error(error));
return deferred.promise;
}
$scope.checkEnter = search => {
$scope.searchTerm = '';
angular.element(document.querySelector('#autocomplete')).blur();
if(search.startsWith('group:') && search.split('group:')[1].trim()) {
$scope.rules.addFilter('group',search.split('group:')[1].trim());
} else if(search.startsWith('level:') && search.split('level:')[1].trim()) {
$scope.rules.addFilter('level',search.split('level:')[1].trim());
} else if(search.startsWith('pci:') && search.split('pci:')[1].trim()) {
$scope.rules.addFilter('pci',search.split('pci:')[1].trim());
} else if(search.startsWith('file:') && search.split('file:')[1].trim()) {
$scope.rules.addFilter('file',search.split('file:')[1].trim());
}
};
//Load
try {
$scope.rules.nextPage('')
.then(() => {
$scope.loading = false;
$scope.analizeRules('');
})
.then(() => $scope.rulesAutoComplete.nextPage(''))
.then(() => $scope.loading = false)
.catch(error => notify.error(error.message));
} catch (e) {
notify.error('Unexpected exception loading controller');
@ -68,15 +76,16 @@ app.controller('rulesController', function ($scope,$rootScope, Notifier, Rules)
$scope.$on('$destroy', () => $scope.rules.reset());
});
app.controller('decodersController', function ($scope,$rootScope, $sce, Notifier, Decoders) {
app.controller('decodersController', function ($scope,$q, $rootScope, $sce, Notifier, Decoders,DecodersAutoComplete) {
$scope.setRulesTab = (tab) => $rootScope.globalsubmenuNavItem2 = tab;
//Initialization
const notify = new Notifier({ location: 'Manager - Decoders' });
$scope.loading = true;
$scope.decoders = Decoders;
$scope.decodersAutoComplete = DecodersAutoComplete;
$scope.typeFilter = "all";
$scope.setRulesTab('decoders');
const colors = [
'#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6
'#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2
@ -87,25 +96,6 @@ app.controller('decodersController', function ($scope,$rootScope, $sce, Notifier
'#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7
];
$scope.analizeDecoders = (search) => {
$scope.autoComplete = [];
if (search !== '') {
$scope.autoComplete.push({
name: search,
type: 'search'
});
}
for(let element of $scope.decoders.items){
$scope.autoComplete.push({
name: element.file,
type: 'file'
});
}
$scope.autoComplete = new Set($scope.autoComplete.map(e => JSON.stringify(e)));
$scope.autoComplete = Array.from($scope.autoComplete).map(e => JSON.parse(e));
};
let timesOpened = 0;
let lastName = false;
@ -140,13 +130,43 @@ app.controller('decodersController', function ($scope,$rootScope, $sce, Notifier
return $sce.trustAsHtml(coloredString);
};
$scope.checkEnter = search => {
$scope.searchTerm = '';
angular.element(document.querySelector('#autocomplete')).blur();
if(search.startsWith('path:') && search.split('path:')[1].trim()) {
$scope.decoders.addFilter('path',search.split('path:')[1].trim());
} else if(search.startsWith('file:') && search.split('file:')[1].trim()) {
$scope.decoders.addFilter('file',search.split('file:')[1].trim());
}
};
$scope.analizeDecoders = search => {
let deferred = $q.defer();
let promise;
$scope.decodersAutoComplete.filters = [];
if(search.startsWith('path:') && search.split('path:')[1].trim()) {
promise = $scope.decodersAutoComplete.addFilter('path',search.split('path:')[1].trim());
} else if(search.startsWith('file:') && search.split('file:')[1].trim()) {
promise = $scope.decodersAutoComplete.addFilter('file',search.split('file:')[1].trim());
} else {
promise = $scope.decodersAutoComplete.addFilter('search',search);
}
promise
.then(() => deferred.resolve($scope.decodersAutoComplete.items))
.catch(error => notify.error(error));
return deferred.promise;
}
//Load
try {
$scope.decoders.nextPage('')
.then(() => {
$scope.loading = false;
$scope.analizeDecoders('');
})
.then(() => $scope.decodersAutoComplete.nextPage())
.then(() => $scope.loading = false)
.catch(error => notify.error(error.message));
} catch (e) {
notify.error('Unexpected exception loading controller');

View File

@ -84,17 +84,20 @@ app.factory('DataHandler', function ($q, apiReq) {
addFilter (filterName, value) {
this.removeFilter(filterName, false);
this.filters.push({
name: filterName,
value: value
});
this.search();
return this.search();
}
removeFilter (filterName, search) {
this.filters = this.filters.filter(filter => filterName !== filter.name);
if(search) this.filters = this.filters.filter(filter => filterName !== filter.name && filter.value !== search);
else this.filters = this.filters.filter(filter => filterName !== filter.name);
if (search) this.search();
}
delete (name, index) {
@ -106,6 +109,7 @@ app.factory('DataHandler', function ($q, apiReq) {
}
search () {
let deferred = $q.defer();
let requestData;
this.end = false;
this.busy = false;
@ -116,11 +120,13 @@ app.factory('DataHandler', function ($q, apiReq) {
limit: this.initialBatch
};
let isUnknown = false;
for(let filter of this.filters){
if (filter.value !== '' && filter.value !== 'Unknown') requestData[filter.name] = filter.value;
if (filter.value !== '' && filter.value !== 'Unknown') requestData[filter.name] = filter.value;
if (filter.value === 'Unknown') isUnknown = true;
}
apiReq.request('GET', this.path, requestData)
.then(data => {
this.items = [];
@ -134,8 +140,11 @@ app.factory('DataHandler', function ($q, apiReq) {
this.items = this.items.filter(item => typeof item.os === 'undefined');
}
this.offset = items.length;
deferred.resolve(true);
})
.catch(console.error);
return deferred.promise;
}
sort(by) {

View File

@ -17,9 +17,22 @@
<span ng-show="agent.status" class="agents-head-5" ng-class="getAgentStatusClass(agent.status)">{{formatAgentStatus(agent.status)}}</span>
</div>
</div>
<span layout="row" class="agents-head-pad-left" layout-align="space-between start" flex="40">
<md-autocomplete id="agentsAutocomplete" flex md-no-cache="true" md-select-on-match="true" md-selected-item="_swpagent" md-selected-item-change="getAgent(_swpagent.id)" md-search-text="searchTerm" md-items="agentAutoComplete in agentsAutoComplete.items" md-item-text="agentAutoComplete.name" md-min-length="0" md-no-asterisk="false" md-menu-class="autocomplete-custom-agents-bar" placeholder="Search by name, ID or IP address">
<md-autocomplete id="agentsAutocomplete" flex
md-no-cache="true"
md-select-on-match="true"
md-selected-item="_swpagent"
md-selected-item-change="getAgent(_swpagent.id)"
md-search-text="searchTerm"
md-items="agentAutoComplete in analizeAgents(searchTerm)"
md-item-text="agentAutoComplete.name"
md-min-length="0"
md-no-asterisk="false"
md-menu-class="autocomplete-custom-agents-bar"
md-search-text-change="analizeAgents(searchTerm)"
placeholder="Search by name, ID or IP address"
lazy-load-data="agentsAutoComplete.nextPage('')">
<md-item-template>
<span class="item-title">
<span><strong md-highlight-text="search" md-highlight-flags="i"> {{agentAutoComplete.name}} ({{agentAutoComplete.id}}) </strong></span>

View File

@ -14,10 +14,27 @@
<div ng-show="!loading" flex layout="column" class="manager-ruleset-decoders-no-padding">
<div id="content" layout="row" layout-align="start start" class="manager-ruleset-decoders-top-content">
<span layout="row" class="manager-ruleset-decoders-top-span" flex layout-align="space-between center">
<md-autocomplete flex md-select-on-match="true" md-no-cache="true" md-selected-item="filter" md-selected-item-change="decoders.addFilter(filter.type, filter.name)" md-search-text="searchTerm" md-items="decoder in autoComplete | filter : searchTerm" md-item-text="decoder.name" md-min-length="0" md-no-asterisk="false" md-menu-class="autocomplete-custom-agents-bar" md-search-text-change="analizeDecoders(searchTerm)" placeholder="Search file">
<md-autocomplete flex
id="Auto"
md-input-id="autocomplete"
md-select-on-match="true"
md-no-cache="noCache"
md-selected-item="filter"
md-selected-item-change="decoders.addFilter('search', filter.name)"
md-search-text="searchTerm"
md-items="decoder in analizeDecoders(searchTerm)"
md-item-text="decoder.name +' '+ decoder.file"
md-min-length="0"
md-no-asterisk="false"
md-menu-class="autocomplete-custom-agents-bar"
md-search-text-change="analizeDecoders(searchTerm)"
placeholder="Search..."
lazy-load-data="decodersAutoComplete.nextPage()"
md-autofocus=""
my-enter="checkEnter(searchTerm)">
<md-item-template>
<span class="item-title">
<span><strong md-highlight-text="search" md-highlight-flags="i"> {{decoder.name}} </strong></span>
<span><strong md-highlight-text="search" md-highlight-flags="i"> {{decoder.name}} {{decoder.file}}</strong></span>
</span>
<span class="item-metadata">
<span class="item-metastat"> {{decoder.type}} </span>
@ -42,12 +59,15 @@
</md-input-container>
</div>
<md-chips readonly="true" ng-show="decoders.hasFilter('search') || decoders.hasFilter('file')">
<md-chip class="wazuh-chip" ng-click="decoders.removeFilter('search', true)" ng-if="decoders.hasFilter('search')">
<span class="bold">Search: {{filter.name}} <i class="fa fa-times" aria-hidden="true"></i></span>
<md-chips readonly="true" ng-show="decoders.hasFilter('search') || decoders.hasFilter('file') || decoders.hasFilter('path')">
<md-chip class="wazuh-chip" ng-click="decoders.removeFilter('search', true)" ng-if="decoders.hasFilter('search') && decoders.getFilter('search')">
<span class="bold">Search: {{decoders.getFilter('search')}} <i class="fa fa-times" aria-hidden="true"></i></span>
</md-chip>
<md-chip class="wazuh-chip" ng-click="decoders.removeFilter('file', true)" ng-if="decoders.hasFilter('file');">
<span class="bold">File: {{filter.name}} <i class="fa fa-times" aria-hidden="true"></i></span>
<span class="bold">File: {{decoders.getFilter('file')}} <i class="fa fa-times" aria-hidden="true"></i></span>
</md-chip>
<md-chip class="wazuh-chip" ng-click="decoders.removeFilter('path', true)" ng-if="decoders.hasFilter('path');">
<span class="bold">Path: {{decoders.getFilter('path')}} <i class="fa fa-times" aria-hidden="true"></i></span>
</md-chip>
</md-chips>

View File

@ -35,13 +35,27 @@
<div ng-show="!loading" flex layout="column">
<div id="content" layout="row" layout-align="start start" class="manager-ruleset-rules-button-bar">
<span layout="row" class="manager-ruleset-rules-button-bar-span" flex layout-align="space-between center">
<md-autocomplete flex md-select-on-match="true" md-no-cache="true" md-selected-item="filter" md-selected-item-change="rules.addFilter(filter.type, filter.name)"
md-search-text="searchTerm" md-items="rule in autoComplete | filter : searchTerm" md-item-text="rule.name" md-min-length="0"
md-no-asterisk="false" md-menu-class="autocomplete-custom-agents-bar" md-search-text-change="analizeRules(searchTerm)"
placeholder="Search for rule file, group or PCI requirement">
<md-autocomplete flex
id="Auto"
md-input-id="autocomplete"
md-select-on-match="true"
md-no-cache="noCache"
md-selected-item="filter"
md-selected-item-change="rules.addFilter('search', filter.description)"
md-search-text="searchTerm"
md-items="rule in analizeRules(searchTerm)"
md-item-text="rule.file + ' - ' + rule.description"
md-min-length="0"
md-no-asterisk="false"
md-menu-class="autocomplete-custom-agents-bar"
md-search-text-change="analizeRules(searchTerm)"
placeholder="Search..."
lazy-load-data="rulesAutoComplete.nextPage()"
md-autofocus=""
my-enter="checkEnter(searchTerm)">
<md-item-template>
<span class="item-title">
<strong md-highlight-text="search" md-highlight-flags="i"> {{rule.name}} </strong>
<strong md-highlight-text="search" md-highlight-flags="i"> {{rule.file}} - {{rule.description}} </strong>
</span>
<span class="item-metadata">
<span class="item-metastat" ng-if="rule.type != 'pci'"> {{rule.type}} </span>
@ -65,7 +79,7 @@
</div>
<md-chips readonly="true" ng-show="rules.hasFilter('level') || rules.hasFilter('search') || rules.hasFilter('file') || rules.hasFilter('group') || rules.hasFilter('pci')">
<md-chip class="wazuh-chip" ng-click="rules.removeFilter('search', true)" ng-if="rules.hasFilter('search')">
<md-chip class="wazuh-chip" ng-click="rules.removeFilter('search', true)" ng-if="rules.hasFilter('search') && rules.getFilter('search')">
<span class="bold">Search: {{rules.getFilter('search')}}
<i class="fa fa-times" aria-hidden="true"></i>
</span>