wazuh-kibana-app/public/controllers/visLoader.js

335 lines
11 KiB
JavaScript
Raw Normal View History

2016-08-02 11:07:26 +00:00
require('ui/styles/base.less');
require('ui/styles/mixins.less');
require('ui/share/styles/index.less');
require('ui/styles/control_group.less');
require('ui/styles/navbar.less');
require('plugins/kibana/visualize/styles/main.less');
require('ui/styles/config.less');
2016-08-02 19:18:21 +00:00
require('ui/styles/spinner.less');
2016-08-02 11:07:26 +00:00
2016-08-01 14:50:18 +00:00
import _ from 'lodash';
import 'plugins/kibana/visualize/saved_visualizations/saved_visualizations';
import 'plugins/kibana/visualize/editor/sidebar';
import 'plugins/kibana/visualize/editor/agg_filter';
import 'ui/visualize';
import 'ui/collapsible_sidebar';
import 'ui/share';
import 'ui/listen';
import 'ui/bind';
import 'ui/fancy_forms';
2016-08-02 19:18:21 +00:00
import 'ui/filter_bar'
2016-08-02 11:54:34 +00:00
2016-08-01 14:50:18 +00:00
import Notifier from 'ui/notify/notifier';
import RegistryVisTypesProvider from 'ui/registry/vis_types';
require('plugins/metric_vis/metric_vis');
require('plugins/table_vis/table_vis');
require('plugins/markdown_vis/markdown_vis');
RegistryVisTypesProvider.register(require('plugins/kbn_vislib_vis_types/histogram'));
RegistryVisTypesProvider.register(require('plugins/kbn_vislib_vis_types/line'));
RegistryVisTypesProvider.register(require('plugins/kbn_vislib_vis_types/pie'));
RegistryVisTypesProvider.register(require('plugins/kbn_vislib_vis_types/area'));
RegistryVisTypesProvider.register(require('plugins/kbn_vislib_vis_types/tile_map'));
import DocTitleProvider from 'ui/doc_title';
import UtilsBrushEventProvider from 'ui/utils/brush_event';
import FilterBarQueryFilterProvider from 'ui/filter_bar/query_filter';
import FilterBarFilterBarClickHandlerProvider from 'ui/filter_bar/filter_bar_click_handler';
import uiRoutes from 'ui/routes';
import uiModules from 'ui/modules';
import 'ui/state_management/app_state';
import StateManagementAppStateProvider from 'ui/state_management/app_state';
import 'plugins/kibana/discover/saved_searches/saved_searches.js';
import 'ui/stringify/register';
import RegistryFieldFormatsProvider from 'ui/registry/field_formats';
2016-08-02 11:07:26 +00:00
import 'ui/kbn_top_nav';
import 'ui/timepicker';
2016-08-02 11:54:34 +00:00
import 'ui/directives/paginate.js';
import 'ui/directives/rows.js';
2016-08-02 11:07:26 +00:00
2016-08-02 19:18:21 +00:00
import 'ui/directives/pretty_duration.js';
import 'ui/parse_query';
import 'ui/persisted_log';
import 'ui/typeahead';
import 'plugins/spy_modes/req_resp_stats_spy_mode';
import 'plugins/spy_modes/table_spy_mode';
2016-08-01 14:50:18 +00:00
require('ui/courier');
2016-08-02 19:18:21 +00:00
var app = require('ui/modules').get('app/wazuh', [])
.directive('kbnVis', [function () {
return {
restrict: 'E',
scope: {
2016-08-03 15:19:33 +00:00
visType: '@visType',
visIndexPattern: '@visIndexPattern',
visA: '@visA',
visG: '@visG',
visFilter: '@visFilter',
visHeight: '@visHeight',
visSearchable: '@visSearchable'
2016-08-02 19:18:21 +00:00
},
2016-08-03 15:19:33 +00:00
template: require('../templates/vis-template.html')
2016-08-02 19:18:21 +00:00
}
2016-08-03 15:19:33 +00:00
}]);
2016-08-01 14:50:18 +00:00
2016-08-02 19:18:21 +00:00
require('ui/modules').get('app/wazuh', [])
2016-08-05 12:25:21 +00:00
.controller('VisEditorW', function ($scope, $route, timefilter, AppState, $location, kbnUrl, $timeout, courier, Private, Promise, savedVisualizations) {
2016-08-09 11:30:08 +00:00
$scope.v = {};
$scope.v.filter = $scope.visFilter;
2016-08-03 15:19:33 +00:00
$scope.chrome = {};
$scope.chrome.getVisible = function () {
return true;
}
2016-08-02 19:18:21 +00:00
2016-08-03 15:19:33 +00:00
var _savedVis = function () {
2016-08-03 15:19:33 +00:00
const visTypes = Private(RegistryVisTypesProvider);
const visType = _.find(visTypes, { name: $scope.visType });
2016-08-02 19:18:21 +00:00
2016-08-03 15:19:33 +00:00
if (!visType) {
throw new Error('You must provide a valid visualization type');
}
2016-08-02 19:18:21 +00:00
2016-08-03 15:19:33 +00:00
if (visType.requiresSearch && !$scope.visIndexPattern) {
throw new Error('You must provide either an indexPattern');
}
2016-08-02 19:18:21 +00:00
2016-08-05 12:25:21 +00:00
return savedVisualizations.get({ 'type': $scope.visType, 'indexPattern': $scope.visIndexPattern, '_g': $scope.visG, '_a': $scope.visA })
.catch(courier.redirectWhenMissing({
'*': '/'
}));
2016-08-03 15:19:33 +00:00
}
2016-08-02 19:18:21 +00:00
2016-08-03 15:19:33 +00:00
_savedVis().then(function (_sVis) {
$scope._loadVisAsync = true;
2016-08-02 19:18:21 +00:00
2016-08-03 15:19:33 +00:00
const savedVis = _sVis;
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
const vis = savedVis.vis;
const editableVis = vis.createEditableVis();
vis.requesting = function () {
const requesting = editableVis.requesting;
requesting.call(vis);
requesting.call(editableVis);
};
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
const searchSource = savedVis.searchSource;
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.topNavMenu = [{
key: 'refresh',
description: 'Refresh',
run: function () { $scope.fetch(); }
}];
2016-08-02 11:07:26 +00:00
2016-08-03 15:19:33 +00:00
if (savedVis.id) {
docTitle.change(savedVis.title);
}
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
let $state = $scope.$state = (function initState() {
$route.current.params._a = $scope.visA;
$route.updateParams({ '_a': $scope.visA });
$route.current.params._g = $scope.visG;
$route.updateParams({ '_g': $scope.visG });
2016-08-03 15:19:33 +00:00
const stateDefaults = {
2016-08-05 12:25:21 +00:00
uiState: {},
linked: false,
2016-08-09 11:30:08 +00:00
query: $scope.visFilter ? $scope.visFilter : { query_string: { analyze_wildcard: '!t', query: '*' } },
2016-08-05 12:25:21 +00:00
filters: [],
2016-08-05 23:25:21 +00:00
vis: {}
2016-08-03 15:19:33 +00:00
};
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$state = new AppState(stateDefaults);
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
return $state;
} ());
function init() {
// export some objects
$scope.savedVis = savedVis;
2016-08-03 15:19:33 +00:00
$scope.searchSource = searchSource;
$scope.vis = vis;
2016-08-03 15:19:33 +00:00
$scope.indexPattern = vis.indexPattern;
$scope.editableVis = editableVis;
$scope.state = $state;
2016-08-03 15:19:33 +00:00
$scope.uiState = $state.makeStateful('uiState');
2016-08-03 15:19:33 +00:00
vis.setUiState($scope.uiState);
2016-08-03 15:19:33 +00:00
$scope.timefilter = timefilter;
$scope.opts = _.pick($scope, 'doSave', 'savedVis', 'shareData', 'timefilter');
const filterBarClickHandler = Private(FilterBarFilterBarClickHandlerProvider);
editableVis.listeners.click = vis.listeners.click = filterBarClickHandler($state);
const brushEvent = Private(UtilsBrushEventProvider);
editableVis.listeners.brush = vis.listeners.brush = brushEvent;
// track state of editable vis vs. "actual" vis
$scope.stageEditableVis = transferVisState(editableVis, vis, true);
$scope.resetEditableVis = transferVisState(vis, editableVis);
2016-08-05 23:25:21 +00:00
2016-08-03 15:19:33 +00:00
$scope.$watch('searchSource.get("index").timeFieldName', function (timeField) {
timefilter.enabled = !!timeField;
});
// update the searchSource when filters update
const queryFilter = Private(FilterBarQueryFilterProvider);
$scope.$listen(queryFilter, 'update', function () {
searchSource.set('filter', queryFilter.getFilters());
$state.save();
});
// fetch data when filters fire fetch event
$scope.$listen(queryFilter, 'fetch', $scope.fetch);
$scope.$listen($state, 'fetch_with_changes', function (keys) {
2016-08-06 00:13:21 +00:00
let $state = $scope.$state = (function initState() {
$route.current.params._a = $scope.visA;
2016-08-09 11:30:08 +00:00
$route.updateParams({ '_a': $scope.visA });
$route.current.params._g = $scope.visG;
2016-08-09 11:30:08 +00:00
$route.updateParams({ '_g': $scope.visG });
const stateDefaults = {
uiState: {},
linked: false,
2016-08-09 11:30:08 +00:00
query: $scope.visFilter ? $scope.visFilter : { query_string: { analyze_wildcard: '!t', query: '*' } },
filters: [],
vis: {}
};
$state = new AppState(stateDefaults);
2016-08-07 15:59:51 +00:00
return $state;
} ());
$scope.state = $state;
2016-08-03 15:19:33 +00:00
if (_.contains(keys, 'linked') && $state.linked === true) {
return;
}
2016-08-01 14:50:18 +00:00
2016-08-09 11:30:08 +00:00
$state.vis.listeners = _.defaults($state.vis.listeners || {}, vis.listeners);
2016-08-01 14:50:18 +00:00
2016-08-09 11:30:08 +00:00
vis.setState($state.vis);
editableVis.setState($state.vis);
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
// we use state to track query, must write before we fetch
2016-08-09 11:30:08 +00:00
if ($scope.v.filter && !$state.linked) {
searchSource.set('query', $scope.v.filter);
2016-08-03 15:19:33 +00:00
} else {
searchSource.set('query', null);
}
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
if (_.isEqual(keys, ['filters'])) {
// updates will happen in filter watcher if needed
return;
}
2016-08-01 14:50:18 +00:00
$scope.$watch("visFilter", function (newValue, oldValue) {
$scope.v.filter = newValue;
$scope.fetch();
});
2016-08-03 15:19:33 +00:00
$scope.fetch();
});
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.$listen(timefilter, 'fetch', _.bindKey($scope, 'fetch'));
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.$on('ready:vis', function () {
$scope.$emit('application.load');
$state.emit('fetch_with_changes');
});
$scope.$on('$destroy', function () {
savedVis.destroy();
});
}
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.fetch = function () {
const queryFilter = Private(FilterBarQueryFilterProvider);
searchSource.set('filter', queryFilter.getFilters());
2016-08-09 11:30:08 +00:00
if (!$state.linked) searchSource.set('query', $scope.v.filter);
2016-08-03 15:19:33 +00:00
if ($scope.vis.type.requiresSearch) {
courier.fetch();
2016-08-01 14:50:18 +00:00
}
2016-08-03 15:19:33 +00:00
};
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.startOver = function () {
//Nothing
};
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.doSave = function () {
savedVis.id = savedVis.title;
// vis.title was not bound and it's needed to reflect title into visState
$state.vis.title = savedVis.title;
savedVis.visState = $state.vis;
savedVis.uiStateJSON = angular.toJson($scope.uiState.getChanges());
savedVis.save()
.then(function (id) {
$scope.kbnTopNav.close('save');
if (id) {
notify.info('Saved Visualization "' + savedVis.title + '"');
if (savedVis.id === $route.current.params.id) return;
}
}, notify.fatal);
};
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$scope.unlink = function () {
if (!$state.linked) return;
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
$state.linked = false;
const parent = searchSource.getParent(true);
const parentsParent = parent.getParent(true);
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
// display unlinking for 2 seconds, unless it is double clicked
$scope.unlinking = $timeout($scope.clearUnlinking, 2000);
2016-08-01 14:50:18 +00:00
2016-08-03 15:19:33 +00:00
delete savedVis.savedSearchId;
parent.set('filter', _.union(searchSource.getOwn('filter'), parent.getOwn('filter')));
// copy over all state except "aggs" and filter, which is already copied
_(parent.toJSON())
.omit('aggs')
.forOwn(function (val, key) {
searchSource.set(key, val);
})
.commit();
2016-08-01 14:50:18 +00:00
2016-08-09 11:30:08 +00:00
$scope.query = searchSource.get('query');
2016-08-03 15:19:33 +00:00
$state.filters = searchSource.get('filter');
searchSource.inherits(parentsParent);
2016-08-01 14:50:18 +00:00
};
2016-08-03 15:19:33 +00:00
$scope.clearUnlinking = function () {
if ($scope.unlinking) {
$timeout.cancel($scope.unlinking);
$scope.unlinking = null;
}
};
function transferVisState(fromVis, toVis, stage) {
return function () {
const view = fromVis.getEnabledState();
const full = fromVis.getState();
toVis.setState(view);
editableVis.dirty = false;
$state.vis = full;
$state.save();
if (stage) $scope.fetch();
};
}
init();
2016-08-03 15:19:33 +00:00
});
2016-08-05 23:25:21 +00:00
});