diff --git a/.bowerrc b/.bowerrc index 6388054bb30e..d31fab554b4e 100644 --- a/.bowerrc +++ b/.bowerrc @@ -1,3 +1,3 @@ { - "directory": "./src/bower_components" -} \ No newline at end of file + "directory": "./src/kibana/bower_components" +} diff --git a/.gitignore b/.gitignore index e19c3b49a381..c61045debfad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ .DS_Store node_modules -src/bower_components +bower_components **/*.css trash build -target \ No newline at end of file +target +.jruby \ No newline at end of file diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 000000000000..75bfecd56a22 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +1.9.3-p547 diff --git a/Gruntfile.js b/Gruntfile.js index 84418a5396fc..fe56233649da 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,9 +12,12 @@ module.exports = function (grunt) { target: __dirname + '/target', // location of the compressed build targets buildApp: __dirname + '/build/kibana', // build directory for the app + jrubyVersion: '1.7.14', + jrubyPath: __dirname + '/.jruby', + unitTestDir: __dirname + '/test/unit', testUtilsDir: __dirname + '/test/utils', - bowerComponentsDir: __dirname + '/src/bower_components', + bowerComponentsDir: __dirname + '/src/kibana/bower_components', meta: { banner: '/*! <%= package.name %> - v<%= package.version %> - ' + @@ -36,4 +39,4 @@ module.exports = function (grunt) { // load task definitions grunt.loadTasks('tasks'); -}; \ No newline at end of file +}; diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000000..042736d536dc --- /dev/null +++ b/LICENSE.md @@ -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. diff --git a/bower.json b/bower.json index a35a8426c6e9..611d9da90f4b 100644 --- a/bower.json +++ b/bower.json @@ -20,32 +20,32 @@ "tests" ], "dependencies": { - "requirejs": "~2.1.10", "angular": "~1.2.14", - "lodash": "~2.4.1", - "d3": "~3.4.8", - "angular-route": "~1.2.14", - "gridster": "~0.5.0", - "angular-mocks": "~1.2.14", - "font-awesome": "~4.0.3", - "requirejs-text": "~2.0.10", - "async": "~0.2.10", - "bootstrap": "~3.1.1", - "jquery": "~2.1.0", - "moment": "~2.5.1", - "require-css": "~0.1.2", - "angular-bootstrap": "~0.10.0", - "jsonpath": "*", - "moment-timezone": "~0.0.3", "angular-bindonce": "~0.3.1", - "angular-ui-ace": "bower", + "angular-bootstrap": "~0.10.0", "angular-elastic": "~2.3.3", - "inflection": "~1.3.5", - "FileSaver": "*", - "elasticsearch": "*", + "angular-mocks": "~1.2.14", + "angular-route": "~1.2.14", + "angular-ui-ace": "bower", + "async": "~0.2.10", "bluebird": "~2.1.3", + "bootstrap": "~3.1.1", + "d3": "~3.4.8", + "elasticsearch": "*", + "Faker": "~1.1.0", + "FileSaver": "*", + "font-awesome": "~4.0.3", + "gridster": "~0.5.0", + "inflection": "~1.3.5", + "jquery": "~2.1.0", + "jsonpath": "*", "lesshat": "~3.0.2", - "Faker": "~1.1.0" + "lodash": "~2.4.1", + "moment": "~2.5.1", + "moment-timezone": "~0.0.3", + "require-css": "~0.1.2", + "requirejs": "~2.1.10", + "requirejs-text": "~2.0.10" }, "devDependencies": {} } diff --git a/package.json b/package.json index 67999eaa7fab..28107a6a1245 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,21 @@ "grunt-contrib-requirejs": "~0.4.4", "grunt-contrib-watch": "~0.5.3", "grunt-mocha": "~0.4.10", + "grunt-replace": "^0.7.9", + "grunt-run": "^0.2.3", "http-proxy": "~1.1.4", "husky": "~0.6.0", "istanbul": "~0.2.4", "load-grunt-config": "~0.7.0", "lodash": "~2.4.1", + "mkdirp": "^0.5.0", "mocha": "~1.20.1", "path-browserify": "0.0.0", + "progress": "^1.1.8", + "request": "^2.40.0", "requirejs": "~2.1.14", - "rjs-build-analysis": "0.0.3" + "rjs-build-analysis": "0.0.3", + "tar": "^1.0.1" }, "scripts": { "test": "grunt test", diff --git a/server/Rakefile b/server/Rakefile deleted file mode 100644 index d1fec40ccaff..000000000000 --- a/server/Rakefile +++ /dev/null @@ -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 diff --git a/server/bin/kibana b/server/bin/kibana deleted file mode 100755 index 1cfa34c06078..000000000000 --- a/server/bin/kibana +++ /dev/null @@ -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) diff --git a/server/config/puma.rb b/server/config/puma.rb deleted file mode 100644 index af9fef9b3fd7..000000000000 --- a/server/config/puma.rb +++ /dev/null @@ -1,2 +0,0 @@ -port 8000 - diff --git a/server/config/web.ru b/server/config/web.ru deleted file mode 100644 index 4ac61a858d4c..000000000000 --- a/server/config/web.ru +++ /dev/null @@ -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 diff --git a/server/lib/app.rb b/server/lib/app.rb deleted file mode 100644 index ebb032864ffd..000000000000 --- a/server/lib/app.rb +++ /dev/null @@ -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 diff --git a/server/public/index.html b/server/public/index.html deleted file mode 100644 index c8dc6e899800..000000000000 --- a/server/public/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - -
-This is the server component of Kibana. It's just a quick prototype of the things we need.
- - - -This should work outside of anything else.
- - diff --git a/server/routes/api.rb b/server/routes/api.rb deleted file mode 100644 index 0653297355d7..000000000000 --- a/server/routes/api.rb +++ /dev/null @@ -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 diff --git a/server/routes/base.rb b/server/routes/base.rb deleted file mode 100644 index 1206802f1e68..000000000000 --- a/server/routes/base.rb +++ /dev/null @@ -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 diff --git a/server/routes/home.rb b/server/routes/home.rb deleted file mode 100644 index be9dc5883f1e..000000000000 --- a/server/routes/home.rb +++ /dev/null @@ -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 diff --git a/src/kibana/apps/dashboard/index.js b/src/kibana/apps/dashboard/index.js index 006aff4cddf4..6980e336d2e2 100644 --- a/src/kibana/apps/dashboard/index.js +++ b/src/kibana/apps/dashboard/index.js @@ -25,7 +25,7 @@ define(function (require) { require('routes') .when('/dashboard', { - templateUrl: 'kibana/apps/dashboard/index.html', + template: require('text!apps/dashboard/index.html'), resolve: { dash: function (savedDashboards) { return savedDashboards.get(); @@ -33,7 +33,7 @@ define(function (require) { } }) .when('/dashboard/:id', { - templateUrl: 'kibana/apps/dashboard/index.html', + template: require('text!apps/dashboard/index.html'), resolve: { dash: function (savedDashboards, Notifier, $route, $location, courier) { return savedDashboards.get($route.current.params.id) @@ -42,7 +42,7 @@ define(function (require) { } }); - app.directive('dashboardApp', function (Notifier, courier, savedVisualizations, appStateFactory, timefilter) { + app.directive('dashboardApp', function (Notifier, courier, savedVisualizations, appStateFactory, timefilter, kbnUrl) { return { controller: function ($scope, $route, $routeParams, $location, configFile) { var notify = new Notifier({ @@ -113,7 +113,7 @@ define(function (require) { .then(function () { notify.info('Saved Dashboard as "' + dash.title + '"'); if (dash.id !== $routeParams.id) { - $location.url('/dashboard/' + encodeURIComponent(dash.id)); + kbnUrl.change('/dashboard/{{id}}', {id: dash.id}); } }) .catch(notify.fatal); diff --git a/src/kibana/apps/dashboard/services/saved_dashboards.js b/src/kibana/apps/dashboard/services/saved_dashboards.js index 03614b903dd4..eb46aecfbb9e 100644 --- a/src/kibana/apps/dashboard/services/saved_dashboards.js +++ b/src/kibana/apps/dashboard/services/saved_dashboards.js @@ -13,7 +13,7 @@ define(function (require) { }); // This is the only thing that gets injected into controllers - module.service('savedDashboards', function (Promise, SavedDashboard, config, es) { + module.service('savedDashboards', function (Promise, SavedDashboard, config, es, kbnUrl) { // Returns a single dashboard by ID, should be the name of the dashboard this.get = function (id) { @@ -23,7 +23,7 @@ define(function (require) { }; this.urlFor = function (id) { - return '#/dashboard/' + encodeURIComponent(id); + return kbnUrl.eval('#/dashboard/{{id}}', {id: id}); }; this.delete = function (ids) { diff --git a/src/kibana/apps/discover/controllers/discover.js b/src/kibana/apps/discover/controllers/discover.js index 0f44a8ad0e38..83ea25a8d7e9 100644 --- a/src/kibana/apps/discover/controllers/discover.js +++ b/src/kibana/apps/discover/controllers/discover.js @@ -46,7 +46,7 @@ define(function (require) { }); app.controller('discover', function ($scope, config, courier, $route, $window, savedSearches, savedVisualizations, - Notifier, $location, globalState, appStateFactory, timefilter, Promise, Private) { + Notifier, $location, globalState, appStateFactory, timefilter, Promise, Private, kbnUrl) { var Vis = Private(require('components/vis/vis')); var SegmentedFetch = Private(require('apps/discover/_segmented_fetch')); @@ -110,7 +110,8 @@ define(function (require) { $state.index = config.get('defaultIndex'); } else { notify.warning(reason + 'Please set a default index to continue.'); - $location.url('/settings/indices'); + kbnUrl.change('/settings/indices'); + return; } } @@ -227,7 +228,7 @@ define(function (require) { .then(function () { notify.info('Saved Data Source "' + savedSearch.title + '"'); if (savedSearch.id !== $route.current.params.id) { - $location.url(globalState.writeToUrl('/discover/' + encodeURIComponent(savedSearch.id))); + kbnUrl.change('/discover/{{id}}', { id: savedSearch.id }); } }); }) @@ -388,7 +389,7 @@ define(function (require) { }; $scope.newQuery = function () { - $location.url('/discover'); + kbnUrl.change('/discover'); }; $scope.updateDataSource = function () { diff --git a/src/kibana/apps/discover/directives/field_chooser.js b/src/kibana/apps/discover/directives/field_chooser.js index b5bb63c26ac5..3740284d3c75 100644 --- a/src/kibana/apps/discover/directives/field_chooser.js +++ b/src/kibana/apps/discover/directives/field_chooser.js @@ -19,10 +19,8 @@ define(function (require) { scope: { fields: '=', toggle: '=', - refresh: '=', data: '=', state: '=', - updateFilterInQuery: '=filter', searchSource: '=' }, template: html, @@ -165,8 +163,7 @@ define(function (require) { count: 5, grouped: false }); - var indexPattern = $scope.searchSource.get('index'); - indexPattern.popularizeField(field.name, 1); + $scope.increaseFieldCounter(field, 1); } else { delete field.details; } diff --git a/src/kibana/apps/discover/directives/table.js b/src/kibana/apps/discover/directives/table.js index 1215ac1d4261..8bbf4edaddd4 100644 --- a/src/kibana/apps/discover/directives/table.js +++ b/src/kibana/apps/discover/directives/table.js @@ -29,23 +29,28 @@ define(function (require) { if ($scope.mapping[column] && !$scope.mapping[column].indexed) return; var sorting = $scope.sorting; + var defaultClass = ['fa', 'fa-sort', 'table-header-sortchange']; - if (!sorting) return []; + if (!sorting) return defaultClass; if (column === sorting[0]) { return ['fa', sorting[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down']; } else { - return ['fa', 'fa-sort', 'table-header-sortchange']; + return defaultClass; } }; $scope.moveLeft = function (column) { var index = _.indexOf($scope.columns, column); + if (index === 0) return; + _.move($scope.columns, index, --index); }; $scope.moveRight = function (column) { var index = _.indexOf($scope.columns, column); + if (index === $scope.columns.length - 1) return; + _.move($scope.columns, index, ++index); }; @@ -112,7 +117,6 @@ define(function (require) { return { restrict: 'A', scope: { - fields: '=', columns: '=', filtering: '=', mapping: '=', @@ -139,27 +143,14 @@ define(function (require) { $scope.maxLength = 250; } - - // for now, rows are "tracked" by their index, but this could eventually - // be configured so that changing the order of the rows won't prevent - // them from staying open on update - function rowId(row) { - var id = $scope.rows.indexOf(row); - return ~id ? id : null; - } - - // inverse of rowId() - function rowForId(id) { - return $scope.rows[id]; - } - // toggle display of the rows details, a full list of the fields from each row - $scope.toggleRow = function (row, event) { + $scope.toggleRow = function () { + var row = $scope.row; var id = row._id; $scope.open = !$scope.open; - var $tr = $(event.delegateTarget.parentElement); + var $tr = element; var $detailsTr = $tr.next(); /// @@ -169,7 +160,7 @@ define(function (require) { $detailsTr.toggle($scope.open); // Change the caret icon - var $toggleIcon = $($(event.delegateTarget).children('i')[0]); + var $toggleIcon = $(element.children().first().find('i')[0]); $toggleIcon.toggleClass('fa-caret-down'); $toggleIcon.toggleClass('fa-caret-right'); @@ -207,7 +198,12 @@ define(function (require) { $scope.filtering(field, row._source[field] || row[field], operation); }; - $scope.$watch('columns', function () { + $scope.$watch('columns', function (columns) { + element.empty(); + createSummaryRow($scope.row, $scope.row._id); + }); + + $scope.$watch('timefield', function (timefield) { element.empty(); createSummaryRow($scope.row, $scope.row._id); }); @@ -216,7 +212,7 @@ define(function (require) { function createSummaryRow(row, id) { var expandTd = $('