From 9f705d87c2cc3131062a5722114fa4eb2b6726a1 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 1 Dec 2015 11:42:34 -0700 Subject: [PATCH 01/16] Initial pass at angularifying legend values --- .../components/legend_value/legend_value.html | 3 ++ .../components/legend_value/legend_value.js | 25 +++++++++++++++ .../components/legend_value/legend_value.less | 10 ++++++ src/ui/public/vislib/lib/legend.js | 32 +++++++++++-------- 4 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 src/ui/public/vislib/components/legend_value/legend_value.html create mode 100644 src/ui/public/vislib/components/legend_value/legend_value.js create mode 100644 src/ui/public/vislib/components/legend_value/legend_value.less diff --git a/src/ui/public/vislib/components/legend_value/legend_value.html b/src/ui/public/vislib/components/legend_value/legend_value.html new file mode 100644 index 0000000000000..a3ad18bf52a63 --- /dev/null +++ b/src/ui/public/vislib/components/legend_value/legend_value.html @@ -0,0 +1,3 @@ +
  • + {{legendData.label}} +
  • \ No newline at end of file diff --git a/src/ui/public/vislib/components/legend_value/legend_value.js b/src/ui/public/vislib/components/legend_value/legend_value.js new file mode 100644 index 0000000000000..38a84552134fa --- /dev/null +++ b/src/ui/public/vislib/components/legend_value/legend_value.js @@ -0,0 +1,25 @@ +define(function (require) { + var _ = require('lodash'); + var html = require('ui/vislib/components/legend_value/legend_value.html'); + var $ = require('jquery'); + + require('ui/modules').get('kibana') + .directive('legendValue', function () { + return { + restrict: 'C', + template: html, + link: function ($scope, $elem) { + + $elem.on('mouseover', function () { + $('[data-label]', $scope.visEl).not('[data-label="' + $scope.legendData.label + '"]').css('opacity', 0.5); + }); + + $elem.on('mouseout', function () { + $('[data-label]', $scope.visEl).css('opacity', 1); + }); + + + } + }; + }); +}); diff --git a/src/ui/public/vislib/components/legend_value/legend_value.less b/src/ui/public/vislib/components/legend_value/legend_value.less new file mode 100644 index 0000000000000..928731ecb7eb9 --- /dev/null +++ b/src/ui/public/vislib/components/legend_value/legend_value.less @@ -0,0 +1,10 @@ +.legend-value:hover { + cursor: pointer; +} + +.legend-ul:hover .legend-value { + opacity: .5; +} +.legend-ul .legend-value:hover { + opacity: 1; +} \ No newline at end of file diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index 5d976d4554d01..28f36786bf62a 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -1,6 +1,10 @@ define(function (require) { - return function LegendFactory(Private) { + require('ui/vislib/components/legend_value/legend_value.js'); + require('ui/vislib/components/legend_value/legend_value.less'); + + return function LegendFactory(Private, $rootScope, $compile) { var d3 = require('d3'); + var $ = require('jquery'); var _ = require('lodash'); var Dispatch = Private(require('ui/vislib/lib/dispatch')); var Data = Private(require('ui/vislib/lib/data')); @@ -133,29 +137,29 @@ define(function (require) { .data(data) .enter() .append('li') - .attr('class', 'color') + .classed('legend-value', true) .each(function (d) { + var $scope = $rootScope.$new(); + $scope.legendData = d; + $scope.color = args.color(d.label); + $scope.visEl = self.el; + + + $compile(this)($scope); + var li = d3.select(this); - self._addIdentifier.call(this, d); + dataLabel(this, d.label); + /* li.append('i') .attr('class', 'fa fa-circle dots') .attr('style', 'color:' + args.color(d.label)); li.append('span').text(d.label); + */ }); }; - /** - * Append the data label to the element - * - * @method _addIdentifier - * @param label {string} label to use - */ - Legend.prototype._addIdentifier = function (d) { - dataLabel(this, d.label); - }; - /** * Renders legend * @@ -184,6 +188,7 @@ define(function (require) { legendDiv.select('.legend-ul').selectAll('li') .on('mouseover', function (d) { + return; var label = d.label; var charts = visEl.selectAll('.chart'); @@ -211,6 +216,7 @@ define(function (require) { eventEl.style('word-break', 'break-all'); }) .on('mouseout', function () { + return; /* * The default opacity of elements in charts may be modified by the * chart constructor, and so may differ from that of the legend From ee8d05f1b8b099f6383f210ce5aee4b41b9cbd38 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 1 Dec 2015 14:35:25 -0700 Subject: [PATCH 02/16] Move color selection to angular directive --- .../components/legend_value/legend_value.html | 26 ++++- .../components/legend_value/legend_value.js | 16 +++ .../components/legend_value/legend_value.less | 42 +++++++ src/ui/public/vislib/lib/legend.js | 107 ++---------------- src/ui/public/vislib/styles/_legend.less | 30 +---- 5 files changed, 98 insertions(+), 123 deletions(-) diff --git a/src/ui/public/vislib/components/legend_value/legend_value.html b/src/ui/public/vislib/components/legend_value/legend_value.html index a3ad18bf52a63..b26ea03277f06 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.html +++ b/src/ui/public/vislib/components/legend_value/legend_value.html @@ -1,3 +1,23 @@ -
  • - {{legendData.label}} -
  • \ No newline at end of file +
    +
    + {{legendData.label}} +
    +
    +
    + +

    + {{legendData.label}} +

    +
    + +
    + +

    + + +

    +
    +
    +
    \ No newline at end of file diff --git a/src/ui/public/vislib/components/legend_value/legend_value.js b/src/ui/public/vislib/components/legend_value/legend_value.js index 38a84552134fa..f8dc163be40be 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.js +++ b/src/ui/public/vislib/components/legend_value/legend_value.js @@ -18,6 +18,22 @@ define(function (require) { $('[data-label]', $scope.visEl).css('opacity', 1); }); + $scope.setColor = function (color) { + var colors = $scope.uiState.get('vis.colors') || {}; + colors[$scope.legendData.label] = color; + $scope.uiState.set('vis.colors', colors); + }; + + $scope.colors = [ + '#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6 + '#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2 + '#629E51', '#E5AC0E', '#64B0C8', '#E0752D', '#BF1B00', '#0A50A1', '#962D82', '#614D93', //4 + '#7EB26D', '#EAB839', '#6ED0E0', '#EF843C', '#E24D42', '#1F78C1', '#BA43A9', '#705DA0', // Normal + '#9AC48A', '#F2C96D', '#65C5DB', '#F9934E', '#EA6460', '#5195CE', '#D683CE', '#806EB7', //5 + '#B7DBAB', '#F4D598', '#70DBED', '#F9BA8F', '#F29191', '#82B5D8', '#E5A8E2', '#AEA2E0', //3 + '#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7 + ]; + } }; diff --git a/src/ui/public/vislib/components/legend_value/legend_value.less b/src/ui/public/vislib/components/legend_value/legend_value.less index 928731ecb7eb9..306bc9f694f44 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.less +++ b/src/ui/public/vislib/components/legend_value/legend_value.less @@ -1,3 +1,45 @@ +@import (reference) "~ui/styles/variables"; + +.legend-value { + margin-left: 5px; + + &-container { + padding: 3px; + } + + &-selected { + background-color: @well-bg; + } + + &-truncate { + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + &-full { + white-space: normal; + word-break: break-all; + } + + &-details { + padding: 5px 0px; + } + + &-color-picker { + .dot { + line-height: 14px; + margin: 2px; + font-size: 14px; + } + + .dot:hover { + margin: 0px; + font-size: 18px + } + } +} + .legend-value:hover { cursor: pointer; } diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index 28f36786bf62a..4fc4cd6de7611 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -93,28 +93,6 @@ define(function (require) { }); }; - Legend.prototype._colorPicker = function (el, label) { - const self = this; - - const container = el.selectAll('div'); - if (!container.empty()) return container.remove(); - - return el - .append('div') - .attr('class', 'color-selector') - .selectAll('i').data(colorPalette) - .enter() - .append('i') - .attr('class', 'fa fa-circle dots') - .attr('style', function (d) { - return `color: ${d};`; - }).on('click', function (d) { - const colors = self.vis.uiState.get('vis.colors') || {}; - colors[label] = d; - self.vis.uiState.set('vis.colors', colors); - }); - }; - /** * Adds list to legend * @@ -138,25 +116,15 @@ define(function (require) { .enter() .append('li') .classed('legend-value', true) + .classed('color', true) .each(function (d) { - var $scope = $rootScope.$new(); - $scope.legendData = d; - $scope.color = args.color(d.label); - $scope.visEl = self.el; - - + var $scope = _.extend($rootScope.$new(), { + visEl: self.el, + color: args.color(d.label), + legendData: d, + uiState: self.vis.uiState + }); $compile(this)($scope); - - var li = d3.select(this); - dataLabel(this, d.label); - - /* - li.append('i') - .attr('class', 'fa fa-circle dots') - .attr('style', 'color:' + args.color(d.label)); - - li.append('span').text(d.label); - */ }); }; @@ -186,64 +154,13 @@ define(function (require) { self.vis.resize(); }); - legendDiv.select('.legend-ul').selectAll('li') - .on('mouseover', function (d) { - return; + legendDiv.selectAll('li.color').each(function (d) { var label = d.label; - var charts = visEl.selectAll('.chart'); - - function filterLabel() { - var pointLabel = this.getAttribute('data-label'); - return pointLabel !== label.toString(); - } - - if (label && label !== 'Count') { - d3.select(this).style('cursor', 'pointer'); - } - - // legend - legendDiv.selectAll('li') - .filter(filterLabel) - .classed('blur_shape', true); - - // all data-label attribute - charts.selectAll('[data-label]') - .filter(filterLabel) - .classed('blur_shape', true); - - var eventEl = d3.select(this); - eventEl.style('white-space', 'inherit'); - eventEl.style('word-break', 'break-all'); - }) - .on('mouseout', function () { - return; /* - * The default opacity of elements in charts may be modified by the - * chart constructor, and so may differ from that of the legend - */ - - var charts = visEl.selectAll('.chart'); - - // legend - legendDiv.selectAll('li') - .classed('blur_shape', false); - - // all data-label attribute - charts.selectAll('[data-label]') - .classed('blur_shape', false); - - var eventEl = d3.select(this); - eventEl.style('white-space', 'nowrap'); - eventEl.style('word-break', 'inherit'); - }); - - legendDiv.selectAll('li.color').each(function (d) { - d3.select(this).on('click', function (d) { - self._colorPicker(d3.select(this), d.label); - }); - //if (label !== undefined && label !== 'Count') { - // d3.select(this).call(self.events.addClickEvent()); - //} + if (label !== undefined && label !== 'Count') { + d3.select(this).call(self.events.addClickEvent()); + } + */ }); }; diff --git a/src/ui/public/vislib/styles/_legend.less b/src/ui/public/vislib/styles/_legend.less index b7d6d89fc35b8..47b35756c15a4 100644 --- a/src/ui/public/vislib/styles/_legend.less +++ b/src/ui/public/vislib/styles/_legend.less @@ -27,40 +27,20 @@ } .legend-ul { + width: 150px; flex: 1 1 1px; overflow-x: hidden; overflow-y: auto; + color: @legend-item-color; list-style-type: none; padding: 0; visibility: visible; min-height: 0; - min-width: 60px; + font-size: 12px; + line-height: 13px; + text-align: left; margin-right: 5px; - - li.color { - min-height: 22px; - padding: 3px 0 3px 0; - text-align: left; - font-size: 12px; - line-height: 13px; - color: @legend-item-color; - cursor: default; - text-align: left; - white-space: nowrap; - overflow-x: hidden; - text-overflow: ellipsis; - max-width: 150px; - - .dots { - padding-right: 5px; - cursor: pointer; - } - } - - .color-selector { - width: 80px; - } } .legend-ul.hidden { From 28c895052abb5ac48f8b884f4c2d80a3944e0f0b Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 2 Dec 2015 10:18:11 -0700 Subject: [PATCH 03/16] Remove relabeling of legend when only 1 series exists --- src/ui/public/vislib/lib/legend.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index 4fc4cd6de7611..5539d1d66a311 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -50,17 +50,8 @@ define(function (require) { }; Legend.prototype._getSeriesLabels = function (data) { - var isOneSeries = data.every(function (chart) { - return chart.series.length === 1; - }); - var values = data.map(function (chart) { - var yLabel = isOneSeries ? chart.yAxisLabel : undefined; - - return chart.series.map(function (series) { - if (yLabel) series.label = yLabel; - return series; - }); + return chart.series; }) .reduce(function (a, b) { return a.concat(b); From 20b6d749f88373d86f7e551921d79b810664fb15 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 2 Dec 2015 17:20:46 -0800 Subject: [PATCH 04/16] Persist legend state, add filter buttons to legend item details --- .../filter_bar/filter_bar_click_handler.js | 7 +++++ .../components/legend_value/legend_value.html | 21 +++++++++----- .../components/legend_value/legend_value.js | 12 +++++++- .../components/legend_value/legend_value.less | 19 +++++------- src/ui/public/vislib/lib/legend.js | 29 +++++++------------ .../public/vislib/partials/legend_header.html | 4 +-- src/ui/public/vislib/styles/_legend.less | 27 +++++++++-------- src/ui/public/visualize/visualize.less | 1 - 8 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/ui/public/filter_bar/filter_bar_click_handler.js b/src/ui/public/filter_bar/filter_bar_click_handler.js index 6a5c7bbf18854..f0442d9542b29 100644 --- a/src/ui/public/filter_bar/filter_bar_click_handler.js +++ b/src/ui/public/filter_bar/filter_bar_click_handler.js @@ -58,6 +58,13 @@ define(function (require) { if (!filters.length) return; + if (event.negate) { + _.each(filters, function (filter) { + filter.meta = filter.meta || {}; + filter.meta.negate = true; + }); + } + filters = dedupFilters($state.filters, uniqFilters(filters)); // We need to add a bunch of filter deduping here. $state.$newFilters = filters; diff --git a/src/ui/public/vislib/components/legend_value/legend_value.html b/src/ui/public/vislib/components/legend_value/legend_value.html index b26ea03277f06..feccc362d3758 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.html +++ b/src/ui/public/vislib/components/legend_value/legend_value.html @@ -1,17 +1,22 @@ -
    -
    +
    +
    {{legendData.label}}
    + +
    -
    - -

    - {{legendData.label}} -

    + +
    + + +
    +
    -

    1 ? true : false; var $scope = _.extend($rootScope.$new(), { + hasFilter: hasFilter, visEl: self.el, color: args.color(d.label), legendData: d, @@ -133,26 +131,21 @@ define(function (require) { this._header(legendDiv, this); this._list(legendDiv, items, this); - var headerIcon = visEl.select('.legend-toggle'); + var headerIcon = visEl.select('.header'); + //var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); + //visEl.select('ul.legend-ul').classed('hidden', !legendOpen); + + //self.vis.set('legendOpen', false); // toggle legend open and closed headerIcon .on('click', function legendClick() { - var legendOpen = !self.vis.get('legendOpen'); - self.vis.set('legendOpen', legendOpen); + var legendOpen = !self.vis.uiState.get('legendOpen'); + self.vis.uiState.set('legendOpen', legendOpen); visEl.select('ul.legend-ul').classed('hidden', legendOpen); self.vis.resize(); }); - - legendDiv.selectAll('li.color').each(function (d) { - var label = d.label; - /* - if (label !== undefined && label !== 'Count') { - d3.select(this).call(self.events.addClickEvent()); - } - */ - }); }; return Legend; diff --git a/src/ui/public/vislib/partials/legend_header.html b/src/ui/public/vislib/partials/legend_header.html index 7c909bcee9920..c8e1ddc10d802 100644 --- a/src/ui/public/vislib/partials/legend_header.html +++ b/src/ui/public/vislib/partials/legend_header.html @@ -1,8 +1,8 @@

    <%= (isOpen) ? - 'Legend ' : - '' + '' : + '' %>
    \ No newline at end of file diff --git a/src/ui/public/vislib/styles/_legend.less b/src/ui/public/vislib/styles/_legend.less index 47b35756c15a4..a1519685314ca 100644 --- a/src/ui/public/vislib/styles/_legend.less +++ b/src/ui/public/vislib/styles/_legend.less @@ -3,23 +3,27 @@ .legend-col-wrapper { .flex-parent(0, 0, auto); + flex-direction: row; z-index: 10; min-height: 0; - .legend-toggle { + .header { + border-right: 1px solid @sidebar-bg; cursor: pointer; - opacity: 0.75; - white-space: nowrap; - font-size: 0.9em; + width: 15px; + } - .legend-open { - margin-right: 20px; - } + .legend-toggle { - .legend-closed { - font-size: 1.5em; - padding-left: 5px; + &:hover { + color: @sidebar-hover-color; + background-color: @sidebar-hover-bg; } + + background-color: @sidebar-bg; + font-size: 10px; + padding: 8px 3px; + border-bottom-left-radius: @border-radius-small; } .column-labels { @@ -27,7 +31,7 @@ } .legend-ul { - width: 150px; + width: 135px; flex: 1 1 1px; overflow-x: hidden; overflow-y: auto; @@ -40,7 +44,6 @@ font-size: 12px; line-height: 13px; text-align: left; - margin-right: 5px; } .legend-ul.hidden { diff --git a/src/ui/public/visualize/visualize.less b/src/ui/public/visualize/visualize.less index 6290045efcdcc..72ba44b04fd50 100644 --- a/src/ui/public/visualize/visualize.less +++ b/src/ui/public/visualize/visualize.less @@ -19,7 +19,6 @@ visualize { transition: opacity 0.01s; &.spy-visible { - margin-bottom: 10px; height: 0px; } From afa135fcc8618e297ffa3cb3552d3534997a55ce Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 4 Dec 2015 09:42:10 -0800 Subject: [PATCH 05/16] fix legend closed by default --- .../components/legend_value/legend_value.html | 10 ++++------ .../components/legend_value/legend_value.js | 1 + src/ui/public/vislib/lib/legend.js | 20 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/ui/public/vislib/components/legend_value/legend_value.html b/src/ui/public/vislib/components/legend_value/legend_value.html index feccc362d3758..e264c2c5635af 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.html +++ b/src/ui/public/vislib/components/legend_value/legend_value.html @@ -17,12 +17,10 @@
    -

    - - -

    + +
    \ No newline at end of file diff --git a/src/ui/public/vislib/components/legend_value/legend_value.js b/src/ui/public/vislib/components/legend_value/legend_value.js index ecdb02e739b3f..5422cbfe2d93e 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.js +++ b/src/ui/public/vislib/components/legend_value/legend_value.js @@ -1,6 +1,7 @@ define(function (require) { var _ = require('lodash'); var html = require('ui/vislib/components/legend_value/legend_value.html'); + var $ = require('jquery'); var d3 = require('d3'); diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index da43cb5373399..5af08b88521e4 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -72,12 +72,14 @@ define(function (require) { */ Legend.prototype._header = function (el, args) { var self = this; + var legendOpen = self.vis.uiState.get('legendOpen'); + if (legendOpen == null) legendOpen = true; return el.append('div') .attr('class', 'header') .append('div') .attr('class', 'column-labels') .html(function () { - return legendHeaderTemplate({ isOpen: self.vis.uiState.get('legendOpen') }); + return legendHeaderTemplate({ isOpen: legendOpen }); }); }; @@ -105,9 +107,7 @@ define(function (require) { .append('li') .classed('legend-value', true) .each(function (d) { - var hasFilter = data.length > 1 ? true : false; var $scope = _.extend($rootScope.$new(), { - hasFilter: hasFilter, visEl: self.el, color: args.color(d.label), legendData: d, @@ -132,18 +132,20 @@ define(function (require) { this._list(legendDiv, items, this); var headerIcon = visEl.select('.header'); - //var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); - //visEl.select('ul.legend-ul').classed('hidden', !legendOpen); + var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); + if (legendOpen == null) legendOpen = true; - //self.vis.set('legendOpen', false); + visEl.select('ul.legend-ul').classed('hidden', !legendOpen); // toggle legend open and closed headerIcon .on('click', function legendClick() { - var legendOpen = !self.vis.uiState.get('legendOpen'); - self.vis.uiState.set('legendOpen', legendOpen); + var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); + legendOpen = (legendOpen == null || legendOpen) ? false : true; + - visEl.select('ul.legend-ul').classed('hidden', legendOpen); + self.vis.uiState.set('legendOpen', legendOpen); + visEl.select('ul.legend-ul').classed('hidden', !legendOpen); self.vis.resize(); }); }; From c79b00c8d1aa4782f311fa39f526dd88679a8179 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 4 Dec 2015 09:48:03 -0800 Subject: [PATCH 06/16] Fix legend hover with series hover --- src/ui/public/vislib/lib/legend.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index 5af08b88521e4..14a023e205c8b 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -105,6 +105,7 @@ define(function (require) { .data(data) .enter() .append('li') + .classed('color', true) .classed('legend-value', true) .each(function (d) { var $scope = _.extend($rootScope.$new(), { From a7e35d9adf75b6f820650407e2db273a8b3533ba Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 4 Dec 2015 10:41:43 -0800 Subject: [PATCH 07/16] Destroy angular scopes --- .../public/vislib/components/legend_value/legend_value.js | 5 +++++ src/ui/public/vislib/lib/legend.js | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ui/public/vislib/components/legend_value/legend_value.js b/src/ui/public/vislib/components/legend_value/legend_value.js index 5422cbfe2d93e..3a0721412a9cd 100644 --- a/src/ui/public/vislib/components/legend_value/legend_value.js +++ b/src/ui/public/vislib/components/legend_value/legend_value.js @@ -17,6 +17,11 @@ define(function (require) { var $state = getAppState(); var clickHandler = filterBarClickHandler($state); + $scope.$on('$destroy', function () { + $elem.off('mouseover'); + $elem.off('mouseout'); + }); + $elem.on('mouseover', function () { $('[data-label]', $scope.visEl).not('[data-label="' + $scope.legendData.label + '"]').css('opacity', 0.5); }); diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js index 14a023e205c8b..6dbf1c6719abc 100644 --- a/src/ui/public/vislib/lib/legend.js +++ b/src/ui/public/vislib/lib/legend.js @@ -29,6 +29,7 @@ define(function (require) { var labels = this.labels = this._getLabels(data, type); var labelsArray = labels.map(function (obj) { return obj.label; }); + this.legendScope = $rootScope.$new(); this.events = new Dispatch(); this.vis = vis; this.el = vis.el; @@ -62,6 +63,10 @@ define(function (require) { return this._getSeriesLabels(data); }; + Legend.prototype.destroy = function () { + this.legendScope.$destroy(); + }; + /** * Adds legend header * @@ -108,7 +113,7 @@ define(function (require) { .classed('color', true) .classed('legend-value', true) .each(function (d) { - var $scope = _.extend($rootScope.$new(), { + var $scope = _.extend(self.legendScope.$new(), { visEl: self.el, color: args.color(d.label), legendData: d, From 9752d18b0a54c3e751db06dfb6a65d4f178700dd Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Sun, 6 Dec 2015 21:34:14 -0700 Subject: [PATCH 08/16] Angularize the entire legend --- .../public/controls/vislib_basic_options.html | 6 - .../visualize/editor/styles/_editor.less | 1 + .../filter_bar/filter_bar_click_handler.js | 20 +-- src/ui/public/utils/find_by_param.js | 13 ++ src/ui/public/vislib/__tests__/lib/legend.js | 129 -------------- .../components/legend_value/legend_value.html | 26 --- .../components/legend_value/legend_value.js | 57 ------- .../components/legend_value/legend_value.less | 47 ----- src/ui/public/vislib/lib/dispatch.js | 15 +- src/ui/public/vislib/lib/handler/handler.js | 12 -- src/ui/public/vislib/lib/handler/types/pie.js | 2 - .../vislib/lib/handler/types/point_series.js | 2 - .../vislib/lib/layout/types/column_layout.js | 2 + src/ui/public/vislib/lib/legend.js | 161 ------------------ src/ui/public/vislib/styles/_legend.less | 70 +++++++- src/ui/public/visualize/visualize.html | 11 +- src/ui/public/visualize/visualize.js | 22 +-- src/ui/public/visualize/visualize.less | 12 +- src/ui/public/visualize/visualize_legend.html | 41 +++++ src/ui/public/visualize/visualize_legend.js | 102 +++++++++++ 20 files changed, 259 insertions(+), 492 deletions(-) create mode 100644 src/ui/public/utils/find_by_param.js delete mode 100644 src/ui/public/vislib/__tests__/lib/legend.js delete mode 100644 src/ui/public/vislib/components/legend_value/legend_value.html delete mode 100644 src/ui/public/vislib/components/legend_value/legend_value.js delete mode 100644 src/ui/public/vislib/components/legend_value/legend_value.less delete mode 100644 src/ui/public/vislib/lib/legend.js create mode 100644 src/ui/public/visualize/visualize_legend.html create mode 100644 src/ui/public/visualize/visualize_legend.js diff --git a/src/plugins/kbn_vislib_vis_types/public/controls/vislib_basic_options.html b/src/plugins/kbn_vislib_vis_types/public/controls/vislib_basic_options.html index 5a694765f77e5..cfc12aae2631f 100644 --- a/src/plugins/kbn_vislib_vis_types/public/controls/vislib_basic_options.html +++ b/src/plugins/kbn_vislib_vis_types/public/controls/vislib_basic_options.html @@ -5,10 +5,4 @@ Show Tooltip
    -
    - -
    diff --git a/src/plugins/kibana/public/visualize/editor/styles/_editor.less b/src/plugins/kibana/public/visualize/editor/styles/_editor.less index d7a988196a33a..be9c5cb6303c4 100644 --- a/src/plugins/kibana/public/visualize/editor/styles/_editor.less +++ b/src/plugins/kibana/public/visualize/editor/styles/_editor.less @@ -56,6 +56,7 @@ } &-content { + height: 1px; .flex-parent(); // overrides for tablet and desktop diff --git a/src/ui/public/filter_bar/filter_bar_click_handler.js b/src/ui/public/filter_bar/filter_bar_click_handler.js index f0442d9542b29..59844f9207bf7 100644 --- a/src/ui/public/filter_bar/filter_bar_click_handler.js +++ b/src/ui/public/filter_bar/filter_bar_click_handler.js @@ -2,21 +2,11 @@ define(function (require) { var _ = require('lodash'); var dedupFilters = require('./lib/dedupFilters'); var uniqFilters = require('./lib/uniqFilters'); - - // given an object or array of objects, return the value of the passed param - // if the param is missing, return undefined - function findByParam(values, param) { - if (_.isArray(values)) { // point series chart - var index = _.findIndex(values, param); - if (index === -1) return; - return values[index][param]; - } - return values[param]; // pie chart - } + var findByParam = require('ui/utils/find_by_param'); return function (Notifier) { return function ($state) { - return function (event) { + return function (event, simulate) { var notify = new Notifier({ location: 'Filter bar' }); @@ -67,7 +57,11 @@ define(function (require) { filters = dedupFilters($state.filters, uniqFilters(filters)); // We need to add a bunch of filter deduping here. - $state.$newFilters = filters; + if (!simulate) { + $state.$newFilters = filters; + } + + return filters; } }; }; diff --git a/src/ui/public/utils/find_by_param.js b/src/ui/public/utils/find_by_param.js new file mode 100644 index 0000000000000..c22a5c6ed00f7 --- /dev/null +++ b/src/ui/public/utils/find_by_param.js @@ -0,0 +1,13 @@ +define(function (require) { + var _ = require('lodash'); + // given an object or array of objects, return the value of the passed param + // if the param is missing, return undefined + return function findByParam(values, param) { + if (_.isArray(values)) { // point series chart + var index = _.findIndex(values, param); + if (index === -1) return; + return values[index][param]; + } + return values[param]; // pie chart + }; +}); \ No newline at end of file diff --git a/src/ui/public/vislib/__tests__/lib/legend.js b/src/ui/public/vislib/__tests__/lib/legend.js deleted file mode 100644 index 2d80681dde185..0000000000000 --- a/src/ui/public/vislib/__tests__/lib/legend.js +++ /dev/null @@ -1,129 +0,0 @@ -var d3 = require('d3'); -var angular = require('angular'); -var _ = require('lodash'); -var $ = require('jquery'); -var ngMock = require('ngMock'); -var expect = require('expect.js'); - -var slices = require('fixtures/vislib/mock_data/histogram/_slices'); -var stackedSeries = require('fixtures/vislib/mock_data/date_histogram/_stacked_series'); -var histogramSlices = require('fixtures/vislib/mock_data/histogram/_slices'); - -var dataArray = [ - stackedSeries, - slices, - histogramSlices, - stackedSeries, - stackedSeries -]; - -var chartTypes = [ - 'histogram', - 'pie', - 'pie', - 'area', - 'line' -]; - -var chartSelectors = { - histogram: '.chart rect', - pie: '.chart path', - area: '.chart path', - line: '.chart circle' -}; - -describe('Vislib Legend Class', function () { - dataArray.forEach(function (data, i) { - describe(chartTypes[i] + ' data', function () { - var visLibParams = { - type: chartTypes[i], - addLegend: true - }; - var Legend; - var vis; - var persistedState; - var $el; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - vis = Private(require('fixtures/vislib/_vis_fixture'))(visLibParams); - persistedState = new (Private(require('ui/persisted_state/persisted_state')))(); - Legend = Private(require('ui/vislib/lib/legend')); - $el = d3.select('body').append('div').attr('class', 'fake-legend'); - vis.render(data, persistedState); - })); - - afterEach(function () { - $(vis.el).remove(); - $('.fake-legend').remove(); - vis = null; - }); - - describe('legend item label matches vis item label', function () { - it('should match the slice label', function () { - var chartType = chartTypes[i]; - var paths = $(vis.el).find(chartSelectors[chartType]).toArray(); - var items = vis.handler.legend.labels; - - items.forEach(function (d) { - var path = _.find(paths, function (path) { - return path.getAttribute('data-label') === String(d.label); - }); - - expect(path).to.be.ok(); - }); - }); - }); - - describe('header method', function () { - it('should append the legend header', function () { - expect($(vis.el).find('.header').length).to.be(1); - expect($(vis.el).find('.column-labels').length).to.be(1); - }); - }); - - describe('list method', function () { - it('should append the legend list', function () { - expect($(vis.el).find('.legend-ul').length).to.be(1); - }); - - it('should contain a list of items', function () { - expect($(vis.el).find('li').length).to.be.greaterThan(1); - }); - - it('should not return an undefined value', function () { - var emptyObject = { - label: '' - }; - var labels = [emptyObject, emptyObject, emptyObject]; - var args = { - _attr: {isOpen: true}, - color: function () { return 'blue'; } - }; - - Legend.prototype._list($el, labels, args); - - $el.selectAll('li').each(function (d) { - expect(d.label).not.to.be(undefined); - }); - }); - }); - - describe('render method', function () { - it('should create a legend toggle', function () { - expect($('.legend-toggle').length).to.be(1); - }); - - it('should have an onclick listener', function () { - expect(!!$('.legend-toggle')[0].__onclick).to.be(true); - expect(!!$('li.color')[0].__onclick).to.be(true); - }); - - it('should attach onmouseover listener', function () { - expect(!!$('li.color')[0].__onmouseover).to.be(true); - }); - }); - }); - }); -}); - diff --git a/src/ui/public/vislib/components/legend_value/legend_value.html b/src/ui/public/vislib/components/legend_value/legend_value.html deleted file mode 100644 index e264c2c5635af..0000000000000 --- a/src/ui/public/vislib/components/legend_value/legend_value.html +++ /dev/null @@ -1,26 +0,0 @@ -
    -
    - {{legendData.label}} -
    - - -
    - -
    - - - -
    - - -
    - - -
    -
    -
    \ No newline at end of file diff --git a/src/ui/public/vislib/components/legend_value/legend_value.js b/src/ui/public/vislib/components/legend_value/legend_value.js deleted file mode 100644 index 3a0721412a9cd..0000000000000 --- a/src/ui/public/vislib/components/legend_value/legend_value.js +++ /dev/null @@ -1,57 +0,0 @@ -define(function (require) { - var _ = require('lodash'); - var html = require('ui/vislib/components/legend_value/legend_value.html'); - - var $ = require('jquery'); - var d3 = require('d3'); - - require('ui/modules').get('kibana') - .directive('legendValue', function (Private, getAppState) { - var filterBarClickHandler = Private(require('ui/filter_bar/filter_bar_click_handler')); - - return { - restrict: 'C', - template: html, - link: function ($scope, $elem) { - - var $state = getAppState(); - var clickHandler = filterBarClickHandler($state); - - $scope.$on('$destroy', function () { - $elem.off('mouseover'); - $elem.off('mouseout'); - }); - - $elem.on('mouseover', function () { - $('[data-label]', $scope.visEl).not('[data-label="' + $scope.legendData.label + '"]').css('opacity', 0.5); - }); - - $elem.on('mouseout', function () { - $('[data-label]', $scope.visEl).css('opacity', 1); - }); - - $scope.setColor = function (color) { - var colors = $scope.uiState.get('vis.colors') || {}; - colors[$scope.legendData.label] = color; - $scope.uiState.set('vis.colors', colors); - }; - - $scope.filter = function (negate) { - clickHandler({point: $scope.legendData, negate: negate}); - }; - - $scope.colors = [ - '#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6 - '#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2 - '#629E51', '#E5AC0E', '#64B0C8', '#E0752D', '#BF1B00', '#0A50A1', '#962D82', '#614D93', //4 - '#7EB26D', '#EAB839', '#6ED0E0', '#EF843C', '#E24D42', '#1F78C1', '#BA43A9', '#705DA0', // Normal - '#9AC48A', '#F2C96D', '#65C5DB', '#F9934E', '#EA6460', '#5195CE', '#D683CE', '#806EB7', //5 - '#B7DBAB', '#F4D598', '#70DBED', '#F9BA8F', '#F29191', '#82B5D8', '#E5A8E2', '#AEA2E0', //3 - '#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7 - ]; - - - } - }; - }); -}); diff --git a/src/ui/public/vislib/components/legend_value/legend_value.less b/src/ui/public/vislib/components/legend_value/legend_value.less deleted file mode 100644 index 835dcbdf55025..0000000000000 --- a/src/ui/public/vislib/components/legend_value/legend_value.less +++ /dev/null @@ -1,47 +0,0 @@ -@import (reference) "~ui/styles/variables"; - -.legend-value { - &-title { - padding: 3px; - - &:hover { - background-color: @sidebar-hover-bg; - } - } - - &-truncate { - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - &-full { - white-space: normal; - word-break: break-all; - background-color: @sidebar-bg; - } - - &-details { - padding: 5px 0px; - margin-left: 3px; - border-bottom: 1px solid @sidebar-bg; - } - - &-color-picker { - .dot { - line-height: 14px; - margin: 2px; - font-size: 14px; - } - - .dot:hover { - margin: 0px; - font-size: 18px - } - } -} - -.legend-value:hover { - cursor: pointer; -} - diff --git a/src/ui/public/vislib/lib/dispatch.js b/src/ui/public/vislib/lib/dispatch.js index fb13291d038d7..68de13d3f46f9 100644 --- a/src/ui/public/vislib/lib/dispatch.js +++ b/src/ui/public/vislib/lib/dispatch.js @@ -226,16 +226,8 @@ define(function (require) { */ Dispatch.prototype.highlightLegend = function (element) { var label = this.getAttribute('data-label'); - if (!label) return; - - d3.select(element) - .select('.legend-ul') - .selectAll('li.color') - .filter(function (d, i) { - return String(d.label) !== label; - }) - .classed('blur_shape', true); + $('[data-label]', element.parentNode).not('[data-label="' + label + '"]').css('opacity', 0.5); }; /** @@ -245,10 +237,7 @@ define(function (require) { * @method unHighlightLegend */ Dispatch.prototype.unHighlightLegend = function (element) { - d3.select(element) - .select('.legend-ul') - .selectAll('li.color') - .classed('blur_shape', false); + $('[data-label]', element.parentNode).css('opacity', 1); }; /** diff --git a/src/ui/public/vislib/lib/handler/handler.js b/src/ui/public/vislib/lib/handler/handler.js index 9892268db9019..8b7ba300bdbcd 100644 --- a/src/ui/public/vislib/lib/handler/handler.js +++ b/src/ui/public/vislib/lib/handler/handler.js @@ -7,7 +7,6 @@ define(function (require) { var Data = Private(require('ui/vislib/lib/data')); var Layout = Private(require('ui/vislib/lib/layout/layout')); - var Legend = Private(require('ui/vislib/lib/legend')); /** * Handles building all the components of the visualization @@ -39,15 +38,10 @@ define(function (require) { this.axisTitle = opts.axisTitle; this.alerts = opts.alerts; - if (this._attr.addLegend) { - this.legend = opts.legend; - } - this.layout = new Layout(vis.el, vis.data, vis._attr.type, opts); this.binder = new Binder(); this.renderArray = _.filter([ this.layout, - this.legend, this.axisTitle, this.chartTitle, this.alerts, @@ -96,12 +90,6 @@ define(function (require) { this._validateData(); this.renderArray.forEach(function (property) { - if (property instanceof Legend) { - self.vis.activeEvents().forEach(function (event) { - self.enable(event, property); - }); - } - if (typeof property.render === 'function') { property.render(); } diff --git a/src/ui/public/vislib/lib/handler/types/pie.js b/src/ui/public/vislib/lib/handler/types/pie.js index 33a29c81257c4..09f8d9cc6c65f 100644 --- a/src/ui/public/vislib/lib/handler/types/pie.js +++ b/src/ui/public/vislib/lib/handler/types/pie.js @@ -2,7 +2,6 @@ define(function (require) { return function PieHandler(Private) { var Handler = Private(require('ui/vislib/lib/handler/handler')); var Data = Private(require('ui/vislib/lib/data')); - var Legend = Private(require('ui/vislib/lib/legend')); var ChartTitle = Private(require('ui/vislib/lib/chart_title')); /* @@ -11,7 +10,6 @@ define(function (require) { return function (vis) { return new Handler(vis, { - legend: new Legend(vis), chartTitle: new ChartTitle(vis.el) }); }; diff --git a/src/ui/public/vislib/lib/handler/types/point_series.js b/src/ui/public/vislib/lib/handler/types/point_series.js index ff3fb08a3b911..69c345ccaefb3 100644 --- a/src/ui/public/vislib/lib/handler/types/point_series.js +++ b/src/ui/public/vislib/lib/handler/types/point_series.js @@ -3,7 +3,6 @@ define(function (require) { var injectZeros = Private(require('ui/vislib/components/zero_injection/inject_zeros')); var Handler = Private(require('ui/vislib/lib/handler/handler')); var Data = Private(require('ui/vislib/lib/data')); - var Legend = Private(require('ui/vislib/lib/legend')); var XAxis = Private(require('ui/vislib/lib/x_axis')); var YAxis = Private(require('ui/vislib/lib/y_axis')); var AxisTitle = Private(require('ui/vislib/lib/axis_title')); @@ -29,7 +28,6 @@ define(function (require) { return new Handler(vis, { data: data, - legend: new Legend(vis, vis.data), axisTitle: new AxisTitle(vis.el, data.get('xAxisLabel'), data.get('yAxisLabel')), chartTitle: new ChartTitle(vis.el), xAxis: new XAxis({ diff --git a/src/ui/public/vislib/lib/layout/types/column_layout.js b/src/ui/public/vislib/lib/layout/types/column_layout.js index 0dfea45abfc28..c777fe301084f 100644 --- a/src/ui/public/vislib/lib/layout/types/column_layout.js +++ b/src/ui/public/vislib/lib/layout/types/column_layout.js @@ -101,10 +101,12 @@ define(function (require) { } ] }, + /* { type: 'div', class: 'legend-col-wrapper' } + */ ] } ]; diff --git a/src/ui/public/vislib/lib/legend.js b/src/ui/public/vislib/lib/legend.js deleted file mode 100644 index 6dbf1c6719abc..0000000000000 --- a/src/ui/public/vislib/lib/legend.js +++ /dev/null @@ -1,161 +0,0 @@ -define(function (require) { - require('ui/vislib/components/legend_value/legend_value.js'); - require('ui/vislib/components/legend_value/legend_value.less'); - - return function LegendFactory(Private, $rootScope, $compile) { - var d3 = require('d3'); - var $ = require('jquery'); - var _ = require('lodash'); - var Dispatch = Private(require('ui/vislib/lib/dispatch')); - var Data = Private(require('ui/vislib/lib/data')); - var legendHeaderTemplate = _.template(require('ui/vislib/partials/legend_header.html')); - var dataLabel = require('ui/vislib/lib/_data_label'); - var color = Private(require('ui/vislib/components/color/color')); - - /** - * Appends legend to the visualization - * - * @class Legend - * @constructor - * @param vis {Object} Reference to Vis Constructor - */ - function Legend(vis) { - if (!(this instanceof Legend)) { - return new Legend(vis); - } - - var data = vis.data.columns || vis.data.rows || [vis.data]; - var type = vis._attr.type; - var labels = this.labels = this._getLabels(data, type); - var labelsArray = labels.map(function (obj) { return obj.label; }); - - this.legendScope = $rootScope.$new(); - this.events = new Dispatch(); - this.vis = vis; - this.el = vis.el; - this.color = color(labelsArray, vis.uiState.get('vis.colors')); - this._attr = _.defaults({}, vis._attr || {}, { - 'legendClass' : 'legend-col-wrapper', - 'blurredOpacity' : 0.3, - 'focusOpacity' : 1, - 'defaultOpacity' : 1, - 'legendDefaultOpacity': 1 - }); - } - - Legend.prototype._getPieLabels = function (data) { - return Data.prototype.pieNames(data); - }; - - Legend.prototype._getSeriesLabels = function (data) { - var values = data.map(function (chart) { - return chart.series; - }) - .reduce(function (a, b) { - return a.concat(b); - }, []); - - return _.uniq(values, 'label'); - }; - - Legend.prototype._getLabels = function (data, type) { - if (type === 'pie') return this._getPieLabels(data); - return this._getSeriesLabels(data); - }; - - Legend.prototype.destroy = function () { - this.legendScope.$destroy(); - }; - - /** - * Adds legend header - * - * @method header - * @param el {HTMLElement} Reference to DOM element - * @param args {Object|*} Legend options - * @returns {*} HTML element - */ - Legend.prototype._header = function (el, args) { - var self = this; - var legendOpen = self.vis.uiState.get('legendOpen'); - if (legendOpen == null) legendOpen = true; - return el.append('div') - .attr('class', 'header') - .append('div') - .attr('class', 'column-labels') - .html(function () { - return legendHeaderTemplate({ isOpen: legendOpen }); - }); - }; - - /** - * Adds list to legend - * - * @method list - * @param el {HTMLElement} Reference to DOM element - * @param arrOfLabels {Array} Array of labels - * @param args {Object|*} Legend options - * @returns {D3.Selection} HTML element with list of labels attached - */ - Legend.prototype._list = function (el, data, args) { - var self = this; - - return el.append('ul') - .attr('class', function () { - var className = 'legend-ul'; - if (self.vis && !self.vis.uiState.get('legendOpen')) className += ' hidden'; - return className; - }) - .selectAll('li') - .data(data) - .enter() - .append('li') - .classed('color', true) - .classed('legend-value', true) - .each(function (d) { - var $scope = _.extend(self.legendScope.$new(), { - visEl: self.el, - color: args.color(d.label), - legendData: d, - uiState: self.vis.uiState - }); - $compile(this)($scope); - }); - }; - - /** - * Renders legend - * - * @method render - * @return {HTMLElement} Legend - */ - Legend.prototype.render = function () { - var self = this; - var visEl = d3.select(this.el); - var legendDiv = visEl.select('.' + this._attr.legendClass); - var items = this.labels; - this._header(legendDiv, this); - this._list(legendDiv, items, this); - - var headerIcon = visEl.select('.header'); - var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); - if (legendOpen == null) legendOpen = true; - - visEl.select('ul.legend-ul').classed('hidden', !legendOpen); - - // toggle legend open and closed - headerIcon - .on('click', function legendClick() { - var legendOpen = self.vis.uiState.get('legendOpen', legendOpen); - legendOpen = (legendOpen == null || legendOpen) ? false : true; - - - self.vis.uiState.set('legendOpen', legendOpen); - visEl.select('ul.legend-ul').classed('hidden', !legendOpen); - self.vis.resize(); - }); - }; - - return Legend; - }; -}); diff --git a/src/ui/public/vislib/styles/_legend.less b/src/ui/public/vislib/styles/_legend.less index a1519685314ca..2b2ae6ac0d738 100644 --- a/src/ui/public/vislib/styles/_legend.less +++ b/src/ui/public/vislib/styles/_legend.less @@ -1,6 +1,11 @@ @import "~ui/styles/mixins"; @import "~ui/styles/variables"; +visualize-legend { + display: flex; + flex-direction: row; +} + .legend-col-wrapper { .flex-parent(0, 0, auto); flex-direction: row; @@ -8,13 +13,11 @@ min-height: 0; .header { - border-right: 1px solid @sidebar-bg; cursor: pointer; width: 15px; } .legend-toggle { - &:hover { color: @sidebar-hover-color; background-color: @sidebar-hover-bg; @@ -22,6 +25,7 @@ background-color: @sidebar-bg; font-size: 10px; + height: 30px; padding: 8px 3px; border-bottom-left-radius: @border-radius-small; } @@ -31,25 +35,83 @@ } .legend-ul { + border-left: 1px solid @sidebar-bg; width: 135px; flex: 1 1 1px; overflow-x: hidden; overflow-y: auto; color: @legend-item-color; - list-style-type: none; padding: 0; + margin-bottom: 0; visibility: visible; min-height: 0; font-size: 12px; line-height: 13px; text-align: left; + + display: flex; + flex-direction: column; } .legend-ul.hidden { visibility: hidden; } +} - .legend-toggle { +.legend-value { + &-title { + padding: 3px; + + &:hover { + background-color: @sidebar-hover-bg; + } + } + + &-truncate { + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + &-full { + white-space: normal; + word-break: break-all; + background-color: @sidebar-bg; + } + + &-details { + border-bottom: 1px solid @sidebar-bg; + + .filter-button { + display: block; + float: left; + width: 50%; + border-radius: 0px; + background-color: @sidebar-bg; + + &:hover { + background-color: @sidebar-hover-bg; + } + } + } + + &-color-picker { + .dot { + line-height: 14px; + margin: 2px; + font-size: 14px; + } + + .dot:hover { + margin: 0px; + font-size: 18px + } } } + +.legend-value:hover { + cursor: pointer; +} + + diff --git a/src/ui/public/visualize/visualize.html b/src/ui/public/visualize/visualize.html index 6b105e5c8fab9..9a307ead8e583 100644 --- a/src/ui/public/visualize/visualize.html +++ b/src/ui/public/visualize/visualize.html @@ -7,9 +7,12 @@

    No results found

    -
    +
    +
    + +
    diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js index fa4dffe04cb88..89ed633d4df6b 100644 --- a/src/ui/public/visualize/visualize.js +++ b/src/ui/public/visualize/visualize.js @@ -1,10 +1,12 @@ define(function (require) { require('ui/modules') .get('kibana/directive') - .directive('visualize', function (Notifier, SavedVis, indexPatterns, Private, config) { + .directive('visualize', function (Notifier, SavedVis, indexPatterns, Private, config, $timeout) { require('ui/visualize/spy'); require('ui/visualize/visualize.less'); + require('ui/visualize/visualize_legend'); + var $ = require('jquery'); var _ = require('lodash'); var visTypes = Private(require('ui/registry/vis_types')); @@ -40,6 +42,7 @@ define(function (require) { } var getVisEl = getter('.visualize-chart'); + var getVisContainer = getter('.vis-container'); var getSpyEl = getter('visualize-spy'); $scope.fullScreenSpy = false; @@ -47,19 +50,16 @@ define(function (require) { $scope.spy.mode = ($scope.uiState) ? $scope.uiState.get('spy.mode', {}) : {}; var applyClassNames = function () { - var $spyEl = getSpyEl(); - var $visEl = getVisEl(); + var $visEl = getVisContainer(); var fullSpy = ($scope.spy.mode && ($scope.spy.mode.fill || $scope.fullScreenSpy)); - // external - $el.toggleClass('only-visualization', !$scope.spy.mode); - $el.toggleClass('visualization-and-spy', $scope.spy.mode && !fullSpy); - $el.toggleClass('only-spy', Boolean(fullSpy)); - if ($spyEl) $spyEl.toggleClass('only', Boolean(fullSpy)); - - // internal - $visEl.toggleClass('spy-visible', Boolean($scope.spy.mode)); $visEl.toggleClass('spy-only', Boolean(fullSpy)); + + $timeout(function () { + if ($visEl.height() < 100) { + $visEl.addClass('spy-only'); + }; + }, 0); }; // we need to wait for some watchers to fire at least once diff --git a/src/ui/public/visualize/visualize.less b/src/ui/public/visualize/visualize.less index 72ba44b04fd50..6879cf173d088 100644 --- a/src/ui/public/visualize/visualize.less +++ b/src/ui/public/visualize/visualize.less @@ -12,19 +12,20 @@ visualize { white-space: pre-line; } - .visualize-chart { + .vis-container { + height: 1px; + display: flex; + flex-direction: row; + flex: 1 1 auto; overflow: auto; -webkit-transition: opacity 0.01s; transition: opacity 0.01s; - &.spy-visible { - height: 0px; - } - &.spy-only { display: none; } + } .loading { @@ -180,3 +181,4 @@ visualize-spy { white-space: pre-wrap; } } + diff --git a/src/ui/public/visualize/visualize_legend.html b/src/ui/public/visualize/visualize_legend.html new file mode 100644 index 0000000000000..9b26e703a37cf --- /dev/null +++ b/src/ui/public/visualize/visualize_legend.html @@ -0,0 +1,41 @@ +
    +
    + +
    +
      + +
    • + +
      +
      + {{legendData.label}} +
      + + +
      +
      + + +
      + +
      + + +
      +
      +
      + +
    • +
    +
    \ No newline at end of file diff --git a/src/ui/public/visualize/visualize_legend.js b/src/ui/public/visualize/visualize_legend.js new file mode 100644 index 0000000000000..30a94c34d98ca --- /dev/null +++ b/src/ui/public/visualize/visualize_legend.js @@ -0,0 +1,102 @@ +define(function (require) { + var _ = require('lodash'); + var html = require('ui/visualize/visualize_legend.html'); + + var $ = require('jquery'); + var d3 = require('d3'); + var findByParam = require('ui/utils/find_by_param'); + + require('ui/modules').get('kibana') + .directive('visualizeLegend', function (Private, getAppState) { + var Data = Private(require('ui/vislib/lib/data')); + var colorPalette = Private(require('ui/vislib/components/color/color')); + var filterBarClickHandler = Private(require('ui/filter_bar/filter_bar_click_handler')); + + return { + restrict: 'E', + template: html, + link: function ($scope, $elem) { + var $state = getAppState(); + var clickHandler = filterBarClickHandler($state); + $scope.open = $scope.uiState.get('vis.legendOpen', true); + + $scope.$watch('renderbot.chartData', function (data) { + if (!data) return; + $scope.data = data; + refresh(); + }); + + $scope.highlightSeries = function (label) { + $('[data-label]', $elem.siblings()).not('[data-label="' + label + '"]').css('opacity', 0.5); + }; + + $scope.unhighlightSeries = function () { + $('[data-label]', $elem.siblings()).css('opacity', 1); + }; + + $scope.setColor = function (label, color) { + var colors = $scope.uiState.get('vis.colors') || {}; + colors[label] = color; + $scope.uiState.set('vis.colors', colors); + refresh(); + }; + + $scope.toggleLegend = function () { + $scope.open = !$scope.uiState.get('vis.legendOpen', true); + $scope.uiState.set('vis.legendOpen', $scope.open); + }; + + $scope.filter = function (legendData, negate) { + clickHandler({point: legendData, negate: negate}); + }; + + $scope.canFilter = function (legendData) { + var filters = clickHandler({point: legendData}, true) || []; + return filters.length; + //return filters == null ? false : true; + }; + + $scope.colors = [ + '#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6 + '#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2 + '#629E51', '#E5AC0E', '#64B0C8', '#E0752D', '#BF1B00', '#0A50A1', '#962D82', '#614D93', //4 + '#7EB26D', '#EAB839', '#6ED0E0', '#EF843C', '#E24D42', '#1F78C1', '#BA43A9', '#705DA0', // Normal + '#9AC48A', '#F2C96D', '#65C5DB', '#F9934E', '#EA6460', '#5195CE', '#D683CE', '#806EB7', //5 + '#B7DBAB', '#F4D598', '#70DBED', '#F9BA8F', '#F29191', '#82B5D8', '#E5A8E2', '#AEA2E0', //3 + '#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7 + ]; + + function refresh() { + var vislibVis = $scope.renderbot.vislibVis; + + if ($scope.uiState.get('vis.legendOpen') == null && vislibVis._attr.addLegend != null) { + $scope.open = vislibVis._attr.addLegend; + } + + $scope.labels = getLabels($scope.data, vislibVis._attr.type); + $scope.getColor = colorPalette(_.pluck($scope.labels, 'label'), $scope.uiState.get('vis.colors')); + } + + // Most of these functions were moved directly from the old Legend class. Not a fan of this. + function getLabels(data, type) { + if (!data) return []; + var data = data.columns || data.rows || [data]; + if (type === 'pie') return Data.prototype.pieNames(data); + return getSeriesLabels(data); + }; + + function getSeriesLabels(data) { + var values = data.map(function (chart) { + return chart.series; + }) + .reduce(function (a, b) { + return a.concat(b); + }, []); + return _.compact(_.uniq(values, 'label')); + } + + + } + }; + }); +}); From 9d6273b8b3485a79672a45477971beb31bdbd4ec Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Sun, 6 Dec 2015 21:47:13 -0700 Subject: [PATCH 09/16] remove commented out code --- src/ui/public/vislib/lib/layout/types/column_layout.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ui/public/vislib/lib/layout/types/column_layout.js b/src/ui/public/vislib/lib/layout/types/column_layout.js index c777fe301084f..0caa60c5b0299 100644 --- a/src/ui/public/vislib/lib/layout/types/column_layout.js +++ b/src/ui/public/vislib/lib/layout/types/column_layout.js @@ -100,13 +100,7 @@ define(function (require) { ] } ] - }, - /* - { - type: 'div', - class: 'legend-col-wrapper' } - */ ] } ]; From 3220c540fd050fe1be0e645e1b383acd9a516c03 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 7 Dec 2015 08:58:45 -0700 Subject: [PATCH 10/16] Remove legend from layout test, vislib no longer does that --- src/ui/public/vislib/__tests__/lib/layout/layout.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ui/public/vislib/__tests__/lib/layout/layout.js b/src/ui/public/vislib/__tests__/lib/layout/layout.js index 7b07b929c8f33..f10949009c951 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/layout.js +++ b/src/ui/public/vislib/__tests__/lib/layout/layout.js @@ -52,7 +52,6 @@ dateHistogramArray.forEach(function (data, i) { expect($(vis.el).find('.vis-wrapper').length).to.be(1); expect($(vis.el).find('.y-axis-col-wrapper').length).to.be(1); expect($(vis.el).find('.vis-col-wrapper').length).to.be(1); - expect($(vis.el).find('.legend-col-wrapper').length).to.be(1); expect($(vis.el).find('.y-axis-col').length).to.be(1); expect($(vis.el).find('.y-axis-title').length).to.be(1); expect($(vis.el).find('.y-axis-div-wrapper').length).to.be(1); From 510639923e02c4c7fc7cc0508e1c1c84a5edd9a8 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 7 Dec 2015 10:44:36 -0700 Subject: [PATCH 11/16] Fix table tests --- src/fixtures/mock_ui_state.js | 18 ++++++++++++++++++ .../table_vis/public/__tests__/_table_vis.js | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/fixtures/mock_ui_state.js diff --git a/src/fixtures/mock_ui_state.js b/src/fixtures/mock_ui_state.js new file mode 100644 index 0000000000000..d9b72c8770bf2 --- /dev/null +++ b/src/fixtures/mock_ui_state.js @@ -0,0 +1,18 @@ +define(function (require) { + var keys = {}; + return { + get: function (path, def) { + return keys[path] == null ? def : keys[path]; + }, + set: function (path, val) { + keys[path] = val; + return val; + }, + on: function (eventName, callback) { + return; + }, + off: function (eventName) { + return; + } + } +}) \ No newline at end of file diff --git a/src/plugins/table_vis/public/__tests__/_table_vis.js b/src/plugins/table_vis/public/__tests__/_table_vis.js index e2068932f61cc..14790fbe83fd1 100644 --- a/src/plugins/table_vis/public/__tests__/_table_vis.js +++ b/src/plugins/table_vis/public/__tests__/_table_vis.js @@ -30,7 +30,8 @@ describe('Integration', function () { $rootScope.vis = vis; $rootScope.esResponse = esResponse; - $el = $(''); + $rootScope.uiState = require('fixtures/mock_ui_state'); + $el = $(''); $compile($el)($rootScope); $rootScope.$apply(); From 3e45978b3790da1bf3d92772df8e683cff17edb0 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 7 Dec 2015 11:05:49 -0700 Subject: [PATCH 12/16] Remove unused legend_header.html --- src/ui/public/vislib/partials/legend_header.html | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/ui/public/vislib/partials/legend_header.html diff --git a/src/ui/public/vislib/partials/legend_header.html b/src/ui/public/vislib/partials/legend_header.html deleted file mode 100644 index c8e1ddc10d802..0000000000000 --- a/src/ui/public/vislib/partials/legend_header.html +++ /dev/null @@ -1,8 +0,0 @@ -
    - - <%= (isOpen) ? - '' : - '' - %> - -
    \ No newline at end of file From f548e9645621ba8e1128f3e7d34c6c1a13964caa Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 7 Dec 2015 13:04:29 -0700 Subject: [PATCH 13/16] Use noop, 1px thing is not needed --- src/fixtures/mock_ui_state.js | 9 +++------ .../kibana/public/visualize/editor/styles/_editor.less | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/fixtures/mock_ui_state.js b/src/fixtures/mock_ui_state.js index d9b72c8770bf2..b0e794722f794 100644 --- a/src/fixtures/mock_ui_state.js +++ b/src/fixtures/mock_ui_state.js @@ -1,4 +1,5 @@ define(function (require) { + var _ = require('lodash'); var keys = {}; return { get: function (path, def) { @@ -8,11 +9,7 @@ define(function (require) { keys[path] = val; return val; }, - on: function (eventName, callback) { - return; - }, - off: function (eventName) { - return; - } + on: _.noop, + off: _.noop } }) \ No newline at end of file diff --git a/src/plugins/kibana/public/visualize/editor/styles/_editor.less b/src/plugins/kibana/public/visualize/editor/styles/_editor.less index be9c5cb6303c4..d7a988196a33a 100644 --- a/src/plugins/kibana/public/visualize/editor/styles/_editor.less +++ b/src/plugins/kibana/public/visualize/editor/styles/_editor.less @@ -56,7 +56,6 @@ } &-content { - height: 1px; .flex-parent(); // overrides for tablet and desktop From a85cb1d7d997cb574d3e6750df562bb3f049e1c4 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 9 Dec 2015 09:19:34 -0700 Subject: [PATCH 14/16] Fix BWC with addLegend --- src/ui/public/visualize/visualize_legend.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/public/visualize/visualize_legend.js b/src/ui/public/visualize/visualize_legend.js index 30a94c34d98ca..a3c60e9c5f86f 100644 --- a/src/ui/public/visualize/visualize_legend.js +++ b/src/ui/public/visualize/visualize_legend.js @@ -42,7 +42,9 @@ define(function (require) { }; $scope.toggleLegend = function () { - $scope.open = !$scope.uiState.get('vis.legendOpen', true); + var bwcAddLegend = $scope.renderbot.vislibVis._attr.addLegend; + var bwcLegendStateDefault = bwcAddLegend == null ? true : bwcAddLegend; + $scope.open = !$scope.uiState.get('vis.legendOpen', bwcLegendStateDefault); $scope.uiState.set('vis.legendOpen', $scope.open); }; @@ -53,7 +55,6 @@ define(function (require) { $scope.canFilter = function (legendData) { var filters = clickHandler({point: legendData}, true) || []; return filters.length; - //return filters == null ? false : true; }; $scope.colors = [ From b16d5a36914e5615b5fc75dae41a0e55e717ed3c Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 9 Dec 2015 10:03:59 -0700 Subject: [PATCH 15/16] move buttons up --- src/ui/public/vislib/styles/_legend.less | 2 +- src/ui/public/visualize/visualize_legend.html | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ui/public/vislib/styles/_legend.less b/src/ui/public/vislib/styles/_legend.less index 2b2ae6ac0d738..5c20042f49b00 100644 --- a/src/ui/public/vislib/styles/_legend.less +++ b/src/ui/public/vislib/styles/_legend.less @@ -77,7 +77,7 @@ visualize-legend { &-full { white-space: normal; word-break: break-all; - background-color: @sidebar-bg; + background-color: @sidebar-hover-bg; } &-details { diff --git a/src/ui/public/visualize/visualize_legend.html b/src/ui/public/visualize/visualize_legend.html index 9b26e703a37cf..4abb1493e4a97 100644 --- a/src/ui/public/visualize/visualize_legend.html +++ b/src/ui/public/visualize/visualize_legend.html @@ -19,8 +19,12 @@ {{legendData.label}} -
    +
    + + +
    +
    -
    - - -
    From 45a315b3cf1bd7fe99371e0fe7830a9e54f9cc68 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Wed, 9 Dec 2015 10:29:42 -0700 Subject: [PATCH 16/16] Always show the scrollbar, keep the color picker a fixed width --- src/ui/public/vislib/styles/_legend.less | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui/public/vislib/styles/_legend.less b/src/ui/public/vislib/styles/_legend.less index 5c20042f49b00..2422aa7cd5db9 100644 --- a/src/ui/public/vislib/styles/_legend.less +++ b/src/ui/public/vislib/styles/_legend.less @@ -36,10 +36,10 @@ visualize-legend { .legend-ul { border-left: 1px solid @sidebar-bg; - width: 135px; + width: 150px; flex: 1 1 1px; overflow-x: hidden; - overflow-y: auto; + overflow-y: scroll; color: @legend-item-color; list-style-type: none; padding: 0; @@ -97,6 +97,8 @@ visualize-legend { } &-color-picker { + width: 130px; + .dot { line-height: 14px; margin: 2px;