From a31d6ed6436c80e94e68a4326fe4ca4e253be41d Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Fri, 25 Apr 2014 11:49:00 -0700 Subject: [PATCH] Dashbaord App updates - Loads visualizations - Uses AppState - Reflows the grid when the browser resizes (buggy, but good enough) closes #60 closes #37 --- src/kibana/apps/dashboard/directives/grid.js | 206 +++++++++++++----- src/kibana/apps/dashboard/directives/panel.js | 30 ++- src/kibana/apps/dashboard/index.html | 11 +- src/kibana/apps/dashboard/index.js | 97 +++++---- src/kibana/apps/dashboard/partials/panel.html | 2 + .../partials/pick_visualization.html | 1 + .../dashboard/partials/save_dashboard.html | 12 +- src/kibana/apps/dashboard/styles/main.css | 44 +++- src/kibana/apps/dashboard/styles/main.less | 68 +++--- .../apps/visualize/directives/canvas.js | 5 +- .../visualize/directives/visualization.js | 32 --- .../apps/visualize/directives/visualize.js | 32 +++ src/kibana/apps/visualize/editor.html | 2 +- src/kibana/apps/visualize/index.js | 2 +- src/kibana/apps/visualize/styles/main.css | 2 +- src/kibana/apps/visualize/styles/main.less | 16 +- .../apps/visualize/styles/visualization.css | 6 + .../apps/visualize/styles/visualization.less | 6 + .../courier/data_source/abstract.js | 4 +- .../components/saved_object/saved_object.js | 1 + src/kibana/styles/_mixins.less | 138 ++++++++++++ src/kibana/styles/main.css | 3 - src/kibana/styles/main.less | 4 - src/kibana/utils/config_template.js | 21 +- src/kibana/utils/rison.js | 3 +- 25 files changed, 524 insertions(+), 224 deletions(-) create mode 100644 src/kibana/apps/dashboard/partials/panel.html create mode 100644 src/kibana/apps/dashboard/partials/pick_visualization.html delete mode 100644 src/kibana/apps/visualize/directives/visualization.js create mode 100644 src/kibana/apps/visualize/directives/visualize.js create mode 100644 src/kibana/apps/visualize/styles/visualization.css create mode 100644 src/kibana/apps/visualize/styles/visualization.less create mode 100644 src/kibana/styles/_mixins.less diff --git a/src/kibana/apps/dashboard/directives/grid.js b/src/kibana/apps/dashboard/directives/grid.js index a2f606fecd77..a78a2a5c435f 100644 --- a/src/kibana/apps/dashboard/directives/grid.js +++ b/src/kibana/apps/dashboard/directives/grid.js @@ -11,89 +11,177 @@ define(function (require) { return { restrict: 'A', scope : { - grid: '=', - control: '=' + panels: '=' }, - link: function ($scope, elem) { - var width = elem.width(); + link: function ($scope, $el) { + var $container = $el.parent(); + var $window = $(window); + var $body = $(document.body); var gridster; // defined in init() - $scope.control = $scope.control || {}; + // number of columns to render + var COLS = 12; + // number of pixed between each column/row + var SPACER = 10; - $scope.$watch('grid', function (grid) { - if (grid === void 0) return; // wait until we have something + var init = function () { + $el.addClass('gridster'); - init(); - $scope.control.unserializeGrid(grid); - }); - - var init = _.once(function () { - elem.addClass('gridster'); - - elem.on('click', 'li i.remove', function (event) { - var target = event.target.parentNode.parentNode; - gridster.remove_widget(target); - }); - - gridster = elem.gridster({ + gridster = $el.gridster({ + max_cols: COLS, + min_cols: COLS, autogenerate_stylesheet: false, - widget_margins: [5, 5], - widget_base_dimensions: [((width - 100) / 12), 100], - min_cols: 12, - max_cols: 12, resize: { - enabled: true + enabled: true, + stop: readGridsterChangeHandler }, - serialize_params: function (el, wgd) { - return { - col: wgd.col, - row: wgd.row, - size_x: wgd.size_x, - size_y: wgd.size_y, - params: el.data('params') - }; + draggable: { + stop: readGridsterChangeHandler } }).data('gridster'); - gridster.generate_stylesheet({namespace: '.gridster'}); - }); - $scope.control.clearGrid = function (cb) { - gridster.remove_all_widgets(); - }; + layout(); + var safeLayout = _.debounce(layout, 200); + $window.on('resize', safeLayout); + + $scope.$watchCollection('panels', function (panels) { + var currentPanels = gridster.$widgets.toArray().map(function (el) { + return getPanelFor(el); + }); + + // panels that are now missing from the panels array + var removed = _.difference(currentPanels, panels); + + // panels that have been added + var added = _.difference(panels, currentPanels); + + if (removed.length) removed.forEach(removePanel); + if (added.length) added.forEach(addPanel); + + // ensure that every panel can be serialized now that we are done + $scope.panels.forEach(makePanelSerializeable); - $scope.control.unserializeGrid = function (grid) { - if (typeof grid === 'string') { - grid = JSON.stringify(grid); - } - gridster.remove_all_widgets(); - grid.forEach(function (panel) { - $scope.control.addWidget(panel); + // alert interested parties that we have finished processing changes to the panels + if (added.length || removed.length) $scope.$root.$broadcast('change:vis'); + }); + + $scope.$on('$destroy', function () { + $window.off('destroy', safeLayout); + + if (!gridster) return; + gridster.$widgets.each(function (el) { + removePanel(getPanelFor(el)); + }); }); }; - $scope.control.serializeGrid = function () { - return gridster.serialize(); + // return the panel object for an element. + // + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // ALWAYS CALL makePanelSerializeable AFTER YOU ARE DONE WITH IT + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + var getPanelFor = function (el) { + var $el = el.jquery ? el : $(el); + var panel = $el.data('panel'); + + panel.$el = $el; + panel.$scope = $el.data('$scope'); + + return panel; }; - $scope.control.addWidget = function (panel) { - panel = panel || {}; + // since the $el and $scope are circular structures, they need to be + // removed from panel before it can be serialized (we also wouldn't + // want them to show up in the url) + var makePanelSerializeable = function (panel) { + delete panel.$el; + delete panel.$scope; + }; + + // tell gridster to remove the panel, and cleanup our metadata + var removePanel = function (panel) { + gridster.remove_widget(panel.$el); + panel.$scope.$destroy(); + + panel.$el.removeData('panel'); + panel.$el.removeData('panel$scope'); + }; + + // tell gridster to add the panel, and create additional meatadata like $scope + var addPanel = function (panel) { _.defaults(panel, { size_x: 3, - size_y: 2, - params: { - type: 'new' - } + size_y: 2 + }); + + // ignore panels that don't have vis id's + if (!panel.visId) throw new Error('missing visId on panel'); + + panel.$scope = $scope.$new(); + panel.$scope.panel = panel; + + panel.$el = $compile('
  • ')(panel.$scope); + + // tell gridster to use the widget + gridster.add_widget(panel.$el, panel.size_x, panel.size_y, panel.col, panel.row); + // update size/col/etc. + refreshPanelStats(panel); + // stash the panel in the element's data + panel.$el.data('panel', panel); + }; + + // ensure that the panel object has the latest size/pos info + var refreshPanelStats = function (panel) { + var data = panel.$el.coords().grid; + panel.size_x = data.size_x; + panel.size_y = data.size_y; + panel.col = data.col; + panel.row = data.row; + }; + + // when gridster tell us it made a change, update each of the panel objects + var readGridsterChangeHandler = function (e, ui, $widget) { + // ensure that our panel objects keep their size in sync + gridster.$widgets.each(function (i, el) { + var panel = getPanelFor(el); + refreshPanelStats(panel); + makePanelSerializeable(panel); + $scope.$root.$broadcast('change:vis'); }); - var wgd = gridster.add_widget('
  • ', - panel.size_x, panel.size_y, panel.col, panel.row); + }; + + // calculate the position and sizing of the gridster el, and the columns within it + // then tell gridster to "reflow" -- which is definitely not supported. + // we may need to consider using a different library + var layout = function () { + // pixels used by all of the spacers + var spacerSize = SPACER * (COLS - 1); + // horizontal padding on the container + var horizPadding = parseInt($container.css('paddingLeft'), 10) + parseInt($container.css('paddingRight'), 10); + + // https://github.com/gcphost/gridster-responsive/blob/97fe43d4b312b409696b1d702e1afb6fbd3bba71/jquery.gridster.js#L1208-L1235 - var template = ''; + var g = gridster; - var element = $compile(template)($scope); - wgd.append(element); - wgd.data('params', panel.params); + g.options.widget_margins = [SPACER / 2, SPACER / 2]; + g.options.widget_base_dimensions = [($container.width() - spacerSize - horizPadding) / COLS, 100]; + g.min_widget_width = (g.options.widget_margins[0] * 2) + g.options.widget_base_dimensions[0]; + g.min_widget_height = (g.options.widget_margins[1] * 2) + g.options.widget_base_dimensions[1]; + // var serializedGrid = g.serialize(); + g.$widgets.each(function (i, widget) { + g.resize_widget($(widget)); + }); + + g.generate_grid_and_stylesheet(); + g.generate_stylesheet({ namespace: '.gridster' }); + + g.get_widgets_from_DOM(); + g.set_dom_grid_height(); + g.drag_api.set_limits(COLS * g.min_widget_width); }; + + init(); } }; }); diff --git a/src/kibana/apps/dashboard/directives/panel.js b/src/kibana/apps/dashboard/directives/panel.js index 7ff66e2d7994..fe1856d17f2e 100644 --- a/src/kibana/apps/dashboard/directives/panel.js +++ b/src/kibana/apps/dashboard/directives/panel.js @@ -1,15 +1,31 @@ define(function (require) { var app = require('modules').get('app/dashboard'); + var _ = require('lodash'); - app.directive('dashboardPanel', function () { + require('apps/visualize/directives/visualize'); + + app.directive('dashboardPanel', function (savedVisualizations, Notifier) { + var notify = new Notifier(); return { restrict: 'E', - scope: { - params: '@' - }, - compile: function (elem, attrs) { - var params = JSON.parse(attrs.params); - elem.html(params.type + ''); + template: require('text!../partials/panel.html'), + requires: '^dashboardGrid', + link: function ($scope, $el) { + // receives panel object from the dashboard grid directive + $scope.$watch('visId', function (visId) { + delete $scope.vis; + if (!$scope.panel.visId) return; + + savedVisualizations.get($scope.panel.visId) + .then(function (vis) { + $scope.vis = vis; + }) + .catch(notify.fatal); + }); + + $scope.remove = function () { + _.pull($scope.panels, $scope.panel); + }; } }; }); diff --git a/src/kibana/apps/dashboard/index.html b/src/kibana/apps/dashboard/index.html index 36844d1d6466..c5144309aa9d 100644 --- a/src/kibana/apps/dashboard/index.html +++ b/src/kibana/apps/dashboard/index.html @@ -8,16 +8,17 @@ - + -
    -
      +
      +
        diff --git a/src/kibana/apps/dashboard/index.js b/src/kibana/apps/dashboard/index.js index c843efee5fe8..a25c53d56098 100644 --- a/src/kibana/apps/dashboard/index.js +++ b/src/kibana/apps/dashboard/index.js @@ -41,74 +41,79 @@ define(function (require) { } }); - app.controller('dashboard', function ($scope, $route, $routeParams, $rootScope, $location, - Promise, es, configFile, createNotifier, courier) { + app.controller('dashboard', function ($scope, $route, $routeParams, $location, configFile, Notifier, courier, + savedVisualizations, AppState, timefilter) { - var notify = createNotifier({ + var notify = new Notifier({ location: 'Dashboard' }); - var dash = $scope.dash = $route.current.locals.dash; - - $scope.editingTitle = false; + timefilter.enabled(true); - // Passed in the grid attr to the directive so we can access the directive's function from - // the controller and view - $scope.gridControl = {}; + var dash = $scope.dash = $route.current.locals.dash; - // All inputs go here. - $scope.input = { - search: void 0 + var stateDefaults = { + title: dash.title, + panels: dash.panelsJSON ? JSON.parse(dash.panelsJSON) : [] }; - // Setup configurable values for config directive, after objects are initialized - $scope.configurable = { - dashboard: dash, - input: $scope.input - }; + var $state = $scope.$state = new AppState(stateDefaults); $scope.$on('$destroy', dash.destroy); - $scope.$watch('dash.panelsJSON', function (val) { - $scope.panels = JSON.parse(val || '[]'); - }); - $scope.configTemplate = new ConfigTemplate({ save: require('text!./partials/save_dashboard.html'), - load: require('text!./partials/load_dashboard.html') + load: require('text!./partials/load_dashboard.html'), + pickVis: require('text!./partials/pick_visualization.html') }); - $scope.openSave = function () { - if ($scope.configTemplate.toggle('save')) { - $scope.configSubmit = $scope.save; - } - }; - - $scope.openLoad = function () { - if ($scope.configTemplate.toggle('load')) { - $scope.configSubmit = null; - } - }; + $scope.openSave = _.partial($scope.configTemplate.toggle, 'save'); + $scope.openLoad = _.partial($scope.configTemplate.toggle, 'load'); + $scope.openAdd = _.partial($scope.configTemplate.toggle, 'pickVis'); + $scope.refresh = _.bindKey(courier, 'fetch'); $scope.save = function () { - var doc = courier.createSource('doc') - .index(configFile.kibanaIndex) - .type('dashboard') - .id($scope.dash.title); - - doc.doIndex({ - title: dash.title, - panelsJSON: JSON.stringify($scope.gridControl.serializeGrid()) - }) + dash.title = $state.title; + dash.panelsJSON = JSON.stringify($state.panels); + + dash.save() .then(function () { - notify.info('Saved Dashboard as "' + $scope.dash.title + '"'); - if ($scope.dash.title !== $routeParams.id) { - $location.url('/dashboard/' + encodeURIComponent($scope.dash.title)); + notify.info('Saved Dashboard as "' + $state.title + '"'); + if ($state.title !== $routeParams.id) { + $location.url('/dashboard/' + encodeURIComponent($state.title)); } }) .catch(notify.fatal); }; - $rootScope.$broadcast('application.load'); + var pendingVis = 0; + $scope.$on('ready:vis', function () { + if (pendingVis) pendingVis--; + if (pendingVis === 0) { + $state.commit(); + courier.fetch(); + } + }); + + // listen for notifications from the grid component that changes have + // been made, rather than watching the panels deeply + $scope.$on('change:vis', function () { + $state.commit(); + }); + + // called by the saved-object-finder when a user clicks a vis + $scope.addVis = function (hit) { + pendingVis++; + $state.panels.push({ visId: hit.id }); + }; + + // Setup configurable values for config directive, after objects are initialized + $scope.opts = { + dashboard: dash, + save: $scope.save, + addVis: $scope.addVis + }; + + $scope.$broadcast('application.load'); }); }); \ No newline at end of file diff --git a/src/kibana/apps/dashboard/partials/panel.html b/src/kibana/apps/dashboard/partials/panel.html new file mode 100644 index 000000000000..ededdaf4cc78 --- /dev/null +++ b/src/kibana/apps/dashboard/partials/panel.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/kibana/apps/dashboard/partials/pick_visualization.html b/src/kibana/apps/dashboard/partials/pick_visualization.html new file mode 100644 index 000000000000..94c92f7d79b0 --- /dev/null +++ b/src/kibana/apps/dashboard/partials/pick_visualization.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/kibana/apps/dashboard/partials/save_dashboard.html b/src/kibana/apps/dashboard/partials/save_dashboard.html index 5f60af3219a9..d69778f6b3f6 100644 --- a/src/kibana/apps/dashboard/partials/save_dashboard.html +++ b/src/kibana/apps/dashboard/partials/save_dashboard.html @@ -1,5 +1,7 @@ -
        - - -
        - +
        +
        + + +
        + +
        \ No newline at end of file diff --git a/src/kibana/apps/dashboard/styles/main.css b/src/kibana/apps/dashboard/styles/main.css index ac3e4a1f5ccc..591bc88a8824 100644 --- a/src/kibana/apps/dashboard/styles/main.css +++ b/src/kibana/apps/dashboard/styles/main.css @@ -71,31 +71,51 @@ body.application-dashboard { background-color: #18bc9c; } -div.application div.dashboard-container { - width: 100%; - background-color: #18bc9c; +.gridster-container { + margin: 0; + padding: 5px; } -[dashboard-grid].gridster { +.gridster { list-style-type: none; display: block; background-color: #18bc9c; - margin-bottom: 0; + margin: 0; + padding: 0; } -[dashboard-grid].gridster .preview-holder { +.gridster .preview-holder { border: none!important; background: #999999 !important; } -[dashboard-grid].gridster li.gs-w { - background: #fff; - padding: 5px; +.gridster i.remove { + cursor: pointer; +} +.gridster dashboard-panel { + display: block; + height: 100%; + background: #ffffff; color: #18bc9c; + padding: 0; font-weight: bold; font-size: 20px; - padding: 10px; overflow: hidden; + position: relative; } -[dashboard-grid] i.remove { - cursor: pointer; +.gridster dashboard-panel .btn { + position: absolute; + color: #d9534f; + top: 0px; + right: 0px; + border: none; + background: none; + opacity: .25; + transition: opacity 0.25s ease-in-out; + -webkit-transition: opacity 0.25s ease-in-out; + -moz-transition: opacity 0.25s ease-in-out; + -ms-transition: opacity 0.25s ease-in-out; + -o-transition: opacity 0.25s ease-in-out; +} +.gridster dashboard-panel .btn:hover { + opacity: 1; } .dashboard-load { margin: 10px; diff --git a/src/kibana/apps/dashboard/styles/main.less b/src/kibana/apps/dashboard/styles/main.less index 54caba65bfce..b472005b3aec 100644 --- a/src/kibana/apps/dashboard/styles/main.less +++ b/src/kibana/apps/dashboard/styles/main.less @@ -1,5 +1,6 @@ @import (reference) "../../../styles/_bootstrap.less"; @import (reference) "../../../styles/theme/_theme.less"; +@import (reference) "../../../styles/_mixins.less"; @dashboard-background: #18bc9c; @@ -7,36 +8,53 @@ body.application-dashboard { background-color: @dashboard-background; } -// Dashboard app container stretches to fill height. Required because gridster is not full height -div.application div.dashboard-container { - width: 100%; - background-color: @dashboard-background; +.gridster-container { + margin: 0; + padding: 5px; } -[dashboard-grid].gridster { +.gridster { list-style-type: none; display: block; background-color: @dashboard-background; - margin-bottom: 0; -} - -[dashboard-grid].gridster .preview-holder { - border: none!important; - background: @gray-light!important; -} - -[dashboard-grid].gridster li.gs-w { - background: #fff; - padding: 5px; - color: @dashboard-background; - font-weight: bold; - font-size: 20px; - padding: 10px; - overflow: hidden; -} - -[dashboard-grid] i.remove { - cursor: pointer; + margin: 0; + padding: 0; + + .preview-holder { + border: none!important; + background: @gray-light!important; + } + + i.remove { + cursor: pointer; + } + + dashboard-panel { + display: block; + height: 100%; + background: @panel-bg; + color: @dashboard-background; + padding: 0; + font-weight: bold; + font-size: 20px; + overflow: hidden; + position: relative; + + .btn { + position: absolute; + color: @brand-danger; + top: 0px; + right: 0px; + border: none; + background: none; + opacity: .25; + .transition(opacity .25s ease-in-out); + + &:hover { + opacity: 1; + } + } + } } .dashboard-load { diff --git a/src/kibana/apps/visualize/directives/canvas.js b/src/kibana/apps/visualize/directives/canvas.js index 0be96b9d4f04..c12f1b24924f 100644 --- a/src/kibana/apps/visualize/directives/canvas.js +++ b/src/kibana/apps/visualize/directives/canvas.js @@ -5,7 +5,10 @@ define(function (require) { module.directive('visCanvas', function ($http) { return { - restrict: 'A', + restrict: 'E', + scope: { + vis: '=' + }, link: function ($scope, $el) { var $window = $(window); var $body = $(document.body); diff --git a/src/kibana/apps/visualize/directives/visualization.js b/src/kibana/apps/visualize/directives/visualization.js deleted file mode 100644 index 575db41fd949..000000000000 --- a/src/kibana/apps/visualize/directives/visualization.js +++ /dev/null @@ -1,32 +0,0 @@ -define(function (require) { - var k4d3 = require('k4d3'); - var $ = require('jquery'); - - function VisualizationDirective(createNotifier) { - return { - restrict: 'E', - template: '
        {{ data | json }}
        ', - scope: { - vis: '=' - }, - link: function ($scope, $el) { - var vis = $scope.vis; - var notify = createNotifier({ - location: vis.type + ' visualization' - }); - - vis.searchSource.onResults().then(function onResults(resp) { - notify.event('render visualization'); - $scope.data = vis.buildChartDataFromResponse(resp); - notify.event('render visualization', true); - - window.canvasVisSource = vis.searchSource; - return vis.searchSource.onResults().then(onResults); - }).catch(notify.fatal); - } - }; - } - - require('modules').get('kibana/directive') - .directive('visualization', VisualizationDirective); -}); \ No newline at end of file diff --git a/src/kibana/apps/visualize/directives/visualize.js b/src/kibana/apps/visualize/directives/visualize.js new file mode 100644 index 000000000000..cc6566fd9e09 --- /dev/null +++ b/src/kibana/apps/visualize/directives/visualize.js @@ -0,0 +1,32 @@ +define(function (require) { + var k4d3 = require('k4d3'); + var $ = require('jquery'); + + require('css!../styles/visualization.css'); + + var module = require('modules').get('kibana/directive'); + + module.directive('visualize', function (createNotifier) { + return { + restrict: 'E', + link: function ($scope, $el) { + $scope.$watch('vis', function (vis, prevVis) { + if (prevVis) prevVis.destroy(); + if (!vis) return; + + var notify = createNotifier({ + location: vis.type + ' visualization' + }); + + vis.searchSource.onResults(function onResults(resp) { + var $disp = $('
        ');
        +            $disp.text(JSON.stringify(vis.buildChartDataFromResponse(resp), null, '  '));
        +            $el.html($disp);
        +          });
        +
        +          $scope.$root.$broadcast('ready:vis');
        +        });
        +      }
        +    };
        +  });
        +});
        \ No newline at end of file
        diff --git a/src/kibana/apps/visualize/editor.html b/src/kibana/apps/visualize/editor.html
        index 5c298c64c4d5..e2e432842c2a 100644
        --- a/src/kibana/apps/visualize/editor.html
        +++ b/src/kibana/apps/visualize/editor.html
        @@ -35,7 +35,7 @@
                 
               
               
        - +
        diff --git a/src/kibana/apps/visualize/index.js b/src/kibana/apps/visualize/index.js index 618f537748aa..61ccc5d498fb 100644 --- a/src/kibana/apps/visualize/index.js +++ b/src/kibana/apps/visualize/index.js @@ -5,7 +5,7 @@ define(function (require) { require('./controllers/wizard'); require('./directives/canvas'); - require('./directives/visualization'); + require('./directives/visualize'); require('./directives/config_category'); require('routes') diff --git a/src/kibana/apps/visualize/styles/main.css b/src/kibana/apps/visualize/styles/main.css index 49b03a83b888..df3f33017712 100644 --- a/src/kibana/apps/visualize/styles/main.css +++ b/src/kibana/apps/visualize/styles/main.css @@ -112,7 +112,7 @@ .vis-editor-content .vis-config-panel .agg-config-interval td:first-child { padding-left: 0px; } -.vis-editor-content .vis-canvas visualization { +.vis-editor-content vis-canvas { display: block; background: black; height: 800px; diff --git a/src/kibana/apps/visualize/styles/main.less b/src/kibana/apps/visualize/styles/main.less index 21734a13c1de..f8f708c62480 100644 --- a/src/kibana/apps/visualize/styles/main.less +++ b/src/kibana/apps/visualize/styles/main.less @@ -58,15 +58,13 @@ } } - .vis-canvas { - visualization { - display: block; - background: black; - height: 800px; - width: 95%; - margin: 0 auto; - overflow: auto; - } + vis-canvas { + display: block; + background: black; + height: 800px; + width: 95%; + margin: 0 auto; + overflow: auto; } } diff --git a/src/kibana/apps/visualize/styles/visualization.css b/src/kibana/apps/visualize/styles/visualization.css new file mode 100644 index 000000000000..bf2f70b51fd8 --- /dev/null +++ b/src/kibana/apps/visualize/styles/visualization.css @@ -0,0 +1,6 @@ +visualize { + display: block; + height: 100%; + width: 100%; + overflow: auto; +} diff --git a/src/kibana/apps/visualize/styles/visualization.less b/src/kibana/apps/visualize/styles/visualization.less new file mode 100644 index 000000000000..49e007f0d457 --- /dev/null +++ b/src/kibana/apps/visualize/styles/visualization.less @@ -0,0 +1,6 @@ +visualize { + display: block; + height: 100%; + width: 100%; + overflow: auto; +} \ No newline at end of file diff --git a/src/kibana/components/courier/data_source/abstract.js b/src/kibana/components/courier/data_source/abstract.js index 3c9260d5a231..3ef22e2bbba5 100644 --- a/src/kibana/components/courier/data_source/abstract.js +++ b/src/kibana/components/courier/data_source/abstract.js @@ -129,14 +129,14 @@ define(function (require) { * be fetched on the next run of the courier * @return {Promise} */ - SourceAbstract.prototype.onResults = function () { + SourceAbstract.prototype.onResults = function (handler) { var source = this; return new Promise.emitter(function (resolve, reject, defer) { source._courier._pendingRequests.push({ source: source, defer: defer }); - }); + }, handler); }; /** diff --git a/src/kibana/components/saved_object/saved_object.js b/src/kibana/components/saved_object/saved_object.js index 34fe83a5b92d..bc903dfca46d 100644 --- a/src/kibana/components/saved_object/saved_object.js +++ b/src/kibana/components/saved_object/saved_object.js @@ -176,6 +176,7 @@ define(function (require) { */ this.destroy = function () { docSource.cancelPending(); + if (obj.searchSource) obj.searchSource.cancelPending(); }; } diff --git a/src/kibana/styles/_mixins.less b/src/kibana/styles/_mixins.less new file mode 100644 index 000000000000..ed9ca4f17c38 --- /dev/null +++ b/src/kibana/styles/_mixins.less @@ -0,0 +1,138 @@ +.text-shadow (@string: 0 1px 3px rgba(0, 0, 0, 0.25)) { + text-shadow: @string; +} +.box-shadow (@string) { + -webkit-box-shadow: @string; + -moz-box-shadow: @string; + box-shadow: @string; +} +.drop-shadow (@x: 0, @y: 1px, @blur: 2px, @spread: 0, @alpha: 0.25) { + -webkit-box-shadow: @x @y @blur @spread rgba(0, 0, 0, @alpha); + -moz-box-shadow: @x @y @blur @spread rgba(0, 0, 0, @alpha); + box-shadow: @x @y @blur @spread rgba(0, 0, 0, @alpha); +} +.inner-shadow (@x: 0, @y: 1px, @blur: 2px, @spread: 0, @alpha: 0.25) { + -webkit-box-shadow: inset @x @y @blur @spread rgba(0, 0, 0, @alpha); + -moz-box-shadow: inset @x @y @blur @spread rgba(0, 0, 0, @alpha); + box-shadow: inset @x @y @blur @spread rgba(0, 0, 0, @alpha); +} + +.box-sizing (@type: border-box) { + -webkit-box-sizing: @type; + -moz-box-sizing: @type; + box-sizing: @type; +} + +.border-radius (@radius: 5px) { + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; + + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.border-radiuses (@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) { + -webkit-border-top-right-radius: @topright; + -webkit-border-bottom-right-radius: @bottomright; + -webkit-border-bottom-left-radius: @bottomleft; + -webkit-border-top-left-radius: @topleft; + + -moz-border-radius-topright: @topright; + -moz-border-radius-bottomright: @bottomright; + -moz-border-radius-bottomleft: @bottomleft; + -moz-border-radius-topleft: @topleft; + + border-top-right-radius: @topright; + border-bottom-right-radius: @bottomright; + border-bottom-left-radius: @bottomleft; + border-top-left-radius: @topleft; + + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; +} + +.opacity (@opacity: 0.5) { + -webkit-opacity: @opacity; + -moz-opacity: @opacity; + opacity: @opacity; +} + +.gradient (@startColor: #eee, @endColor: white) { + background-color: @startColor; + background: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor)); + background: -webkit-linear-gradient(top, @startColor, @endColor); + background: -moz-linear-gradient(top, @startColor, @endColor); + background: -ms-linear-gradient(top, @startColor, @endColor); + background: -o-linear-gradient(top, @startColor, @endColor); +} +.horizontal-gradient (@startColor: #eee, @endColor: white) { + background-color: @startColor; + background-image: -webkit-gradient(linear, left top, right top, from(@startColor), to(@endColor)); + background-image: -webkit-linear-gradient(left, @startColor, @endColor); + background-image: -moz-linear-gradient(left, @startColor, @endColor); + background-image: -ms-linear-gradient(left, @startColor, @endColor); + background-image: -o-linear-gradient(left, @startColor, @endColor); +} + +.animation (@name, @duration: 300ms, @delay: 0, @ease: ease) { + -webkit-animation: @name @duration @delay @ease; + -moz-animation: @name @duration @delay @ease; + -ms-animation: @name @duration @delay @ease; +} + +.transition (@transition) { + -webkit-transition: @transition; + -moz-transition: @transition; + -ms-transition: @transition; + -o-transition: @transition; +} +.transform(@string){ + -webkit-transform: @string; + -moz-transform: @string; + -ms-transform: @string; + -o-transform: @string; +} +.scale (@factor) { + -webkit-transform: scale(@factor); + -moz-transform: scale(@factor); + -ms-transform: scale(@factor); + -o-transform: scale(@factor); +} +.rotate (@deg) { + -webkit-transform: rotate(@deg); + -moz-transform: rotate(@deg); + -ms-transform: rotate(@deg); + -o-transform: rotate(@deg); +} +.skew (@deg, @deg2) { + -webkit-transform: skew(@deg, @deg2); + -moz-transform: skew(@deg, @deg2); + -ms-transform: skew(@deg, @deg2); + -o-transform: skew(@deg, @deg2); +} +.translate (@x, @y:0) { + -webkit-transform: translate(@x, @y); + -moz-transform: translate(@x, @y); + -ms-transform: translate(@x, @y); + -o-transform: translate(@x, @y); +} +.translate3d (@x, @y: 0, @z: 0) { + -webkit-transform: translate3d(@x, @y, @z); + -moz-transform: translate3d(@x, @y, @z); + -ms-transform: translate3d(@x, @y, @z); + -o-transform: translate3d(@x, @y, @z); +} +.perspective (@value: 1000) { + -webkit-perspective: @value; + -moz-perspective: @value; + -ms-perspective: @value; + perspective: @value; +} +.transform-origin (@x:center, @y:center) { + -webkit-transform-origin: @x @y; + -moz-transform-origin: @x @y; + -ms-transform-origin: @x @y; + -o-transform-origin: @x @y; +} \ No newline at end of file diff --git a/src/kibana/styles/main.css b/src/kibana/styles/main.css index 28d6f1eb0dab..b49926634d62 100644 --- a/src/kibana/styles/main.css +++ b/src/kibana/styles/main.css @@ -6540,9 +6540,6 @@ notifications { .navbar-nav li a { cursor: pointer; } -.container-default { - margin-top: 10px; -} .navbar { margin-bottom: 0px!important; } diff --git a/src/kibana/styles/main.less b/src/kibana/styles/main.less index 218fc3900764..0dd1b204a2f5 100644 --- a/src/kibana/styles/main.less +++ b/src/kibana/styles/main.less @@ -47,10 +47,6 @@ notifications { cursor: pointer; } -.container-default { - margin-top: 10px; -} - .navbar { margin-bottom: 0px!important; } diff --git a/src/kibana/utils/config_template.js b/src/kibana/utils/config_template.js index 44cec3cc0221..4bae945aabf5 100644 --- a/src/kibana/utils/config_template.js +++ b/src/kibana/utils/config_template.js @@ -1,28 +1,29 @@ define(function (require) { function ConfigTemplate(templates) { - this.current = null; + var template = this; + template.current = null; - this.toggle = function (name) { + template.toggle = function (name) { var toSwitch = templates[name]; - if (this.current === toSwitch) { - this.current = null; + if (template.current === toSwitch) { + template.current = null; return false; } else { - this.current = toSwitch; + template.current = toSwitch; return true; } }; - this.close = function (name) { + template.close = function (name) { var toClose = templates[name]; - if (this.current === toClose) { - this.current = null; + if (template.current === toClose) { + template.current = null; } }; - this.toString = function () { - return this.current; + template.toString = function () { + return template.current; }; } diff --git a/src/kibana/utils/rison.js b/src/kibana/utils/rison.js index c4b68dd7dfba..819c57ec60e2 100644 --- a/src/kibana/utils/rison.js +++ b/src/kibana/utils/rison.js @@ -190,7 +190,8 @@ rison.quote = function(x) { return "'" + x + "'"; }, undefined: function (x) { - throw new Error("rison can't encode the undefined value"); + // ignore undefined just like JSON + // throw new Error("rison can't encode the undefined value"); } };