');
$compile($el)($rootScope);
$rootScope.$apply();
+
}
function OneRangeVis(params) {
@@ -89,20 +90,25 @@ describe('Integration', function () {
it('passes the table groups to the kbnAggTableGroup directive', function () {
init(new OneRangeVis(), fixtures.oneRangeBucket);
- const $atg = $el.find('kbn-agg-table-group').first();
- expect($atg.size()).to.be(1);
- expect($atg.attr('group')).to.be('tableGroups');
- expect($atg.isolateScope().group).to.be($atg.scope().tableGroups);
+ $rootScope.$on('renderComplete', () => {
+ const $atg = $el.find('kbn-agg-table-group').first();
+ expect($atg.size()).to.be(1);
+ expect($atg.attr('group')).to.be('tableGroups');
+ expect($atg.isolateScope().group).to.be($atg.scope().tableGroups);
+ });
+
});
it('displays an error if the search had no hits', function () {
init(new OneRangeVis(), { hits: { total: 0, hits: [] } });
- expect($el.find('kbn-agg-table-group').size()).to.be(0);
+ $rootScope.$on('renderComplete', () => {
+ expect($el.find('kbn-agg-table-group').size()).to.be(0);
- const $err = $el.find('.table-vis-error');
- expect($err.size()).to.be(1);
- expect($err.text().trim()).to.be('No results found');
+ const $err = $el.find('.table-vis-error');
+ expect($err.size()).to.be(1);
+ expect($err.text().trim()).to.be('No results found');
+ });
});
it('displays an error if the search hits, but didn\'t create any rows', function () {
@@ -121,10 +127,12 @@ describe('Integration', function () {
init(new ThreeTermVis(visParams), resp);
- expect($el.find('kbn-agg-table-group').size()).to.be(0);
+ $rootScope.$on('renderComplete', () => {
+ expect($el.find('kbn-agg-table-group').size()).to.be(0);
- const $err = $el.find('.table-vis-error');
- expect($err.size()).to.be(1);
- expect($err.text().trim()).to.be('No results found');
+ const $err = $el.find('.table-vis-error');
+ expect($err.size()).to.be(1);
+ expect($err.text().trim()).to.be('No results found');
+ });
});
});
diff --git a/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js b/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js
index bf5dd7c5870978..6f458fa3aa4132 100644
--- a/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js
+++ b/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js
@@ -58,6 +58,7 @@ describe('Controller', function () {
$rootScope.vis = vis;
$rootScope.uiState = new AppState({ uiState: {} }).makeStateful('uiState');
+ $rootScope.renderComplete = () => {};
$rootScope.newScope = function (scope) { $scope = scope; };
$el = $('')
diff --git a/src/core_plugins/tagcloud/public/tag_cloud_controller.js b/src/core_plugins/tagcloud/public/tag_cloud_controller.js
index 0680183696e245..3beea10eb69f51 100644
--- a/src/core_plugins/tagcloud/public/tag_cloud_controller.js
+++ b/src/core_plugins/tagcloud/public/tag_cloud_controller.js
@@ -20,6 +20,7 @@ module.controller('KbnTagCloudController', function ($scope, $element, Private,
const aggConfigResult = new AggConfigResult(aggs[0], false, event, event);
clickHandler({ point: { aggConfigResult: aggConfigResult } });
});
+
tagCloud.on('renderComplete', () => {
const truncatedMessage = containerNode.querySelector('.tagcloud-truncated-message');
@@ -33,13 +34,9 @@ module.controller('KbnTagCloudController', function ($scope, $element, Private,
const bucketName = containerNode.querySelector('.tagcloud-custom-label');
bucketName.innerHTML = `${$scope.vis.aggs[0].makeLabel()} - ${$scope.vis.aggs[1].makeLabel()}`;
-
-
truncatedMessage.style.display = truncated ? 'block' : 'none';
-
const status = tagCloud.getStatus();
-
if (TagCloud.STATUS.COMPLETE === status) {
incompleteMessage.style.display = 'none';
} else if (TagCloud.STATUS.INCOMPLETE === status) {
@@ -87,14 +84,9 @@ module.controller('KbnTagCloudController', function ($scope, $element, Private,
$scope.$watch('vis.params', (options) => tagCloud.setOptions(options));
- $scope.$watch(getContainerSize, _.debounce(() => {
+ $scope.$watch('resize', () => {
tagCloud.resize();
- }, 1000, { trailing: true }), true);
-
-
- function getContainerSize() {
- return { width: $element.width(), height: $element.height() };
- }
+ });
function getValue(metricsAgg, bucket) {
let size = metricsAgg.getValue(bucket);
diff --git a/src/core_plugins/tile_map/public/__tests__/geohash_layer.js b/src/core_plugins/tile_map/public/__tests__/geohash_layer.js
index c61ed5d991bf8e..147f5fee0769dd 100644
--- a/src/core_plugins/tile_map/public/__tests__/geohash_layer.js
+++ b/src/core_plugins/tile_map/public/__tests__/geohash_layer.js
@@ -1,6 +1,6 @@
import expect from 'expect.js';
-import { KibanaMap } from 'ui/vis_maps/kibana_map';
-import { GeohashLayer } from 'ui/vis_maps/geohash_layer';
+import { KibanaMap } from '../kibana_map';
+import { GeohashLayer } from '../geohash_layer';
import { GeoHashSampleData } from './geohash_sample_data';
describe('kibana_map tests', function () {
diff --git a/src/core_plugins/tile_map/public/__tests__/kibana_map.js b/src/core_plugins/tile_map/public/__tests__/kibana_map.js
index a3752e42c2d644..a1f6195528755b 100644
--- a/src/core_plugins/tile_map/public/__tests__/kibana_map.js
+++ b/src/core_plugins/tile_map/public/__tests__/kibana_map.js
@@ -1,5 +1,5 @@
import expect from 'expect.js';
-import { KibanaMap } from 'ui/vis_maps/kibana_map';
+import { KibanaMap } from '../kibana_map';
describe('kibana_map tests', function () {
@@ -40,13 +40,13 @@ describe('kibana_map tests', function () {
teardownDOM();
});
- it('should instantiate with world in view', function () {
+ it('should instantiate at zoom level 2', function () {
const bounds = kibanaMap.getBounds();
- expect(bounds.bottom_right.lon).to.equal(180);
- expect(bounds.top_left.lon).to.equal(-180);
+ expect(bounds.bottom_right.lon).to.equal(90);
+ expect(bounds.top_left.lon).to.equal(-90);
expect(kibanaMap.getCenter().lon).to.equal(0);
expect(kibanaMap.getCenter().lat).to.equal(0);
- expect(kibanaMap.getZoomLevel()).to.equal(1);
+ expect(kibanaMap.getZoomLevel()).to.equal(2);
});
it('should resize to fit container', function () {
diff --git a/src/ui/public/vis_maps/__tests__/service_settings.js b/src/core_plugins/tile_map/public/__tests__/service_settings.js
similarity index 95%
rename from src/ui/public/vis_maps/__tests__/service_settings.js
rename to src/core_plugins/tile_map/public/__tests__/service_settings.js
index a54fb6b1c5ec81..bca96a6a36b588 100644
--- a/src/ui/public/vis_maps/__tests__/service_settings.js
+++ b/src/core_plugins/tile_map/public/__tests__/service_settings.js
@@ -15,19 +15,18 @@ describe('service_settings (FKA tilemaptest)', function () {
const manifestUrl2 = 'https://foobar/v1/manifest';
const manifest = {
- 'services': [
- {
- 'id': 'tiles_v2',
- 'name': 'Elastic Tile Service',
- 'manifest': tmsManifestUrl,
- 'type': 'tms'
- },
- {
- 'id': 'geo_layers',
- 'name': 'Elastic Layer Service',
- 'manifest': vectorManifestUrl,
- 'type': 'file'
- }
+ 'services': [{
+ 'id': 'tiles_v2',
+ 'name': 'Elastic Tile Service',
+ 'manifest': tmsManifestUrl,
+ 'type': 'tms'
+ },
+ {
+ 'id': 'geo_layers',
+ 'name': 'Elastic Layer Service',
+ 'manifest': vectorManifestUrl,
+ 'type': 'file'
+ }
]
};
diff --git a/src/core_plugins/tile_map/public/__tests__/tilemap_settings.js b/src/core_plugins/tile_map/public/__tests__/tilemap_settings.js
deleted file mode 100644
index e5d8982aac2e50..00000000000000
--- a/src/core_plugins/tile_map/public/__tests__/tilemap_settings.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-import url from 'url';
-
-describe('tilemaptest - TileMapSettingsTests-deprecated', function () {
- let tilemapSettings;
- let loadSettings;
-
- beforeEach(ngMock.module('kibana', ($provide) => {
- $provide.decorator('tilemapsConfig', () => ({
- manifestServiceUrl: 'https://proxy-tiles.elastic.co/v1/manifest',
- deprecated: {
- isOverridden: true,
- config: {
- url: 'https://tiles.elastic.co/v1/default/{z}/{x}/{y}.png?my_app_name=kibana_tests',
- options: {
- minZoom: 1,
- maxZoom: 10,
- attribution: '© [Elastic Tile Service](https://www.elastic.co/elastic_tile_service)'
- }
- },
- }
- }));
- }));
-
- beforeEach(ngMock.inject(function ($injector, $rootScope) {
- tilemapSettings = $injector.get('tilemapSettings');
-
- loadSettings = () => {
- tilemapSettings.loadSettings();
- $rootScope.$digest();
- };
- }));
-
- describe('getting settings', function () {
- beforeEach(function () {
- loadSettings();
- });
-
- it('should get url', function () {
-
- const mapUrl = tilemapSettings.getUrl();
- expect(mapUrl).to.contain('{x}');
- expect(mapUrl).to.contain('{y}');
- expect(mapUrl).to.contain('{z}');
-
- const urlObject = url.parse(mapUrl, true);
- expect(urlObject.hostname).to.be('tiles.elastic.co');
- expect(urlObject.query).to.have.property('my_app_name', 'kibana_tests');
-
- });
-
- it('should get options', function () {
- const options = tilemapSettings.getTMSOptions();
- expect(options).to.have.property('minZoom');
- expect(options).to.have.property('maxZoom');
- expect(options).to.have.property('attribution');
- });
-
- });
-});
diff --git a/src/core_plugins/tile_map/public/__tests__/tilemap_settings_mocked.js b/src/core_plugins/tile_map/public/__tests__/tilemap_settings_mocked.js
deleted file mode 100644
index 3f34c40e9c1edf..00000000000000
--- a/src/core_plugins/tile_map/public/__tests__/tilemap_settings_mocked.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-import url from 'url';
-
-describe('tilemaptest - TileMapSettingsTests-mocked', function () {
- let tilemapSettings;
- let tilemapsConfig;
- let loadSettings;
-
- beforeEach(ngMock.module('kibana', ($provide) => {
- $provide.decorator('tilemapsConfig', () => ({
- manifestServiceUrl: 'http://foo.bar/manifest',
- deprecated: {
- isOverridden: false,
- config: {
- url: '',
- options: {
- minZoom: 1,
- maxZoom: 10,
- attribution: '© [Elastic Tile Service](https://www.elastic.co/elastic_tile_service)'
- }
- },
- }
- }));
- }));
-
- beforeEach(ngMock.inject(($injector, $httpBackend) => {
- tilemapSettings = $injector.get('tilemapSettings');
- tilemapsConfig = $injector.get('tilemapsConfig');
-
- loadSettings = (expectedUrl) => {
- // body and headers copied from https://proxy-tiles.elastic.co/v1/manifest
- const MANIFEST_BODY = `{
- "services":[
- {
- "id":"road_map",
- "url":"https://proxy-tiles.elastic.co/v1/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana",
- "minZoom":0,
- "maxZoom":12,
- "attribution":"© [Elastic Tile Service](https://www.elastic.co/elastic-tile-service)"
- }
- ]
- }`;
-
- const MANIFEST_HEADERS = {
- 'access-control-allow-methods': 'GET, OPTIONS',
- 'access-control-allow-origin': '*',
- 'content-length': `${MANIFEST_BODY.length}`,
- 'content-type': 'application/json; charset=utf-8',
- date: (new Date()).toUTCString(),
- server: 'tileprox/20170102101655-a02e54d',
- status: '200',
- };
-
- $httpBackend
- .expect('GET', expectedUrl ? expectedUrl : () => true)
- .respond(MANIFEST_BODY, MANIFEST_HEADERS);
-
- tilemapSettings.loadSettings();
-
- $httpBackend.flush();
- };
- }));
-
- afterEach(ngMock.inject($httpBackend => {
- $httpBackend.verifyNoOutstandingRequest();
- $httpBackend.verifyNoOutstandingExpectation();
- }));
-
- describe('getting settings', function () {
- beforeEach(() => {
- loadSettings();
- });
-
-
- it('should get url', async function () {
-
- const mapUrl = tilemapSettings.getUrl();
- expect(mapUrl).to.contain('{x}');
- expect(mapUrl).to.contain('{y}');
- expect(mapUrl).to.contain('{z}');
-
- const urlObject = url.parse(mapUrl, true);
- expect(urlObject).to.have.property('hostname', 'proxy-tiles.elastic.co');
- expect(urlObject.query).to.have.property('my_app_name', 'kibana');
- expect(urlObject.query).to.have.property('elastic_tile_service_tos', 'agree');
- expect(urlObject.query).to.have.property('my_app_version');
-
- });
-
- it('should get options', async function () {
- const options = tilemapSettings.getTMSOptions();
- expect(options).to.have.property('minZoom', 0);
- expect(options).to.have.property('maxZoom', 12);
- expect(options).to.have.property('attribution').contain('©'); // html entity for ©, ensures that attribution is escaped
- });
-
- });
-
- describe('modify', function () {
- function assertQuery(expected) {
- const mapUrl = tilemapSettings.getUrl();
- const urlObject = url.parse(mapUrl, true);
- Object.keys(expected).forEach(key => {
- expect(urlObject.query).to.have.property(key, expected[key]);
- });
- }
-
- it('accepts an object', () => {
- tilemapSettings.addQueryParams({ foo: 'bar' });
- loadSettings();
- assertQuery({ foo: 'bar' });
- });
-
- it('merged additions with previous values', () => {
- // ensure that changes are always additive
- tilemapSettings.addQueryParams({ foo: 'bar' });
- tilemapSettings.addQueryParams({ bar: 'stool' });
- loadSettings();
- assertQuery({ foo: 'bar', bar: 'stool' });
- });
-
- it('overwrites conflicting previous values', () => {
- // ensure that conflicts are overwritten
- tilemapSettings.addQueryParams({ foo: 'bar' });
- tilemapSettings.addQueryParams({ bar: 'stool' });
- tilemapSettings.addQueryParams({ foo: 'tstool' });
- loadSettings();
- assertQuery({ foo: 'tstool', bar: 'stool' });
- });
-
- it('merges query params into manifest request', () => {
- tilemapSettings.addQueryParams({ foo: 'bar' });
- tilemapsConfig.manifestServiceUrl = 'http://test.com/manifest?v=1';
- loadSettings('http://test.com/manifest?v=1&my_app_version=1.2.3&foo=bar');
- });
-
- });
-
-});
diff --git a/src/core_plugins/tile_map/public/editors/tile_map.html b/src/core_plugins/tile_map/public/editors/tile_map.html
index b215b68bb0e188..e4201184dde1e8 100644
--- a/src/core_plugins/tile_map/public/editors/tile_map.html
+++ b/src/core_plugins/tile_map/public/editors/tile_map.html
@@ -4,8 +4,8 @@
diff --git a/src/core_plugins/tile_map/public/kibana_map.js b/src/core_plugins/tile_map/public/kibana_map.js
index da48554c5220ef..e657deff532eb9 100644
--- a/src/core_plugins/tile_map/public/kibana_map.js
+++ b/src/core_plugins/tile_map/public/kibana_map.js
@@ -101,7 +101,7 @@ export class KibanaMap extends EventEmitter {
minZoom: options.minZoom,
maxZoom: options.maxZoom,
center: options.center ? options.center : [0, 0],
- zoom: options.zoom ? options.zoom : 0
+ zoom: options.zoom ? options.zoom : 2
};
this._leafletMap = L.map(containerNode, leafletOptions);
diff --git a/src/ui/public/vis_maps/lib/service_settings.js b/src/core_plugins/tile_map/public/lib/service_settings.js
similarity index 100%
rename from src/ui/public/vis_maps/lib/service_settings.js
rename to src/core_plugins/tile_map/public/lib/service_settings.js
diff --git a/src/core_plugins/tile_map/public/lib/tilemap_settings.js b/src/core_plugins/tile_map/public/lib/tilemap_settings.js
deleted file mode 100644
index 54571ecc0d3a5f..00000000000000
--- a/src/core_plugins/tile_map/public/lib/tilemap_settings.js
+++ /dev/null
@@ -1,208 +0,0 @@
-import { uiModules } from 'ui/modules';
-import _ from 'lodash';
-import marked from 'marked';
-import { modifyUrl } from 'ui/url';
-
-marked.setOptions({
- gfm: true, // Github-flavored markdown
- sanitize: true // Sanitize HTML tags
-});
-
-uiModules.get('kibana')
- .service('tilemapSettings', function ($http, tilemapsConfig, $sanitize, kbnVersion) {
- const attributionFromConfig = $sanitize(marked(tilemapsConfig.deprecated.config.options.attribution || ''));
- const optionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { attribution: attributionFromConfig });
- const extendUrl = (url, props) => (
- modifyUrl(url, parsed => _.merge(parsed, props))
- );
-
- /**
- * Unescape a url template that was escaped by encodeURI() so leaflet
- * will be able to correctly locate the varables in the template
- * @param {String} url
- * @return {String}
- */
- const unescapeTemplateVars = url => {
- const ENCODED_TEMPLATE_VARS_RE = /%7B(\w+?)%7D/g;
- return url.replace(ENCODED_TEMPLATE_VARS_RE, (total, varName) => `{${varName}}`);
- };
-
- class TilemapSettings {
-
- constructor() {
-
- this._queryParams = {
- my_app_version: kbnVersion
- };
- this._error = null;
-
- //initialize settings with the default of the configuration
- this._url = tilemapsConfig.deprecated.config.url;
- this._tmsOptions = optionsFromConfig;
-
- this._invalidateSettings();
-
- }
-
-
- _invalidateSettings() {
-
- this._settingsInitialized = false;
- this._loadSettings = _.once(async() => {
-
- if (tilemapsConfig.deprecated.isOverridden) {//if settings are overridden, we will use those.
- this._settingsInitialized = true;
- }
-
- if (this._settingsInitialized) {
- return true;
- }
-
- return this._getTileServiceManifest(tilemapsConfig.manifestServiceUrl, this._queryParams)
- .then(response => {
- const service = _.get(response, 'data.services[0]');
- if (!service) {
- throw new Error('Manifest response does not include sufficient service data.');
- }
-
- this._error = null;
- this._tmsOptions = {
- attribution: $sanitize(marked(service.attribution)),
- minZoom: service.minZoom,
- maxZoom: service.maxZoom,
- subdomains: service.subdomains || []
- };
-
- this._url = unescapeTemplateVars(extendUrl(service.url, {
- query: this._queryParams
- }));
-
- this._settingsInitialized = true;
- })
- .catch(e => {
- this._settingsInitialized = true;
-
- if (!e) {
- e = new Error('Unkown error');
- }
-
- if (!(e instanceof Error)) {
- e = new Error(e.data || `status ${e.statusText || e.status}`);
- }
-
- this._error = new Error(`Could not retrieve manifest from the tile service: ${e.message}`);
- })
- .then(() => {
- return true;
- });
- });
- }
-
- /**
- * Must be called before getUrl/getTMSOptions/getMapOptions can be called.
- */
- loadSettings() {
- return this._loadSettings();
- }
-
- /**
- * Add optional query-parameters for the request.
- * These are only applied when requesting dfrom the manifest.
- *
- * @param additionalQueryParams
- */
- addQueryParams(additionalQueryParams) {
-
- //check if there are any changes in the settings.
- let changes = false;
- for (const key in additionalQueryParams) {
- if (additionalQueryParams.hasOwnProperty(key)) {
- if (additionalQueryParams[key] !== this._queryParams[key]) {
- changes = true;
- break;
- }
- }
- }
-
- if (changes) {
- this._queryParams = _.assign({}, this._queryParams, additionalQueryParams);
- this._invalidateSettings();
- }
-
- }
-
- /**
- * Get the url of the default TMS
- * @return {string}
- */
- getUrl() {
- if (!this._settingsInitialized) {
- throw new Error('Cannot retrieve url before calling .loadSettings first');
- }
- return this._url;
- }
-
- /**
- * Get the options of the default TMS
- * @return {{}}
- */
- getTMSOptions() {
- if (!this._settingsInitialized) {
- throw new Error('Cannot retrieve options before calling .loadSettings first');
- }
- return this._tmsOptions;
- }
-
-
- /**
- * @return {{maxZoom: (*|number), minZoom: (*|number)}}
- */
- getMinMaxZoom(isWMSEnabled) {
- if (isWMSEnabled) {
- return {
- minZoom: 0,
- maxZoom: 18
- };
- }
-
- //Otherwise, we use the settings from the yml.
- //note that it is no longer possible to only override the zoom-settings, since all options are read from the manifest
- //by default.
- //For a custom configuration, users will need to override tilemap.url as well.
- return {
- minZoom: this._tmsOptions.minZoom,
- maxZoom: this._tmsOptions.maxZoom
- };
-
- }
-
- isInitialized() {
- return this._settingsInitialized;
- }
-
-
- /**
- * Checks if there was an error during initialization of the parameters
- */
- hasError() {
- return this._error !== null;
- }
-
- getError() {
- return this._error;
- }
-
- /**
- * Make this a method to allow for overrides by test code
- */
- _getTileServiceManifest(manifestUrl) {
- return $http({
- url: extendUrl(manifestUrl, { query: this._queryParams }),
- method: 'GET'
- });
- }
-
- }
-
- return new TilemapSettings();
- });
diff --git a/src/core_plugins/tile_map/public/maps_renderbot.js b/src/core_plugins/tile_map/public/maps_renderbot.js
deleted file mode 100644
index e8dd48a9aaec93..00000000000000
--- a/src/core_plugins/tile_map/public/maps_renderbot.js
+++ /dev/null
@@ -1,258 +0,0 @@
-import $ from 'jquery';
-import _ from 'lodash';
-import { FilterBarPushFilterProvider } from 'ui/filter_bar/push_filter';
-import { KibanaMap } from './kibana_map';
-import { GeohashLayer } from './geohash_layer';
-import './lib/tilemap_settings';
-import './styles/_tilemap.less';
-
-
-module.exports = function MapsRenderbotFactory(Private, $injector, tilemapSettings, Notifier, courier, getAppState) {
-
- const notify = new Notifier({ location: 'Tilemap' });
-
- class MapsRenderbot {
-
- constructor(vis, $el, uiState) {
- this.vis = vis;
- this.$el = $el;
- this.uiState = uiState;
- this._geohashLayer = null;
- this._kibanaMap = null;
- this._$container = $el;
- this._kibanaMapReady = this._makeKibanaMap($el);
-
- this._baseLayerDirty = true;
- this._dataDirty = true;
- this._paramsDirty = true;
- }
-
- resize() {
- if (this._kibanaMap) {
- this._kibanaMap.resize();
- }
- }
-
- async _makeKibanaMap() {
-
- if (!tilemapSettings.isInitialized()) {
- await tilemapSettings.loadSettings();
- }
-
- if (tilemapSettings.getError()) {
- //Still allow the visualization to be built, but show a toast that there was a problem retrieving map settings
- //Even though the basemap will not display, the user will at least still see the overlay data
- notify.warning(tilemapSettings.getError().message);
- }
-
- if (this._kibanaMap) {
- this._kibanaMap.destroy();
- }
- const containerElement = $(this._$container)[0];
- const options = _.clone(this._getMinMaxZoom());
- const uiState = this.vis.getUiState();
- const zoomFromUiState = parseInt(uiState.get('mapZoom'));
- const centerFromUIState = uiState.get('mapCenter');
- options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.type.visConfig.defaults.mapZoom;
- options.center = centerFromUIState ? centerFromUIState : this.vis.type.visConfig.defaults.mapCenter;
-
- this._kibanaMap = new KibanaMap(containerElement, options);
- this._kibanaMap.addDrawControl();
- this._kibanaMap.addFitControl();
- this._kibanaMap.addLegendControl();
- this._kibanaMap.persistUiStateForVisualization(this.vis);
-
- let previousPrecision = this._kibanaMap.getAutoPrecision();
- let precisionChange = false;
- this._kibanaMap.on('zoomchange', () => {
- precisionChange = (previousPrecision !== this._kibanaMap.getAutoPrecision());
- previousPrecision = this._kibanaMap.getAutoPrecision();
- });
- this._kibanaMap.on('zoomend', () => {
-
- const isAutoPrecision = _.get(this._chartData, 'geohashGridAgg.params.autoPrecision', true);
- if (!isAutoPrecision) {
- return;
- }
-
- this._dataDirty = true;
- if (precisionChange) {
- courier.fetch();
- } else {
- this._recreateGeohashLayer();
- this._dataDirty = false;
- this._doRenderComplete();
- }
- });
-
-
- this._kibanaMap.on('drawCreated:rectangle', event => {
- addSpatialFilter(_.get(this._chartData, 'geohashGridAgg'), 'geo_bounding_box', event.bounds);
- });
- this._kibanaMap.on('drawCreated:polygon', event => {
- addSpatialFilter(_.get(this._chartData, 'geohashGridAgg'), 'geo_polygon', { points: event.points });
- });
- this._kibanaMap.on('baseLayer:loaded', () => {
- this._baseLayerDirty = false;
- this._doRenderComplete();
- });
- this._kibanaMap.on('baseLayer:loading', () => {
- this._baseLayerDirty = true;
- });
- }
-
- _getMinMaxZoom() {
- const mapParams = this._getMapsParams();
- return tilemapSettings.getMinMaxZoom(mapParams.wms.enabled);
- }
-
- _recreateGeohashLayer() {
- if (this._geohashLayer) {
- this._kibanaMap.removeLayer(this._geohashLayer);
- }
- if (!this._geohashGeoJson) {
- return;
- }
- const geohashOptions = this._getGeohashOptions();
- this._geohashLayer = new GeohashLayer(this._chartData.geoJson, geohashOptions, this._kibanaMap.getZoomLevel(), this._kibanaMap);
- this._kibanaMap.addLayer(this._geohashLayer);
- }
-
-
- /**
- * called on data change
- * @param esResponse
- */
- async render(esResponse) {
- this._dataDirty = true;
- this._kibanaMapReady.then(() => {
- this._chartData = esResponse;
- this._geohashGeoJson = this._chartData.geoJson;
- this._recreateGeohashLayer();
- this._kibanaMap.useUiStateFromVisualization(this.vis);
- this._kibanaMap.resize();
- this._dataDirty = false;
- this._doRenderComplete();
- });
- }
-
- destroy() {
- if (this._kibanaMap) {
- this._kibanaMap.destroy();
- }
- }
-
- /**
- * called on options change (vis.params change)
- */
- updateParams() {
-
- this._paramsDirty = true;
- this._kibanaMapReady.then(async() => {
- const mapParams = this._getMapsParams();
- const { minZoom, maxZoom } = this._getMinMaxZoom();
-
- if (mapParams.wms.enabled) {
-
- if (maxZoom > this._kibanaMap.getMaxZoomLevel()) {
- this._geohashLayer = null;
- this._kibanaMapReady = this._makeKibanaMap();
- }
-
- this._kibanaMap.setBaseLayer({
- baseLayerType: 'wms',
- options: {
- minZoom: minZoom,
- maxZoom: maxZoom,
- url: mapParams.wms.url,
- ...mapParams.wms.options
- }
- });
- } else {
-
- if (maxZoom < this._kibanaMap.getMaxZoomLevel()) {
- this._geohashLayer = null;
- this._kibanaMapReady = this._makeKibanaMap();
- this._kibanaMap.setZoomLevel(maxZoom);
- }
-
- if (!tilemapSettings.hasError()) {
- const url = tilemapSettings.getUrl();
- const options = tilemapSettings.getTMSOptions();
- this._kibanaMap.setBaseLayer({
- baseLayerType: 'tms',
- options: { url, ...options }
- });
- }
- }
- const geohashOptions = this._getGeohashOptions();
- if (!this._geohashLayer || !this._geohashLayer.isReusable(geohashOptions)) {
- this._recreateGeohashLayer();
- }
-
- this._kibanaMap.setDesaturateBaseLayer(mapParams.isDesaturated);
- this._kibanaMap.setShowTooltip(mapParams.addTooltip);
- this._kibanaMap.setLegendPosition(mapParams.legendPosition);
-
- this._kibanaMap.useUiStateFromVisualization(this.vis);
- this._kibanaMap.resize();
- this._paramsDirty = false;
- this._doRenderComplete();
- });
- }
-
- _getMapsParams() {
- return _.assign(
- {},
- this.vis.type.visConfig.defaults,
- {
- type: this.vis.type.name,
- hasTimeField: this.vis.indexPattern && this.vis.indexPattern.hasTimeField()// Add attribute which determines whether an index is time based or not.
- },
- this.vis.params
- );
- }
-
- _getGeohashOptions() {
- const newParams = this._getMapsParams();
- return {
- valueFormatter: this._chartData ? this._chartData.valueFormatter : null,
- tooltipFormatter: this._chartData ? this._chartData.tooltipFormatter : null,
- mapType: newParams.mapType,
- heatmap: {
- heatBlur: newParams.heatBlur,
- heatMaxZoom: newParams.heatMaxZoom,
- heatMinOpacity: newParams.heatMinOpacity,
- heatRadius: newParams.heatRadius
- }
- };
- }
-
- _doRenderComplete() {
- if (this._paramsDirty || this._dataDirty || this._baseLayerDirty) {
- return false;
- }
- this.$el.trigger('renderComplete');
- return true;
- }
-
- }
-
- function addSpatialFilter(agg, filterName, filterData) {
- if (!agg) {
- return;
- }
-
- const indexPatternName = agg.vis.indexPattern.id;
- const field = agg.fieldName();
- const filter = {};
- filter[filterName] = { ignore_unmapped: true };
- filter[filterName][field] = filterData;
-
- const putFilter = Private(FilterBarPushFilterProvider)(getAppState());
- return putFilter(filter, false, indexPatternName);
- }
-
-
- return MapsRenderbot;
-};
diff --git a/src/core_plugins/tile_map/public/maps_visualization.js b/src/core_plugins/tile_map/public/maps_visualization.js
index 0e2f52e6f2c32b..227de739b4fdaf 100644
--- a/src/core_plugins/tile_map/public/maps_visualization.js
+++ b/src/core_plugins/tile_map/public/maps_visualization.js
@@ -1,33 +1,281 @@
import 'ui/vislib';
import 'plugins/kbn_vislib_vis_types/controls/vislib_basic_options';
-import MapsVisTypeMapsRenderbotProvider from './maps_renderbot';
import $ from 'jquery';
+import _ from 'lodash';
+import { FilterBarPushFilterProvider } from 'ui/filter_bar/push_filter';
+import { KibanaMap } from './kibana_map';
+import { GeohashLayer } from './geohash_layer';
+import './lib/service_settings';
+import './styles/_tilemap.less';
-export function MapsVisualizationProvider(Private) {
- const MapsRenderbot = Private(MapsVisTypeMapsRenderbotProvider);
+export function MapsVisualizationProvider(Private, $injector, serviceSettings, Notifier, courier, getAppState) {
- class MapsVisController {
- constructor(el, vis) {
- this.el = $(el);
- this._vis = vis;
- this.renderbot = new MapsRenderbot(this._vis, this.el, vis.getUiState());
+ const notify = new Notifier({ location: 'Coordinate Map' });
+
+ class MapsVisualization {
+
+ constructor(element, vis) {
+
+ this.vis = vis;
+ this.$el = $(element);
+ this._$container = this.$el;
+
+
+ this._geohashLayer = null;
+ this._kibanaMap = null;
+ this._kibanaMapReady = this._makeKibanaMap();
+ this._baseLayerDirty = true;
+ this._dataDirty = true;
+ this._paramsDirty = true;
+ this._currentParams = null;
+ }
+
+ destroy() {
+ if (this._kibanaMap) {
+ this._kibanaMap.destroy();
+ }
}
async render(esResponse) {
- //todo: should notify of render-completeness, which it isn't doing correctly now
- this.renderbot.render(esResponse);
+
+ if (esResponse && typeof esResponse.geohashGridAgg === 'undefined') {
+ this.updateParams();
+ return;
+ }
+
+ //todo: do render complete!
+ this._dataDirty = true;
+ this._kibanaMapReady.then(() => {
+ this._chartData = esResponse;
+ this._geohashGeoJson = this._chartData.geoJson;
+ this._recreateGeohashLayer();
+ this._kibanaMap.useUiStateFromVisualization(this.vis);
+ this._kibanaMap.resize();
+ this._dataDirty = false;
+ this._doRenderComplete();
+ });
}
resize() {
- this.renderbot.resize();
+ if (this._kibanaMap) {
+ this._kibanaMap.resize();
+ }
}
- destroy() {
- this.renderbot.destroy();
+ //**********************************************************************************************************
+
+ async _makeKibanaMap() {
+
+ try {
+ this._tmsService = await serviceSettings.getTMSService();
+ this._tmsError = null;
+ } catch (e) {
+ this._tmsService = null;
+ this._tmsError = e;
+ notify.warning(e.message);
+ }
+
+ if (this._kibanaMap) {
+ this._kibanaMap.destroy();
+ }
+ const containerElement = $(this._$container)[0];
+ const options = _.clone(this._getMinMaxZoom());
+ const uiState = this.vis.getUiState();
+ const zoomFromUiState = parseInt(uiState.get('mapZoom'));
+ const centerFromUIState = uiState.get('mapCenter');
+ options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.type.visConfig.defaults.mapZoom;
+ options.center = centerFromUIState ? centerFromUIState : this.vis.type.visConfig.defaults.mapCenter;
+
+ this._kibanaMap = new KibanaMap(containerElement, options);
+ this._kibanaMap.addDrawControl();
+ this._kibanaMap.addFitControl();
+ this._kibanaMap.addLegendControl();
+ this._kibanaMap.persistUiStateForVisualization(this.vis);
+
+ let previousPrecision = this._kibanaMap.getAutoPrecision();
+ let precisionChange = false;
+ this._kibanaMap.on('zoomchange', () => {
+ precisionChange = (previousPrecision !== this._kibanaMap.getAutoPrecision());
+ previousPrecision = this._kibanaMap.getAutoPrecision();
+ });
+ this._kibanaMap.on('zoomend', () => {
+
+ const isAutoPrecision = _.get(this._chartData, 'geohashGridAgg.params.autoPrecision', true);
+ if (!isAutoPrecision) {
+ return;
+ }
+
+ this._dataDirty = true;
+ if (precisionChange) {
+ courier.fetch();
+ } else {
+ this._recreateGeohashLayer();
+ this._dataDirty = false;
+ this._doRenderComplete();
+ }
+ });
+
+
+ this._kibanaMap.on('drawCreated:rectangle', event => {
+ addSpatialFilter(_.get(this._chartData, 'geohashGridAgg'), 'geo_bounding_box', event.bounds);
+ });
+ this._kibanaMap.on('drawCreated:polygon', event => {
+ addSpatialFilter(_.get(this._chartData, 'geohashGridAgg'), 'geo_polygon', { points: event.points });
+ });
+ this._kibanaMap.on('baseLayer:loaded', () => {
+ this._baseLayerDirty = false;
+ this._doRenderComplete();
+ });
+ this._kibanaMap.on('baseLayer:loading', () => {
+ this._baseLayerDirty = true;
+ });
+ }
+
+ _getMinMaxZoom() {
+ const mapParams = this._getMapsParams();
+ if (this._tmsError) {
+ return serviceSettings.getFallbackZoomSettings(mapParams.wms.enabled);
+ } else {
+ return this._tmsService.getMinMaxZoom(mapParams.wms.enabled);
+ }
+ }
+
+ _recreateGeohashLayer() {
+ if (this._geohashLayer) {
+ this._kibanaMap.removeLayer(this._geohashLayer);
+ }
+ if (!this._geohashGeoJson) {
+ return;
+ }
+ const geohashOptions = this._getGeohashOptions();
+ this._geohashLayer = new GeohashLayer(this._chartData.geoJson, geohashOptions, this._kibanaMap.getZoomLevel(), this._kibanaMap);
+ this._kibanaMap.addLayer(this._geohashLayer);
+ }
+
+
+ /**
+ * called on options change (vis.params change)
+ */
+ async updateParams() {
+
+
+ this._paramsDirty = true;
+ await this._kibanaMapReady;
+
+ const mapParams = this._getMapsParams();
+ if (_.eq(this._currentParams, mapParams)) {
+ this._paramsDirty = false;
+ return;
+ }
+
+ this._currentParams = mapParams;
+ const { minZoom, maxZoom } = this._getMinMaxZoom();
+
+ if (mapParams.wms.enabled) {
+
+ if (maxZoom > this._kibanaMap.getMaxZoomLevel()) {
+ this._geohashLayer = null;
+ this._kibanaMapReady = this._makeKibanaMap();
+ }
+
+ this._kibanaMap.setBaseLayer({
+ baseLayerType: 'wms',
+ options: {
+ minZoom: minZoom,
+ maxZoom: maxZoom,
+ url: mapParams.wms.url,
+ ...mapParams.wms.options
+ }
+ });
+ } else {
+
+ if (maxZoom < this._kibanaMap.getMaxZoomLevel()) {
+ this._geohashLayer = null;
+ this._kibanaMapReady = this._makeKibanaMap();
+ this._kibanaMap.setZoomLevel(maxZoom);
+ }
+
+ if (!this._tmsError) {
+ const url = this._tmsService.getUrl();
+ const options = this._tmsService.getTMSOptions();
+ this._kibanaMap.setBaseLayer({
+ baseLayerType: 'tms',
+ options: { url, ...options }
+ });
+ }
+ }
+ const geohashOptions = this._getGeohashOptions();
+ if (!this._geohashLayer || !this._geohashLayer.isReusable(geohashOptions)) {
+ this._recreateGeohashLayer();
+ }
+
+ }
+
+ _getMapsParams() {
+ return _.assign(
+ {},
+ this.vis.type.visConfig.defaults,
+ { type: this.vis.type.name },
+ this.vis.params
+ );
+ }
+
+ _getGeohashOptions() {
+ const newParams = this._getMapsParams();
+ return {
+ valueFormatter: this._chartData ? this._chartData.valueFormatter : null,
+ tooltipFormatter: this._chartData ? this._chartData.tooltipFormatter : null,
+ mapType: newParams.mapType,
+ heatmap: {
+ heatBlur: newParams.heatBlur,
+ heatMaxZoom: newParams.heatMaxZoom,
+ heatMinOpacity: newParams.heatMinOpacity,
+ heatRadius: newParams.heatRadius
+ }
+ };
+ }
+
+ _doRenderComplete() {
+
+ return;
+
+ if (this._paramsDirty || this._dataDirty || this._baseLayerDirty) {
+ const mapParams = this._getMapsParams();
+ this._kibanaMap.setDesaturateBaseLayer(mapParams.isDesaturated);
+ this._kibanaMap.setShowTooltip(mapParams.addTooltip);
+ this._kibanaMap.setLegendPosition(mapParams.legendPosition);
+
+ this._kibanaMap.useUiStateFromVisualization(this.vis);
+ this._kibanaMap.resize();
+ this._paramsDirty = false;
+
+
+ // this._doRenderComplete();
+
+ return;
+ }
+ this.$el.trigger('renderComplete');
}
+
}
- return MapsVisController;
+ function addSpatialFilter(agg, filterName, filterData) {
+ if (!agg) {
+ return;
+ }
+
+ const indexPatternName = agg.vis.indexPattern.id;
+ const field = agg.fieldName();
+ const filter = {};
+ filter[filterName] = { ignore_unmapped: true };
+ filter[filterName][field] = filterData;
+
+ const putFilter = Private(FilterBarPushFilterProvider)(getAppState());
+ return putFilter(filter, false, indexPatternName);
+ }
+
+
+ return MapsVisualization;
}
diff --git a/src/core_plugins/timelion/public/vis/index.js b/src/core_plugins/timelion/public/vis/index.js
index f45b7a518ed8ff..6c32a909506c6e 100644
--- a/src/core_plugins/timelion/public/vis/index.js
+++ b/src/core_plugins/timelion/public/vis/index.js
@@ -2,11 +2,11 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { CATEGORY } from 'ui/vis/vis_category';
import image from '../images/icon-timelion.svg';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
-import { RequestHandlersRegistryProvider } from 'ui/registry/request_handlers';
+import { VisRequestHandlersRegistryProvider } from 'ui/registry/vis_request_handlers';
import { TimelionRequestHandlerProvider } from './timelion_request_handler';
define(function (require) {
- // we also need to load the controller and used by the template
+ // we also need to load the controller and directive used by the template
require('plugins/timelion/vis/timelion_vis_controller');
require('plugins/timelion/directives/timelion_expression_input');
@@ -15,7 +15,7 @@ define(function (require) {
// register the provider with the visTypes registry so that other know it exists
VisTypesRegistryProvider.register(TimelionVisProvider);
- RequestHandlersRegistryProvider.register(TimelionRequestHandlerProvider);
+ VisRequestHandlersRegistryProvider.register(TimelionRequestHandlerProvider);
function TimelionVisProvider(Private) {
const VisFactory = Private(VisFactoryProvider);
diff --git a/src/ui/public/agg_types/__tests__/agg_param_writer.js b/src/ui/public/agg_types/__tests__/agg_param_writer.js
index ea46c558fd3ebb..ffdd9c475f37a8 100644
--- a/src/ui/public/agg_types/__tests__/agg_param_writer.js
+++ b/src/ui/public/agg_types/__tests__/agg_param_writer.js
@@ -3,6 +3,7 @@ import { VisProvider } from 'ui/vis';
import { AggTypesIndexProvider } from 'ui/agg_types/index';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
+import { VisAggConfigProvider } from 'ui/vis/agg_config';
// eslint-disable-next-line kibana-custom/no-default-export
export default function AggParamWriterHelper(Private) {
@@ -10,6 +11,7 @@ export default function AggParamWriterHelper(Private) {
const aggTypes = Private(AggTypesIndexProvider);
const visTypes = Private(VisTypesRegistryProvider);
const stubbedLogstashIndexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
+ const AggConfig = Private(VisAggConfigProvider);
/**
* Helper object for writing aggParams. Specify an aggType and it will find a vis & schema, and
@@ -66,7 +68,7 @@ export default function AggParamWriterHelper(Private) {
}
self.vis = new Vis(self.indexPattern, {
- type: self.visType
+ type: self.visType.name
});
}
@@ -79,17 +81,26 @@ export default function AggParamWriterHelper(Private) {
if (self.aggType.type === 'metrics') {
paramValues.field = _.sample(self.indexPattern.fields.byType.number);
} else {
- paramValues.field = _.sample(self.indexPattern.fields.byType.string);
+ const type = self.aggType.params.byName.field.filterFieldTypes || 'string';
+ let field;
+ do {
+ field = _.sample(self.indexPattern.fields.byType[type]);
+ } while (!field.aggregatable);
+ paramValues.field = field.name;
}
}
+
+ const agg = new AggConfig(self.vis, {
+ id: 1,
+ schema: self.visAggSchema.name,
+ type: self.aggType.name,
+ params: paramValues
+ });
+
self.vis.setState({
type: self.vis.type.name,
- aggs: [{
- type: self.aggType,
- schema: self.visAggSchema,
- params: paramValues
- }]
+ aggs: [agg.toJSON()]
});
const aggConfig = _.find(self.vis.aggs, function (aggConfig) {
diff --git a/src/ui/public/registry/response_handlers.js b/src/ui/public/registry/response_handlers.js
deleted file mode 100644
index 6cc7203f1d3c71..00000000000000
--- a/src/ui/public/registry/response_handlers.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { uiRegistry } from 'ui/registry/_registry';
-export const ResponseHandlersRegistryProvider = uiRegistry({
- name: 'responseHandlers',
- index: ['name'],
- order: ['title']
-});
diff --git a/src/ui/public/registry/editor_types.js b/src/ui/public/registry/vis_editor_types.js
similarity index 52%
rename from src/ui/public/registry/editor_types.js
rename to src/ui/public/registry/vis_editor_types.js
index 29fc1a7e152c9e..646c63dc621724 100644
--- a/src/ui/public/registry/editor_types.js
+++ b/src/ui/public/registry/vis_editor_types.js
@@ -1,7 +1,7 @@
import { uiRegistry } from 'ui/registry/_registry';
-export const EditorTypesRegistryProvider = uiRegistry({
- name: 'editorTypes',
+export const VisEditorTypesRegistryProvider = uiRegistry({
+ name: 'visEditorTypes',
index: ['name'],
order: ['title']
});
diff --git a/src/ui/public/registry/request_handlers.js b/src/ui/public/registry/vis_request_handlers.js
similarity index 50%
rename from src/ui/public/registry/request_handlers.js
rename to src/ui/public/registry/vis_request_handlers.js
index 85e6a85ad07fbd..bdcd55fb0cc8d6 100644
--- a/src/ui/public/registry/request_handlers.js
+++ b/src/ui/public/registry/vis_request_handlers.js
@@ -1,6 +1,6 @@
import { uiRegistry } from 'ui/registry/_registry';
-export const RequestHandlersRegistryProvider = uiRegistry({
- name: 'requestHandlers',
+export const VisRequestHandlersRegistryProvider = uiRegistry({
+ name: 'visRequestHandlers',
index: ['name'],
order: ['title']
});
diff --git a/src/ui/public/registry/vis_response_handlers.js b/src/ui/public/registry/vis_response_handlers.js
new file mode 100644
index 00000000000000..dd1bdc3bcf627a
--- /dev/null
+++ b/src/ui/public/registry/vis_response_handlers.js
@@ -0,0 +1,6 @@
+import { uiRegistry } from 'ui/registry/_registry';
+export const VisResponseHandlersRegistryProvider = uiRegistry({
+ name: 'visResponseHandlers',
+ index: ['name'],
+ order: ['title']
+});
diff --git a/src/ui/public/vis/__tests__/_vis.js b/src/ui/public/vis/__tests__/_vis.js
index 2a3c3bc4800848..cc42d661fca88d 100644
--- a/src/ui/public/vis/__tests__/_vis.js
+++ b/src/ui/public/vis/__tests__/_vis.js
@@ -40,10 +40,6 @@ describe('Vis Class', function () {
expect(vis).to.have.property('type');
expect(vis.type).to.eql(visTypes.byName.pie);
- expect(vis).to.have.property('listeners');
- expect(vis.listeners).to.have.property('click');
- expect(vis.listeners.click).to.eql(_.noop);
-
expect(vis).to.have.property('params');
expect(vis.params).to.have.property('isDonut', true);
expect(vis).to.have.property('indexPattern', indexPattern);
@@ -63,10 +59,6 @@ describe('Vis Class', function () {
expect(state).to.have.property('params');
expect(state.params).to.have.property('isDonut', true);
- expect(state).to.have.property('listeners');
- expect(state.listeners).to.have.property('click');
- expect(state.listeners.click).to.eql(_.noop);
-
expect(state).to.have.property('aggs');
expect(state.aggs).to.have.length(3);
});
@@ -86,8 +78,6 @@ describe('Vis Class', function () {
expect(vis.type).to.eql(visTypes.byName.histogram);
expect(vis).to.have.property('aggs');
expect(vis.aggs).to.have.length(1);
- expect(vis).to.have.property('listeners');
- expect(vis.listeners).to.eql({});
expect(vis).to.have.property('params');
expect(vis.params).to.have.property('addLegend', true);
expect(vis.params).to.have.property('addTooltip', true);
diff --git a/src/ui/public/vis/editors/default/agg_add.html b/src/ui/public/vis/editors/default/agg_add.html
index 0c0b037a17062d..51e75740812246 100644
--- a/src/ui/public/vis/editors/default/agg_add.html
+++ b/src/ui/public/vis/editors/default/agg_add.html
@@ -21,7 +21,7 @@
Cancel
diff --git a/src/ui/public/vis/editors/default/sidebar.html b/src/ui/public/vis/editors/default/sidebar.html
index 6b2b609486e564..9a556619b4d511 100644
--- a/src/ui/public/vis/editors/default/sidebar.html
+++ b/src/ui/public/vis/editors/default/sidebar.html
@@ -53,9 +53,12 @@
tooltip-popup-delay="400"
tooltip-append-to-body="1"
>
-
-
-
+
{
+ $scope.vis.params = _.cloneDeep(params);
+ $scope.$apply();
+ };
const renderReactComponent = () => {
const Component = $scope.editor;
- render(, $el[0]);
+ render(, $el[0]);
};
// Bind the `editor` template with the scope.
if (reactOptionsComponent) {
@@ -38,7 +43,7 @@ uiModules
$optionContainer.append($editor);
}
- $scope.$watchGroup(['visData', 'visualizeEditor'], () => {
+ $scope.$watchGroup(['visData', 'visualizeEditor', 'vis.params'], () => {
if (reactOptionsComponent) {
renderReactComponent();
}
diff --git a/src/ui/public/vis/request_handlers/courier.js b/src/ui/public/vis/request_handlers/courier.js
index 03df31a972d3b3..b230bf349b0f07 100644
--- a/src/ui/public/vis/request_handlers/courier.js
+++ b/src/ui/public/vis/request_handlers/courier.js
@@ -7,8 +7,10 @@ const CourierRequestHandlerProvider = function (Private, courier) {
return {
name: 'courier',
handler: function (vis, appState, uiState, searchSource) {
- searchSource.set('filter', appState.filters);
- if (!appState.linked) searchSource.set('query', appState.query);
+ if (appState) {
+ searchSource.set('filter', appState.filters);
+ if (!appState.linked) searchSource.set('query', appState.query);
+ }
return new Promise((resolve, reject) => {
searchSource.onResults().then(resp => {
diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js
index 2e0f2d4b69c9b0..f6d8da57e953a6 100644
--- a/src/ui/public/vis/vis.js
+++ b/src/ui/public/vis/vis.js
@@ -52,7 +52,10 @@ export function VisProvider(Private, indexPatterns, timefilter, getAppState) {
filter: (event) => {
const appState = getAppState();
filterBarClickHandler(appState)(event);
- }, brush: brushEvent(visState),
+ }, brush: (event) => {
+ const appState = getAppState();
+ brushEvent(appState)(event);
+ }
}
};
}
@@ -127,7 +130,8 @@ export function VisProvider(Private, indexPatterns, timefilter, getAppState) {
clone() {
const uiJson = this.hasUiState() ? this.getUiState().toJSON() : {};
- return new Vis(this.indexPattern, this.getState(), uiJson);
+ const uiState = new PersistedState(uiJson);
+ return new Vis(this.indexPattern, this.getState(), uiState);
}
requesting() {
diff --git a/src/ui/public/vis/vis_types/angular_vis_type.js b/src/ui/public/vis/vis_types/angular_vis_type.js
index 92a63398a057c8..b25e1701c652f6 100644
--- a/src/ui/public/vis/vis_types/angular_vis_type.js
+++ b/src/ui/public/vis/vis_types/angular_vis_type.js
@@ -16,6 +16,7 @@ export function AngularVisTypeProvider(Private, $compile, $rootScope) {
return new Promise((resolve, reject) => {
const updateScope = () => {
this.$scope.vis = this.vis.clone();
+ this.$scope.vis.setUiState(this.vis.getUiState());
this.$scope.esResponse = esResponse;
this.$scope.renderComplete = resolve;
this.$scope.renderFailed = reject;
diff --git a/src/ui/public/vis/vis_types/base_vis_type.js b/src/ui/public/vis/vis_types/base_vis_type.js
index 09d39ddb28f320..406a09e4fc1ccb 100644
--- a/src/ui/public/vis/vis_types/base_vis_type.js
+++ b/src/ui/public/vis/vis_types/base_vis_type.js
@@ -20,7 +20,7 @@ export function VisTypeProvider() {
defaults: {}, // default configuration
},
requestHandler: 'courier', // select one from registry or pass a function
- responseHandler: 'tabify',
+ responseHandler: 'none',
editor: 'default',
editorConfig: {
collections: {}, // collections used for configuration (list of positions, ...)
diff --git a/src/ui/public/vis/vis_types/react_vis_type.js b/src/ui/public/vis/vis_types/react_vis_type.js
index b9833e03f4905a..df47641541039f 100644
--- a/src/ui/public/vis/vis_types/react_vis_type.js
+++ b/src/ui/public/vis/vis_types/react_vis_type.js
@@ -22,7 +22,7 @@ export function ReactVisTypeProvider(Private) {
resize() {
if (this.visData) {
- this.render(this.vis, this.visData);
+ this.render(this.visData);
}
}
diff --git a/src/ui/public/vis/vis_types/vislib_vis_type.js b/src/ui/public/vis/vis_types/vislib_vis_type.js
index 069ef366702c48..cff05fac59e22c 100644
--- a/src/ui/public/vis/vis_types/vislib_vis_type.js
+++ b/src/ui/public/vis/vis_types/vislib_vis_type.js
@@ -3,6 +3,7 @@ import 'plugins/kbn_vislib_vis_types/controls/vislib_basic_options';
import 'plugins/kbn_vislib_vis_types/controls/point_series_options';
import 'plugins/kbn_vislib_vis_types/controls/line_interpolation_option';
import 'plugins/kbn_vislib_vis_types/controls/heatmap_options';
+import 'plugins/kbn_vislib_vis_types/controls/gauge_options';
import 'plugins/kbn_vislib_vis_types/controls/point_series';
import { VisTypeProvider } from './base_vis_type';
import { AggResponsePointSeriesProvider } from 'ui/agg_response/point_series/point_series';
@@ -20,6 +21,8 @@ export function VislibVisTypeProvider(Private) {
}
render(esResponse) {
+ if (!esResponse) return;
+ this._response = esResponse;
if (this.vis.vislibVis) {
this.destroy();
} else {
@@ -37,11 +40,11 @@ export function VislibVisTypeProvider(Private) {
}
resize() {
- return;
+ this.render(this._response);
}
destroy() {
- if (this.vislibVis) {
+ if (this.vis.vislibVis) {
this.vis.vislibVis.off('brush', this.vis.API.events.brush);
this.vis.vislibVis.off('click', this.vis.API.events.filter);
this.vis.vislibVis.destroy();
diff --git a/src/ui/public/vislib/vis.js b/src/ui/public/vislib/vis.js
index 902e5dcd3080d6..7ec10dba650e54 100644
--- a/src/ui/public/vislib/vis.js
+++ b/src/ui/public/vislib/vis.js
@@ -1,15 +1,12 @@
import _ from 'lodash';
import d3 from 'd3';
-import { Binder } from 'ui/binder';
import { KbnError } from 'ui/errors';
import { EventsProvider } from 'ui/events';
-import { ResizeCheckerProvider } from 'ui/resize_checker';
import './styles/main.less';
import { VislibVisConfigProvider } from './lib/vis_config';
import { VisHandlerProvider } from './lib/handler';
export function VislibVisProvider(Private) {
- const ResizeChecker = Private(ResizeCheckerProvider);
const Events = Private(EventsProvider);
const VisConfig = Private(VislibVisConfigProvider);
const Handler = Private(VisHandlerProvider);
@@ -26,13 +23,7 @@ export function VislibVisProvider(Private) {
constructor($el, visConfigArgs) {
super(arguments);
this.el = $el.get ? $el.get(0) : $el;
- this.binder = new Binder();
this.visConfigArgs = _.cloneDeep(visConfigArgs);
-
- // bind the resize function so it can be used as an event handler
- this.resize = _.bind(this.resize, this);
- this.resizeChecker = new ResizeChecker(this.el);
- this.binder.on(this.resizeChecker, 'resize', this.resize);
}
hasLegend() {
@@ -69,7 +60,7 @@ export function VislibVisProvider(Private) {
this.visConfig = new VisConfig(this.visConfigArgs, this.data, this.uiState, this.el);
this.handler = new Handler(this, this.visConfig);
- this._runWithoutResizeChecker('render');
+ this._runOnHandler('render');
}
getLegendLabels() {
@@ -80,29 +71,6 @@ export function VislibVisProvider(Private) {
return this.visConfig ? this.visConfig.get('legend.colors', null) : null;
}
- /**
- * Resizes the visualization
- *
- * @method resize
- */
- resize() {
- if (!this.data) {
- return;
- }
-
- if (this.handler && _.isFunction(this.handler.resize)) {
- this._runOnHandler('resize');
- } else {
- this.render(this.data, this.uiState);
- }
- }
-
- _runWithoutResizeChecker(method) {
- this.resizeChecker.modifySizeWithoutTriggeringResize(() => {
- this._runOnHandler(method);
- });
- }
-
_runOnHandler(method) {
try {
this.handler[method]();
@@ -128,8 +96,6 @@ export function VislibVisProvider(Private) {
destroy() {
const selection = d3.select(this.el).select('.vis-wrapper');
- this.binder.destroy();
- this.resizeChecker.destroy();
if (this.uiState) this.uiState.off('change', this._uiStateChangeHandler);
if (this.handler) this._runOnHandler('destroy');
diff --git a/src/ui/public/visualize/__tests__/visualize.js b/src/ui/public/visualize/__tests__/visualize.js
index 9075ee4d59f69f..8c45260ae39ecf 100644
--- a/src/ui/public/visualize/__tests__/visualize.js
+++ b/src/ui/public/visualize/__tests__/visualize.js
@@ -4,6 +4,8 @@ import ngMock from 'ng_mock';
import { VisProvider } from 'ui/vis';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
import FixturesStubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
+import MockState from 'fixtures/mock_state';
+
describe('visualize directive', function () {
let $rootScope;
let $compile;
@@ -13,6 +15,7 @@ describe('visualize directive', function () {
let indexPattern;
let fixtures;
let searchSource;
+ let appState;
beforeEach(ngMock.module('kibana', 'kibana/table_vis'));
beforeEach(ngMock.inject(function (Private, $injector) {
@@ -20,6 +23,8 @@ describe('visualize directive', function () {
$compile = $injector.get('$compile');
fixtures = require('fixtures/fake_hierarchical_data');
Vis = Private(VisProvider);
+ appState = new MockState({ filters: [] });
+ appState.toJSON = () => { return {}; };
indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
searchSource = Private(FixturesStubbedSearchSourceProvider);
}));
@@ -31,8 +36,13 @@ describe('visualize directive', function () {
$rootScope.vis = vis;
$rootScope.esResponse = esResponse;
$rootScope.uiState = require('fixtures/mock_ui_state');
+ $rootScope.appState = appState;
$rootScope.searchSource = searchSource;
- $el = $('');
+ $rootScope.savedObject = {
+ vis: vis,
+ searchSource: searchSource
+ };
+ $el = $('');
$compile($el)($rootScope);
$rootScope.$apply();
@@ -40,9 +50,8 @@ describe('visualize directive', function () {
}
function CreateVis(params, requiresSearch) {
- return new Vis(indexPattern, {
+ const vis = new Vis(indexPattern, {
type: 'table',
- requiresSearch: requiresSearch,
params: params || {},
aggs: [
{ type: 'count', schema: 'metric' },
@@ -59,6 +68,11 @@ describe('visualize directive', function () {
}
]
});
+
+ vis.type.requestHandler = requiresSearch ? 'default' : 'none';
+ vis.type.responseHandler = 'none';
+ vis.type.requiresSearch = false;
+ return vis;
}
it('searchSource.onResults should not be called when requiresSearch is false', function () {
diff --git a/src/ui/public/visualize/visualization_editor.js b/src/ui/public/visualize/visualization_editor.js
index 8340f7bfb264f6..aa22d44f712b54 100644
--- a/src/ui/public/visualize/visualization_editor.js
+++ b/src/ui/public/visualize/visualization_editor.js
@@ -4,13 +4,13 @@ import 'ui/visualize/visualize.less';
import 'ui/visualize/visualize_legend';
import { uiModules } from 'ui/modules';
import 'angular-sanitize';
-import { EditorTypesRegistryProvider } from 'ui/registry/editor_types';
+import { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types';
import { ResizeCheckerProvider } from 'ui/resize_checker';
uiModules
.get('kibana/directive', ['ngSanitize'])
.directive('visualizationEditor', function (Private) {
- const editorTypes = Private(EditorTypesRegistryProvider);
+ const editorTypes = Private(VisEditorTypesRegistryProvider);
const ResizeChecker = Private(ResizeCheckerProvider);
return {
diff --git a/src/ui/public/visualize/visualize.html b/src/ui/public/visualize/visualize.html
index be06f2b26523f4..24bc1350d945cb 100644
--- a/src/ui/public/visualize/visualize.html
+++ b/src/ui/public/visualize/visualize.html
@@ -6,8 +6,6 @@
ui-state="uiState"
class="vis-editor-content"
search-source="savedObj.searchSource"
- render-counter
- data-shared-item
/>
diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js
index cf1b0966ba73e1..ccc0d358ba50bf 100644
--- a/src/ui/public/visualize/visualize.js
+++ b/src/ui/public/visualize/visualize.js
@@ -1,8 +1,8 @@
import { uiModules } from 'ui/modules';
import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
import visualizeTemplate from 'ui/visualize/visualize.html';
-import { RequestHandlersRegistryProvider } from 'ui/registry/request_handlers';
-import { ResponseHandlersRegistryProvider } from 'ui/registry/response_handlers';
+import { VisRequestHandlersRegistryProvider } from 'ui/registry/vis_request_handlers';
+import { VisResponseHandlersRegistryProvider } from 'ui/registry/vis_response_handlers';
import 'angular-sanitize';
import './visualization';
import './visualization_editor';
@@ -13,10 +13,10 @@ import {
uiModules
.get('kibana/directive', ['ngSanitize'])
-.directive('visualize', function (Notifier, Private, timefilter) {
+.directive('visualize', function (Notifier, Private, timefilter, getAppState) {
const notify = new Notifier({ location: 'Visualize' });
- const requestHandlers = Private(RequestHandlersRegistryProvider);
- const responseHandlers = Private(ResponseHandlersRegistryProvider);
+ const requestHandlers = Private(VisRequestHandlersRegistryProvider);
+ const responseHandlers = Private(VisResponseHandlersRegistryProvider);
function getHandler(from, name) {
if (typeof name === 'function') return name;
@@ -39,6 +39,8 @@ uiModules
$scope.vis.showSpyPanel = $scope.showSpyPanel || false;
$scope.vis.editorMode = $scope.editorMode;
+ if (!$scope.appState) $scope.appState = getAppState();
+
const requestHandler = getHandler(requestHandlers, $scope.vis.type.requestHandler);
const responseHandler = getHandler(responseHandlers, $scope.vis.type.responseHandler);
@@ -75,19 +77,25 @@ uiModules
}
});
- const stateMonitor = stateMonitorFactory.create($scope.appState);
- if ($scope.vis.type.requiresSearch) {
+ if ($scope.appState) {
+ const stateMonitor = stateMonitorFactory.create($scope.appState);
stateMonitor.onChange((status, type, keys) => {
- if (['query', 'filters', 'vis'].includes(keys[0])) {
- $scope.vis.setState($scope.appState.vis);
+ if (keys[0] === 'vis') {
+ if ($scope.appState.vis) $scope.vis.setState($scope.appState.vis);
+ $scope.fetch();
+ }
+ if ($scope.vis.type.requiresSearch && ['query', 'filters'].includes(keys[0])) {
$scope.fetch();
}
});
-
- // visualize needs to know about timeFilter
- $scope.$listen(timefilter, 'fetch', $scope.fetch);
}
+ // visualize needs to know about timeFilter
+ $scope.$listen(timefilter, 'fetch', $scope.fetch);
+ $scope.$on('renderComplete', () => {
+ $el.trigger('renderComplete');
+ });
+
$scope.fetch();
}
};
diff --git a/src/ui/public/visualize/visualize_legend.js b/src/ui/public/visualize/visualize_legend.js
index a084cc59ef7127..a3211ceef8ec28 100644
--- a/src/ui/public/visualize/visualize_legend.js
+++ b/src/ui/public/visualize/visualize_legend.js
@@ -6,7 +6,7 @@ import { uiModules } from 'ui/modules';
uiModules.get('kibana')
-.directive('visualizeLegend', function (Private, getAppState) {
+.directive('visualizeLegend', function (Private, getAppState, $timeout) {
const Data = Private(VislibLibDataProvider);
const filterBarClickHandler = Private(FilterBarClickHandlerProvider);
@@ -62,7 +62,10 @@ uiModules.get('kibana')
const bwcAddLegend = $scope.vis.params.addLegend;
const bwcLegendStateDefault = bwcAddLegend == null ? true : bwcAddLegend;
$scope.open = !$scope.uiState.get('vis.legendOpen', bwcLegendStateDefault);
- $scope.uiState.set('vis.legendOpen', $scope.open);
+ // open should be applied on template before we update uiState
+ $timeout(() => {
+ $scope.uiState.set('vis.legendOpen', $scope.open);
+ });
};
$scope.getToggleLegendClasses = function () {
diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js
index dafc7bebdde689..afec9a5948d33d 100644
--- a/test/functional/page_objects/visualize_page.js
+++ b/test/functional/page_objects/visualize_page.js
@@ -582,7 +582,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
// 1). get the maximim chart Y-Axis marker value
return remote
.setFindTimeout(defaultFindTimeout)
- .findByCssSelector(`div.y-axis-div-wrapper > div > svg > g.${axis} > g:last-of-type`)
+ .findByCssSelector(`div.y-axis-div-wrapper > div > svg:last-of-type > g.${axis} > g:last-of-type`)
.getVisibleText()
.then(function (yLabel) {
yAxisLabel = yLabel.replace(/,/g, '');
@@ -791,7 +791,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
waitForVisualization() {
return remote
.setFindTimeout(defaultFindTimeout)
- .findByCssSelector('visualize-legend');
+ .findByCssSelector('visualization');
}
clickMapButton(zoomSelector) {