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-06 02:41:00 +00:00
|
|
|
|
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() {
|
2016-08-22 17:12:24 +00:00
|
|
|
$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-06 02:41:00 +00:00
|
|
|
|
2016-08-03 15:19:33 +00:00
|
|
|
$scope.searchSource = searchSource;
|
|
|
|
$scope.vis = vis;
|
2016-08-06 02:41:00 +00:00
|
|
|
|
2016-08-03 15:19:33 +00:00
|
|
|
$scope.indexPattern = vis.indexPattern;
|
|
|
|
$scope.editableVis = editableVis;
|
|
|
|
$scope.state = $state;
|
2016-08-06 02:41:00 +00:00
|
|
|
|
2016-08-03 15:19:33 +00:00
|
|
|
$scope.uiState = $state.makeStateful('uiState');
|
2016-08-06 02:41:00 +00:00
|
|
|
|
2016-08-03 15:19:33 +00:00
|
|
|
vis.setUiState($scope.uiState);
|
2016-08-06 02:41:00 +00:00
|
|
|
|
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
|
|
|
|
2016-08-06 02:41:00 +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 });
|
2016-08-06 02:41:00 +00:00
|
|
|
$route.current.params._g = $scope.visG;
|
2016-08-09 11:30:08 +00:00
|
|
|
$route.updateParams({ '_g': $scope.visG });
|
2016-08-06 02:41:00 +00:00
|
|
|
const stateDefaults = {
|
|
|
|
uiState: {},
|
|
|
|
linked: false,
|
2016-08-09 11:30:08 +00:00
|
|
|
query: $scope.visFilter ? $scope.visFilter : { query_string: { analyze_wildcard: '!t', query: '*' } },
|
2016-08-06 02:41:00 +00:00
|
|
|
filters: [],
|
|
|
|
vis: {}
|
|
|
|
};
|
|
|
|
$state = new AppState(stateDefaults);
|
2016-08-07 15:59:51 +00:00
|
|
|
|
2016-08-06 02:41:00 +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
|
|
|
|
2016-08-10 04:30:55 +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-06 02:41:00 +00:00
|
|
|
|
2016-08-03 15:19:33 +00:00
|
|
|
});
|
|
|
|
|
2016-08-05 23:25:21 +00:00
|
|
|
});
|