Merge branch 'master' into vislib/refactor

Conflicts:
	.gitignore
This commit is contained in:
Spencer Alger 2014-09-11 09:11:03 -07:00
commit 0bfdaf814c
112 changed files with 1907 additions and 481 deletions

View file

@ -1,3 +1,3 @@
{
"directory": "./src/bower_components"
}
"directory": "./src/kibana/bower_components"
}

5
.gitignore vendored
View file

@ -1,7 +1,8 @@
.DS_Store
node_modules
src/bower_components
bower_components
**/*.css
trash
build
target
target
.jruby

1
.ruby-version Normal file
View file

@ -0,0 +1 @@
1.9.3-p547

View file

@ -12,9 +12,12 @@ module.exports = function (grunt) {
target: __dirname + '/target', // location of the compressed build targets
buildApp: __dirname + '/build/kibana', // build directory for the app
jrubyVersion: '1.7.14',
jrubyPath: __dirname + '/.jruby',
unitTestDir: __dirname + '/test/unit',
testUtilsDir: __dirname + '/test/utils',
bowerComponentsDir: __dirname + '/src/bower_components',
bowerComponentsDir: __dirname + '/src/kibana/bower_components',
meta: {
banner: '/*! <%= package.name %> - v<%= package.version %> - ' +
@ -36,4 +39,4 @@ module.exports = function (grunt) {
// load task definitions
grunt.loadTasks('tasks');
};
};

7
LICENSE.md Normal file
View file

@ -0,0 +1,7 @@
Copyright 2012-2014 Elasticsearch BV
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

View file

@ -20,32 +20,32 @@
"tests"
],
"dependencies": {
"requirejs": "~2.1.10",
"angular": "~1.2.14",
"lodash": "~2.4.1",
"d3": "~3.4.8",
"angular-route": "~1.2.14",
"gridster": "~0.5.0",
"angular-mocks": "~1.2.14",
"font-awesome": "~4.0.3",
"requirejs-text": "~2.0.10",
"async": "~0.2.10",
"bootstrap": "~3.1.1",
"jquery": "~2.1.0",
"moment": "~2.5.1",
"require-css": "~0.1.2",
"angular-bootstrap": "~0.10.0",
"jsonpath": "*",
"moment-timezone": "~0.0.3",
"angular-bindonce": "~0.3.1",
"angular-ui-ace": "bower",
"angular-bootstrap": "~0.10.0",
"angular-elastic": "~2.3.3",
"inflection": "~1.3.5",
"FileSaver": "*",
"elasticsearch": "*",
"angular-mocks": "~1.2.14",
"angular-route": "~1.2.14",
"angular-ui-ace": "bower",
"async": "~0.2.10",
"bluebird": "~2.1.3",
"bootstrap": "~3.1.1",
"d3": "~3.4.8",
"elasticsearch": "*",
"Faker": "~1.1.0",
"FileSaver": "*",
"font-awesome": "~4.0.3",
"gridster": "~0.5.0",
"inflection": "~1.3.5",
"jquery": "~2.1.0",
"jsonpath": "*",
"lesshat": "~3.0.2",
"Faker": "~1.1.0"
"lodash": "~2.4.1",
"moment": "~2.5.1",
"moment-timezone": "~0.0.3",
"require-css": "~0.1.2",
"requirejs": "~2.1.10",
"requirejs-text": "~2.0.10"
},
"devDependencies": {}
}

View file

@ -20,15 +20,21 @@
"grunt-contrib-requirejs": "~0.4.4",
"grunt-contrib-watch": "~0.5.3",
"grunt-mocha": "~0.4.10",
"grunt-replace": "^0.7.9",
"grunt-run": "^0.2.3",
"http-proxy": "~1.1.4",
"husky": "~0.6.0",
"istanbul": "~0.2.4",
"load-grunt-config": "~0.7.0",
"lodash": "~2.4.1",
"mkdirp": "^0.5.0",
"mocha": "~1.20.1",
"path-browserify": "0.0.0",
"progress": "^1.1.8",
"request": "^2.40.0",
"requirejs": "~2.1.14",
"rjs-build-analysis": "0.0.3"
"rjs-build-analysis": "0.0.3",
"tar": "^1.0.1"
},
"scripts": {
"test": "grunt test",

View file

@ -1,30 +0,0 @@
require "java"
require "warbler"
HERE = File.expand_path(File.dirname(__FILE__))
task "default" => "jar:run"
namespace "jar" do
desc "Run the project jar file"
task "run" => "jar" do
exec("cd #{HERE} && rm -rf /tmp/kibana* && cp kibana.jar /tmp && cd /tmp && unzip -o kibana.jar 'kibana/public/*' && unzip -o kibana.jar kibana/config/web.ru && env PUBLIC_FOLDER=/tmp/kibana/public java -server -jar kibana.jar kibana/config/web.ru")
end
end
desc "Create the project jar file"
task "jar" do
system("cd #{HERE} && jruby -S warble")
end
# desc "Watch for changes"
# task "watch" => "vendor/fswatch" do
# system("killall fswatch")
# system("fswatch #{HERE}/lib \"bash -c \\\"kill -SIGUSR2 \\\`ps u|grep [o]rg.jruby.Main|grep bin/puma|awk {\'print \\\$2\'}\\\`\\\"\" &")
# end
desc "Run the project from jruby"
# task "run" => "watch" do
task "run" do
exec("cd #{HERE} && jruby -S bundle exec jruby -S bin/kibana config/web.ru")
end

View file

@ -1,38 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'puma' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0"
HERE = File.expand_path(File.dirname(__FILE__))
if ARGV.first
str = ARGV.first
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
if str =~ /\A_(.*)_\z/
version = $1
ARGV.shift
end
end
# Include the puma config unless it's been overriden
unless ARGV.include?('-C')
ARGV << '-C'
ARGV << "#{HERE}/../config/puma.rb"
end
# Include the rack config if it hasn't been included
if (ARGV.grep(/config\/web\.ru/)).empty?
ARGV << "#{HERE}/../config/web.ru"
end
print ARGV, "\n"
gem 'puma', version
load Gem.bin_path('puma', 'puma', version)

View file

@ -1,2 +0,0 @@
port 8000

View file

@ -1,12 +0,0 @@
# Add the libs directory to the load path
ROOT = File.expand_path("#{File.dirname(__FILE__)}/../")
$LOAD_PATH.unshift(ROOT)
require "rubygems"
require "bundler/setup"
# Require the application
require "#{ROOT}/lib/app"
# Run the application
run Kibana::App

View file

@ -1,27 +0,0 @@
# Add the root of the project to the $LOAD_PATH, For some reason it seems
# to be getting lost when we use warble to make the jar. This fixes it :D
$LOAD_PATH.unshift(ROOT)
require "rack/reverse_proxy"
require "routes/home"
require "routes/api"
module Kibana
class App < Sinatra::Base
configure do
set :root, ROOT
set :public_folder, "#{ROOT}/public"
set :httponly, true
end
# Rack middleware goes here
use Rack::ReverseProxy do
reverse_proxy /^\/elasticsearch(.*)$/, 'http://localhost:9200$1'
end
# Routes go here
use Routes::Home
use Routes::Api
end
end

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Welcome to the Future Home of Kibana</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12 text-center" style="padding-top: 40px;">
<h1>Welcome to the Future Home of Kibana</h1>
<p>This is the server component of Kibana. It's just a quick prototype of the things we need.</p>
<p><a href="/test.html">Static Server</a></p>
<p><a href="/api/foo">Server Side APIs</a></p>
<p><a href="/elasticsearch">Elasticsearch Proxy</a></p>
<h3>Much more coming soon...</h3>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,9 +0,0 @@
<html>
<head>
<title>This is a test file</title>
</head>
<body>
<h1>This is a test</h1>
<p>This should work outside of anything else.</p>
</body>
</html>

View file

@ -1,16 +0,0 @@
require "routes/base"
require "lib/helpers"
module Kibana
module Routes
class Api < Base
helpers Kibana::Helpers
get "/api/foo" do
json :foo => doSomething()
end
end
end
end

View file

@ -1,15 +0,0 @@
require "sinatra/base"
require "sinatra/json"
module Kibana
module Routes
class Base < Sinatra::Base
helpers Sinatra::JSON
configure do
# Confirgure stuffs here
end
end
end
end

View file

@ -1,13 +0,0 @@
require "routes/base"
module Kibana
module Routes
class Home < Base
get "/" do
File.read(File.join(ROOT, 'public', 'index.html'))
end
end
end
end

View file

@ -25,7 +25,7 @@ define(function (require) {
require('routes')
.when('/dashboard', {
templateUrl: 'kibana/apps/dashboard/index.html',
template: require('text!apps/dashboard/index.html'),
resolve: {
dash: function (savedDashboards) {
return savedDashboards.get();
@ -33,7 +33,7 @@ define(function (require) {
}
})
.when('/dashboard/:id', {
templateUrl: 'kibana/apps/dashboard/index.html',
template: require('text!apps/dashboard/index.html'),
resolve: {
dash: function (savedDashboards, Notifier, $route, $location, courier) {
return savedDashboards.get($route.current.params.id)
@ -42,7 +42,7 @@ define(function (require) {
}
});
app.directive('dashboardApp', function (Notifier, courier, savedVisualizations, appStateFactory, timefilter) {
app.directive('dashboardApp', function (Notifier, courier, savedVisualizations, appStateFactory, timefilter, kbnUrl) {
return {
controller: function ($scope, $route, $routeParams, $location, configFile) {
var notify = new Notifier({
@ -113,7 +113,7 @@ define(function (require) {
.then(function () {
notify.info('Saved Dashboard as "' + dash.title + '"');
if (dash.id !== $routeParams.id) {
$location.url('/dashboard/' + encodeURIComponent(dash.id));
kbnUrl.change('/dashboard/{{id}}', {id: dash.id});
}
})
.catch(notify.fatal);

View file

@ -13,7 +13,7 @@ define(function (require) {
});
// This is the only thing that gets injected into controllers
module.service('savedDashboards', function (Promise, SavedDashboard, config, es) {
module.service('savedDashboards', function (Promise, SavedDashboard, config, es, kbnUrl) {
// Returns a single dashboard by ID, should be the name of the dashboard
this.get = function (id) {
@ -23,7 +23,7 @@ define(function (require) {
};
this.urlFor = function (id) {
return '#/dashboard/' + encodeURIComponent(id);
return kbnUrl.eval('#/dashboard/{{id}}', {id: id});
};
this.delete = function (ids) {

View file

@ -46,7 +46,7 @@ define(function (require) {
});
app.controller('discover', function ($scope, config, courier, $route, $window, savedSearches, savedVisualizations,
Notifier, $location, globalState, appStateFactory, timefilter, Promise, Private) {
Notifier, $location, globalState, appStateFactory, timefilter, Promise, Private, kbnUrl) {
var Vis = Private(require('components/vis/vis'));
var SegmentedFetch = Private(require('apps/discover/_segmented_fetch'));
@ -110,7 +110,8 @@ define(function (require) {
$state.index = config.get('defaultIndex');
} else {
notify.warning(reason + 'Please set a default index to continue.');
$location.url('/settings/indices');
kbnUrl.change('/settings/indices');
return;
}
}
@ -227,7 +228,7 @@ define(function (require) {
.then(function () {
notify.info('Saved Data Source "' + savedSearch.title + '"');
if (savedSearch.id !== $route.current.params.id) {
$location.url(globalState.writeToUrl('/discover/' + encodeURIComponent(savedSearch.id)));
kbnUrl.change('/discover/{{id}}', { id: savedSearch.id });
}
});
})
@ -388,7 +389,7 @@ define(function (require) {
};
$scope.newQuery = function () {
$location.url('/discover');
kbnUrl.change('/discover');
};
$scope.updateDataSource = function () {

View file

@ -19,10 +19,8 @@ define(function (require) {
scope: {
fields: '=',
toggle: '=',
refresh: '=',
data: '=',
state: '=',
updateFilterInQuery: '=filter',
searchSource: '='
},
template: html,
@ -165,8 +163,7 @@ define(function (require) {
count: 5,
grouped: false
});
var indexPattern = $scope.searchSource.get('index');
indexPattern.popularizeField(field.name, 1);
$scope.increaseFieldCounter(field, 1);
} else {
delete field.details;
}

View file

@ -29,23 +29,28 @@ define(function (require) {
if ($scope.mapping[column] && !$scope.mapping[column].indexed) return;
var sorting = $scope.sorting;
var defaultClass = ['fa', 'fa-sort', 'table-header-sortchange'];
if (!sorting) return [];
if (!sorting) return defaultClass;
if (column === sorting[0]) {
return ['fa', sorting[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down'];
} else {
return ['fa', 'fa-sort', 'table-header-sortchange'];
return defaultClass;
}
};
$scope.moveLeft = function (column) {
var index = _.indexOf($scope.columns, column);
if (index === 0) return;
_.move($scope.columns, index, --index);
};
$scope.moveRight = function (column) {
var index = _.indexOf($scope.columns, column);
if (index === $scope.columns.length - 1) return;
_.move($scope.columns, index, ++index);
};
@ -112,7 +117,6 @@ define(function (require) {
return {
restrict: 'A',
scope: {
fields: '=',
columns: '=',
filtering: '=',
mapping: '=',
@ -139,27 +143,14 @@ define(function (require) {
$scope.maxLength = 250;
}
// for now, rows are "tracked" by their index, but this could eventually
// be configured so that changing the order of the rows won't prevent
// them from staying open on update
function rowId(row) {
var id = $scope.rows.indexOf(row);
return ~id ? id : null;
}
// inverse of rowId()
function rowForId(id) {
return $scope.rows[id];
}
// toggle display of the rows details, a full list of the fields from each row
$scope.toggleRow = function (row, event) {
$scope.toggleRow = function () {
var row = $scope.row;
var id = row._id;
$scope.open = !$scope.open;
var $tr = $(event.delegateTarget.parentElement);
var $tr = element;
var $detailsTr = $tr.next();
///
@ -169,7 +160,7 @@ define(function (require) {
$detailsTr.toggle($scope.open);
// Change the caret icon
var $toggleIcon = $($(event.delegateTarget).children('i')[0]);
var $toggleIcon = $(element.children().first().find('i')[0]);
$toggleIcon.toggleClass('fa-caret-down');
$toggleIcon.toggleClass('fa-caret-right');
@ -207,7 +198,12 @@ define(function (require) {
$scope.filtering(field, row._source[field] || row[field], operation);
};
$scope.$watch('columns', function () {
$scope.$watch('columns', function (columns) {
element.empty();
createSummaryRow($scope.row, $scope.row._id);
});
$scope.$watch('timefield', function (timefield) {
element.empty();
createSummaryRow($scope.row, $scope.row._id);
});
@ -216,7 +212,7 @@ define(function (require) {
function createSummaryRow(row, id) {
var expandTd = $('<td>').html('<i class="fa fa-caret-right"></span>')
.attr('ng-click', 'toggleRow(row, $event)');
.attr('ng-click', 'toggleRow()');
$compile(expandTd)($scope);
element.append(expandTd);
@ -240,11 +236,7 @@ define(function (require) {
*/
function _displayField(el, row, field, truncate) {
var val = _getValForField(row, field, truncate);
if (val instanceof DOMNode) {
el.append(val);
} else {
el.text(val);
}
el.text(val);
return el;
}
@ -266,17 +258,9 @@ define(function (require) {
// undefined and null should just be an empty string
val = (val == null) ? '' : val;
// truncate
// truncate the column text, not the details
if (typeof val === 'string' && val.length > $scope.maxLength) {
if (untruncate) {
var complete = val;
val = document.createElement('kbn-truncated');
val.setAttribute('orig', complete);
val.setAttribute('length', $scope.maxLength);
val = $compile(val)($scope)[0];// return the actual element
} else {
val = val.substring(0, $scope.maxLength) + '...';
}
val = val.substring(0, $scope.maxLength) + '...';
}
return val;

View file

@ -3,7 +3,8 @@
<tbody>
<tr ng-repeat="row in rows |limitTo:limit track by row._index+row._id"
kbn-table-row="row"
columns="columns" mapping="mapping" sorting="sorting" timefield="timefield" max-length="maxLength" filtering="filtering"></tr>
columns="columns" mapping="mapping" sorting="sorting" timefield="timefield" max-length="maxLength" filtering="filtering"
class="discover-table-row"></tr>
</tbody>
</table>
<kbn-infinite-scroll more="addRows"></kbn-infinite-scroll>

View file

@ -3,7 +3,7 @@
<span ng-click="sort(timefield)">Time <i ng-class="headerClass(timefield)"></i></span>
</th>
<th ng-repeat="name in columns">
<span ng-click="sort(name)">
<span ng-click="sort(name)" class="table-header-name">
{{name}} <i ng-class="headerClass(name)"></i>
</span>
<span class="table-header-move">

View file

@ -15,7 +15,7 @@ define(function (require) {
title: 'searches'
});
module.service('savedSearches', function (Promise, config, configFile, es, createNotifier, SavedSearch) {
module.service('savedSearches', function (Promise, config, configFile, es, createNotifier, SavedSearch, kbnUrl) {
var notify = createNotifier({
@ -27,7 +27,7 @@ define(function (require) {
};
this.urlFor = function (id) {
return '#/discover/' + encodeURIComponent(id);
return kbnUrl.eval('#/discover/{{id}}', {id: id});
};
this.delete = function (ids) {

View file

@ -2,8 +2,8 @@
<nav class="navbar navbar-default navbar-static-top subnav">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li ng-repeat="s in sections" ng-class="s.class">
<a class="navbar-link" ng-href="{{s.url}}">{{s.display}}</a>
<li ng-repeat="section in sections" ng-class="section.class">
<a class="navbar-link" ng-href="{{section.url}}">{{section.display}}</a>
</li>
</ul>
</div>

View file

@ -14,7 +14,7 @@ define(function (require) {
// wrapper directive, which sets some global stuff up like the left nav
require('modules').get('apps/settings')
.directive('kbnSettingsIndices', function ($route, config) {
.directive('kbnSettingsIndices', function ($route, config, kbnUrl) {
return {
restrict: 'E',
transclude: true,
@ -31,7 +31,7 @@ define(function (require) {
.map(function (id) {
return {
id: id,
url: '#/settings/indices/' + encodeURIComponent(id),
url: kbnUrl.eval('#/settings/indices/{{id}}', {id: id}),
class: 'sidebar-item-title ' + ($scope.edittingId === id ? 'active' : ''),
default: $scope.defaultIndex === id
};

View file

@ -41,7 +41,7 @@ define(function (require) {
'kibana/notify',
'kibana/courier'
])
.controller('VisEditor', function ($scope, $route, timefilter, appStateFactory, $location, globalState, $timeout) {
.controller('VisEditor', function ($scope, $route, timefilter, appStateFactory, $location, kbnUrl, $timeout) {
var _ = require('lodash');
var angular = require('angular');
@ -157,11 +157,7 @@ define(function (require) {
if (savedVis.id === $route.current.params.id) return;
$location.url(
globalState.writeToUrl(
'/visualize/edit/' + encodeURIComponent(savedVis.id)
)
);
kbnUrl.change('/visualize/edit/{{id}}', {id: savedVis.id});
}, notify.fatal);
};

View file

@ -11,7 +11,7 @@ define(function (require) {
title: 'visualizations'
});
app.service('savedVisualizations', function (Promise, es, config, SavedVis, Private, Notifier) {
app.service('savedVisualizations', function (Promise, es, config, SavedVis, Private, Notifier, kbnUrl) {
var visTypes = Private(require('components/vis_types/index'));
var notify = new Notifier({
location: 'saved visualization service'
@ -22,7 +22,7 @@ define(function (require) {
};
this.urlFor = function (id) {
return '#/visualize/edit/' + encodeURIComponent(id);
return kbnUrl.eval('#/visualize/edit/{{id}}', {id: id});
};
this.delete = function (ids) {

View file

@ -24,9 +24,9 @@ define(function (require) {
}
});
module.controller('VisualizeWizardStep1', function ($route, $scope, $location, timefilter) {
module.controller('VisualizeWizardStep1', function ($route, $scope, $location, timefilter, kbnUrl) {
$scope.step2WithSearchUrl = function (hit) {
return '#/visualize/step/2?savedSearchId=' + encodeURIComponent(hit.id);
return kbnUrl.eval('#/visualize/step/2?savedSearchId={{id}}', {id: hit.id});
};
timefilter.enabled = false;
@ -38,7 +38,7 @@ define(function (require) {
$scope.$watch('indexPattern.selection', function (pattern) {
if (!pattern) return;
$location.url('/visualize/step/2?indexPattern=' + encodeURIComponent(pattern));
kbnUrl.change('/visualize/step/2?indexPattern={{pattern}}', {pattern: pattern});
});
});

View file

@ -8,7 +8,6 @@ define(function (require) {
if (query.query_string && query.query_string.query) {
return query.query_string.query;
}
return JSON.stringify(query);
}
@ -32,4 +31,4 @@ define(function (require) {
]
});
};
});
});

View file

@ -3,7 +3,7 @@ define(function (require) {
'kibana/notify'
]);
var configFile = require('config_file');
var configFile = JSON.parse(require('text!config'));
// allow the rest of the app to get the configFile easily
module.constant('configFile', configFile);

View file

@ -1,7 +1,7 @@
define(function (require) {
var errors = require('errors');
return function RedirectWhenMissingFn($location, $route, globalState, Notifier) {
return function RedirectWhenMissingFn($location, kbnUrl, globalState, Notifier) {
var SavedObjectNotFound = errors.SavedObjectNotFound;
var notify = new Notifier();
@ -27,7 +27,7 @@ define(function (require) {
if (!url) url = '/';
notify.error(err);
$route.changeUrl(globalState.writeToUrl(url));
kbnUrl.change(url);
return;
};
};

View file

@ -1,5 +1,5 @@
define(function (require) {
return function EnsureSomeIndexPatternsFn(Private, Notifier, $location, $route) {
return function EnsureSomeIndexPatternsFn(Private, Notifier, $location, kbnUrl) {
var errors = require('errors');
var notify = new Notifier();
@ -7,7 +7,7 @@ define(function (require) {
return function promiseHandler(patterns) {
if (!patterns || patterns.length === 0) {
// notify.warning(new errors.NoDefinedIndexPatterns());
$route.change('/settings/indices');
kbnUrl.changePath('/settings/indices');
}
return patterns;

View file

@ -21,8 +21,8 @@ define(function (require) {
template: html,
controller: function ($scope) {
var init = function () {
$scope.formatRelative();
$scope.setMode($scope.mode);
$scope.formatRelative();
};
$scope.format = 'MMMM Do YYYY, HH:mm:ss.SSS';
@ -136,4 +136,4 @@ define(function (require) {
};
});
});
});

View file

@ -0,0 +1,97 @@
define(function (require) {
require('filters/uriescape');
require('filters/rison');
var _ = require('lodash');
var rison = require('utils/rison');
var location = require('modules').get('kibana/url');
location.service('kbnUrl', function ($route, $location, $rootScope, globalState, $parse) {
var self = this;
self.reloading = false;
self.change = function (url, paramObj, forceReload) {
self._changeLocation('url', url, paramObj, forceReload);
};
self.changePath = function (url, paramObj, forceReload) {
self._changeLocation('path', url, paramObj, forceReload);
};
self._changeLocation = function (type, url, paramObj, forceReload) {
var doReload = false;
if (_.isBoolean(paramObj)) {
forceReload = paramObj;
paramObj = undefined;
}
url = self.eval(url, paramObj);
// path change
if (type === 'path') {
if (url !== $location.path()) {
$location.path(globalState.writeToUrl(url));
doReload = (!self.matches(url));
}
// default to url change
} else {
if (url !== $location.url()) {
$location.url(globalState.writeToUrl(url));
doReload = (!self.matches(url));
}
}
if (forceReload || doReload) {
self.reload();
}
};
self.eval = function (url, paramObj) {
paramObj = paramObj || {};
return parseUrlPrams(url, paramObj);
};
self.matches = function (url) {
var route = $route.current.$$route;
if (!route || !route.regexp) return false;
return route.regexp.test(url);
};
$rootScope.$on('$routeUpdate', reloadingComplete);
$rootScope.$on('$routeChangeStart', reloadingComplete);
function parseUrlPrams(url, paramObj) {
return url.replace(/\{\{([^\}]+)\}\}/g, function (match, expr) {
// remove filters
var key = expr.split('|')[0].trim();
// verify that the expression can be evaluated
var p = $parse(key)(paramObj);
// if evaluation can't be made, throw
if (_.isUndefined(p)) {
throw new Error('Replacement failed, unresolved expression: ' + expr);
}
// append uriescape filter if not included
if (expr.indexOf('uriescape') === -1) {
expr += '|uriescape';
}
return $parse(expr)(paramObj);
});
}
self.reload = function () {
if (!self.reloading) {
$route.reload();
self.reloading = true;
}
};
function reloadingComplete() {
self.reloading = false;
}
});
});

View file

@ -8,11 +8,12 @@ define(function (require) {
require('components/config/config');
require('components/courier/courier');
require('components/notify/notify');
require('components/state_management/app_state_factory');
require('components/filter_bar/filter_bar');
require('components/storage/storage');
require('components/notify/notify');
require('components/persisted_log/persisted_log');
require('components/state_management/app_state_factory');
require('components/storage/storage');
require('components/url/url');
require('directives/click_focus');
require('directives/info');
require('directives/spinner');

View file

@ -4,7 +4,6 @@ define(function (require) {
.directive('confirmClick', function () {
return {
restrict: 'A',
scope: {},
link: function ($scope, $elem, attrs) {
$elem.bind('click', function () {
var message = attrs.confirmation || 'Are you sure?';

View file

@ -25,7 +25,7 @@ define(function (require) {
var stringify = function () {
var text;
// If both parts are date math, try to look up a reasonable string
if (!moment.isMoment($scope.from) && !moment.isMoment($scope.to)) {
if ($scope.from && $scope.to && !moment.isMoment($scope.from) && !moment.isMoment($scope.to)) {
var tryLookup = lookupByRange[$scope.from.toString() + ' to ' + $scope.to.toString()];
if (tryLookup) {
$elem.text(tryLookup.display);

View file

@ -3,7 +3,7 @@ define(function (require) {
var _ = require('lodash');
var rison = require('utils/rison');
module.directive('savedObjectFinder', function (savedSearches, savedVisualizations, savedDashboards, $location, $route) {
module.directive('savedObjectFinder', function (savedSearches, savedVisualizations, savedDashboards, $location, kbnUrl) {
var vars = {
searches: {
@ -85,12 +85,12 @@ define(function (require) {
// angular wants the '/path', not '#/path'
var path = url.substr(1);
if ($route.matches(path)) {
if (kbnUrl.matches(path)) {
$event.preventDefault();
// change works with paths, but we are only here because the paths
// are the same, so we have to change the whole url to be the new path
$route.changeUrl(path);
kbnUrl.change(path);
}
};

View file

@ -0,0 +1,16 @@
define(function (require) {
var rison = require('utils/rison');
var module = require('modules').get('kibana');
module.filter('rison', function () {
return function (str) {
return rison.encode(str);
};
});
module.filter('risonDecode', function () {
return function (str) {
return rison.decode(str);
};
});
});

View file

@ -4,7 +4,7 @@
define(function (require) {
var _ = require('lodash');
require('modules')
.get('kbn/filters')
.get('kibana')
.filter('shortDots', function (config) {
return function (str) {
if (!_.isString(str) || config.get('shortDots:enable') !== true) {

View file

@ -1,6 +1,6 @@
define(function (require) {
require('modules')
.get('kbn/filters')
.get('kibana')
.filter('uriescape', function () {
return function (str) {
return encodeURIComponent(str);

View file

@ -7,11 +7,11 @@
<meta name="viewport" content="width=device-width">
<title>Kibana 4</title>
<!-- load the root require context -->
<script src="bower_components/requirejs/require.js"></script>
<script src="/bower_components/requirejs/require.js"></script>
<script src="kibana/require.config.js"></script>
<script src="/require.config.js"></script>
<script>require(['kibana'], function (kibana) { kibana.init(); });</script>
<link rel="stylesheet" href="kibana/styles/main.css" >
<link rel="stylesheet" href="/styles/main.css" >
</head>
<body ng-controller="kibana" ng-class="'application-'+activeApp">
<kbn-notifications list="notifList"></kbn-notifications>

View file

@ -12,7 +12,7 @@ define(function (require) {
require('angular-route');
require('angular-bindonce');
var configFile = require('config_file');
var configFile = JSON.parse(require('text!config'));
var kibana = modules.get('kibana', [
// list external requirements here
@ -21,7 +21,7 @@ define(function (require) {
'ngRoute'
]);
configFile.elasticsearch = configFile.elasticsearch || ('http://' + window.location.hostname + ':9200');
configFile.elasticsearch = ('http://' + window.location.hostname + '/elasticsearch/');
kibana
// This stores the Kibana revision number, @REV@ is replaced by grunt.

View file

@ -1,9 +1,7 @@
require.config({
baseUrl: './kibana',
baseUrl: './',
paths: {
kibana: './index',
config_file: '../config',
kibana: 'index',
// special utils
routes: 'utils/routes/index',
errors: 'components/errors',
@ -11,27 +9,27 @@ require.config({
lodash: 'utils/_mixins',
// bower_components
'angular-bindonce': '../bower_components/angular-bindonce/bindonce',
'angular-bootstrap': '../bower_components/angular-bootstrap/ui-bootstrap-tpls',
'angular-elastic': '../bower_components/angular-elastic/elastic',
'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',
angular: '../bower_components/angular/angular',
async: '../bower_components/async/lib/async',
bower_components: '../bower_components',
css: '../bower_components/require-css/css',
d3: '../bower_components/d3/d3',
elasticsearch: '../bower_components/elasticsearch/elasticsearch.angular',
faker: '../bower_components/Faker/faker',
file_saver: '../bower_components/FileSaver/FileSaver',
gridster: '../bower_components/gridster/dist/jquery.gridster',
inflection: '../bower_components/inflection/lib/inflection',
jquery: '../bower_components/jquery/dist/jquery',
jsonpath: '../bower_components/jsonpath/lib/jsonpath',
lodash_src: '../bower_components/lodash/dist/lodash',
moment: '../bower_components/moment/moment',
text: '../bower_components/requirejs-text/text'
'angular-bindonce': 'bower_components/angular-bindonce/bindonce',
'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap-tpls',
'angular-elastic': 'bower_components/angular-elastic/elastic',
'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',
angular: 'bower_components/angular/angular',
async: 'bower_components/async/lib/async',
bower_components: 'bower_components',
css: 'bower_components/require-css/css',
d3: 'bower_components/d3/d3',
elasticsearch: 'bower_components/elasticsearch/elasticsearch.angular',
faker: 'bower_components/Faker/faker',
file_saver: 'bower_components/FileSaver/FileSaver',
gridster: 'bower_components/gridster/dist/jquery.gridster',
inflection: 'bower_components/inflection/lib/inflection',
jquery: 'bower_components/jquery/dist/jquery',
jsonpath: 'bower_components/jsonpath/lib/jsonpath',
lodash_src: 'bower_components/lodash/dist/lodash',
moment: 'bower_components/moment/moment',
text: 'bower_components/requirejs-text/text'
},
shim: {
angular: {

View file

@ -14,4 +14,4 @@ define(function (require) {
return es;
});
});
});

View file

@ -62,10 +62,6 @@ define(function (require) {
}()));
}
Timefilter.prototype.enabled = function (state) {
this.enabled = !!state;
};
Timefilter.prototype.get = function (indexPattern) {
var filter;
var timefield = indexPattern.timeFieldName && _.find(indexPattern.fields, {name: indexPattern.timeFieldName});

View file

@ -1,4 +1,4 @@
@bs-less-dir: "../../bower_components/bootstrap/less";
@bs-less-dir: "../bower_components/bootstrap/less";
// Core variables and mixins
@import "theme/_variables.less";

View file

@ -1,4 +1,4 @@
@import "../../bower_components/font-awesome/less/font-awesome.less";
@import "../bower_components/font-awesome/less/font-awesome.less";
@import (reference) "lesshat.less";
// generic mixins

View file

@ -1,5 +1,5 @@
define(function (require) {
return function routeSetup(Promise, kbnSetup, config, $route, indexPatterns, Notifier) {
return function routeSetup(Promise, kbnSetup, config, $route, kbnUrl, indexPatterns, Notifier) {
var errors = require('errors');
var NoDefaultIndexPattern = errors.NoDefaultIndexPattern;
@ -26,7 +26,7 @@ define(function (require) {
if (err instanceof NoDefaultIndexPattern || err instanceof NoDefinedIndexPatterns) {
// .change short circuits the routes by calling $route.refresh(). We can safely swallow this error
// after reporting it to the user
$route.change('/settings/indices');
kbnUrl.change('/settings/indices');
(new Notifier()).error(err);
} else {
return Promise.reject(err);
@ -34,4 +34,4 @@ define(function (require) {
}
};
};
});
});

View file

@ -5,42 +5,6 @@ define(function (require) {
require('components/setup/setup');
require('services/promises');
require('modules').get('kibana')
.config(function ($provide) {
// decorate the $route object to include a change and changeUrl method
$provide.decorator('$route', function ($delegate, $location, $rootScope) {
var reloading;
var doneReloading = function () { reloading = false; };
$rootScope.$on('$routeUpdate', doneReloading);
$rootScope.$on('$routeChangeStart', doneReloading);
var reload = function () {
if (!reloading) $delegate.reload();
reloading = true;
};
$delegate.change = function (path) {
if (path !== $location.path()) {
$location.path(path);
reload();
}
};
$delegate.changeUrl = function (url) {
if (url !== $location.url()) {
$location.url(url);
reload();
}
};
$delegate.matches = function (url) {
var route = $delegate.current.$$route;
if (!route || !route.regexp) return null;
return route.regexp.test(url);
};
return $delegate;
});
});
function RouteManager() {
var when = [];
var additions = [];

19
src/server/DIST_README.md Normal file
View file

@ -0,0 +1,19 @@
# Kibana @@version
Kibana is an open source (Apache Licensed), 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.
## Installation
* Download: http://www.elasticsearch.org/overview/kibana/installation/
* Run **bin/kibana** on unix, or **bin/kibana.bat** on Windows.
* Visit http://localhost:5601
## Need Help?
Need help? Try #elasticsearch or #logstash on Freenode IRC. You can also find help on the elasticsearch-users@googlegroups.com or logstash-users@googlegroups.com mailing lists.
You can also find documentation at http://www.elasticsearch.com/guide/en/kibana/current
## Contributing
If you have a bugfix or new feature that you would like to contribute to Kibana, please find or open an issue about it first. Kibana is an open source project that is available on Github: https://github.com/elasticsearch/kibana

View file

@ -1,5 +1,3 @@
ruby "1.9.3", :engine => 'jruby', :engine_version => '1.7.13'
source "https://rubygems.org"
gem 'sinatra', :require => 'sinatra/base'
@ -8,3 +6,4 @@ gem 'puma'
gem 'warbler'
gem 'elasticsearch'
gem 'rack-reverse-proxy', :require => 'rack/reverse_proxy'
gem 'colorize'

View file

@ -2,6 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
backports (3.6.0)
colorize (0.7.3)
elasticsearch (1.0.4)
elasticsearch-api (= 1.0.4)
elasticsearch-transport (= 1.0.4)
@ -52,6 +53,7 @@ PLATFORMS
ruby
DEPENDENCIES
colorize
elasticsearch
puma
rack-reverse-proxy

83
src/server/bin/initialize Executable file
View file

@ -0,0 +1,83 @@
#!/usr/bin/env ruby
require "optparse"
require 'rubygems'
require 'puma/cli'
require "yaml"
HERE = File.expand_path(File.dirname(__FILE__))
module Kibana
def self.global_settings
@settings ||= {}
end
end
# Defaults for the options
options = {
:config => File.expand_path("#{HERE}/../config/kibana.yml") || ENV["CONFIG_PATH"]
}
# Create a new parser
parser = OptionParser.new do |opts|
opts.on('-e', '--elasticsearch URI', 'Elasticsearch instance') do |arg|
options[:elasticsearch] = arg
end
opts.on('-c', '--config PATH', 'Path to config file') do |arg|
options[:config] = arg
end
opts.on('-p', '--port PORT', 'Kibana port') do |arg|
options[:port] = arg
end
opts.on('-H', '--host HOST', 'Kibana host') do |arg|
options[:host] = arg
end
opts.on('-v', '--version', 'Display version') do |arg|
puts ENV['KIBANA_VERSION'] || 'dev-build'
exit
end
opts.on('-h', '--help', 'Display this screen') do
puts opts
exit
end
end
# Set the usage banner
parser.banner = "Usage: kibana <options>\n\n"
# Parse the command line arguments
parser.parse! ARGV
# Load the config from default
config = YAML.load(IO.read(options[:config]))
# Set the override for the port
port = (options[:port] || config['port'])
# Set the override for the host
host = (options[:host] || config['host'])
# Set the override for Elasticsaerch
elasticsearch = (options[:elasticsearch] || config['elasticsearch'])
# If the env isn't set we need to set it to development
ENV["RACK_ENV"] = "development" if ENV["RACK_ENV"].nil?
# Set the global_settings that are shared across every app
Kibana.global_settings[:port] = port || 5601
Kibana.global_settings[:host] = host || '0.0.0.0'
Kibana.global_settings[:config] = config
Kibana.global_settings[:elasticsearch] = elasticsearch
Kibana.global_settings[:root] = File.expand_path("#{File.dirname(__FILE__)}/../")
# Set the public folder based on whether we are running in production or not.
if ENV['RACK_ENV'] == ('production')
Kibana.global_settings[:public_folder] = File.expand_path("#{File.dirname(__FILE__)}/../public/")
else
Kibana.global_settings[:public_folder] = File.expand_path("#{File.dirname(__FILE__)}/../../kibana/")
end
# Add the root of the project to the load path
$LOAD_PATH.unshift(Kibana.global_settings[:root])
require "lib/server"
Kibana::Server.run(Kibana.global_settings)

25
src/server/bin/kibana.bat Normal file
View file

@ -0,0 +1,25 @@
@echo off
SETLOCAL
if not defined JAVA_HOME goto java_home_err
set SCRIPT_DIR=%~dp0
for %%I in ("%SCRIPT_DIR%..") do set DIR=%%~dpfI
set RACK_ENV=production
set CONFIG_PATH=%DIR%\config\kibana.yml
set KIBANA_VERSION=@@version
TITLE Kibana %KIBANA_VERSION%
"%JAVA_HOME%\bin\java" -jar "%DIR%\lib\kibana.jar" %*
:java_home_err
echo JAVA_HOME enviroment variable must be set!
pause
goto finally
:finally
ENDLOCAL

30
src/server/bin/kibana.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/sh
SCRIPT=$0
# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
# Drop everything prior to ->
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
DIR=$(dirname "${SCRIPT}")
if [ -x "${JAVA_HOME}/bin/java" ]; then
JAVA="${JAVA_HOME}/bin/java"
else
JAVA=`which java`
fi
if [ ! -x "${JAVA}" ]; then
echo "Could not find any executable Java binary. Please install Java in your PATH or set JAVA_HOME"
exit 1
fi
KIBANA_VERSION=@@version CONFIG_PATH=${DIR}/../config/kibana.yml RACK_ENV=production exec "${JAVA}" -jar "${DIR}/../lib/kibana.jar" "$@"

View file

@ -0,0 +1,20 @@
# Kibana is served by a backend server. This controls which port to use.
port: 5601
# The Elasticsearch instance to user for all your queries
elasticsearch: "http://localhost:9200"
# Kibana uses and index in Elasticsearch to store saved searches, visualizations
# and dashboard. It will create an new index if it doesn't already exist.
kibanaIndex: "kibana-int"
# Applications loaded and included into Kibana. Use the settings below to
# customize the applications and thier names.
apps:
- { id: "discover", name: "Discover" }
- { id: "visualize", name: "Visualize" }
- { id: "dashboard", name: "Dashboard" }
- { id: "settings", name: "Settings" }
# The default application to laad.
defaultAppId: "discover"

22
src/server/config/web.ru Normal file
View file

@ -0,0 +1,22 @@
require "rubygems"
require "bundler/setup"
ROOT = File.expand_path("#{File.dirname(__FILE__)}/../")
if ENV['RACK_ENV'] == ('development')
PUBLIC_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../kibana/")
CONFIG_PATH = File.expand_path("#{File.dirname(__FILE__)}/kibana.yml")
end
if ENV['RACK_ENV'] == ('production')
PUBLIC_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../public/")
CONFIG_PATH = ENV["CONFIG_PATH"]
end
$LOAD_PATH.unshift(ROOT)
# Require the application
require "#{ROOT}/lib/app"
# Run the application
run Kibana::App

View file

@ -0,0 +1,44 @@
require "rack/commonlogger"
require "colorize"
class ColorLogger < Rack::CommonLogger
def log(env, status, header, begin_at)
now = Time.now
length = extract_content_length(header)
case status
when 300..399
statusColor = :yellow
when 400..499
statusColor = :red
when 500..599
statusColor = :magenta
else
statusColor = :green
end
msg = (now.strftime('%b %d, %Y @ %H:%M:%S.%L')).light_black << ' '
msg << env["REQUEST_METHOD"].light_blue << ' '
msg << env["PATH_INFO"]
msg << (env["QUERY_STRING"].empty? ? '' : "?#{env["QUERY_STRING"]}" ) << ' '
msg << status.to_s.send(statusColor) << ' '
msg << ((now - begin_at) * 1000).to_i.to_s << 'ms - ' << length
msg << "\n"
# If there is an error then we need to append the stack
if env['sinatra.error'] && status != 404
error = env['sinatra.error']
msg << "#{error.message}\n #{error.backtrace.join("\n ")}".send(statusColor)
msg << "\n"
end
logger = @logger || env['rack.errors']
if logger.respond_to?(:write)
logger.write(msg)
else
logger << msg
end
end
end

View file

@ -0,0 +1,46 @@
require "rack/commonlogger"
class JSONLogger < Rack::CommonLogger
def log(env, status, header, begin_at)
now = Time.now
length = extract_content_length(header)
data = {
"@timestamp" => now.iso8601,
:status => status.to_s[0..3],
:level => status < 399 ? "INFO" : 'ERROR',
:name => "Kibana",
:request_method => env["REQUEST_METHOD"],
:request => env["PATH_INFO"] + (env["QUERY_STRING"].empty? ? "" : "#{env['QUERY_STRING']}"),
:path => env["PATH_INFO"],
:query_string => env["QUERY_STRING"],
:remote_addr => env['HTTP_X_FORWARD_FOR'] || env["REMOTE_ADDR"],
:remote_user => env["REMOTE_USER"],
:http_version => env["HTTP_VERSION"],
:content_length => length,
:response_time => ((now - begin_at) * 1000).to_i # convert to milliseconds
}
# If there is an error then we need to append the stack
if env['sinatra.error']
error = env['sinatra.error']
data[:error] = {
:name => error.class.to_s,
:message => error.message,
:stack => error.backtrace
}
end
data[:message] = "#{data[:request_method]} #{data[:path]+(data[:query_string].empty? ? '' : '?'+data[:query_string])} #{data[:status]} #{data[:response_time]}ms - #{data[:content_length].empty? ? '-' : data[:content_length]}"
logger = @logger || env['rack.errors']
msg = data.to_json+"\n"
if logger.respond_to?(:write)
logger.write(msg)
else
logger << msg
end
end
end

68
src/server/lib/app.rb Normal file
View file

@ -0,0 +1,68 @@
# Add the root of the project to the $LOAD_PATH, For some reason it seems
# to be getting lost when we use warble to make the jar. This fixes it :D
$LOAD_PATH.unshift(Kibana.global_settings[:root])
require "logger"
require "json"
require "lib/JSONLogger"
require "lib/ColorLogger"
require "routes/home"
require "sinatra/json"
require "routes/proxy"
class Logger
alias_method :write, :<<
end
module Kibana
class App < Sinatra::Base
helpers Sinatra::JSON
configure do
logger = Logger.new(STDOUT)
logger.formatter = proc do |severity, datetime, progname, msg|
data = {
'@timestamp' => datetime.iso8601,
:level => severity,
:name => progname || "Kibana",
:message => msg
}
data.to_json + "\n"
end
set :logger, logger
disable :raise_errors
disable :show_exceptions
disable :dump_errors
end
configure :production do
use JSONLogger, settings.logger
end
configure :development do
use ColorLogger, settings.logger
end
error do
500
end
error 400 do
json :status => 500, :message => "Bad Request"
end
error 500 do
json :status => 500, :message => "Internal Server Error"
end
not_found do
json :status => 404, :message => "Not Found"
end
# Routes go here
use Routes::Home
use Routes::Proxy
end
end

60
src/server/lib/server.rb Normal file
View file

@ -0,0 +1,60 @@
require "rubygems"
require "bundler/setup"
require "puma"
require "colorize"
require "json"
require "#{Kibana.global_settings[:root]}/lib/app"
# Require the application
module Kibana
module Server
DEFAULTS = {
:host => '0.0.0.0',
:port => 5601,
:threads => '0:16',
:verbose => false
}
def self.log(msg)
if ENV['RACK_ENV'] == 'production'
data = {
"@timestamp" => Time.now.iso8601,
:level => 'INFO',
:name => 'Kibana',
:message => msg
}
puts data.to_json
else
message = (Time.now.strftime('%b %d, %Y @ %H:%M:%S.%L')).light_black << ' '
message << msg.yellow
puts message
end
end
def self.run(options = {})
options = DEFAULTS.merge(options)
min, max = options[:threads].split(':', 2)
app = Kibana::App.new()
server = Puma::Server.new(app)
# Configure server
server.add_tcp_listener(options[:host], options[:port])
server.min_threads = min
server.max_threads = max
begin
log("Kibana server started on tcp://#{options[:host]}:#{options[:port]} in #{ENV['RACK_ENV']} mode.")
server.run.join
rescue Interrupt
log("Kibana server gracefully stopping, waiting for requests to finish")
server.stop(true)
log("Kibana server stopped.")
end
end
end
end

21
src/server/routes/base.rb Normal file
View file

@ -0,0 +1,21 @@
require "sinatra/base"
require "sinatra/json"
require "yaml"
module Kibana
module Routes
class Base < Sinatra::Base
helpers Sinatra::JSON
configure do
config = Kibana.global_settings[:config].clone()
config['elasticsearch'] = Kibana.global_settings[:elasticsearch]
config['port'] = Kibana.global_settings[:port].to_i
set :root, Kibana.global_settings[:root]
set :public_folder, Kibana.global_settings[:public_folder]
set :httponly, true
set :config, config
end
end
end
end

21
src/server/routes/home.rb Normal file
View file

@ -0,0 +1,21 @@
require "routes/base"
module Kibana
module Routes
class Home < Base
get "/" do
File.read(File.join(settings.public_folder, 'index.html'))
end
get "/config" do
# Clone the settings object and change the elasticsearch attribute
# to the proxy for elasticsearch
data = settings.config.clone()
data['elasticsearch'] = "#{request.scheme}://#{request.host}:#{request.port}/elasticsearch"
json data
end
end
end
end

View file

@ -0,0 +1,14 @@
require "routes/base"
require "rack/reverse_proxy"
module Kibana
module Routes
class Proxy < Base
# Rack middleware goes here
config = settings.config
use Rack::ReverseProxy do
reverse_proxy(/^\/elasticsearch(.*)$/, "#{config["elasticsearch"]}$1")
end
end
end
end

View file

@ -4,9 +4,18 @@ module.exports = function (grunt) {
'clean:build',
'require_css_deps:copy',
'less',
'copy:kibana_src',
'touch_config',
'requirejs',
'clean:unneeded_source_in_build',
'copy:server_src',
'download_jruby',
'install_gems',
'warble',
'replace:dist',
'copy:dist',
'chmod_kibana',
'compress:build_zip',
'compress:build_tarball'
]);
};
};

9
tasks/chmod_kibana.js Normal file
View file

@ -0,0 +1,9 @@
var fs = require('fs');
var join = require('path').join;
module.exports = function (grunt) {
grunt.registerTask('chmod_kibana', 'Chmods bin/kibana', function () {
var done = this.async();
var path = join(grunt.config.get('build'), 'dist', 'bin', 'kibana');
fs.chmod(path, 0755, done);
});
};

View file

@ -6,20 +6,19 @@ module.exports = function (grunt) {
unneeded_source_in_build: {
src: [
// select all top level folders in bower_components
'<%= build %>/bower_components/*',
'<%= build %>/kibana/public/bower_components/*',
// exclude the following top level components
'!<%= build %>/bower_components/' + notIncludedComponents,
'!<%= build %>/kibana/public/bower_components/' + notIncludedComponents,
// remove the contents of K4D3, font-awesome, and requirejs except necessary files
'<%= build %>/bower_components/' + notIncludedComponents + '/*',
'!<%= build %>/bower_components/requirejs/require.js',
'!<%= build %>/bower_components/font-awesome/fonts',
'<%= build %>/**/_empty_',
'<%= build %>/**/*.less',
'<%= appBuild %>/{css-builder,normalize}.js',
'<%= app %>/{css-builder,normalize}.js',
'<%= build %>/kibana/public/bower_components/' + notIncludedComponents + '/*',
'!<%= build %>/kibana/public/bower_components/requirejs/require.js',
'!<%= build %>/kibana/public/bower_components/font-awesome/fonts',
'<%= build %>/kibana/public/**/_empty_',
'<%= build %>/kibana/public/**/*.less',
'<%= build %>/kibana/public/config',
'<%= build %>/kibana/public/{css-builder,normalize}.js',
'<%= app %>/public/{css-builder,normalize}.js',
]
}
};
};
};

View file

@ -6,7 +6,7 @@ module.exports = function (grunt) {
return _.mapValues({
build_zip: archiveName() + '.zip',
build_tarball: archiveName() + '.zip',
build_tarball: archiveName() + '.tar.gz',
plugin: archiveName(true) + '.tar.gz'
}, function (filename, task) {
return {
@ -16,11 +16,11 @@ module.exports = function (grunt) {
files: [
{
expand: true,
cwd: '<%= build %>',
cwd: '<%= build %>/dist',
src: ['**/*'],
dest: '<%= pkg.name %>' + (task === 'plugin' ? '/_site' : '')
}
]
};
});
};
};

71
tasks/config/copy.js Normal file
View file

@ -0,0 +1,71 @@
module.exports = function (grunt) {
var config = {
kibana_src: {
expand: true,
cwd: '<%= app %>',
src: '**',
dest: '<%= build %>/src/'
},
server_src: {
files: [
{
src: '<%= src %>/server/Gemfile',
dest: '<%= build %>/kibana/Gemfile'
},
{
src: '<%= src %>/server/Gemfile.lock',
dest: '<%= build %>/kibana/Gemfile.lock'
},
{
src: '<%= src %>/server/bin/initialize',
dest: '<%= build %>/kibana/bin/initialize'
},
{
expand: true,
cwd: '<%= src %>/server/config/',
src: '**',
dest: '<%= build %>/kibana/config'
},
{
expand: true,
cwd: '<%= src %>/server/lib/',
src: '**',
dest: '<%= build %>/kibana/lib'
},
{
expand: true,
cwd: '<%= src %>/server/routes/',
src: '**',
dest: '<%= build %>/kibana/routes'
}
]
},
dist: {
options: { mode: true },
files: [
{
src: '<%= root %>/LICENSE.md',
dest: '<%= build %>/dist/LICENSE.md'
},
{
expand: true,
cwd: '<%= build %>/kibana/',
src: '*.jar',
dest: '<%= build %>/dist/lib/'
},
{
expand: true,
cwd: '<%= src %>/server/config/',
src: 'kibana.yml',
dest: '<%= build %>/dist/config/'
}
]
}
};
return config;
};

View file

@ -17,8 +17,9 @@ module.exports = function (grunt) {
ignores: [
'node_modules/*',
'dist/*',
'sample/*'
'sample/*',
'<%= src %>/kibana/bower_components/**/*'
]
}
};
};
};

View file

@ -1,4 +1,4 @@
var bc = require('path').join(__dirname, '../../src/bower_components');
var bc = require('path').join(__dirname, '../../src/kibana/bower_components');
module.exports = {
src: {

31
tasks/config/replace.js Normal file
View file

@ -0,0 +1,31 @@
var join = require('path').join;
module.exports = function (grunt) {
var pkg = grunt.config.get('pkg');
var build = grunt.config.get('build');
var src = grunt.config.get('src');
var config = {
dist: {
options: {
patterns: [
{ match: 'version', replacement: pkg.version }
]
},
files: [
{
src: [join(src, 'server', 'DIST_README.md')],
dest: join(build, 'dist', 'README.md')
},
{
src: [join(src, 'server', 'bin', 'kibana.sh')],
dest: join(build, 'dist', 'bin', 'kibana')
},
{
src: [join(src, 'server', 'bin', 'kibana.bat')],
dest: join(build, 'dist', 'bin', 'kibana.bat')
}
]
}
};
return config;
};

View file

@ -2,14 +2,15 @@ module.exports = function (grunt) {
var config = {
build: {
options: {
appDir: '<%= src %>',
dir: '<%= build %>',
mainConfigFile: '<%= app %>/require.config.js',
appDir: '<%= build %>/src',
dir: '<%= build %>/kibana/public',
mainConfigFile: '<%= build %>/src/require.config.js',
modules: [
{
name: 'kibana',
excludeShallow: [
'../config',
'text!config'
],
include: [
'controllers/kibana'
@ -60,10 +61,10 @@ module.exports = function (grunt) {
// include each app
var main = config.build.options.modules[0];
var configFile = require('requirejs')(grunt.config.get('src') + '/config.js');
var configFile = require('requirejs')(grunt.config.get('app') + '/config.js');
configFile.apps.forEach(function (app) {
main.include.push('apps/' + app.id + '/index');
});
return config;
};
};

28
tasks/config/run.js Normal file
View file

@ -0,0 +1,28 @@
module.exports = function (grunt) {
var jrubyPath = grunt.config.get('jrubyPath');
var jruby = jrubyPath + '/bin/jruby';
var cmd = grunt.config.get('src') + '/server/bin/initialize';
var config = {
mri_server: {
options: {
wait: false
// quiet: true
},
cmd: cmd
},
jruby_server: {
options: {
wait: false
// quiet: true
},
cmd: jruby,
args: [
cmd
]
}
};
return config;
};

View file

@ -1,4 +1,16 @@
module.exports = function (grunt) {
var kibana_server_tasks = [];
if (grunt.option('use-mri')) {
kibana_server_tasks = [
'stop:mri_server',
'run:mri_server'
];
} else {
kibana_server_tasks = [
'stop:jruby_server',
'run:jruby_server'
];
}
var config = {
test: {
files: [
@ -26,6 +38,16 @@ module.exports = function (grunt) {
'<%= testUtilsDir %>/istanbul_reporter/report.clientside.jade'
],
tasks: ['jade:clientside']
},
kibana_server: {
files: [
'src/server/**/*.rb',
'src/server/**/*.yml'
],
tasks: kibana_server_tasks,
options: {
spawn: false
}
}
};

View file

@ -1,8 +1,21 @@
module.exports = function (grunt) {
grunt.registerTask('dev', [
var useJRuby = grunt.option('use-jruby');
var tasks = [
'less',
'jade',
'jade'
];
if (useJRuby) {
tasks = tasks.concat([
'download_jruby',
'install_gems',
'run:jruby_server',
'wait_for_jruby'
]);
} else {
tasks = tasks.concat(['run:mri_server']);
}
grunt.registerTask('dev', tasks.concat([
'maybe_start_server',
'watch'
]);
};
]));
};

46
tasks/download_jruby.js Normal file
View file

@ -0,0 +1,46 @@
var zlib = require('zlib');
var tar = require('tar');
var request = require('request');
var mkdirp = require('mkdirp');
var ProgressBar = require('progress');
var fs = require('fs');
module.exports = function (grunt) {
grunt.registerTask('download_jruby', 'Downloads and installs jruby', function () {
var done = this.async();
var jrubyPath = grunt.config.get('jrubyPath');
var jrubyVersion = grunt.config.get('jrubyVersion');
var url = 'http://jruby.org.s3.amazonaws.com/downloads/' + jrubyVersion + '/jruby-bin-' + jrubyVersion + '.tar.gz';
fs.stat(jrubyPath, function (err, stat) {
if (err) {
mkdirp(jrubyPath, function (err) {
if (err) return done(err);
var unzip = zlib.createGunzip();
var out = tar.Extract({ path: jrubyPath, strip: 1 });
out.on('close', done).on('error', done);
var req = request.get(url);
var bar;
if (!process.env.JENKINS_HOME) {
req.on('response', function (resp) {
var total = parseInt(resp.headers['content-length'], 10);
bar = new ProgressBar('[:bar] :percent :etas', {
complete: '=',
incomplete: ' ',
width: 80,
clear: true,
total: total
});
});
req.on('data', function (buffer) {
bar.tick(buffer.length);
});
}
req.pipe(unzip).pipe(out);
});
} else {
done();
}
});
});
};

20
tasks/install_gems.js Normal file
View file

@ -0,0 +1,20 @@
var child_process = require('child_process');
var join = require('path').join;
module.exports = function (grunt) {
grunt.registerTask('install_gems', 'Install Ruby Gems', function () {
var done = this.async();
var gemfile = join(grunt.config.get('src'), 'server', 'Gemfile');
var jrubyPath = grunt.config.get('jrubyPath');
var jruby = jrubyPath + '/bin/jruby -S';
var command = jruby + ' gem install bundler && ' + jruby + ' bundle install --gemfile ' + gemfile;
child_process.exec(command, function (err, stdout, stderr) {
if (err) {
grunt.log.error(stderr);
return done(err);
}
grunt.log.writeln(stdout);
return done();
});
});
};

View file

@ -8,8 +8,8 @@ module.exports = function (grunt) {
].forEach(function (dep) {
grunt.file.copy(
join(grunt.config.get('bowerComponentsDir'), 'require-css', dep),
join(grunt.config.get('app'), dep)
join(grunt.config.get('build'), 'src', dep)
);
});
});
};
};

View file

@ -1,20 +1,34 @@
var _ = require('lodash');
module.exports = function (grunt) {
/* jshint scripturl:true */
grunt.registerTask('test', [
var rubyTasks;
if (grunt.option('use-mri')) {
rubyTasks = [
'run:mri_server',
];
} else {
rubyTasks = [
'download_jruby',
'install_gems',
'run:jruby_server',
'wait_for_jruby'
];
}
grunt.registerTask('test', rubyTasks.concat([
'maybe_start_server',
'jade',
'mocha:unit',
'jshint'
]);
]));
grunt.registerTask('coverage', [
grunt.registerTask('coverage', rubyTasks.concat([
'blanket',
'maybe_start_server',
'mocha:coverage'
]);
]));
grunt.registerTask('test:watch', [
grunt.registerTask('test:watch', rubyTasks.concat([
'maybe_start_server',
'watch:test'
]);
]));
};

8
tasks/touch_config.js Normal file
View file

@ -0,0 +1,8 @@
module.exports = function (grunt) {
var join = require('path').join;
grunt.registerTask('touch_config', function () {
var configFile = join(grunt.config.get('build'), 'src', 'config');
grunt.log.ok('Touching: ' + configFile);
grunt.file.write(configFile, 'delete this');
});
};

18
tasks/wait_for_jruby.js Normal file
View file

@ -0,0 +1,18 @@
var request = require('request');
module.exports = function (grunt) {
grunt.registerTask('wait_for_jruby', 'Is it started yet?', function () {
var done = this.async();
function checkJRuby() {
request('http://127.0.0.1:5601', function (err, resp) {
if (err) {
setTimeout(checkJRuby, 1000);
} else {
done();
}
});
}
checkJRuby();
});
};

20
tasks/warble.js Normal file
View file

@ -0,0 +1,20 @@
var child_process = require('child_process');
var join = require('path').join;
module.exports = function (grunt) {
grunt.registerTask('warble', 'Creates an executable jar.', function () {
var done = this.async();
var jrubyPath = grunt.config.get('jrubyPath');
var command = jrubyPath + '/bin/jruby -S warble';
var options = {
cwd: join(grunt.config.get('build'), 'kibana')
};
child_process.exec(command, options, function (err, stdout, stderr) {
if (err) {
grunt.log.error(stderr);
return done(err);
}
grunt.log.writeln(stdout);
return done();
});
});
};

View file

@ -5,7 +5,7 @@
<link rel="stylesheet" href="/node_modules/mocha/mocha.css" />
<script src="/node_modules/expect.js/index.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<script src="/src/bower_components/requirejs/require.js"></script>
<script src="/src/kibana/bower_components/requirejs/require.js"></script>
<script src="/src/kibana/require.config.js"></script>
<script>(function () {
var COVERAGE = !!(/coverage/i.test(window.location.search));
@ -18,13 +18,14 @@
require.config({
baseUrl: '/src/kibana',
paths: {
config: '/config',
test_utils: '../../test/utils',
fixtures: '../../test/unit/fixtures',
specs: '../../test/unit/specs',
sinon: '../../test/utils/sinon',
bluebird: '../bower_components/bluebird/js/browser/bluebird',
angular: '../bower_components/angular-mocks/angular-mocks',
angular_src: '../bower_components/angular/angular'
bluebird: 'bower_components/bluebird/js/browser/bluebird',
angular: 'bower_components/angular-mocks/angular-mocks',
angular_src: 'bower_components/angular/angular'
},
shim: {
angular: {
@ -61,6 +62,7 @@
'kibana',
'sinon/sinon',
'specs/apps/discover/hit_sort_fn',
'specs/apps/discover/directives/table',
'specs/apps/discover/segmented_fetch',
'specs/directives/confirm-click',
'specs/directives/timepicker',
@ -71,10 +73,12 @@
'specs/filters/field_type',
'specs/filters/uriescape',
'specs/filters/moment',
'specs/filters/rison',
'specs/filters/short_dots',
'specs/filters/start_from',
'specs/services/storage',
'specs/services/persisted_log',
'specs/services/url',
'specs/utils/datemath',
'specs/utils/interval',
'specs/utils/versionmath',

View file

@ -7,7 +7,6 @@ define(function (require) {
require('angular-route');
// Load the code for the directive
require('index');
require('apps/visualize/index');
require('apps/dashboard/index');
@ -54,4 +53,4 @@ define(function (require) {
});
});
});

View file

@ -0,0 +1,381 @@
define(function (require) {
var angular = require('angular');
var $ = require('jquery');
var _ = require('lodash');
var sinon = require('test_utils/auto_release_sinon');
// Load the kibana app dependencies.
require('angular-route');
require('apps/discover/index');
var $parentScope, $scope, config;
// Stub out a minimal mapping of 3 fields
var mapping = {
bytes: {
indexed: true,
type: 'number'
},
request: {
indexed: false,
type: 'string'
},
timestamp: {
indexed: true,
type: 'date'
},
};
// Sets up the directive, take an element, and a list of properties to attach to the parent scope.
var init = function ($elem, props) {
module('kibana');
inject(function ($rootScope, $compile, _config_) {
config = _config_;
$parentScope = $rootScope;
_.assign($parentScope, props);
$compile($elem)($parentScope);
$elem.scope().$digest();
$scope = $elem.isolateScope();
});
};
var destroy = function () {
$scope.$destroy();
$parentScope.$destroy();
};
// For testing column removing/adding for the header and the rows
//
var columnTests = function (elemType, parentElem) {
it('should create only the toggle column by default', function (done) {
var childElems = parentElem.find(elemType);
expect(childElems.length).to.be(1);
done();
});
it('should create a time column if the timefield is defined', function (done) {
// Should include a column for toggling and the time column by default
$parentScope.timefield = 'timestamp';
parentElem.scope().$digest();
var childElems = parentElem.find(elemType);
expect(childElems.length).to.be(2);
done();
});
it('should be able to add and remove columns', function (done) {
var childElems;
// Should include a column for toggling and the time column by default
$parentScope.columns = ['bytes'];
parentElem.scope().$digest();
childElems = parentElem.find(elemType);
expect(childElems.length).to.be(2);
expect($(childElems[1]).text()).to.contain('bytes');
$parentScope.columns = ['bytes', 'request'];
parentElem.scope().$digest();
childElems = parentElem.find(elemType);
expect(childElems.length).to.be(3);
expect($(childElems[2]).text()).to.contain('request');
$parentScope.columns = ['request'];
parentElem.scope().$digest();
childElems = parentElem.find(elemType);
expect(childElems.length).to.be(2);
expect($(childElems[1]).text()).to.contain('request');
done();
});
};
describe('discover table directives', function () {
describe('kbnTableHeader', function () {
var $elem = angular.element(
'<thead kbn-table-header columns="columns" mapping="mapping" sort="sort" timefield="timefield"></thead>'
);
beforeEach(function () {
init($elem, {
mapping: mapping,
columns: [],
sorting: [],
});
});
afterEach(function () {
destroy();
});
describe('adding and removing columns', function () {
columnTests('th', $elem);
});
describe('sorting', function () {
it('should have a sort function that sets the elements of the sort array', function (done) {
expect($scope.sort).to.be.a(Function);
done();
});
it('should have a headClasser function that determines the css classes of the sort icons', function (done) {
expect($scope.headerClass).to.be.a(Function);
done();
});
it('should sort asc by default, then by desc if already sorting', function (done) {
var field = 'bytes';
// Should not be sorted at first
expect($scope.sorting).to.eql(undefined);
expect($scope.headerClass(field)).to.contain('fa-sort');
$scope.sort(field);
expect($scope.sorting).to.eql([field, 'asc']);
expect($scope.headerClass(field)).to.contain('fa-sort-up');
$scope.sort(field);
expect($scope.sorting).to.eql([field, 'desc']);
expect($scope.headerClass(field)).to.contain('fa-sort-down');
$scope.sort(field);
expect($scope.sorting).to.eql([field, 'asc']);
expect($scope.headerClass(field)).to.contain('fa-sort-up');
// Should show the default sort for any other field
expect($scope.headerClass('timestamp')).to.contain('fa-sort');
done();
});
it('should NOT sort unindexed fields', function (done) {
$scope.sort('request');
expect($scope.sorting).to.be(undefined);
done();
});
});
describe('moving columns', function () {
beforeEach(function () {
$parentScope.columns = _.keys($scope.mapping);
$elem.scope().$digest();
});
it('should move columns to the right', function () {
$scope.moveRight('bytes');
expect($scope.columns[1]).to.be('bytes');
$scope.moveRight('bytes');
expect($scope.columns[2]).to.be('bytes');
});
it('shouldnt move the last column to the right', function () {
expect($scope.columns[2]).to.be('timestamp');
$scope.moveRight('timestamp');
expect($scope.columns[2]).to.be('timestamp');
});
it('should move columns to the left', function () {
$scope.moveLeft('timestamp');
expect($scope.columns[1]).to.be('timestamp');
$scope.moveLeft('request');
expect($scope.columns[1]).to.be('request');
});
it('shouldnt move the first column to the left', function () {
expect($scope.columns[0]).to.be('bytes');
$scope.moveLeft('bytes');
expect($scope.columns[0]).to.be('bytes');
});
});
});
var longString = Array(50).join('_');
var getFakeRow = function (id) {
var columns = _.keys(mapping);
return {
_formatted: _.zipObject(_.map(columns, function (c) { return [c, c + '_formatted_' + id + longString]; })),
_source: _.zipObject(_.map(columns, function (c) { return [c, c + '_original_' + id + longString]; })),
_id: id,
_index: 'test',
sort: [id]
};
};
describe('kbnTable', function () {
var $elem = angular.element(
'<kbn-table ' +
'columns="columns" ' +
'rows="rows" ' +
'sorting="sorting"' +
'filtering="filtering"' +
'maxLength=maxLength ' +
'mapping="mapping"' +
'timefield="timefield" ' +
'></thead>'
);
beforeEach(function () {
// A tiny window
sinon.stub($.prototype, 'height', function () { return 100; });
// Convince the infinite scroll that there's still a lot of room left.
sinon.stub($.prototype, 'scrollTop', function () { return -200; });
var rows = _.times(200, function (i) {
return getFakeRow(i);
});
init($elem, {
columns: ['bytes'],
rows: rows,
sorting: [],
filtering: sinon.spy(),
maxLength: 50,
mapping: mapping,
timefield: 'timestamp'
});
});
afterEach(function () {
destroy();
});
it('should have a header and a table element', function (done) {
expect($elem.find('thead').length).to.be(1);
expect($elem.find('table').length).to.be(1);
done();
});
it('should have 50 rows to start', function (done) {
var tr = $elem.find('.discover-table-row');
expect(tr.length).to.be(50);
done();
});
it('should have an addRows function that adds 50 rows', function (done) {
expect($scope.addRows).to.be.a(Function);
$scope.addRows();
$elem.scope().$digest();
var tr = $elem.find('.discover-table-row');
expect(tr.length).to.be(100);
done();
});
});
describe('kbnTableRow', function () {
var $elem = angular.element(
'<tr kbn-table-row="row" ' +
'columns="columns" ' +
'sorting="sorting"' +
'filtering="filtering"' +
'max-length=maxLength ' +
'mapping="mapping"' +
'timefield="timefield" ' +
'></tr>'
);
beforeEach(function () {
init($elem, {
row: getFakeRow(0),
columns: [],
sorting: [],
filtering: sinon.spy(),
maxLength: 50,
mapping: mapping,
});
// Ignore the metaFields (_id, _type, etc) since we don't have a mapping for them
sinon.stub(config, 'get').withArgs('metaFields').returns([]);
});
afterEach(function () {
destroy();
});
describe('adding and removing columns', function () {
columnTests('td', $elem);
});
describe('details row', function () {
it('should be an empty tr by default', function () {
expect($elem.next().is('tr')).to.be(true);
expect($elem.next().text()).to.be('');
});
});
describe('details row', function () {
it('should be an empty tr by default', function () {
expect($elem.next().is('tr')).to.be(true);
expect($elem.next().text()).to.be('');
});
it('should expand the detail row when the toggle arrow is clicked', function () {
$elem.children(':first-child').click();
$scope.$digest();
expect($elem.next().text()).to.not.be('');
});
describe('expanded', function () {
var $details;
beforeEach(function () {
// Open the row
$scope.toggleRow();
$scope.$digest();
$details = $elem.next();
});
afterEach(function () {
// Close the row
$scope.toggleRow();
$scope.$digest();
});
it('should be a tr', function () {
expect($details.is('tr')).to.be(true);
});
it('should have a row for each field', function () {
var rows = $details.find('tr');
var row = $scope.row;
expect($details.find('tr').length).to.be(3);
});
it('should have a row for each field', function () {
var rows = $details.find('tr');
var row = $scope.row;
expect($details.find('tr').length).to.be(3);
});
describe('filtering', function () {
it('should filter when you click on the filter buttons', function () {
$details.find('.fa-search-plus').first().click();
expect($scope.filtering.calledOnce).to.be(true);
$details.find('.fa-search-minus').first().click();
expect($scope.filtering.calledTwice).to.be(true);
});
});
});
});
});
});
});

View file

@ -8,9 +8,6 @@ define(function (require) {
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('apps/discover/index');
var $parentScope, $scope, $elem;
@ -37,7 +34,7 @@ define(function (require) {
$elem.scope().$digest();
// Grab the isolate scope so we can test it
$scope = $elem.isolateScope();
$scope = $elem.scope();
// Add a function to check the run status of.
$scope.runThis = sinon.spy();
@ -123,4 +120,4 @@ define(function (require) {
});
});
});

View file

@ -2,12 +2,7 @@ define(function (require) {
var angular = require('angular');
var $ = require('jquery');
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('apps/discover/index');
var $parentScope, $scope, $elem;
@ -66,4 +61,4 @@ define(function (require) {
});
});
});

View file

@ -9,8 +9,6 @@ define(function (require) {
var removeFilter = require('components/filter_bar/lib/removeFilter');
var removeAll = require('components/filter_bar/lib/removeAll');
// Load kibana
require('index');
require('components/filter_bar/filter_bar');
describe('Filter Bar Directive', function () {

View file

@ -5,9 +5,6 @@ define(function (require) {
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('apps/discover/index');
var $parentScope, $scope, $elem;
@ -52,4 +49,4 @@ define(function (require) {
});
});
});

View file

@ -9,8 +9,6 @@ define(function (require) {
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('apps/visualize/index');
require('apps/dashboard/index');

View file

@ -5,9 +5,6 @@ define(function (require) {
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('apps/discover/index');
var $parentScope, $scope, $elem;
@ -93,4 +90,4 @@ define(function (require) {
});
});
});

View file

@ -4,9 +4,6 @@ define(function (require) {
// Load the kibana app dependencies.
require('angular-route');
// Load kibana and its applications
require('index');
require('components/typeahead/typeahead');
// TODO: This should not be needed, timefilter is only included here, it should move

Some files were not shown because too many files have changed in this diff Show more