diff --git a/Gruntfile.js b/Gruntfile.js index e921bfadfd12..77b2035bea58 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -29,7 +29,22 @@ module.exports = function (grunt) { '<%= package.homepage ? " * " + package.homepage + "\\n" : "" %>' + ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= package.author.company %>;' + ' Licensed <%= package.license %> */\n' - } + }, + + lessFiles: [ + '<%= src %>/kibana/components/*/*.less', + '<%= src %>/kibana/styles/main.less', + '<%= src %>/kibana/components/vislib/styles/main.less', + '<%= plugins %>/dashboard/styles/main.less', + '<%= plugins %>/discover/styles/main.less', + '<%= plugins %>/settings/styles/main.less', + '<%= plugins %>/visualize/styles/main.less', + '<%= plugins %>/visualize/styles/visualization.less', + '<%= plugins %>/visualize/styles/main.less', + '<%= plugins %>/table_vis/table_vis.less', + '<%= plugins %>/metric_vis/metric_vis.less', + '<%= plugins %>/markdown_vis/markdown_vis.less' + ] }; grunt.config.merge(config); diff --git a/docs/production.asciidoc b/docs/production.asciidoc index 724da60892a7..2da131424a39 100644 --- a/docs/production.asciidoc +++ b/docs/production.asciidoc @@ -24,7 +24,7 @@ If you are using Shield to authenticate Elasticsearch users, you need to provide the Kibana server with credentials so it can access the `.kibana` index and monitor the cluster. -To configure credentials the Kibana server, set the `kibana_elasticsearch_username` and +To configure credentials for the Kibana server, set the `kibana_elasticsearch_username` and `kibana_elasticsearch_password` properties in `kibana.yml`: ---- diff --git a/docs/setup.asciidoc b/docs/setup.asciidoc index fad929b628e1..72a1757f35a9 100644 --- a/docs/setup.asciidoc +++ b/docs/setup.asciidoc @@ -16,7 +16,7 @@ NOTE: If your Elasticsearch installation is protected by http://www.elastic.co/o === Install and Start Kibana To get Kibana up and running: -. Download the http://www.elastic.co/overview/kibana/installation/[Kibana 4 binary package] for your platform. +. Download the https://www.elastic.co/downloads/kibana[Kibana 4 binary package] for your platform. . Extract the `.zip` or `tar.gz` archive file. . Run Kibana from the install directory: `bin/kibana` (Linux/MacOSX) or `bin\kibana.bat` (Windows). @@ -35,7 +35,7 @@ To configure the Elasticsearch indices you want to access with Kibana: + image:images/Start-Page.jpg[Kibana start page] + -. Specify an index pattern that matches the name of one or more of your Elasticsearch indices. By default, Kibana guesses that you're you're working with data being fed into Elasticsearch by Logstash. If that's the case, you can use the default `logstash-*` as your index pattern. The asterisk (*) matches zero or more characters in an index's name. If your Elasticsearch indices follow some other naming convention, enter an appropriate pattern. The "pattern" can also simply be the name of a single index. +. Specify an index pattern that matches the name of one or more of your Elasticsearch indices. By default, Kibana guesses that you're working with data being fed into Elasticsearch by Logstash. If that's the case, you can use the default `logstash-*` as your index pattern. The asterisk (*) matches zero or more characters in an index's name. If your Elasticsearch indices follow some other naming convention, enter an appropriate pattern. The "pattern" can also simply be the name of a single index. . Select the index field that contains the timestamp that you want to use to perform time-based comparisons. Kibana reads the index mapping to list all of the fields that contain a timestamp. If your index doesn't have time-based data, disable the *Index contains time-based events* option. . If new indices are generated periodically and have a timestamp appended to the name, select the *Use event times to create index names* option and select the *Index pattern interval*. This improves search performance by enabling Kibana to search only those indices that could contain data in the time range you specify. This is primarily applicable if you are using Logstash to feed data into Elasticsearch. . Click *Create* to add the index pattern. This first pattern is automatically configured as the default. When you have more than one index pattern, you can designate which one to use as the default from *Settings > Indices*. diff --git a/src/kibana/components/agg_types/buckets/create_filter/range.js b/src/kibana/components/agg_types/buckets/create_filter/range.js index ee230d7028f2..f3b74853d829 100644 --- a/src/kibana/components/agg_types/buckets/create_filter/range.js +++ b/src/kibana/components/agg_types/buckets/create_filter/range.js @@ -4,10 +4,10 @@ define(function (require) { return function (aggConfig, key) { var splits = key.split(/\-/); var gte = Number(splits[0]); - var lte = Number(splits[1]); + var lt = Number(splits[1]); return buildRangeFilter(aggConfig.params.field, { gte: gte, - lte: lte + lt: lt }, aggConfig.vis.indexPattern); }; }; diff --git a/src/kibana/components/agg_types/controls/filters.html b/src/kibana/components/agg_types/controls/filters.html index ca3feea0e140..4f4569e9d3e1 100644 --- a/src/kibana/components/agg_types/controls/filters.html +++ b/src/kibana/components/agg_types/controls/filters.html @@ -1,6 +1,6 @@
- +
- Add filter + Add Filter
diff --git a/src/kibana/components/agg_types/metrics/cardinality.js b/src/kibana/components/agg_types/metrics/cardinality.js index 9ed33ddc38f7..bac71054a292 100644 --- a/src/kibana/components/agg_types/metrics/cardinality.js +++ b/src/kibana/components/agg_types/metrics/cardinality.js @@ -4,7 +4,7 @@ define(function (require) { return new MetricAggType({ name: 'cardinality', - title: 'Unique count', + title: 'Unique Count', makeLabel: function (aggConfig) { return 'Unique count of ' + aggConfig.params.field.displayName; }, diff --git a/src/kibana/components/filter_bar/lib/mapRange.js b/src/kibana/components/filter_bar/lib/mapRange.js index a55b1c2b9315..49a17ce8a5c6 100644 --- a/src/kibana/components/filter_bar/lib/mapRange.js +++ b/src/kibana/components/filter_bar/lib/mapRange.js @@ -9,9 +9,9 @@ define(function (require) { .get(filter.meta.index).then(function (indexPattern) { key = _.keys(filter.range)[0]; field = indexPattern.fields.byName[key]; - from = filter.range[key].gte || filter.range[key].gt; - to = filter.range[key].lte || filter.range[key].lt; + from = (filter.range[key].gte != null) ? filter.range[key].gte : filter.range[key].gt; from = field.format.convert(from); + to = (filter.range[key].lte != null) ? filter.range[key].lte : filter.range[key].lt; to = field.format.convert(to); value = from + ' to ' + to; return { key: key, value: value }; diff --git a/src/kibana/components/index_patterns/_flatten_hit.js b/src/kibana/components/index_patterns/_flatten_hit.js index a1857f5d4840..5c2275faf037 100644 --- a/src/kibana/components/index_patterns/_flatten_hit.js +++ b/src/kibana/components/index_patterns/_flatten_hit.js @@ -16,6 +16,6 @@ define(function (require) { } }); - return hit.$$_flattened = _.merge(source, fields, _.pick(hit, self.metaFields)); + return hit.$$_flattened = _.merge(source, fields, _.pick(hit, self.metaFields), _.pick(hit.fields, self.metaFields)); }; }); diff --git a/src/kibana/plugins/dashboard/components/panel/panel.js b/src/kibana/plugins/dashboard/components/panel/panel.js index 4c3397bb329f..dad79b878da1 100644 --- a/src/kibana/plugins/dashboard/components/panel/panel.js +++ b/src/kibana/plugins/dashboard/components/panel/panel.js @@ -6,7 +6,6 @@ define(function (require) { .get('app/dashboard') .directive('dashboardPanel', function (savedVisualizations, savedSearches, Notifier, Private, $compile) { var _ = require('lodash'); - var filterBarClickHandler = Private(require('components/filter_bar/filter_bar_click_handler')); var loadPanel = Private(require('plugins/dashboard/components/panel/lib/load_panel')); var notify = new Notifier(); diff --git a/src/kibana/plugins/discover/components/field_chooser/field_chooser.js b/src/kibana/plugins/discover/components/field_chooser/field_chooser.js index 3717d50a17d3..a19b7bfe7440 100644 --- a/src/kibana/plugins/discover/components/field_chooser/field_chooser.js +++ b/src/kibana/plugins/discover/components/field_chooser/field_chooser.js @@ -153,7 +153,8 @@ define(function (require) { schema: 'segment', params: { field: field.name, - size: config.get('discover:aggs:terms:size', 20) + size: config.get('discover:aggs:terms:size', 20), + orderBy: '2' } }; } @@ -165,17 +166,12 @@ define(function (require) { filters: $scope.state.filters || [], query: $scope.state.query || undefined, vis: { + type: type, aggs: [ agg, - {schema: 'metric', type: 'count'} + {schema: 'metric', type: 'count', 'id': '2'} ] - }, - metric: [{ - agg: 'count', - }], - segment: [agg], - group: [], - split: [], + } }) }); }; diff --git a/src/kibana/plugins/discover/controllers/discover.js b/src/kibana/plugins/discover/controllers/discover.js index a03aabfd6b86..b057a8c2c5c1 100644 --- a/src/kibana/plugins/discover/controllers/discover.js +++ b/src/kibana/plugins/discover/controllers/discover.js @@ -243,7 +243,7 @@ define(function (require) { $scope.searchSource.onError(function (err) { console.log(err); - notify.error('An error occured with your request. Reset your inputs and try again.'); + notify.error('An error occurred with your request. Reset your inputs and try again.'); }).catch(notify.fatal); function initForTime() { diff --git a/src/kibana/plugins/discover/index.html b/src/kibana/plugins/discover/index.html index 1ee99121b388..6bcbb946b566 100644 --- a/src/kibana/plugins/discover/index.html +++ b/src/kibana/plugins/discover/index.html @@ -93,13 +93,13 @@

Expand your time range

-

I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is not data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking the time picker in the top right corner of your screen. +

I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is no data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking the time picker in the top right corner of your screen.

Refine your query

- The search bar at the top allows Kibana uses Elasticsearch's support for Lucene Query String syntax. Let's say we're searching web server logs that have been parsed into a few fields. + The search bar at the top uses Elasticsearch's support for Lucene Query String syntax. Let's say we're searching web server logs that have been parsed into a few fields.

diff --git a/src/kibana/plugins/settings/sections/advanced/index.js b/src/kibana/plugins/settings/sections/advanced/index.js index d20202198807..8c5f8f210cbd 100644 --- a/src/kibana/plugins/settings/sections/advanced/index.js +++ b/src/kibana/plugins/settings/sections/advanced/index.js @@ -1,6 +1,8 @@ define(function (require) { var _ = require('lodash'); var configDefaults = require('components/config/defaults'); + var getValType = require('plugins/settings/sections/advanced/lib/get_val_type'); + require('plugins/settings/sections/advanced/advanced_row'); @@ -38,7 +40,7 @@ define(function (require) { var conf = { name: name, defVal: def.value, - type: (def.type || _.isArray(val) || typeof val), + type: getValType(def, val), description: def.description, value: val, }; diff --git a/src/kibana/plugins/settings/sections/advanced/lib/get_val_type.js b/src/kibana/plugins/settings/sections/advanced/lib/get_val_type.js new file mode 100644 index 000000000000..2ba250c72cf8 --- /dev/null +++ b/src/kibana/plugins/settings/sections/advanced/lib/get_val_type.js @@ -0,0 +1,22 @@ +define(function (require) { + var _ = require('lodash'); + + /** + * @param {object} advanced setting definition object + * @param {?} current value of the setting + * @returns {string} the type to use for determining the display and editor + */ + function getValType(def, value) { + if (def.type) { + return def.type; + } + + if (_.isArray(value) || _.isArray(def.value)) { + return 'array'; + } + + return (typeof def.value); + } + + return getValType; +}); diff --git a/src/kibana/require.config.js b/src/kibana/require.config.js index fd4c68a54081..c7334130585c 100644 --- a/src/kibana/require.config.js +++ b/src/kibana/require.config.js @@ -15,6 +15,7 @@ require.config({ 'angular-route': 'bower_components/angular-route/angular-route', 'angular-ui-ace': 'bower_components/angular-ui-ace/ui-ace', ace: 'bower_components/ace-builds/src-noconflict/ace', + 'ace-json': 'bower_components/ace-builds/src-noconflict/mode-json', angular: 'bower_components/angular/angular', async: 'bower_components/async/lib/async', bower_components: 'bower_components', @@ -46,7 +47,8 @@ require.config({ 'elasticsearch': ['angular'], 'angular-bootstrap': ['angular'], 'angular-bindonce': ['angular'], - 'angular-ui-ace': ['angular', 'ace'], + 'ace-json': ['ace'], + 'angular-ui-ace': ['angular', 'ace', 'ace-json'], 'ng-clip': ['angular', 'zeroclipboard'], inflection: { exports: 'inflection' diff --git a/tasks/build.js b/tasks/build.js index b84b34c3f4cc..3964eb61d3d9 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -4,7 +4,7 @@ module.exports = function (grunt) { 'clean:target', 'clean:build', 'require_css_deps:copy', - 'less', + 'less:build', 'copy:kibana_src', 'clean:dev_only_plugins', 'touch_config', diff --git a/tasks/config/less.js b/tasks/config/less.js index 21e9c640f9a2..5e2b10945c73 100644 --- a/tasks/config/less.js +++ b/tasks/config/less.js @@ -1,26 +1,26 @@ -var bc = require('path').join(__dirname, '../../src/kibana/bower_components'); - module.exports = { - src: { - src: [ - '<%= src %>/kibana/components/*/*.less', - '<%= src %>/kibana/styles/main.less', - '<%= src %>/kibana/components/vislib/styles/main.less', - '<%= plugins %>/dashboard/styles/main.less', - '<%= plugins %>/discover/styles/main.less', - '<%= plugins %>/settings/styles/main.less', - '<%= plugins %>/visualize/styles/main.less', - '<%= plugins %>/visualize/styles/visualization.less', - '<%= plugins %>/visualize/styles/main.less', - '<%= plugins %>/table_vis/table_vis.less', - '<%= plugins %>/metric_vis/metric_vis.less', - '<%= plugins %>/markdown_vis/markdown_vis.less' - ], + options: { + sourceMapBasepath: '<%= src %>/kibana', + sourceMapRootpath: '/', + ieCompat: false, + paths: [ + '<%= src %>/kibana/bower_components/lesshat/build/' + ] + }, + dev: { + src: '<%= lessFiles %>', expand: true, ext: '.css', options: { - ieCompat: false, - paths: [bc + '/lesshat/build/'] + sourceMap: true + } + }, + build: { + src: '<%= lessFiles %>', + expand: true, + ext: '.css', + options: { + sourceMap: false } } }; diff --git a/tasks/config/watch.js b/tasks/config/watch.js index 95e107eba900..86e777f29927 100644 --- a/tasks/config/watch.js +++ b/tasks/config/watch.js @@ -15,7 +15,7 @@ module.exports = function (grunt) { '<%= app %>/**/components/**/*.less', '<%= app %>/**/components/vislib/components/styles/**/*.less' ], - tasks: ['less'] + tasks: ['less:dev'] }, jade: { diff --git a/tasks/dev.js b/tasks/dev.js index 2167bc6804e3..ac9550c40200 100644 --- a/tasks/dev.js +++ b/tasks/dev.js @@ -3,7 +3,7 @@ module.exports = function (grunt) { grunt.registerTask('dev', function () { var tasks = [ - 'less', + 'less:dev', 'jade', 'esvm:dev', 'maybe_start_kibana', diff --git a/tasks/test.js b/tasks/test.js index 941b5803a2cc..bdb558823c08 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -28,7 +28,7 @@ module.exports = function (grunt) { 'jshint', 'maybe_start_kibana', 'jade', - 'less' + 'less:build' ]; addTestTask(tasks); if (process.env.TRAVIS) tasks.unshift('esvm:dev'); diff --git a/test/unit/specs/components/agg_types/buckets/create_filter/range.js b/test/unit/specs/components/agg_types/buckets/create_filter/range.js index 49fbe7c7a7ca..b8d26b62e8de 100644 --- a/test/unit/specs/components/agg_types/buckets/create_filter/range.js +++ b/test/unit/specs/components/agg_types/buckets/create_filter/range.js @@ -38,7 +38,7 @@ define(function (require) { expect(filter.meta).to.have.property('index', indexPattern.id); expect(filter.range).to.have.property('bytes'); expect(filter.range.bytes).to.have.property('gte', 1024.0); - expect(filter.range.bytes).to.have.property('lte', 2048.0); + expect(filter.range.bytes).to.have.property('lt', 2048.0); }); }); diff --git a/test/unit/specs/plugins/settings/sections/advanced/lib/get_val_type.js b/test/unit/specs/plugins/settings/sections/advanced/lib/get_val_type.js new file mode 100644 index 000000000000..5d64ae59f61d --- /dev/null +++ b/test/unit/specs/plugins/settings/sections/advanced/lib/get_val_type.js @@ -0,0 +1,32 @@ +define(function (require) { + var getValType = require('plugins/settings/sections/advanced/lib/get_val_type'); + describe('Settings', function () { + describe('Advanced', function () { + describe('getValType(def, val)', function () { + it('should be a function', function () { + expect(getValType).to.be.a(Function); + }); + + it('should return the explicitly defined type of a setting', function () { + expect(getValType({type: 'string'})).to.be('string'); + expect(getValType({type: 'json'})).to.be('json'); + expect(getValType({type: 'string', value: 5})).to.be('string'); + }); + + it('should return array if the value is an Array and there is no defined type', function () { + expect(getValType({type: 'string'}, [1, 2, 3])).to.be('string'); + expect(getValType({type: 'json', value: [1, 2, 3]})).to.be('json'); + + expect(getValType({value: 'someString'}, [1, 2, 3])).to.be('array'); + expect(getValType({value: [1, 2, 3]}, 'someString')).to.be('array'); + + }); + + it('should return the type of the default value if there is no type and it is not an array', function () { + expect(getValType({value: 'someString'})).to.be('string'); + expect(getValType({value: 'someString'}, 42)).to.be('string'); + }); + }); + }); + }); +});