mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Merge branch 'master' into addTileMapTests
This commit is contained in:
commit
409ec9d55c
41 changed files with 448 additions and 183 deletions
10
README.md
10
README.md
|
@ -1,4 +1,4 @@
|
|||
# Kibana 5.0.0-alpha5
|
||||
# Kibana 5.0.0-alpha6
|
||||
|
||||
Kibana is an open source ([Apache Licensed](https://github.com/elastic/kibana/blob/master/LICENSE.md)), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elasticsearch.
|
||||
|
||||
|
@ -43,7 +43,7 @@ For the daring, snapshot builds are available. These builds are created after ea
|
|||
|
||||
| platform | |
|
||||
| --- | --- |
|
||||
| OSX | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-darwin-x86_64.tar.gz) |
|
||||
| Linux x64 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-linux-x86_64.tar.gz) [deb](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-amd64.deb) [rpm](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-x86_64.rpm) |
|
||||
| Linux x86 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-linux-x86.tar.gz) [deb](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-i386.deb) [rpm](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-i686.rpm) |
|
||||
| Windows | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha5-SNAPSHOT-windows-x86.zip) |
|
||||
| OSX | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-darwin-x86_64.tar.gz) |
|
||||
| Linux x64 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-linux-x86_64.tar.gz) [deb](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-amd64.deb) [rpm](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-x86_64.rpm) |
|
||||
| Linux x86 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-linux-x86.tar.gz) [deb](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-i386.deb) [rpm](https://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-i686.rpm) |
|
||||
| Windows | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-alpha6-SNAPSHOT-windows-x86.zip) |
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[[setup-repositories]]
|
||||
=== Kibana Repositories
|
||||
=== Install Kibana using a Linux Package Manager
|
||||
|
||||
Binary packages for Kibana are available for Unix distributions that support the `apt` and `yum` tools. We also have
|
||||
repositories available for APT and YUM based distributions.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[[setup]]
|
||||
== Getting Kibana Up and Running
|
||||
== Installing Kibana
|
||||
You can set up Kibana and start exploring your Elasticsearch indices in minutes.
|
||||
All you need is:
|
||||
|
||||
* Elasticsearch {esversion}
|
||||
* A modern web browser - http://www.elastic.co/subscriptions/matrix#matrix_browsers[Supported Browsers].
|
||||
* A modern web browser - https://www.elastic.co/support/matrix#show_browsers[Supported Browsers].
|
||||
* Information about your Elasticsearch installation:
|
||||
** URL of the Elasticsearch instance you want to connect to.
|
||||
** Which Elasticsearch indices you want to search.
|
||||
|
@ -12,15 +12,40 @@ All you need is:
|
|||
NOTE: If your Elasticsearch installation is protected by http://www.elastic.co/overview/shield/[{scyld}], see
|
||||
{shield}/kibana.html#using-kibana4-with-shield[{scyld} with Kibana] for additional setup instructions.
|
||||
|
||||
=== Upgrading Kibana
|
||||
|
||||
Your existing Kibana version is generally compatible with the next minor version release of Elasticsearch.
|
||||
This means you should upgrade your Elasticsearch cluster(s) before or at the same time as Kibana.
|
||||
We cannot guarantee compatibility between major version releases so in those cases both Elasticsearch and Kibana must be upgraded together.
|
||||
|
||||
To upgrade Kibana:
|
||||
|
||||
. Create a https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html[snapshot] of the existing `.kibana` index.
|
||||
. Back up the `kibana.yml` configuration file.
|
||||
. Take note of the Kibana plugins that are installed:
|
||||
* `bin/kibana plugin --list` on 4.x versions of Kibana.
|
||||
* `bin/kibana-plugin list` on 5.x versions of Kibana.
|
||||
. To upgrade from an Archive File:
|
||||
.. Extract the new version of Kibana into a different directory. See steps below.
|
||||
.. Migrate any custom configuration from your old kibana.yml to your new one
|
||||
.. Follow other steps below to complete the new installation.
|
||||
.. Once the new version is fully configured and working with required plugins, remove the previous version of Kibana
|
||||
. To upgrade using a Linux Package Manager:
|
||||
.. Uninstall the existing Kibana package: `apt-get remove kibana` or `yum remove kibana`
|
||||
.. Install the new Kibana package. There have been some installer issues between various version of Kibana so the uninstall and install process is safer than an upgrade.
|
||||
|
||||
|
||||
[float]
|
||||
[[install]]
|
||||
=== Install and Start Kibana
|
||||
=== Install and Start Kibana from an Archive File
|
||||
|
||||
To get Kibana up and running:
|
||||
|
||||
. Download the https://www.elastic.co/downloads/kibana[Kibana {version} binary package] for your platform.
|
||||
. Extract the `.zip` or `tar.gz` archive file.
|
||||
. After installing, run Kibana from the install directory: `bin/kibana` (Linux/MacOSX) or `bin\kibana.bat` (Windows).
|
||||
. If you're upgrading, migrate any configuration changes from the previous `kibana.yml` to the new version.
|
||||
. Install Kibana plugins (optional).
|
||||
. Run Kibana from the install directory: `bin/kibana` (Linux/MacOSX) or `bin\kibana.bat` (Windows).
|
||||
|
||||
On Unix, you can instead run the package manager suited for your distribution.
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"dashboarding"
|
||||
],
|
||||
"private": false,
|
||||
"version": "5.0.0-alpha5",
|
||||
"version": "5.0.0-alpha6",
|
||||
"build": {
|
||||
"number": 8467,
|
||||
"sha": "6cb7fec4e154faa0a4a3fee4b33dfef91b9870d9"
|
||||
|
|
|
@ -426,6 +426,12 @@ var rules = {
|
|||
script: {
|
||||
// populated by a global rule
|
||||
}
|
||||
},
|
||||
"matrix_stats": {
|
||||
__template: {
|
||||
fields: []
|
||||
},
|
||||
fields: ["{field}"]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -93,11 +93,23 @@ module.exports = function (api) {
|
|||
],
|
||||
url_params: {
|
||||
"analyzer": "",
|
||||
"char_filters": [],
|
||||
"char_filter": [],
|
||||
"field": "",
|
||||
"filters": [],
|
||||
"filter": [],
|
||||
"text": "",
|
||||
"tokenizer": ""
|
||||
"tokenizer": "",
|
||||
"explain": "__flag__",
|
||||
"attributes": []
|
||||
},
|
||||
data_autocomplete_rules: {
|
||||
text: [],
|
||||
field: "{field}",
|
||||
analyzer: "",
|
||||
tokenizer: "",
|
||||
char_filter: [],
|
||||
filter: [],
|
||||
explain: {__one_of: [false, true]},
|
||||
attributes: []
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -18,9 +18,20 @@ module.exports.send = function (method, path, data, server, disable_auth_alert)
|
|||
// delayed loading for circular references
|
||||
var settings = require("./settings");
|
||||
|
||||
let contentType;
|
||||
if (data) {
|
||||
try {
|
||||
JSON.parse(data);
|
||||
contentType = 'application/json';
|
||||
} catch (e) {
|
||||
contentType = 'text/plain';
|
||||
}
|
||||
}
|
||||
|
||||
var options = {
|
||||
url: '../api/console/proxy?uri=' + encodeURIComponent(path),
|
||||
data: method == "GET" ? null : data,
|
||||
contentType,
|
||||
cache: false,
|
||||
crossDomain: true,
|
||||
type: method,
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
Bar Mode
|
||||
</label>
|
||||
<select class="form-control" ng-model="vis.params.mode" ng-options="mode for mode in vis.type.params.modes"></select>
|
||||
<label>
|
||||
Y-Axis Scale
|
||||
</label>
|
||||
<select class="form-control" ng-model="vis.params.scale" ng-options="mode for mode in vis.type.params.scales"></select>
|
||||
</div>
|
||||
<point-series-options></point-series-options>
|
||||
<vislib-basic-options></vislib-basic-options>
|
||||
|
|
|
@ -83,6 +83,7 @@ uiModules.get('apps/management')
|
|||
|
||||
ingest.delete($scope.indexPattern.id)
|
||||
.then($scope.indexPattern.destroy.bind($scope.indexPattern))
|
||||
.then(refreshKibanaIndex)
|
||||
.then(function () {
|
||||
$location.url('/management/data/index');
|
||||
})
|
||||
|
|
|
@ -86,7 +86,8 @@ app.service('savedVisualizations', function (Promise, es, kbnIndex, SavedVis, Pr
|
|||
simple_query_string: {
|
||||
query: searchString + '*',
|
||||
fields: ['title^3', 'description'],
|
||||
default_operator: 'AND'
|
||||
default_operator: 'AND',
|
||||
analyze_wildcard: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import Promise from 'bluebird';
|
||||
import Joi from 'joi';
|
||||
import _ from 'lodash';
|
||||
import override from './override';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import _ from 'lodash';
|
||||
module.exports = function (dot, nestedObj, flattenArrays) {
|
||||
let key; // original key
|
||||
let stack = []; // track key stack
|
||||
let flatObj = {};
|
||||
(function flattenObj(obj) {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import Joi from 'joi';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { get } from 'lodash';
|
||||
import { randomBytes } from 'crypto';
|
||||
import os from 'os';
|
||||
|
|
|
@ -127,8 +127,13 @@ module.exports = class Plugin {
|
|||
server.exposeStaticDir(`/plugins/${id}/{path*}`, this.publicDir);
|
||||
}
|
||||
|
||||
this.status = kbnServer.status.createForPlugin(this);
|
||||
server.expose('status', this.status);
|
||||
// Many of the plugins are simply adding static assets to the server and we don't need
|
||||
// to track their "status". Since plugins must have an init() function to even set its status
|
||||
// we shouldn't even create a status unless the plugin can use it.
|
||||
if (this.externalInit !== _.noop) {
|
||||
this.status = kbnServer.status.createForPlugin(this);
|
||||
server.expose('status', this.status);
|
||||
}
|
||||
|
||||
return await attempt(this.externalInit, [server, options], this);
|
||||
};
|
||||
|
@ -148,7 +153,7 @@ module.exports = class Plugin {
|
|||
|
||||
// Only change the plugin status to green if the
|
||||
// intial status has not been changed
|
||||
if (this.status.state === 'uninitialized') {
|
||||
if (this.status && this.status.state === 'uninitialized') {
|
||||
this.status.green('Ready');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,14 @@ function KbnError(msg, constructor) {
|
|||
errors.KbnError = KbnError;
|
||||
_.class(KbnError).inherits(Error);
|
||||
|
||||
/**
|
||||
* If the error permits, propagate the error to be rendered on screen
|
||||
* @param handler the handlers that can render the error message to the screen.
|
||||
*/
|
||||
KbnError.prototype.displayToScreen = function (handler) {
|
||||
throw this;
|
||||
};
|
||||
|
||||
/**
|
||||
* HastyRefresh error class
|
||||
* @param {String} [msg] - An error message that will probably end up in a log.
|
||||
|
@ -204,71 +212,81 @@ errors.NoDefaultIndexPattern = function NoDefaultIndexPattern(type) {
|
|||
_.class(errors.NoDefaultIndexPattern).inherits(KbnError);
|
||||
|
||||
|
||||
/**
|
||||
* used by the vislib, when the container is too small
|
||||
* @param {String} message - the message to provide with the error
|
||||
*/
|
||||
errors.ContainerTooSmall = function ContainerTooSmall() {
|
||||
errors.PersistedStateError = function PersistedStateError(msg) {
|
||||
KbnError.call(this,
|
||||
'This container is too small to render the visualization',
|
||||
errors.ContainerTooSmall);
|
||||
};
|
||||
_.class(errors.ContainerTooSmall).inherits(KbnError);
|
||||
_.class(errors.PersistedStateError).inherits(KbnError);
|
||||
|
||||
|
||||
/**
|
||||
* UI Errors
|
||||
*/
|
||||
errors.VislibError = class VislibError extends KbnError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
displayToScreen(handler) {
|
||||
handler.error(this.message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
errors.ContainerTooSmall = class ContainerTooSmall extends errors.VislibError {
|
||||
constructor() {
|
||||
super('This container is too small to render the visualization');
|
||||
}
|
||||
};
|
||||
|
||||
errors.InvalidWiggleSelection = class InvalidWiggleSelection extends errors.VislibError {
|
||||
constructor() {
|
||||
super('In wiggle mode the area chart requires ordered values on the x-axis. Try using a Histogram or Date Histogram aggregation.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
errors.PieContainsAllZeros = class PieContainsAllZeros extends errors.VislibError {
|
||||
constructor() {
|
||||
super('No results displayed because all values equal 0.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
errors.InvalidLogScaleValues = class InvalidLogScaleValues extends errors.VislibError {
|
||||
constructor() {
|
||||
super('Values less than 1 cannot be displayed on a log scale');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
errors.StackedBarChartConfig = class StackedBarChartConfig extends errors.VislibError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* error thrown when user tries to render an chart with less
|
||||
* than the required number of data points
|
||||
* @param {String} message - the message to provide with the error
|
||||
*/
|
||||
errors.NotEnoughData = function NotEnoughData(message) {
|
||||
KbnError.call(this, message, errors.NotEnoughData);
|
||||
errors.NotEnoughData = class NotEnoughData extends errors.VislibError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
}
|
||||
};
|
||||
_.class(errors.NotEnoughData).inherits(KbnError);
|
||||
|
||||
/**
|
||||
* error thrown when no results are returned from an elasticsearch query
|
||||
*/
|
||||
errors.NoResults = function NoResults() {
|
||||
KbnError.call(this,
|
||||
'No results found',
|
||||
errors.NoResults);
|
||||
errors.NoResults = class NoResults extends errors.VislibError {
|
||||
constructor() {
|
||||
super('No results found');
|
||||
}
|
||||
};
|
||||
_.class(errors.NoResults).inherits(KbnError);
|
||||
|
||||
/**
|
||||
* error thrown when no results are returned from an elasticsearch query
|
||||
*/
|
||||
errors.PieContainsAllZeros = function PieContainsAllZeros() {
|
||||
KbnError.call(this,
|
||||
'No results displayed because all values equal 0',
|
||||
errors.PieContainsAllZeros);
|
||||
};
|
||||
_.class(errors.PieContainsAllZeros).inherits(KbnError);
|
||||
|
||||
/**
|
||||
* error thrown when no results are returned from an elasticsearch query
|
||||
*/
|
||||
errors.InvalidLogScaleValues = function InvalidLogScaleValues() {
|
||||
KbnError.call(this,
|
||||
'Values less than 1 cannot be displayed on a log scale',
|
||||
errors.InvalidLogScaleValues);
|
||||
};
|
||||
_.class(errors.InvalidLogScaleValues).inherits(KbnError);
|
||||
|
||||
/** error thrown when wiggle chart is selected for non linear data */
|
||||
errors.InvalidWiggleSelection = function InvalidWiggleSelection() {
|
||||
KbnError.call(this,
|
||||
'In wiggle mode the area chart requires ordered values on the x-axis. Try using a Histogram or Date Histogram aggregation.',
|
||||
errors.InvalidWiggleSelection);
|
||||
};
|
||||
_.class(errors.InvalidWiggleSelection).inherits(KbnError);
|
||||
|
||||
errors.PersistedStateError = function PersistedStateError(msg) {
|
||||
KbnError.call(this,
|
||||
msg || 'PersistedState Error',
|
||||
errors.PersistedStateError);
|
||||
};
|
||||
_.class(errors.PersistedStateError).inherits(KbnError);
|
||||
|
||||
|
||||
export default errors;
|
||||
|
|
|
@ -66,6 +66,10 @@ describe('Notifier', function () {
|
|||
expect(notify('error').lifetime).to.equal(300000);
|
||||
});
|
||||
|
||||
it('sets truncation length to 250', function () {
|
||||
expect(notify('error').truncationLength).to.equal(250);
|
||||
});
|
||||
|
||||
it('sets timeRemaining and decrements', function () {
|
||||
let notif = notify('error');
|
||||
|
||||
|
@ -143,6 +147,10 @@ describe('Notifier', function () {
|
|||
expect(notify('warning').lifetime).to.equal(10000);
|
||||
});
|
||||
|
||||
it('sets truncation length to 250', function () {
|
||||
expect(notify('warning').truncationLength).to.equal(250);
|
||||
});
|
||||
|
||||
it('does not allow reporting', function () {
|
||||
let includesReport = _.includes(notify('warning').actions, 'report');
|
||||
expect(includesReport).to.false;
|
||||
|
@ -181,6 +189,10 @@ describe('Notifier', function () {
|
|||
expect(notify('info').lifetime).to.equal(5000);
|
||||
});
|
||||
|
||||
it('sets truncation length to 250', function () {
|
||||
expect(notify('info').truncationLength).to.equal(250);
|
||||
});
|
||||
|
||||
it('does not allow reporting', function () {
|
||||
let includesReport = _.includes(notify('info').actions, 'report');
|
||||
expect(includesReport).to.false;
|
||||
|
@ -229,16 +241,18 @@ describe('Notifier', function () {
|
|||
// destroy the default custom notification, avoid duplicate handling
|
||||
customNotification.clear();
|
||||
|
||||
const explicitLifetimeParams = _.defaults({ lifetime: 20000 }, customParams);
|
||||
customNotification = notifier.custom(customText, explicitLifetimeParams);
|
||||
const overrideParams = _.defaults({ lifetime: 20000, truncationLength: 1000 }, customParams);
|
||||
customNotification = notifier.custom(customText, overrideParams);
|
||||
|
||||
expect(customNotification).to.have.property('type', 'info'); // default
|
||||
expect(customNotification).to.have.property('title', explicitLifetimeParams.title); // passed in
|
||||
expect(customNotification).to.have.property('lifetime', explicitLifetimeParams.lifetime); // passed in
|
||||
expect(customNotification).to.have.property('title', overrideParams.title); // passed in thru customParams
|
||||
expect(customNotification).to.have.property('truncationLength', overrideParams.truncationLength); // passed in thru overrideParams
|
||||
expect(customNotification).to.have.property('lifetime', overrideParams.lifetime); // passed in thru overrideParams
|
||||
|
||||
expect(explicitLifetimeParams.type).to.be(undefined);
|
||||
expect(explicitLifetimeParams.title).to.be.a('string');
|
||||
expect(explicitLifetimeParams.lifetime).to.be.a('number');
|
||||
expect(overrideParams.type).to.be(undefined);
|
||||
expect(overrideParams.title).to.be.a('string');
|
||||
expect(overrideParams.truncationLength).to.be.a('number');
|
||||
expect(overrideParams.lifetime).to.be.a('number');
|
||||
});
|
||||
|
||||
it('sets the content', function () {
|
||||
|
@ -340,6 +354,10 @@ describe('Notifier', function () {
|
|||
expect(notify('banner').title).to.equal('Attention');
|
||||
});
|
||||
|
||||
it('sets truncation length to 250 by default', function () {
|
||||
expect(notify('banner').truncationLength).to.equal(250);
|
||||
});
|
||||
|
||||
it('sets lifetime to 3000000 by default', function () {
|
||||
expect(notify('banner').lifetime).to.equal(3000000);
|
||||
});
|
||||
|
|
|
@ -188,7 +188,8 @@ Notifier.config = {
|
|||
warningLifetime: 10000,
|
||||
infoLifetime: 5000,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
clearInterval: window.clearInterval,
|
||||
defaultTruncationLength: 250
|
||||
};
|
||||
|
||||
Notifier.applyConfig = function (config) {
|
||||
|
@ -331,6 +332,7 @@ Notifier.prototype.error = function (err, opts, cb) {
|
|||
const config = _.assign({
|
||||
type: 'danger',
|
||||
content: formatMsg(err, this.from),
|
||||
truncationLength: Notifier.config.defaultTruncationLength,
|
||||
icon: 'warning',
|
||||
title: 'Error',
|
||||
lifetime: Notifier.config.errorLifetime,
|
||||
|
@ -354,6 +356,7 @@ Notifier.prototype.warning = function (msg, opts, cb) {
|
|||
const config = _.assign({
|
||||
type: 'warning',
|
||||
content: formatMsg(msg, this.from),
|
||||
truncationLength: Notifier.config.defaultTruncationLength,
|
||||
icon: 'warning',
|
||||
title: 'Warning',
|
||||
lifetime: Notifier.config.warningLifetime,
|
||||
|
@ -376,6 +379,7 @@ Notifier.prototype.info = function (msg, opts, cb) {
|
|||
const config = _.assign({
|
||||
type: 'info',
|
||||
content: formatMsg(msg, this.from),
|
||||
truncationLength: Notifier.config.defaultTruncationLength,
|
||||
icon: 'info-circle',
|
||||
title: 'Debug',
|
||||
lifetime: Notifier.config.infoLifetime,
|
||||
|
@ -394,6 +398,7 @@ Notifier.prototype.banner = function (msg, cb) {
|
|||
type: 'banner',
|
||||
title: 'Attention',
|
||||
content: formatMsg(msg, this.from),
|
||||
truncationLength: Notifier.config.defaultTruncationLength,
|
||||
lifetime: Notifier.config.bannerLifetime,
|
||||
actions: ['accept']
|
||||
}, cb);
|
||||
|
@ -448,6 +453,7 @@ Notifier.prototype.custom = function (msg, config, cb) {
|
|||
type: 'info',
|
||||
title: 'Notification',
|
||||
content: formatMsg(msg, this.from),
|
||||
truncationLength: config.truncationLength || Notifier.config.defaultTruncationLength,
|
||||
lifetime: getLifetime(config.type)
|
||||
}, config);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<i class="fa" ng-class="'fa-' + notif.icon" tooltip="{{notif.title}}"></i>
|
||||
|
||||
<kbn-truncated source="{{notif.content | markdown}}" is-html="true" length="250" class="toast-message" /></kbn-truncated>
|
||||
<kbn-truncated source="{{notif.content | markdown}}" is-html="true" length="{{notif.truncationLength}}" class="toast-message" /></kbn-truncated>
|
||||
|
||||
<div class="btn-group pull-right toast-controls">
|
||||
<button
|
||||
|
|
|
@ -38,7 +38,7 @@ uiModules
|
|||
template: function ($el, $attrs) {
|
||||
return $el.html();
|
||||
},
|
||||
controller: function ($scope, $element, $attrs, $transclude) {
|
||||
controller: function ($scope, $element, $attrs, $transclude, $injector) {
|
||||
if (!$scope.definition) throw new Error('render-directive must have a definition attribute');
|
||||
|
||||
const { controller, controllerAs, scope } = $scope.definition;
|
||||
|
@ -46,8 +46,16 @@ uiModules
|
|||
applyScopeBindings(scope, $scope, $attrs);
|
||||
|
||||
if (controller) {
|
||||
if (controllerAs) $scope[controllerAs] = this;
|
||||
$scope.$eval(controller, { $scope, $element, $attrs, $transclude });
|
||||
if (controllerAs) {
|
||||
$scope[controllerAs] = this;
|
||||
}
|
||||
|
||||
const locals = { $scope, $element, $attrs, $transclude };
|
||||
const controllerInstance = $injector.invoke(controller, this, locals) || this;
|
||||
|
||||
if (controllerAs) {
|
||||
$scope[controllerAs] = controllerInstance;
|
||||
}
|
||||
}
|
||||
},
|
||||
link: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import StateManagementStateProvider from 'ui/state_management/state';
|
|||
import PersistedStatePersistedStateProvider from 'ui/persisted_state/persisted_state';
|
||||
let urlParam = '_a';
|
||||
|
||||
function AppStateProvider(Private, $rootScope, getAppState) {
|
||||
function AppStateProvider(Private, $rootScope, $location) {
|
||||
let State = Private(StateManagementStateProvider);
|
||||
let PersistedState = Private(PersistedStatePersistedStateProvider);
|
||||
let persistedStates;
|
||||
|
@ -16,7 +16,7 @@ function AppStateProvider(Private, $rootScope, getAppState) {
|
|||
eventUnsubscribers = [];
|
||||
|
||||
AppState.Super.call(this, urlParam, defaults);
|
||||
getAppState._set(this);
|
||||
AppState.getAppState._set(this);
|
||||
}
|
||||
|
||||
// if the url param is missing, write it back
|
||||
|
@ -24,7 +24,7 @@ function AppStateProvider(Private, $rootScope, getAppState) {
|
|||
|
||||
AppState.prototype.destroy = function () {
|
||||
AppState.Super.prototype.destroy.call(this);
|
||||
getAppState._set(null);
|
||||
AppState.getAppState._set(null);
|
||||
_.callEach(eventUnsubscribers);
|
||||
};
|
||||
|
||||
|
@ -64,6 +64,26 @@ function AppStateProvider(Private, $rootScope, getAppState) {
|
|||
return persistedStates[prop];
|
||||
};
|
||||
|
||||
AppState.getAppState = (function () {
|
||||
let currentAppState;
|
||||
|
||||
function get() {
|
||||
return currentAppState;
|
||||
}
|
||||
|
||||
// Checks to see if the appState might already exist, even if it hasn't been newed up
|
||||
get.previouslyStored = function () {
|
||||
let search = $location.search();
|
||||
return search[urlParam] ? true : false;
|
||||
};
|
||||
|
||||
get._set = function (current) {
|
||||
currentAppState = current;
|
||||
};
|
||||
|
||||
return get;
|
||||
}());
|
||||
|
||||
return AppState;
|
||||
}
|
||||
|
||||
|
@ -71,24 +91,8 @@ modules.get('kibana/global_state')
|
|||
.factory('AppState', function (Private) {
|
||||
return Private(AppStateProvider);
|
||||
})
|
||||
.service('getAppState', function ($location) {
|
||||
let currentAppState;
|
||||
|
||||
function get() {
|
||||
return currentAppState;
|
||||
}
|
||||
|
||||
// Checks to see if the appState might already exist, even if it hasn't been newed up
|
||||
get.previouslyStored = function () {
|
||||
let search = $location.search();
|
||||
return search[urlParam] ? true : false;
|
||||
};
|
||||
|
||||
get._set = function (current) {
|
||||
currentAppState = current;
|
||||
};
|
||||
|
||||
return get;
|
||||
.service('getAppState', function (Private) {
|
||||
return Private(AppStateProvider).getAppState;
|
||||
});
|
||||
|
||||
export default AppStateProvider;
|
||||
|
|
|
@ -7,7 +7,7 @@ import uiModules from 'ui/modules';
|
|||
|
||||
let module = uiModules.get('kibana/global_state');
|
||||
|
||||
module.service('globalState', function (Private, $rootScope, $location) {
|
||||
function GlobalStateProvider(Private, $rootScope, $location) {
|
||||
let State = Private(StateManagementStateProvider);
|
||||
|
||||
_.class(GlobalState).inherits(State);
|
||||
|
@ -23,4 +23,9 @@ module.service('globalState', function (Private, $rootScope, $location) {
|
|||
};
|
||||
|
||||
return new GlobalState();
|
||||
}
|
||||
|
||||
module.service('globalState', function (Private) {
|
||||
return Private(GlobalStateProvider);
|
||||
});
|
||||
export default GlobalStateProvider;
|
||||
|
|
58
src/ui/public/stringify/__tests__/_boolean.js
Normal file
58
src/ui/public/stringify/__tests__/_boolean.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
import RegistryFieldFormatsProvider from 'ui/registry/field_formats';
|
||||
|
||||
describe('Boolean Format', function () {
|
||||
|
||||
let boolean;
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
const fieldFormats = Private(RegistryFieldFormatsProvider);
|
||||
boolean = fieldFormats.getInstance('boolean');
|
||||
}));
|
||||
|
||||
|
||||
[
|
||||
{
|
||||
input: 0,
|
||||
expected: 'false'
|
||||
},
|
||||
{
|
||||
input: 'no',
|
||||
expected: 'false'
|
||||
},
|
||||
{
|
||||
input: false,
|
||||
expected: 'false'
|
||||
},
|
||||
{
|
||||
input: 'false',
|
||||
expected: 'false'
|
||||
},
|
||||
{
|
||||
input: 1,
|
||||
expected: 'true'
|
||||
},
|
||||
{
|
||||
input: 'yes',
|
||||
expected: 'true'
|
||||
},
|
||||
{
|
||||
input: true,
|
||||
expected: 'true'
|
||||
},
|
||||
{
|
||||
input: 'true',
|
||||
expected: 'true'
|
||||
},
|
||||
{
|
||||
input: ' True ',//should handle trailing and mixed case
|
||||
expected: 'true'
|
||||
}
|
||||
].forEach((test)=> {
|
||||
it(`convert ${test.input} to boolean`, ()=> {
|
||||
expect(boolean.convert(test.input)).to.be(test.expected);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -19,10 +19,12 @@ const formatIds = [
|
|||
'string',
|
||||
'url',
|
||||
'_source',
|
||||
'truncate'
|
||||
'truncate',
|
||||
'boolean'
|
||||
];
|
||||
|
||||
module.exports = describe('conformance', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private, $injector) {
|
||||
fieldFormats = Private(RegistryFieldFormatsProvider);
|
||||
|
|
|
@ -7,5 +7,6 @@ import './_color';
|
|||
import './_date';
|
||||
import './_duration';
|
||||
import './_truncate';
|
||||
import './_boolean';
|
||||
describe('Stringify Component', function () {
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ import stringifyString from 'ui/stringify/types/string';
|
|||
import stringifySource from 'ui/stringify/types/source';
|
||||
import stringifyColor from 'ui/stringify/types/color';
|
||||
import stringifyTruncate from 'ui/stringify/types/truncate';
|
||||
import stringifyBoolean from 'ui/stringify/types/boolean';
|
||||
|
||||
fieldFormats.register(stringifyUrl);
|
||||
fieldFormats.register(stringifyBytes);
|
||||
|
@ -22,3 +23,4 @@ fieldFormats.register(stringifyString);
|
|||
fieldFormats.register(stringifySource);
|
||||
fieldFormats.register(stringifyColor);
|
||||
fieldFormats.register(stringifyTruncate);
|
||||
fieldFormats.register(stringifyBoolean);
|
||||
|
|
42
src/ui/public/stringify/types/boolean.js
Normal file
42
src/ui/public/stringify/types/boolean.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
import IndexPatternsFieldFormatProvider from 'ui/index_patterns/_field_format/field_format';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default function TruncateFormatProvider(Private) {
|
||||
|
||||
let FieldFormat = Private(IndexPatternsFieldFormatProvider);
|
||||
|
||||
class Bool extends FieldFormat {
|
||||
|
||||
constructor(params) {
|
||||
super(params);
|
||||
}
|
||||
|
||||
_convert(value) {
|
||||
|
||||
if (typeof value === 'string') {
|
||||
value = value.trim().toLowerCase();
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case false:
|
||||
case 0:
|
||||
case 'false':
|
||||
case 'no':
|
||||
return 'false';
|
||||
case true:
|
||||
case 1:
|
||||
case 'true':
|
||||
case 'yes':
|
||||
return 'true';
|
||||
default:
|
||||
return _.asPrettyString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bool.id = 'boolean';
|
||||
Bool.title = 'Boolean';
|
||||
Bool.fieldType = ['boolean', 'number', 'string'];
|
||||
|
||||
return Bool;
|
||||
};
|
|
@ -5,6 +5,7 @@ import ngMock from 'ng_mock';
|
|||
import faker from 'faker';
|
||||
import _ from 'lodash';
|
||||
import MockState from 'fixtures/mock_state';
|
||||
import AppStateProvider from 'ui/state_management/app_state';
|
||||
import 'ui/url';
|
||||
|
||||
// global vars, injected and mocked in init()
|
||||
|
@ -12,12 +13,11 @@ let kbnUrl;
|
|||
let $route;
|
||||
let $location;
|
||||
let $rootScope;
|
||||
let globalStateMock;
|
||||
let appState;
|
||||
|
||||
|
||||
function init() {
|
||||
ngMock.module('kibana/url', 'kibana', function ($provide) {
|
||||
ngMock.module('kibana/url', 'kibana', function ($provide, PrivateProvider) {
|
||||
$provide.service('$route', function () {
|
||||
return {
|
||||
reload: _.noop
|
||||
|
@ -25,19 +25,10 @@ function init() {
|
|||
});
|
||||
|
||||
appState = { destroy: sinon.stub() };
|
||||
$provide.service('getAppState', function () {
|
||||
return function () {
|
||||
return appState;
|
||||
};
|
||||
});
|
||||
|
||||
$provide.service('globalState', function () {
|
||||
globalStateMock = new MockState();
|
||||
globalStateMock.removeFromUrl = function (url) {
|
||||
return url;
|
||||
};
|
||||
|
||||
return globalStateMock;
|
||||
PrivateProvider.swap(AppStateProvider, $decorate => {
|
||||
const AppState = $decorate();
|
||||
AppState.getAppState = () => appState;
|
||||
return AppState;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -433,7 +424,7 @@ describe('kbnUrl', function () {
|
|||
|
||||
it('returns false if the passed url doesn\'t match the current route', function () {
|
||||
next.path = '/not current';
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
|
||||
describe('if the passed url does match the route', function () {
|
||||
|
@ -441,14 +432,14 @@ describe('kbnUrl', function () {
|
|||
describe('and the path is the same', function () {
|
||||
describe('and the search params are the same', function () {
|
||||
it('returns true', function () {
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(true);
|
||||
});
|
||||
});
|
||||
describe('but the search params are different', function () {
|
||||
it('returns false', function () {
|
||||
next.search = {};
|
||||
prev.search = { q: 'search term' };
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -460,14 +451,14 @@ describe('kbnUrl', function () {
|
|||
|
||||
describe('and the search params are the same', function () {
|
||||
it('returns false', function () {
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
});
|
||||
describe('but the search params are different', function () {
|
||||
it('returns false', function () {
|
||||
next.search = {};
|
||||
prev.search = { q: 'search term' };
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -481,14 +472,14 @@ describe('kbnUrl', function () {
|
|||
describe('and the path is the same', function () {
|
||||
describe('and the search params are the same', function () {
|
||||
it('returns true', function () {
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(true);
|
||||
});
|
||||
});
|
||||
describe('but the search params are different', function () {
|
||||
it('returns true', function () {
|
||||
next.search = {};
|
||||
prev.search = { q: 'search term' };
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -500,14 +491,14 @@ describe('kbnUrl', function () {
|
|||
|
||||
describe('and the search params are the same', function () {
|
||||
it('returns false', function () {
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
});
|
||||
describe('but the search params are different', function () {
|
||||
it('returns false', function () {
|
||||
next.search = {};
|
||||
prev.search = { q: 'search term' };
|
||||
expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false);
|
||||
expect(kbnUrl._shouldAutoReload(next, prev, $route)).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,12 +3,12 @@ import 'ui/filters/uriescape';
|
|||
import 'ui/filters/rison';
|
||||
import uiModules from 'ui/modules';
|
||||
import rison from 'rison-node';
|
||||
|
||||
import AppStateProvider from 'ui/state_management/app_state';
|
||||
|
||||
uiModules.get('kibana/url')
|
||||
.service('kbnUrl', function (Private) { return Private(KbnUrlProvider); });
|
||||
|
||||
function KbnUrlProvider($route, $location, $rootScope, globalState, $parse, getAppState) {
|
||||
function KbnUrlProvider($injector, $location, $rootScope, $parse, Private) {
|
||||
let self = this;
|
||||
|
||||
/**
|
||||
|
@ -162,21 +162,25 @@ function KbnUrlProvider($route, $location, $rootScope, globalState, $parse, getA
|
|||
search: $location.search()
|
||||
};
|
||||
|
||||
if (self._shouldAutoReload(next, prev)) {
|
||||
let appState = getAppState();
|
||||
if (appState) appState.destroy();
|
||||
if ($injector.has('$route')) {
|
||||
const $route = $injector.get('$route');
|
||||
|
||||
reloading = $rootScope.$on('$locationChangeSuccess', function () {
|
||||
// call the "unlisten" function returned by $on
|
||||
reloading();
|
||||
reloading = false;
|
||||
if (self._shouldAutoReload(next, prev, $route)) {
|
||||
const appState = Private(AppStateProvider).getAppState();
|
||||
if (appState) appState.destroy();
|
||||
|
||||
$route.reload();
|
||||
});
|
||||
reloading = $rootScope.$on('$locationChangeSuccess', function () {
|
||||
// call the "unlisten" function returned by $on
|
||||
reloading();
|
||||
reloading = false;
|
||||
|
||||
$route.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self._shouldAutoReload = function (next, prev) {
|
||||
self._shouldAutoReload = function (next, prev, $route) {
|
||||
if (reloading) return false;
|
||||
|
||||
let route = $route.current && $route.current.$$route;
|
||||
|
|
|
@ -9,18 +9,22 @@ describe('slugifyId()', function () {
|
|||
['test?test', 'test-questionmark-test'],
|
||||
['test=test', 'test-equal-test'],
|
||||
['test&test', 'test-ampersand-test'],
|
||||
['test%test', 'test-percent-test'],
|
||||
['test / test', 'test-slash-test'],
|
||||
['test ? test', 'test-questionmark-test'],
|
||||
['test = test', 'test-equal-test'],
|
||||
['test & test', 'test-ampersand-test'],
|
||||
['test % test', 'test-percent-test'],
|
||||
['test / ^test', 'test-slash-^test'],
|
||||
['test ? test', 'test-questionmark-test'],
|
||||
['test = test', 'test-equal-test'],
|
||||
['test & test', 'test-ampersand-test'],
|
||||
['test % test', 'test-percent-test'],
|
||||
['test/test/test', 'test-slash-test-slash-test'],
|
||||
['test?test?test', 'test-questionmark-test-questionmark-test'],
|
||||
['test&test&test', 'test-ampersand-test-ampersand-test'],
|
||||
['test=test=test', 'test-equal-test-equal-test']
|
||||
['test=test=test', 'test-equal-test-equal-test'],
|
||||
['test%test%test', 'test-percent-test-percent-test']
|
||||
];
|
||||
|
||||
_.each(fixtures, function (fixture) {
|
||||
|
|
|
@ -6,7 +6,8 @@ export default function (id) {
|
|||
'/' : '-slash-',
|
||||
'\\?' : '-questionmark-',
|
||||
'\\&' : '-ampersand-',
|
||||
'=' : '-equal-'
|
||||
'=' : '-equal-',
|
||||
'%' : '-percent-'
|
||||
};
|
||||
_.each(trans, function (val, key) {
|
||||
let regex = new RegExp(key, 'g');
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import d3 from 'd3';
|
||||
import angular from 'angular';
|
||||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
import VislibVisProvider from 'ui/vislib/vis';
|
||||
|
|
|
@ -95,10 +95,9 @@ export default function YAxisFactory(Private) {
|
|||
* Return the domain for log scale, i.e. the extent of the log scale.
|
||||
* Log scales must begin at 1 since the log(0) = -Infinity
|
||||
*
|
||||
* @param scale
|
||||
* @param yMin
|
||||
* @param yMax
|
||||
* @returns {*[]}
|
||||
* @param {Number} min
|
||||
* @param {Number} max
|
||||
* @returns {Array}
|
||||
*/
|
||||
YAxis.prototype._logDomain = function (min, max) {
|
||||
if (min < 0 || max < 0) return this._throwLogScaleValuesError();
|
||||
|
|
|
@ -93,19 +93,13 @@ export default function VisFactory(Private) {
|
|||
try {
|
||||
this.handler[method]();
|
||||
} catch (error) {
|
||||
// If involving height and width of the container, log error to screen.
|
||||
// Because we have to wait for the DOM element to initialize, we do not
|
||||
// want to throw an error when the DOM `el` is zero
|
||||
if (error instanceof errors.ContainerTooSmall ||
|
||||
error instanceof errors.InvalidWiggleSelection ||
|
||||
error instanceof errors.InvalidLogScaleValues ||
|
||||
error instanceof errors.PieContainsAllZeros ||
|
||||
error instanceof errors.NotEnoughData ||
|
||||
error instanceof errors.NoResults) {
|
||||
this.handler.error(error.message);
|
||||
|
||||
if (error instanceof errors.KbnError) {
|
||||
error.displayToScreen(this.handler);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ import d3 from 'd3';
|
|||
import _ from 'lodash';
|
||||
import VislibVisualizationsChartProvider from 'ui/vislib/visualizations/_chart';
|
||||
import VislibComponentsTooltipProvider from 'ui/vislib/components/tooltip';
|
||||
import errors from 'ui/errors';
|
||||
|
||||
export default function PointSeriesChartProvider(Private) {
|
||||
|
||||
let Chart = Private(VislibVisualizationsChartProvider);
|
||||
|
@ -68,13 +70,18 @@ export default function PointSeriesChartProvider(Private) {
|
|||
}));
|
||||
};
|
||||
|
||||
PointSeriesChart.prototype._invalidLogScaleValues = function (data) {
|
||||
return data.series && data.series.some(function (d) {
|
||||
return d.values && d.values.some(function (e) {
|
||||
return e.y < 1;
|
||||
});
|
||||
});
|
||||
|
||||
PointSeriesChart.prototype.validateDataCompliesWithScalingMethod = function (data) {
|
||||
const invalidLogScale = data.series && data.series.some(valuesSmallerThanOne);
|
||||
if (this._attr.scale === 'log' && invalidLogScale) {
|
||||
throw new errors.InvalidLogScaleValues();
|
||||
}
|
||||
};
|
||||
function valuesSmallerThanOne(d) {
|
||||
return d.values && d.values.some(e => e.y < 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates rects to show buckets outside of the ordered.min and max, returns rects
|
||||
|
|
|
@ -3,13 +3,10 @@ import _ from 'lodash';
|
|||
import $ from 'jquery';
|
||||
import moment from 'moment';
|
||||
import errors from 'ui/errors';
|
||||
import VislibLibDataProvider from 'ui/vislib/lib/data';
|
||||
import VislibVisualizationsPointSeriesChartProvider from 'ui/vislib/visualizations/_point_series_chart';
|
||||
import VislibVisualizationsTimeMarkerProvider from 'ui/vislib/visualizations/time_marker';
|
||||
export default function ColumnChartFactory(Private) {
|
||||
|
||||
let DataClass = Private(VislibLibDataProvider);
|
||||
|
||||
let PointSeriesChart = Private(VislibVisualizationsPointSeriesChartProvider);
|
||||
let TimeMarker = Private(VislibVisualizationsTimeMarkerProvider);
|
||||
|
||||
|
@ -118,7 +115,6 @@ export default function ColumnChartFactory(Private) {
|
|||
let yScale = this.handler.yAxis.yScale;
|
||||
let height = yScale.range()[0];
|
||||
let yMin = this.handler.yAxis.yScale.domain()[0];
|
||||
let self = this;
|
||||
|
||||
let barWidth;
|
||||
if (data.ordered && data.ordered.date) {
|
||||
|
@ -178,7 +174,6 @@ export default function ColumnChartFactory(Private) {
|
|||
ColumnChart.prototype.addGroupedBars = function (bars) {
|
||||
let xScale = this.handler.xAxis.xScale;
|
||||
let yScale = this.handler.yAxis.yScale;
|
||||
let yMin = this.handler.yAxis.yMin;
|
||||
let data = this.chartData;
|
||||
let n = data.series.length;
|
||||
let height = yScale.range()[0];
|
||||
|
@ -263,7 +258,6 @@ export default function ColumnChartFactory(Private) {
|
|||
let margin = this._attr.margin;
|
||||
let elWidth = this._attr.width = $elem.width();
|
||||
let elHeight = this._attr.height = $elem.height();
|
||||
let yMin = this.handler.yAxis.yMin;
|
||||
let yScale = this.handler.yAxis.yScale;
|
||||
let xScale = this.handler.xAxis.xScale;
|
||||
let minWidth = 20;
|
||||
|
@ -284,13 +278,22 @@ export default function ColumnChartFactory(Private) {
|
|||
|
||||
width = elWidth;
|
||||
height = elHeight - margin.top - margin.bottom;
|
||||
if (width < minWidth || height < minHeight) {
|
||||
throw new errors.ContainerTooSmall();
|
||||
}
|
||||
self.validateDataCompliesWithScalingMethod(data);
|
||||
|
||||
if (addTimeMarker) {
|
||||
timeMarker = new TimeMarker(times, xScale, height);
|
||||
}
|
||||
|
||||
if (width < minWidth || height < minHeight) {
|
||||
throw new errors.ContainerTooSmall();
|
||||
if (
|
||||
data.series.length > 1 &&
|
||||
(self._attr.scale === 'log' || self._attr.scale === 'square root') &&
|
||||
(self._attr.mode === 'stacked' || self._attr.mode === 'percentage')
|
||||
) {
|
||||
throw new errors.StackedBarChartConfig(`Cannot display ${self._attr.mode} bar charts for multiple data series \
|
||||
with a ${self._attr.scale} scaling method. Try 'linear' scaling instead.`);
|
||||
}
|
||||
|
||||
div = d3.select(this);
|
||||
|
|
|
@ -303,18 +303,16 @@ export default function LineChartFactory(Private) {
|
|||
|
||||
width = elWidth - margin.left - margin.right;
|
||||
height = elHeight - margin.top - margin.bottom;
|
||||
if (width < minWidth || height < minHeight) {
|
||||
throw new errors.ContainerTooSmall();
|
||||
}
|
||||
self.validateDataCompliesWithScalingMethod(data);
|
||||
|
||||
if (addTimeMarker) {
|
||||
timeMarker = new TimeMarker(times, xScale, height);
|
||||
}
|
||||
|
||||
if (self._attr.scale === 'log' && self._invalidLogScaleValues(data)) {
|
||||
throw new errors.InvalidLogScaleValues();
|
||||
}
|
||||
|
||||
if (width < minWidth || height < minHeight) {
|
||||
throw new errors.ContainerTooSmall();
|
||||
}
|
||||
|
||||
div = d3.select(el);
|
||||
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
ng-mouseenter="highlight($event)"
|
||||
ng-mouseleave="unhighlight($event)"
|
||||
data-label="{{legendData.label}}"
|
||||
class="legend-value color">
|
||||
class="legend-value color"
|
||||
>
|
||||
|
||||
<div class="legend-value-container">
|
||||
<div
|
||||
ng-click="showDetails = !showDetails"
|
||||
ng-class="showDetails ? 'legend-value-full' : 'legend-value-truncate'"
|
||||
class="legend-value-title">
|
||||
class="legend-value-title"
|
||||
tooltip="{{legendData.label}}"
|
||||
>
|
||||
<i class="fa fa-circle" ng-style="{color: getColor(legendData.label)}"></i> {{legendData.label}}
|
||||
</div>
|
||||
|
||||
|
@ -29,7 +32,8 @@
|
|||
<i ng-repeat="choice in colors"
|
||||
ng-click="setColor(legendData.label, choice)"
|
||||
ng-class="choice == getColor(legendData.label) ? 'fa-circle-o' : 'fa-circle'"
|
||||
ng-style="{color: choice}" class="fa dot">
|
||||
ng-style="{color: choice}" class="fa dot"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -102,10 +102,33 @@ describe('ui settings', function () {
|
|||
|
||||
describe('#getDefaults()', function () {
|
||||
it('is promised the default values', async function () {
|
||||
const { server, uiSettings, configGet } = instantiate();
|
||||
const {server, uiSettings, configGet} = instantiate();
|
||||
const defaults = await uiSettings.getDefaults();
|
||||
expect(isEqual(defaults, defaultsProvider())).to.equal(true);
|
||||
});
|
||||
|
||||
|
||||
describe('defaults for formatters', async function () {
|
||||
|
||||
const defaults = defaultsProvider();
|
||||
const mapping = JSON.parse(defaults['format:defaultTypeMap'].value);
|
||||
const expected = {
|
||||
ip: {id: 'ip', params: {}},
|
||||
date: {id: 'date', params: {}},
|
||||
number: {id: 'number', params: {}},
|
||||
boolean: {id: 'boolean', params: {}},
|
||||
_source: {id: '_source', params: {}},
|
||||
_default_: {id: 'string', params: {}}
|
||||
};
|
||||
|
||||
Object.keys(mapping).forEach(function (dataType) {
|
||||
it(`should configure ${dataType}`, function () {
|
||||
expect(expected.hasOwnProperty(dataType)).to.equal(true);
|
||||
expect(mapping[dataType].id).to.equal(expected[dataType].id);
|
||||
expect(JSON.stringify(mapping[dataType].params)).to.equal(JSON.stringify(expected[dataType].params));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUserProvided()', function () {
|
||||
|
|
|
@ -160,6 +160,7 @@ export default function defaultSettingsProvider() {
|
|||
"ip": { "id": "ip", "params": {} },
|
||||
"date": { "id": "date", "params": {} },
|
||||
"number": { "id": "number", "params": {} },
|
||||
"boolean": { "id": "boolean", "params": {} },
|
||||
"_source": { "id": "_source", "params": {} },
|
||||
"_default_": { "id": "string", "params": {} }
|
||||
}`,
|
||||
|
|
|
@ -62,6 +62,18 @@ bdd.describe('visualize app', function describeIndexTests() {
|
|||
bdd.describe('area charts', function indexPatternCreation() {
|
||||
var vizName1 = 'Visualization AreaChart';
|
||||
|
||||
bdd.it('should save and load with special characters', function pageHeader() {
|
||||
const vizNamewithSpecialChars = vizName1 + '/?&=%';
|
||||
return PageObjects.visualize.saveVisualization(vizNamewithSpecialChars)
|
||||
.then(function (message) {
|
||||
PageObjects.common.debug(`Saved viz message = ${message}`);
|
||||
expect(message).to.be(`Visualization Editor: Saved Visualization "${vizNamewithSpecialChars}"`);
|
||||
})
|
||||
.then(function testVisualizeWaitForToastMessageGone() {
|
||||
return PageObjects.visualize.waitForToastMessageGone();
|
||||
});
|
||||
});
|
||||
|
||||
bdd.it('should save and load', function pageHeader() {
|
||||
return PageObjects.visualize.saveVisualization(vizName1)
|
||||
.then(function (message) {
|
||||
|
|
|
@ -175,7 +175,7 @@ define(function (require) {
|
|||
method: 'GET'
|
||||
})
|
||||
.then(function (body) {
|
||||
expect(body.pipelines[0].id).to.be('kibana-logstash-*');
|
||||
expect(body).to.have.property('kibana-logstash-*');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue