UNPKG

kibana-with-account

Version:

kibana-with-account is develop based kibana project

285 lines (234 loc) 9.44 kB
define(function (require) { var _ = require('lodash'); require('plugins/kibana/visualize/saved_visualizations/saved_visualizations'); require('plugins/kibana/visualize/editor/sidebar'); require('plugins/kibana/visualize/editor/agg_filter'); require('ui/visualize'); require('ui/collapsible_sidebar'); require('ui/share'); require('ui/routes') .when('/visualize/create', { template: require('plugins/kibana/visualize/editor/editor.html'), resolve: { savedVis: function (savedVisualizations, courier, $route, Private) { var visTypes = Private(require('ui/registry/vis_types')); var visType = _.find(visTypes, {name: $route.current.params.type}); if (visType.requiresSearch && !$route.current.params.indexPattern && !$route.current.params.savedSearchId) { throw new Error('You must provide either an indexPattern or a savedSearchId'); } return savedVisualizations.get($route.current.params) .catch(courier.redirectWhenMissing({ '*': '/visualize' })); } } }) .when('/visualize/edit/:id', { template: require('plugins/kibana/visualize/editor/editor.html'), resolve: { savedVis: function (savedVisualizations, courier, $route) { return savedVisualizations.get($route.current.params.id) .catch(courier.redirectWhenMissing({ 'visualization': '/visualize', 'search': '/settings/objects/savedVisualizations/' + $route.current.params.id, 'index-pattern': '/settings/objects/savedVisualizations/' + $route.current.params.id, 'index-pattern-field': '/settings/objects/savedVisualizations/' + $route.current.params.id })); } } }); require('ui/modules') .get('app/visualize', [ 'kibana/notify', 'kibana/courier' ]) .controller('VisEditor', function ($scope, $route, timefilter, AppState, $location, kbnUrl, $timeout, courier, Private, Promise) { var angular = require('angular'); var ConfigTemplate = require('ui/ConfigTemplate'); var Notifier = require('ui/notify/notifier'); var docTitle = Private(require('ui/doc_title')); var brushEvent = Private(require('ui/utils/brush_event')); var queryFilter = Private(require('ui/filter_bar/query_filter')); var filterBarClickHandler = Private(require('ui/filter_bar/filter_bar_click_handler')); var notify = new Notifier({ location: 'Visualization Editor' }); var savedVis = $route.current.locals.savedVis; var vis = savedVis.vis; var editableVis = vis.createEditableVis(); vis.requesting = function () { var requesting = editableVis.requesting; requesting.call(vis); requesting.call(editableVis); }; var searchSource = savedVis.searchSource; // config panel templates var configTemplate = new ConfigTemplate({ save: require('plugins/kibana/visualize/editor/panels/save.html'), load: require('plugins/kibana/visualize/editor/panels/load.html'), share: require('plugins/kibana/visualize/editor/panels/share.html'), }); if (savedVis.id) { docTitle.change(savedVis.title); } var $state = $scope.$state = (function initState() { var savedVisState = vis.getState(); var stateDefaults = { uiState: savedVis.uiStateJSON ? JSON.parse(savedVis.uiStateJSON) : {}, linked: !!savedVis.savedSearchId, query: searchSource.getOwn('query') || {query_string: {query: '*'}}, filters: searchSource.getOwn('filter') || [], vis: savedVisState }; $state = new AppState(stateDefaults); if (!angular.equals($state.vis, savedVisState)) { Promise.try(function () { vis.setState($state.vis); editableVis.setState($state.vis); }) .catch(courier.redirectWhenMissing({ 'index-pattern-field': '/visualize' })); } return $state; }()); function init() { // export some objects $scope.savedVis = savedVis; $scope.searchSource = searchSource; $scope.vis = vis; $scope.indexPattern = vis.indexPattern; $scope.editableVis = editableVis; $scope.state = $state; $scope.uiState = $state.makeStateful('uiState'); $scope.conf = _.pick($scope, 'doSave', 'savedVis', 'shareData'); $scope.configTemplate = configTemplate; editableVis.listeners.click = vis.listeners.click = filterBarClickHandler($state); 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); $scope.$watch(function () { return editableVis.getState(); }, function (newState) { editableVis.dirty = !angular.equals(newState, vis.getState()); $scope.responseValueAggs = null; try { $scope.responseValueAggs = editableVis.aggs.getResponseAggs().filter(function (agg) { return _.get(agg, 'schema.group') === 'metrics'; }); } // this can fail when the agg.type is changed but the // params have not been set yet. watcher will trigger again // when the params update catch (e) {} // eslint-disable-line no-empty }, true); $state.replace(); $scope.$watch('searchSource.get("index").timeFieldName', function (timeField) { timefilter.enabled = !!timeField; }); // update the searchSource when filters update $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) { if (_.contains(keys, 'linked') && $state.linked === true) { // abort and reload route $route.reload(); return; } if (_.contains(keys, 'vis')) { $state.vis.listeners = _.defaults($state.vis.listeners || {}, vis.listeners); // only update when we need to, otherwise colors change and we // risk loosing an in-progress result vis.setState($state.vis); editableVis.setState($state.vis); } // we use state to track query, must write before we fetch if ($state.query && !$state.linked) { searchSource.set('query', $state.query); } else { searchSource.set('query', null); } if (_.isEqual(keys, ['filters'])) { // updates will happen in filter watcher if needed return; } $scope.fetch(); }); // Without this manual emission, we'd miss filters and queries that were on the $state initially $state.emit('fetch_with_changes'); $scope.$listen(timefilter, 'fetch', _.bindKey($scope, 'fetch')); $scope.$on('ready:vis', function () { $scope.$emit('application.load'); }); $scope.$on('$destroy', function () { savedVis.destroy(); }); } $scope.fetch = function () { $state.save(); searchSource.set('filter', queryFilter.getFilters()); if (!$state.linked) searchSource.set('query', $state.query); if ($scope.vis.type.requiresSearch) { courier.fetch(); } }; $scope.startOver = function () { kbnUrl.change('/visualize', {}); }; $scope.doSave = function () { savedVis.id = savedVis.title; savedVis.visState = $state.vis; savedVis.uiStateJSON = angular.toJson($scope.uiState.getChanges()); savedVis.save() .then(function (id) { configTemplate.close('save'); if (id) { notify.info('Saved Visualization "' + savedVis.title + '"'); if (savedVis.id === $route.current.params.id) return; kbnUrl.change('/visualize/edit/{{id}}', {id: savedVis.id}); } }, notify.fatal); }; $scope.unlink = function () { if (!$state.linked) return; $state.linked = false; var parent = searchSource.getParent(true); var parentsParent = parent.getParent(true); // display unlinking for 2 seconds, unless it is double clicked $scope.unlinking = $timeout($scope.clearUnlinking, 2000); 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(); $state.query = searchSource.get('query'); $state.filters = searchSource.get('filter'); searchSource.inherits(parentsParent); }; $scope.clearUnlinking = function () { if ($scope.unlinking) { $timeout.cancel($scope.unlinking); $scope.unlinking = null; } }; function transferVisState(fromVis, toVis, fetch) { return function () { toVis.setState(fromVis.getState()); editableVis.dirty = false; $state.vis = vis.getState(); $state.save(); if (fetch) $scope.fetch(); }; } init(); }); });