Merge branch 'master' into vislib/refactor
Conflicts: .gitignore
This commit is contained in:
commit
0bfdaf814c
4
.bowerrc
4
.bowerrc
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"directory": "./src/bower_components"
|
"directory": "./src/kibana/bower_components"
|
||||||
}
|
}
|
||||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,7 +1,8 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
src/bower_components
|
bower_components
|
||||||
**/*.css
|
**/*.css
|
||||||
trash
|
trash
|
||||||
build
|
build
|
||||||
target
|
target
|
||||||
|
.jruby
|
1
.ruby-version
Normal file
1
.ruby-version
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1.9.3-p547
|
|
@ -12,9 +12,12 @@ module.exports = function (grunt) {
|
||||||
target: __dirname + '/target', // location of the compressed build targets
|
target: __dirname + '/target', // location of the compressed build targets
|
||||||
buildApp: __dirname + '/build/kibana', // build directory for the app
|
buildApp: __dirname + '/build/kibana', // build directory for the app
|
||||||
|
|
||||||
|
jrubyVersion: '1.7.14',
|
||||||
|
jrubyPath: __dirname + '/.jruby',
|
||||||
|
|
||||||
unitTestDir: __dirname + '/test/unit',
|
unitTestDir: __dirname + '/test/unit',
|
||||||
testUtilsDir: __dirname + '/test/utils',
|
testUtilsDir: __dirname + '/test/utils',
|
||||||
bowerComponentsDir: __dirname + '/src/bower_components',
|
bowerComponentsDir: __dirname + '/src/kibana/bower_components',
|
||||||
|
|
||||||
meta: {
|
meta: {
|
||||||
banner: '/*! <%= package.name %> - v<%= package.version %> - ' +
|
banner: '/*! <%= package.name %> - v<%= package.version %> - ' +
|
||||||
|
@ -36,4 +39,4 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
// load task definitions
|
// load task definitions
|
||||||
grunt.loadTasks('tasks');
|
grunt.loadTasks('tasks');
|
||||||
};
|
};
|
||||||
|
|
7
LICENSE.md
Normal file
7
LICENSE.md
Normal 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.
|
42
bower.json
42
bower.json
|
@ -20,32 +20,32 @@
|
||||||
"tests"
|
"tests"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"requirejs": "~2.1.10",
|
|
||||||
"angular": "~1.2.14",
|
"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-bindonce": "~0.3.1",
|
||||||
"angular-ui-ace": "bower",
|
"angular-bootstrap": "~0.10.0",
|
||||||
"angular-elastic": "~2.3.3",
|
"angular-elastic": "~2.3.3",
|
||||||
"inflection": "~1.3.5",
|
"angular-mocks": "~1.2.14",
|
||||||
"FileSaver": "*",
|
"angular-route": "~1.2.14",
|
||||||
"elasticsearch": "*",
|
"angular-ui-ace": "bower",
|
||||||
|
"async": "~0.2.10",
|
||||||
"bluebird": "~2.1.3",
|
"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",
|
"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": {}
|
"devDependencies": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,21 @@
|
||||||
"grunt-contrib-requirejs": "~0.4.4",
|
"grunt-contrib-requirejs": "~0.4.4",
|
||||||
"grunt-contrib-watch": "~0.5.3",
|
"grunt-contrib-watch": "~0.5.3",
|
||||||
"grunt-mocha": "~0.4.10",
|
"grunt-mocha": "~0.4.10",
|
||||||
|
"grunt-replace": "^0.7.9",
|
||||||
|
"grunt-run": "^0.2.3",
|
||||||
"http-proxy": "~1.1.4",
|
"http-proxy": "~1.1.4",
|
||||||
"husky": "~0.6.0",
|
"husky": "~0.6.0",
|
||||||
"istanbul": "~0.2.4",
|
"istanbul": "~0.2.4",
|
||||||
"load-grunt-config": "~0.7.0",
|
"load-grunt-config": "~0.7.0",
|
||||||
"lodash": "~2.4.1",
|
"lodash": "~2.4.1",
|
||||||
|
"mkdirp": "^0.5.0",
|
||||||
"mocha": "~1.20.1",
|
"mocha": "~1.20.1",
|
||||||
"path-browserify": "0.0.0",
|
"path-browserify": "0.0.0",
|
||||||
|
"progress": "^1.1.8",
|
||||||
|
"request": "^2.40.0",
|
||||||
"requirejs": "~2.1.14",
|
"requirejs": "~2.1.14",
|
||||||
"rjs-build-analysis": "0.0.3"
|
"rjs-build-analysis": "0.0.3",
|
||||||
|
"tar": "^1.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt test",
|
"test": "grunt test",
|
||||||
|
|
|
@ -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
|
|
|
@ -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)
|
|
|
@ -1,2 +0,0 @@
|
||||||
port 8000
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -25,7 +25,7 @@ define(function (require) {
|
||||||
|
|
||||||
require('routes')
|
require('routes')
|
||||||
.when('/dashboard', {
|
.when('/dashboard', {
|
||||||
templateUrl: 'kibana/apps/dashboard/index.html',
|
template: require('text!apps/dashboard/index.html'),
|
||||||
resolve: {
|
resolve: {
|
||||||
dash: function (savedDashboards) {
|
dash: function (savedDashboards) {
|
||||||
return savedDashboards.get();
|
return savedDashboards.get();
|
||||||
|
@ -33,7 +33,7 @@ define(function (require) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.when('/dashboard/:id', {
|
.when('/dashboard/:id', {
|
||||||
templateUrl: 'kibana/apps/dashboard/index.html',
|
template: require('text!apps/dashboard/index.html'),
|
||||||
resolve: {
|
resolve: {
|
||||||
dash: function (savedDashboards, Notifier, $route, $location, courier) {
|
dash: function (savedDashboards, Notifier, $route, $location, courier) {
|
||||||
return savedDashboards.get($route.current.params.id)
|
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 {
|
return {
|
||||||
controller: function ($scope, $route, $routeParams, $location, configFile) {
|
controller: function ($scope, $route, $routeParams, $location, configFile) {
|
||||||
var notify = new Notifier({
|
var notify = new Notifier({
|
||||||
|
@ -113,7 +113,7 @@ define(function (require) {
|
||||||
.then(function () {
|
.then(function () {
|
||||||
notify.info('Saved Dashboard as "' + dash.title + '"');
|
notify.info('Saved Dashboard as "' + dash.title + '"');
|
||||||
if (dash.id !== $routeParams.id) {
|
if (dash.id !== $routeParams.id) {
|
||||||
$location.url('/dashboard/' + encodeURIComponent(dash.id));
|
kbnUrl.change('/dashboard/{{id}}', {id: dash.id});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(notify.fatal);
|
.catch(notify.fatal);
|
||||||
|
|
|
@ -13,7 +13,7 @@ define(function (require) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// This is the only thing that gets injected into controllers
|
// 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
|
// Returns a single dashboard by ID, should be the name of the dashboard
|
||||||
this.get = function (id) {
|
this.get = function (id) {
|
||||||
|
@ -23,7 +23,7 @@ define(function (require) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.urlFor = function (id) {
|
this.urlFor = function (id) {
|
||||||
return '#/dashboard/' + encodeURIComponent(id);
|
return kbnUrl.eval('#/dashboard/{{id}}', {id: id});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.delete = function (ids) {
|
this.delete = function (ids) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ define(function (require) {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('discover', function ($scope, config, courier, $route, $window, savedSearches, savedVisualizations,
|
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 Vis = Private(require('components/vis/vis'));
|
||||||
var SegmentedFetch = Private(require('apps/discover/_segmented_fetch'));
|
var SegmentedFetch = Private(require('apps/discover/_segmented_fetch'));
|
||||||
|
@ -110,7 +110,8 @@ define(function (require) {
|
||||||
$state.index = config.get('defaultIndex');
|
$state.index = config.get('defaultIndex');
|
||||||
} else {
|
} else {
|
||||||
notify.warning(reason + 'Please set a default index to continue.');
|
notify.warning(reason + 'Please set a default index to continue.');
|
||||||
$location.url('/settings/indices');
|
kbnUrl.change('/settings/indices');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +228,7 @@ define(function (require) {
|
||||||
.then(function () {
|
.then(function () {
|
||||||
notify.info('Saved Data Source "' + savedSearch.title + '"');
|
notify.info('Saved Data Source "' + savedSearch.title + '"');
|
||||||
if (savedSearch.id !== $route.current.params.id) {
|
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 () {
|
$scope.newQuery = function () {
|
||||||
$location.url('/discover');
|
kbnUrl.change('/discover');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updateDataSource = function () {
|
$scope.updateDataSource = function () {
|
||||||
|
|
|
@ -19,10 +19,8 @@ define(function (require) {
|
||||||
scope: {
|
scope: {
|
||||||
fields: '=',
|
fields: '=',
|
||||||
toggle: '=',
|
toggle: '=',
|
||||||
refresh: '=',
|
|
||||||
data: '=',
|
data: '=',
|
||||||
state: '=',
|
state: '=',
|
||||||
updateFilterInQuery: '=filter',
|
|
||||||
searchSource: '='
|
searchSource: '='
|
||||||
},
|
},
|
||||||
template: html,
|
template: html,
|
||||||
|
@ -165,8 +163,7 @@ define(function (require) {
|
||||||
count: 5,
|
count: 5,
|
||||||
grouped: false
|
grouped: false
|
||||||
});
|
});
|
||||||
var indexPattern = $scope.searchSource.get('index');
|
$scope.increaseFieldCounter(field, 1);
|
||||||
indexPattern.popularizeField(field.name, 1);
|
|
||||||
} else {
|
} else {
|
||||||
delete field.details;
|
delete field.details;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,23 +29,28 @@ define(function (require) {
|
||||||
if ($scope.mapping[column] && !$scope.mapping[column].indexed) return;
|
if ($scope.mapping[column] && !$scope.mapping[column].indexed) return;
|
||||||
|
|
||||||
var sorting = $scope.sorting;
|
var sorting = $scope.sorting;
|
||||||
|
var defaultClass = ['fa', 'fa-sort', 'table-header-sortchange'];
|
||||||
|
|
||||||
if (!sorting) return [];
|
if (!sorting) return defaultClass;
|
||||||
|
|
||||||
if (column === sorting[0]) {
|
if (column === sorting[0]) {
|
||||||
return ['fa', sorting[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down'];
|
return ['fa', sorting[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down'];
|
||||||
} else {
|
} else {
|
||||||
return ['fa', 'fa-sort', 'table-header-sortchange'];
|
return defaultClass;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.moveLeft = function (column) {
|
$scope.moveLeft = function (column) {
|
||||||
var index = _.indexOf($scope.columns, column);
|
var index = _.indexOf($scope.columns, column);
|
||||||
|
if (index === 0) return;
|
||||||
|
|
||||||
_.move($scope.columns, index, --index);
|
_.move($scope.columns, index, --index);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.moveRight = function (column) {
|
$scope.moveRight = function (column) {
|
||||||
var index = _.indexOf($scope.columns, column);
|
var index = _.indexOf($scope.columns, column);
|
||||||
|
if (index === $scope.columns.length - 1) return;
|
||||||
|
|
||||||
_.move($scope.columns, index, ++index);
|
_.move($scope.columns, index, ++index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,7 +117,6 @@ define(function (require) {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
scope: {
|
scope: {
|
||||||
fields: '=',
|
|
||||||
columns: '=',
|
columns: '=',
|
||||||
filtering: '=',
|
filtering: '=',
|
||||||
mapping: '=',
|
mapping: '=',
|
||||||
|
@ -139,27 +143,14 @@ define(function (require) {
|
||||||
$scope.maxLength = 250;
|
$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
|
// 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;
|
var id = row._id;
|
||||||
|
|
||||||
$scope.open = !$scope.open;
|
$scope.open = !$scope.open;
|
||||||
|
|
||||||
var $tr = $(event.delegateTarget.parentElement);
|
var $tr = element;
|
||||||
var $detailsTr = $tr.next();
|
var $detailsTr = $tr.next();
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -169,7 +160,7 @@ define(function (require) {
|
||||||
$detailsTr.toggle($scope.open);
|
$detailsTr.toggle($scope.open);
|
||||||
|
|
||||||
// Change the caret icon
|
// 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-down');
|
||||||
$toggleIcon.toggleClass('fa-caret-right');
|
$toggleIcon.toggleClass('fa-caret-right');
|
||||||
|
|
||||||
|
@ -207,7 +198,12 @@ define(function (require) {
|
||||||
$scope.filtering(field, row._source[field] || row[field], operation);
|
$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();
|
element.empty();
|
||||||
createSummaryRow($scope.row, $scope.row._id);
|
createSummaryRow($scope.row, $scope.row._id);
|
||||||
});
|
});
|
||||||
|
@ -216,7 +212,7 @@ define(function (require) {
|
||||||
function createSummaryRow(row, id) {
|
function createSummaryRow(row, id) {
|
||||||
|
|
||||||
var expandTd = $('<td>').html('<i class="fa fa-caret-right"></span>')
|
var expandTd = $('<td>').html('<i class="fa fa-caret-right"></span>')
|
||||||
.attr('ng-click', 'toggleRow(row, $event)');
|
.attr('ng-click', 'toggleRow()');
|
||||||
$compile(expandTd)($scope);
|
$compile(expandTd)($scope);
|
||||||
element.append(expandTd);
|
element.append(expandTd);
|
||||||
|
|
||||||
|
@ -240,11 +236,7 @@ define(function (require) {
|
||||||
*/
|
*/
|
||||||
function _displayField(el, row, field, truncate) {
|
function _displayField(el, row, field, truncate) {
|
||||||
var val = _getValForField(row, field, truncate);
|
var val = _getValForField(row, field, truncate);
|
||||||
if (val instanceof DOMNode) {
|
el.text(val);
|
||||||
el.append(val);
|
|
||||||
} else {
|
|
||||||
el.text(val);
|
|
||||||
}
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,17 +258,9 @@ define(function (require) {
|
||||||
// undefined and null should just be an empty string
|
// undefined and null should just be an empty string
|
||||||
val = (val == null) ? '' : val;
|
val = (val == null) ? '' : val;
|
||||||
|
|
||||||
// truncate
|
// truncate the column text, not the details
|
||||||
if (typeof val === 'string' && val.length > $scope.maxLength) {
|
if (typeof val === 'string' && val.length > $scope.maxLength) {
|
||||||
if (untruncate) {
|
val = val.substring(0, $scope.maxLength) + '...';
|
||||||
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) + '...';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="row in rows |limitTo:limit track by row._index+row._id"
|
<tr ng-repeat="row in rows |limitTo:limit track by row._index+row._id"
|
||||||
kbn-table-row="row"
|
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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<kbn-infinite-scroll more="addRows"></kbn-infinite-scroll>
|
<kbn-infinite-scroll more="addRows"></kbn-infinite-scroll>
|
|
@ -3,7 +3,7 @@
|
||||||
<span ng-click="sort(timefield)">Time <i ng-class="headerClass(timefield)"></i></span>
|
<span ng-click="sort(timefield)">Time <i ng-class="headerClass(timefield)"></i></span>
|
||||||
</th>
|
</th>
|
||||||
<th ng-repeat="name in columns">
|
<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>
|
{{name}} <i ng-class="headerClass(name)"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="table-header-move">
|
<span class="table-header-move">
|
||||||
|
|
|
@ -15,7 +15,7 @@ define(function (require) {
|
||||||
title: 'searches'
|
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({
|
var notify = createNotifier({
|
||||||
|
@ -27,7 +27,7 @@ define(function (require) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.urlFor = function (id) {
|
this.urlFor = function (id) {
|
||||||
return '#/discover/' + encodeURIComponent(id);
|
return kbnUrl.eval('#/discover/{{id}}', {id: id});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.delete = function (ids) {
|
this.delete = function (ids) {
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<nav class="navbar navbar-default navbar-static-top subnav">
|
<nav class="navbar navbar-default navbar-static-top subnav">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li ng-repeat="s in sections" ng-class="s.class">
|
<li ng-repeat="section in sections" ng-class="section.class">
|
||||||
<a class="navbar-link" ng-href="{{s.url}}">{{s.display}}</a>
|
<a class="navbar-link" ng-href="{{section.url}}">{{section.display}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@ define(function (require) {
|
||||||
|
|
||||||
// wrapper directive, which sets some global stuff up like the left nav
|
// wrapper directive, which sets some global stuff up like the left nav
|
||||||
require('modules').get('apps/settings')
|
require('modules').get('apps/settings')
|
||||||
.directive('kbnSettingsIndices', function ($route, config) {
|
.directive('kbnSettingsIndices', function ($route, config, kbnUrl) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
transclude: true,
|
transclude: true,
|
||||||
|
@ -31,7 +31,7 @@ define(function (require) {
|
||||||
.map(function (id) {
|
.map(function (id) {
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
url: '#/settings/indices/' + encodeURIComponent(id),
|
url: kbnUrl.eval('#/settings/indices/{{id}}', {id: id}),
|
||||||
class: 'sidebar-item-title ' + ($scope.edittingId === id ? 'active' : ''),
|
class: 'sidebar-item-title ' + ($scope.edittingId === id ? 'active' : ''),
|
||||||
default: $scope.defaultIndex === id
|
default: $scope.defaultIndex === id
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@ define(function (require) {
|
||||||
'kibana/notify',
|
'kibana/notify',
|
||||||
'kibana/courier'
|
'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 _ = require('lodash');
|
||||||
var angular = require('angular');
|
var angular = require('angular');
|
||||||
|
@ -157,11 +157,7 @@ define(function (require) {
|
||||||
|
|
||||||
if (savedVis.id === $route.current.params.id) return;
|
if (savedVis.id === $route.current.params.id) return;
|
||||||
|
|
||||||
$location.url(
|
kbnUrl.change('/visualize/edit/{{id}}', {id: savedVis.id});
|
||||||
globalState.writeToUrl(
|
|
||||||
'/visualize/edit/' + encodeURIComponent(savedVis.id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}, notify.fatal);
|
}, notify.fatal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ define(function (require) {
|
||||||
title: 'visualizations'
|
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 visTypes = Private(require('components/vis_types/index'));
|
||||||
var notify = new Notifier({
|
var notify = new Notifier({
|
||||||
location: 'saved visualization service'
|
location: 'saved visualization service'
|
||||||
|
@ -22,7 +22,7 @@ define(function (require) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.urlFor = function (id) {
|
this.urlFor = function (id) {
|
||||||
return '#/visualize/edit/' + encodeURIComponent(id);
|
return kbnUrl.eval('#/visualize/edit/{{id}}', {id: id});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.delete = function (ids) {
|
this.delete = function (ids) {
|
||||||
|
|
|
@ -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) {
|
$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;
|
timefilter.enabled = false;
|
||||||
|
@ -38,7 +38,7 @@ define(function (require) {
|
||||||
|
|
||||||
$scope.$watch('indexPattern.selection', function (pattern) {
|
$scope.$watch('indexPattern.selection', function (pattern) {
|
||||||
if (!pattern) return;
|
if (!pattern) return;
|
||||||
$location.url('/visualize/step/2?indexPattern=' + encodeURIComponent(pattern));
|
kbnUrl.change('/visualize/step/2?indexPattern={{pattern}}', {pattern: pattern});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ define(function (require) {
|
||||||
if (query.query_string && query.query_string.query) {
|
if (query.query_string && query.query_string.query) {
|
||||||
return query.query_string.query;
|
return query.query_string.query;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(query);
|
return JSON.stringify(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,4 +31,4 @@ define(function (require) {
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ define(function (require) {
|
||||||
'kibana/notify'
|
'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
|
// allow the rest of the app to get the configFile easily
|
||||||
module.constant('configFile', configFile);
|
module.constant('configFile', configFile);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
define(function (require) {
|
define(function (require) {
|
||||||
var errors = require('errors');
|
var errors = require('errors');
|
||||||
|
|
||||||
return function RedirectWhenMissingFn($location, $route, globalState, Notifier) {
|
return function RedirectWhenMissingFn($location, kbnUrl, globalState, Notifier) {
|
||||||
var SavedObjectNotFound = errors.SavedObjectNotFound;
|
var SavedObjectNotFound = errors.SavedObjectNotFound;
|
||||||
|
|
||||||
var notify = new Notifier();
|
var notify = new Notifier();
|
||||||
|
@ -27,7 +27,7 @@ define(function (require) {
|
||||||
if (!url) url = '/';
|
if (!url) url = '/';
|
||||||
|
|
||||||
notify.error(err);
|
notify.error(err);
|
||||||
$route.changeUrl(globalState.writeToUrl(url));
|
kbnUrl.change(url);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
define(function (require) {
|
define(function (require) {
|
||||||
return function EnsureSomeIndexPatternsFn(Private, Notifier, $location, $route) {
|
return function EnsureSomeIndexPatternsFn(Private, Notifier, $location, kbnUrl) {
|
||||||
var errors = require('errors');
|
var errors = require('errors');
|
||||||
var notify = new Notifier();
|
var notify = new Notifier();
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ define(function (require) {
|
||||||
return function promiseHandler(patterns) {
|
return function promiseHandler(patterns) {
|
||||||
if (!patterns || patterns.length === 0) {
|
if (!patterns || patterns.length === 0) {
|
||||||
// notify.warning(new errors.NoDefinedIndexPatterns());
|
// notify.warning(new errors.NoDefinedIndexPatterns());
|
||||||
$route.change('/settings/indices');
|
kbnUrl.changePath('/settings/indices');
|
||||||
}
|
}
|
||||||
|
|
||||||
return patterns;
|
return patterns;
|
||||||
|
|
|
@ -21,8 +21,8 @@ define(function (require) {
|
||||||
template: html,
|
template: html,
|
||||||
controller: function ($scope) {
|
controller: function ($scope) {
|
||||||
var init = function () {
|
var init = function () {
|
||||||
$scope.formatRelative();
|
|
||||||
$scope.setMode($scope.mode);
|
$scope.setMode($scope.mode);
|
||||||
|
$scope.formatRelative();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.format = 'MMMM Do YYYY, HH:mm:ss.SSS';
|
$scope.format = 'MMMM Do YYYY, HH:mm:ss.SSS';
|
||||||
|
@ -136,4 +136,4 @@ define(function (require) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
97
src/kibana/components/url/url.js
Normal file
97
src/kibana/components/url/url.js
Normal 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -8,11 +8,12 @@ define(function (require) {
|
||||||
|
|
||||||
require('components/config/config');
|
require('components/config/config');
|
||||||
require('components/courier/courier');
|
require('components/courier/courier');
|
||||||
require('components/notify/notify');
|
|
||||||
require('components/state_management/app_state_factory');
|
|
||||||
require('components/filter_bar/filter_bar');
|
require('components/filter_bar/filter_bar');
|
||||||
require('components/storage/storage');
|
require('components/notify/notify');
|
||||||
require('components/persisted_log/persisted_log');
|
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/click_focus');
|
||||||
require('directives/info');
|
require('directives/info');
|
||||||
require('directives/spinner');
|
require('directives/spinner');
|
||||||
|
|
|
@ -4,7 +4,6 @@ define(function (require) {
|
||||||
.directive('confirmClick', function () {
|
.directive('confirmClick', function () {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
scope: {},
|
|
||||||
link: function ($scope, $elem, attrs) {
|
link: function ($scope, $elem, attrs) {
|
||||||
$elem.bind('click', function () {
|
$elem.bind('click', function () {
|
||||||
var message = attrs.confirmation || 'Are you sure?';
|
var message = attrs.confirmation || 'Are you sure?';
|
||||||
|
|
|
@ -25,7 +25,7 @@ define(function (require) {
|
||||||
var stringify = function () {
|
var stringify = function () {
|
||||||
var text;
|
var text;
|
||||||
// If both parts are date math, try to look up a reasonable string
|
// 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()];
|
var tryLookup = lookupByRange[$scope.from.toString() + ' to ' + $scope.to.toString()];
|
||||||
if (tryLookup) {
|
if (tryLookup) {
|
||||||
$elem.text(tryLookup.display);
|
$elem.text(tryLookup.display);
|
||||||
|
|
|
@ -3,7 +3,7 @@ define(function (require) {
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var rison = require('utils/rison');
|
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 = {
|
var vars = {
|
||||||
searches: {
|
searches: {
|
||||||
|
@ -85,12 +85,12 @@ define(function (require) {
|
||||||
|
|
||||||
// angular wants the '/path', not '#/path'
|
// angular wants the '/path', not '#/path'
|
||||||
var path = url.substr(1);
|
var path = url.substr(1);
|
||||||
if ($route.matches(path)) {
|
if (kbnUrl.matches(path)) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
|
|
||||||
// change works with paths, but we are only here because the paths
|
// 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
|
// are the same, so we have to change the whole url to be the new path
|
||||||
$route.changeUrl(path);
|
kbnUrl.change(path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
16
src/kibana/filters/rison.js
Normal file
16
src/kibana/filters/rison.js
Normal 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);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
|
@ -4,7 +4,7 @@
|
||||||
define(function (require) {
|
define(function (require) {
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
require('modules')
|
require('modules')
|
||||||
.get('kbn/filters')
|
.get('kibana')
|
||||||
.filter('shortDots', function (config) {
|
.filter('shortDots', function (config) {
|
||||||
return function (str) {
|
return function (str) {
|
||||||
if (!_.isString(str) || config.get('shortDots:enable') !== true) {
|
if (!_.isString(str) || config.get('shortDots:enable') !== true) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
define(function (require) {
|
define(function (require) {
|
||||||
require('modules')
|
require('modules')
|
||||||
.get('kbn/filters')
|
.get('kibana')
|
||||||
.filter('uriescape', function () {
|
.filter('uriescape', function () {
|
||||||
return function (str) {
|
return function (str) {
|
||||||
return encodeURIComponent(str);
|
return encodeURIComponent(str);
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>Kibana 4</title>
|
<title>Kibana 4</title>
|
||||||
<!-- load the root require context -->
|
<!-- 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>
|
<script>require(['kibana'], function (kibana) { kibana.init(); });</script>
|
||||||
<link rel="stylesheet" href="kibana/styles/main.css" >
|
<link rel="stylesheet" href="/styles/main.css" >
|
||||||
</head>
|
</head>
|
||||||
<body ng-controller="kibana" ng-class="'application-'+activeApp">
|
<body ng-controller="kibana" ng-class="'application-'+activeApp">
|
||||||
<kbn-notifications list="notifList"></kbn-notifications>
|
<kbn-notifications list="notifList"></kbn-notifications>
|
|
@ -12,7 +12,7 @@ define(function (require) {
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
require('angular-bindonce');
|
require('angular-bindonce');
|
||||||
|
|
||||||
var configFile = require('config_file');
|
var configFile = JSON.parse(require('text!config'));
|
||||||
|
|
||||||
var kibana = modules.get('kibana', [
|
var kibana = modules.get('kibana', [
|
||||||
// list external requirements here
|
// list external requirements here
|
||||||
|
@ -21,7 +21,7 @@ define(function (require) {
|
||||||
'ngRoute'
|
'ngRoute'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
configFile.elasticsearch = configFile.elasticsearch || ('http://' + window.location.hostname + ':9200');
|
configFile.elasticsearch = ('http://' + window.location.hostname + '/elasticsearch/');
|
||||||
|
|
||||||
kibana
|
kibana
|
||||||
// This stores the Kibana revision number, @REV@ is replaced by grunt.
|
// This stores the Kibana revision number, @REV@ is replaced by grunt.
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
require.config({
|
require.config({
|
||||||
baseUrl: './kibana',
|
baseUrl: './',
|
||||||
paths: {
|
paths: {
|
||||||
kibana: './index',
|
kibana: 'index',
|
||||||
config_file: '../config',
|
|
||||||
|
|
||||||
// special utils
|
// special utils
|
||||||
routes: 'utils/routes/index',
|
routes: 'utils/routes/index',
|
||||||
errors: 'components/errors',
|
errors: 'components/errors',
|
||||||
|
@ -11,27 +9,27 @@ require.config({
|
||||||
lodash: 'utils/_mixins',
|
lodash: 'utils/_mixins',
|
||||||
|
|
||||||
// bower_components
|
// bower_components
|
||||||
'angular-bindonce': '../bower_components/angular-bindonce/bindonce',
|
'angular-bindonce': 'bower_components/angular-bindonce/bindonce',
|
||||||
'angular-bootstrap': '../bower_components/angular-bootstrap/ui-bootstrap-tpls',
|
'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap-tpls',
|
||||||
'angular-elastic': '../bower_components/angular-elastic/elastic',
|
'angular-elastic': 'bower_components/angular-elastic/elastic',
|
||||||
'angular-route': '../bower_components/angular-route/angular-route',
|
'angular-route': 'bower_components/angular-route/angular-route',
|
||||||
'angular-ui-ace': '../bower_components/angular-ui-ace/ui-ace',
|
'angular-ui-ace': 'bower_components/angular-ui-ace/ui-ace',
|
||||||
ace: '../bower_components/ace-builds/src-noconflict/ace',
|
ace: 'bower_components/ace-builds/src-noconflict/ace',
|
||||||
angular: '../bower_components/angular/angular',
|
angular: 'bower_components/angular/angular',
|
||||||
async: '../bower_components/async/lib/async',
|
async: 'bower_components/async/lib/async',
|
||||||
bower_components: '../bower_components',
|
bower_components: 'bower_components',
|
||||||
css: '../bower_components/require-css/css',
|
css: 'bower_components/require-css/css',
|
||||||
d3: '../bower_components/d3/d3',
|
d3: 'bower_components/d3/d3',
|
||||||
elasticsearch: '../bower_components/elasticsearch/elasticsearch.angular',
|
elasticsearch: 'bower_components/elasticsearch/elasticsearch.angular',
|
||||||
faker: '../bower_components/Faker/faker',
|
faker: 'bower_components/Faker/faker',
|
||||||
file_saver: '../bower_components/FileSaver/FileSaver',
|
file_saver: 'bower_components/FileSaver/FileSaver',
|
||||||
gridster: '../bower_components/gridster/dist/jquery.gridster',
|
gridster: 'bower_components/gridster/dist/jquery.gridster',
|
||||||
inflection: '../bower_components/inflection/lib/inflection',
|
inflection: 'bower_components/inflection/lib/inflection',
|
||||||
jquery: '../bower_components/jquery/dist/jquery',
|
jquery: 'bower_components/jquery/dist/jquery',
|
||||||
jsonpath: '../bower_components/jsonpath/lib/jsonpath',
|
jsonpath: 'bower_components/jsonpath/lib/jsonpath',
|
||||||
lodash_src: '../bower_components/lodash/dist/lodash',
|
lodash_src: 'bower_components/lodash/dist/lodash',
|
||||||
moment: '../bower_components/moment/moment',
|
moment: 'bower_components/moment/moment',
|
||||||
text: '../bower_components/requirejs-text/text'
|
text: 'bower_components/requirejs-text/text'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
angular: {
|
angular: {
|
||||||
|
|
|
@ -14,4 +14,4 @@ define(function (require) {
|
||||||
|
|
||||||
return es;
|
return es;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,10 +62,6 @@ define(function (require) {
|
||||||
}()));
|
}()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Timefilter.prototype.enabled = function (state) {
|
|
||||||
this.enabled = !!state;
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.get = function (indexPattern) {
|
Timefilter.prototype.get = function (indexPattern) {
|
||||||
var filter;
|
var filter;
|
||||||
var timefield = indexPattern.timeFieldName && _.find(indexPattern.fields, {name: indexPattern.timeFieldName});
|
var timefield = indexPattern.timeFieldName && _.find(indexPattern.fields, {name: indexPattern.timeFieldName});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@bs-less-dir: "../../bower_components/bootstrap/less";
|
@bs-less-dir: "../bower_components/bootstrap/less";
|
||||||
|
|
||||||
// Core variables and mixins
|
// Core variables and mixins
|
||||||
@import "theme/_variables.less";
|
@import "theme/_variables.less";
|
||||||
|
|
|
@ -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";
|
@import (reference) "lesshat.less";
|
||||||
|
|
||||||
// generic mixins
|
// generic mixins
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
define(function (require) {
|
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 errors = require('errors');
|
||||||
var NoDefaultIndexPattern = errors.NoDefaultIndexPattern;
|
var NoDefaultIndexPattern = errors.NoDefaultIndexPattern;
|
||||||
|
@ -26,7 +26,7 @@ define(function (require) {
|
||||||
if (err instanceof NoDefaultIndexPattern || err instanceof NoDefinedIndexPatterns) {
|
if (err instanceof NoDefaultIndexPattern || err instanceof NoDefinedIndexPatterns) {
|
||||||
// .change short circuits the routes by calling $route.refresh(). We can safely swallow this error
|
// .change short circuits the routes by calling $route.refresh(). We can safely swallow this error
|
||||||
// after reporting it to the user
|
// after reporting it to the user
|
||||||
$route.change('/settings/indices');
|
kbnUrl.change('/settings/indices');
|
||||||
(new Notifier()).error(err);
|
(new Notifier()).error(err);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
|
@ -34,4 +34,4 @@ define(function (require) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,42 +5,6 @@ define(function (require) {
|
||||||
require('components/setup/setup');
|
require('components/setup/setup');
|
||||||
require('services/promises');
|
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() {
|
function RouteManager() {
|
||||||
var when = [];
|
var when = [];
|
||||||
var additions = [];
|
var additions = [];
|
||||||
|
|
19
src/server/DIST_README.md
Normal file
19
src/server/DIST_README.md
Normal 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
|
|
@ -1,5 +1,3 @@
|
||||||
ruby "1.9.3", :engine => 'jruby', :engine_version => '1.7.13'
|
|
||||||
|
|
||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'sinatra', :require => 'sinatra/base'
|
gem 'sinatra', :require => 'sinatra/base'
|
||||||
|
@ -8,3 +6,4 @@ gem 'puma'
|
||||||
gem 'warbler'
|
gem 'warbler'
|
||||||
gem 'elasticsearch'
|
gem 'elasticsearch'
|
||||||
gem 'rack-reverse-proxy', :require => 'rack/reverse_proxy'
|
gem 'rack-reverse-proxy', :require => 'rack/reverse_proxy'
|
||||||
|
gem 'colorize'
|
|
@ -2,6 +2,7 @@ GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
backports (3.6.0)
|
backports (3.6.0)
|
||||||
|
colorize (0.7.3)
|
||||||
elasticsearch (1.0.4)
|
elasticsearch (1.0.4)
|
||||||
elasticsearch-api (= 1.0.4)
|
elasticsearch-api (= 1.0.4)
|
||||||
elasticsearch-transport (= 1.0.4)
|
elasticsearch-transport (= 1.0.4)
|
||||||
|
@ -52,6 +53,7 @@ PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
colorize
|
||||||
elasticsearch
|
elasticsearch
|
||||||
puma
|
puma
|
||||||
rack-reverse-proxy
|
rack-reverse-proxy
|
83
src/server/bin/initialize
Executable file
83
src/server/bin/initialize
Executable 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
25
src/server/bin/kibana.bat
Normal 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
30
src/server/bin/kibana.sh
Executable 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" "$@"
|
20
src/server/config/kibana.yml
Normal file
20
src/server/config/kibana.yml
Normal 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
22
src/server/config/web.ru
Normal 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
|
44
src/server/lib/ColorLogger.rb
Normal file
44
src/server/lib/ColorLogger.rb
Normal 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
|
||||||
|
|
||||||
|
|
46
src/server/lib/JSONLogger.rb
Normal file
46
src/server/lib/JSONLogger.rb
Normal 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
68
src/server/lib/app.rb
Normal 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
60
src/server/lib/server.rb
Normal 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
21
src/server/routes/base.rb
Normal 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
21
src/server/routes/home.rb
Normal 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
|
14
src/server/routes/proxy.rb
Normal file
14
src/server/routes/proxy.rb
Normal 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
|
|
@ -4,9 +4,18 @@ module.exports = function (grunt) {
|
||||||
'clean:build',
|
'clean:build',
|
||||||
'require_css_deps:copy',
|
'require_css_deps:copy',
|
||||||
'less',
|
'less',
|
||||||
|
'copy:kibana_src',
|
||||||
|
'touch_config',
|
||||||
'requirejs',
|
'requirejs',
|
||||||
'clean:unneeded_source_in_build',
|
'clean:unneeded_source_in_build',
|
||||||
|
'copy:server_src',
|
||||||
|
'download_jruby',
|
||||||
|
'install_gems',
|
||||||
|
'warble',
|
||||||
|
'replace:dist',
|
||||||
|
'copy:dist',
|
||||||
|
'chmod_kibana',
|
||||||
'compress:build_zip',
|
'compress:build_zip',
|
||||||
'compress:build_tarball'
|
'compress:build_tarball'
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
9
tasks/chmod_kibana.js
Normal file
9
tasks/chmod_kibana.js
Normal 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);
|
||||||
|
});
|
||||||
|
};
|
|
@ -6,20 +6,19 @@ module.exports = function (grunt) {
|
||||||
unneeded_source_in_build: {
|
unneeded_source_in_build: {
|
||||||
src: [
|
src: [
|
||||||
// select all top level folders in bower_components
|
// select all top level folders in bower_components
|
||||||
'<%= build %>/bower_components/*',
|
'<%= build %>/kibana/public/bower_components/*',
|
||||||
// exclude the following top level 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
|
// remove the contents of K4D3, font-awesome, and requirejs except necessary files
|
||||||
'<%= build %>/bower_components/' + notIncludedComponents + '/*',
|
'<%= build %>/kibana/public/bower_components/' + notIncludedComponents + '/*',
|
||||||
'!<%= build %>/bower_components/requirejs/require.js',
|
'!<%= build %>/kibana/public/bower_components/requirejs/require.js',
|
||||||
'!<%= build %>/bower_components/font-awesome/fonts',
|
'!<%= build %>/kibana/public/bower_components/font-awesome/fonts',
|
||||||
|
'<%= build %>/kibana/public/**/_empty_',
|
||||||
'<%= build %>/**/_empty_',
|
'<%= build %>/kibana/public/**/*.less',
|
||||||
'<%= build %>/**/*.less',
|
'<%= build %>/kibana/public/config',
|
||||||
'<%= appBuild %>/{css-builder,normalize}.js',
|
'<%= build %>/kibana/public/{css-builder,normalize}.js',
|
||||||
'<%= app %>/{css-builder,normalize}.js',
|
'<%= app %>/public/{css-builder,normalize}.js',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
return _.mapValues({
|
return _.mapValues({
|
||||||
build_zip: archiveName() + '.zip',
|
build_zip: archiveName() + '.zip',
|
||||||
build_tarball: archiveName() + '.zip',
|
build_tarball: archiveName() + '.tar.gz',
|
||||||
plugin: archiveName(true) + '.tar.gz'
|
plugin: archiveName(true) + '.tar.gz'
|
||||||
}, function (filename, task) {
|
}, function (filename, task) {
|
||||||
return {
|
return {
|
||||||
|
@ -16,11 +16,11 @@ module.exports = function (grunt) {
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: '<%= build %>',
|
cwd: '<%= build %>/dist',
|
||||||
src: ['**/*'],
|
src: ['**/*'],
|
||||||
dest: '<%= pkg.name %>' + (task === 'plugin' ? '/_site' : '')
|
dest: '<%= pkg.name %>' + (task === 'plugin' ? '/_site' : '')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
71
tasks/config/copy.js
Normal file
71
tasks/config/copy.js
Normal 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;
|
||||||
|
};
|
|
@ -17,8 +17,9 @@ module.exports = function (grunt) {
|
||||||
ignores: [
|
ignores: [
|
||||||
'node_modules/*',
|
'node_modules/*',
|
||||||
'dist/*',
|
'dist/*',
|
||||||
'sample/*'
|
'sample/*',
|
||||||
|
'<%= src %>/kibana/bower_components/**/*'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 = {
|
module.exports = {
|
||||||
src: {
|
src: {
|
||||||
|
|
31
tasks/config/replace.js
Normal file
31
tasks/config/replace.js
Normal 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;
|
||||||
|
};
|
|
@ -2,14 +2,15 @@ module.exports = function (grunt) {
|
||||||
var config = {
|
var config = {
|
||||||
build: {
|
build: {
|
||||||
options: {
|
options: {
|
||||||
appDir: '<%= src %>',
|
appDir: '<%= build %>/src',
|
||||||
dir: '<%= build %>',
|
dir: '<%= build %>/kibana/public',
|
||||||
mainConfigFile: '<%= app %>/require.config.js',
|
mainConfigFile: '<%= build %>/src/require.config.js',
|
||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
name: 'kibana',
|
name: 'kibana',
|
||||||
excludeShallow: [
|
excludeShallow: [
|
||||||
'../config',
|
'../config',
|
||||||
|
'text!config'
|
||||||
],
|
],
|
||||||
include: [
|
include: [
|
||||||
'controllers/kibana'
|
'controllers/kibana'
|
||||||
|
@ -60,10 +61,10 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
// include each app
|
// include each app
|
||||||
var main = config.build.options.modules[0];
|
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) {
|
configFile.apps.forEach(function (app) {
|
||||||
main.include.push('apps/' + app.id + '/index');
|
main.include.push('apps/' + app.id + '/index');
|
||||||
});
|
});
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
28
tasks/config/run.js
Normal file
28
tasks/config/run.js
Normal 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;
|
||||||
|
|
||||||
|
};
|
|
@ -1,4 +1,16 @@
|
||||||
module.exports = function (grunt) {
|
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 = {
|
var config = {
|
||||||
test: {
|
test: {
|
||||||
files: [
|
files: [
|
||||||
|
@ -26,6 +38,16 @@ module.exports = function (grunt) {
|
||||||
'<%= testUtilsDir %>/istanbul_reporter/report.clientside.jade'
|
'<%= testUtilsDir %>/istanbul_reporter/report.clientside.jade'
|
||||||
],
|
],
|
||||||
tasks: ['jade:clientside']
|
tasks: ['jade:clientside']
|
||||||
|
},
|
||||||
|
kibana_server: {
|
||||||
|
files: [
|
||||||
|
'src/server/**/*.rb',
|
||||||
|
'src/server/**/*.yml'
|
||||||
|
],
|
||||||
|
tasks: kibana_server_tasks,
|
||||||
|
options: {
|
||||||
|
spawn: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
21
tasks/dev.js
21
tasks/dev.js
|
@ -1,8 +1,21 @@
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
grunt.registerTask('dev', [
|
var useJRuby = grunt.option('use-jruby');
|
||||||
|
var tasks = [
|
||||||
'less',
|
'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',
|
'maybe_start_server',
|
||||||
'watch'
|
'watch'
|
||||||
]);
|
]));
|
||||||
};
|
};
|
||||||
|
|
46
tasks/download_jruby.js
Normal file
46
tasks/download_jruby.js
Normal 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
20
tasks/install_gems.js
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -8,8 +8,8 @@ module.exports = function (grunt) {
|
||||||
].forEach(function (dep) {
|
].forEach(function (dep) {
|
||||||
grunt.file.copy(
|
grunt.file.copy(
|
||||||
join(grunt.config.get('bowerComponentsDir'), 'require-css', dep),
|
join(grunt.config.get('bowerComponentsDir'), 'require-css', dep),
|
||||||
join(grunt.config.get('app'), dep)
|
join(grunt.config.get('build'), 'src', dep)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +1,34 @@
|
||||||
|
var _ = require('lodash');
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
/* jshint scripturl:true */
|
/* 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',
|
'maybe_start_server',
|
||||||
'jade',
|
'jade',
|
||||||
'mocha:unit',
|
'mocha:unit',
|
||||||
'jshint'
|
'jshint'
|
||||||
]);
|
]));
|
||||||
|
|
||||||
grunt.registerTask('coverage', [
|
grunt.registerTask('coverage', rubyTasks.concat([
|
||||||
'blanket',
|
'blanket',
|
||||||
'maybe_start_server',
|
'maybe_start_server',
|
||||||
'mocha:coverage'
|
'mocha:coverage'
|
||||||
]);
|
]));
|
||||||
|
|
||||||
grunt.registerTask('test:watch', [
|
grunt.registerTask('test:watch', rubyTasks.concat([
|
||||||
'maybe_start_server',
|
'maybe_start_server',
|
||||||
'watch:test'
|
'watch:test'
|
||||||
]);
|
]));
|
||||||
};
|
};
|
||||||
|
|
8
tasks/touch_config.js
Normal file
8
tasks/touch_config.js
Normal 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
18
tasks/wait_for_jruby.js
Normal 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
20
tasks/warble.js
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -5,7 +5,7 @@
|
||||||
<link rel="stylesheet" href="/node_modules/mocha/mocha.css" />
|
<link rel="stylesheet" href="/node_modules/mocha/mocha.css" />
|
||||||
<script src="/node_modules/expect.js/index.js"></script>
|
<script src="/node_modules/expect.js/index.js"></script>
|
||||||
<script src="/node_modules/mocha/mocha.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 src="/src/kibana/require.config.js"></script>
|
||||||
<script>(function () {
|
<script>(function () {
|
||||||
var COVERAGE = !!(/coverage/i.test(window.location.search));
|
var COVERAGE = !!(/coverage/i.test(window.location.search));
|
||||||
|
@ -18,13 +18,14 @@
|
||||||
require.config({
|
require.config({
|
||||||
baseUrl: '/src/kibana',
|
baseUrl: '/src/kibana',
|
||||||
paths: {
|
paths: {
|
||||||
|
config: '/config',
|
||||||
test_utils: '../../test/utils',
|
test_utils: '../../test/utils',
|
||||||
fixtures: '../../test/unit/fixtures',
|
fixtures: '../../test/unit/fixtures',
|
||||||
specs: '../../test/unit/specs',
|
specs: '../../test/unit/specs',
|
||||||
sinon: '../../test/utils/sinon',
|
sinon: '../../test/utils/sinon',
|
||||||
bluebird: '../bower_components/bluebird/js/browser/bluebird',
|
bluebird: 'bower_components/bluebird/js/browser/bluebird',
|
||||||
angular: '../bower_components/angular-mocks/angular-mocks',
|
angular: 'bower_components/angular-mocks/angular-mocks',
|
||||||
angular_src: '../bower_components/angular/angular'
|
angular_src: 'bower_components/angular/angular'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
angular: {
|
angular: {
|
||||||
|
@ -61,6 +62,7 @@
|
||||||
'kibana',
|
'kibana',
|
||||||
'sinon/sinon',
|
'sinon/sinon',
|
||||||
'specs/apps/discover/hit_sort_fn',
|
'specs/apps/discover/hit_sort_fn',
|
||||||
|
'specs/apps/discover/directives/table',
|
||||||
'specs/apps/discover/segmented_fetch',
|
'specs/apps/discover/segmented_fetch',
|
||||||
'specs/directives/confirm-click',
|
'specs/directives/confirm-click',
|
||||||
'specs/directives/timepicker',
|
'specs/directives/timepicker',
|
||||||
|
@ -71,10 +73,12 @@
|
||||||
'specs/filters/field_type',
|
'specs/filters/field_type',
|
||||||
'specs/filters/uriescape',
|
'specs/filters/uriescape',
|
||||||
'specs/filters/moment',
|
'specs/filters/moment',
|
||||||
|
'specs/filters/rison',
|
||||||
'specs/filters/short_dots',
|
'specs/filters/short_dots',
|
||||||
'specs/filters/start_from',
|
'specs/filters/start_from',
|
||||||
'specs/services/storage',
|
'specs/services/storage',
|
||||||
'specs/services/persisted_log',
|
'specs/services/persisted_log',
|
||||||
|
'specs/services/url',
|
||||||
'specs/utils/datemath',
|
'specs/utils/datemath',
|
||||||
'specs/utils/interval',
|
'specs/utils/interval',
|
||||||
'specs/utils/versionmath',
|
'specs/utils/versionmath',
|
||||||
|
|
|
@ -7,7 +7,6 @@ define(function (require) {
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load the code for the directive
|
// Load the code for the directive
|
||||||
require('index');
|
|
||||||
require('apps/visualize/index');
|
require('apps/visualize/index');
|
||||||
require('apps/dashboard/index');
|
require('apps/dashboard/index');
|
||||||
|
|
||||||
|
@ -54,4 +53,4 @@ define(function (require) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
381
test/unit/specs/apps/discover/directives/table.js
Normal file
381
test/unit/specs/apps/discover/directives/table.js
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -8,9 +8,6 @@ define(function (require) {
|
||||||
// Load the kibana app dependencies.
|
// Load the kibana app dependencies.
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
|
|
||||||
require('apps/discover/index');
|
require('apps/discover/index');
|
||||||
|
|
||||||
var $parentScope, $scope, $elem;
|
var $parentScope, $scope, $elem;
|
||||||
|
@ -37,7 +34,7 @@ define(function (require) {
|
||||||
$elem.scope().$digest();
|
$elem.scope().$digest();
|
||||||
|
|
||||||
// Grab the isolate scope so we can test it
|
// Grab the isolate scope so we can test it
|
||||||
$scope = $elem.isolateScope();
|
$scope = $elem.scope();
|
||||||
|
|
||||||
// Add a function to check the run status of.
|
// Add a function to check the run status of.
|
||||||
$scope.runThis = sinon.spy();
|
$scope.runThis = sinon.spy();
|
||||||
|
@ -123,4 +120,4 @@ define(function (require) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,12 +2,7 @@ define(function (require) {
|
||||||
var angular = require('angular');
|
var angular = require('angular');
|
||||||
var $ = require('jquery');
|
var $ = require('jquery');
|
||||||
|
|
||||||
// Load the kibana app dependencies.
|
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
|
|
||||||
require('apps/discover/index');
|
require('apps/discover/index');
|
||||||
|
|
||||||
var $parentScope, $scope, $elem;
|
var $parentScope, $scope, $elem;
|
||||||
|
@ -66,4 +61,4 @@ define(function (require) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,6 @@ define(function (require) {
|
||||||
var removeFilter = require('components/filter_bar/lib/removeFilter');
|
var removeFilter = require('components/filter_bar/lib/removeFilter');
|
||||||
var removeAll = require('components/filter_bar/lib/removeAll');
|
var removeAll = require('components/filter_bar/lib/removeAll');
|
||||||
|
|
||||||
// Load kibana
|
|
||||||
require('index');
|
|
||||||
require('components/filter_bar/filter_bar');
|
require('components/filter_bar/filter_bar');
|
||||||
|
|
||||||
describe('Filter Bar Directive', function () {
|
describe('Filter Bar Directive', function () {
|
||||||
|
|
|
@ -5,9 +5,6 @@ define(function (require) {
|
||||||
// Load the kibana app dependencies.
|
// Load the kibana app dependencies.
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
|
|
||||||
require('apps/discover/index');
|
require('apps/discover/index');
|
||||||
|
|
||||||
var $parentScope, $scope, $elem;
|
var $parentScope, $scope, $elem;
|
||||||
|
@ -52,4 +49,4 @@ define(function (require) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,6 @@ define(function (require) {
|
||||||
// Load the kibana app dependencies.
|
// Load the kibana app dependencies.
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
require('apps/visualize/index');
|
require('apps/visualize/index');
|
||||||
require('apps/dashboard/index');
|
require('apps/dashboard/index');
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@ define(function (require) {
|
||||||
// Load the kibana app dependencies.
|
// Load the kibana app dependencies.
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
|
|
||||||
require('apps/discover/index');
|
require('apps/discover/index');
|
||||||
|
|
||||||
var $parentScope, $scope, $elem;
|
var $parentScope, $scope, $elem;
|
||||||
|
@ -93,4 +90,4 @@ define(function (require) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,9 +4,6 @@ define(function (require) {
|
||||||
|
|
||||||
// Load the kibana app dependencies.
|
// Load the kibana app dependencies.
|
||||||
require('angular-route');
|
require('angular-route');
|
||||||
|
|
||||||
// Load kibana and its applications
|
|
||||||
require('index');
|
|
||||||
require('components/typeahead/typeahead');
|
require('components/typeahead/typeahead');
|
||||||
|
|
||||||
// TODO: This should not be needed, timefilter is only included here, it should move
|
// 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
Loading…
Reference in a new issue