mongo_browser 0.1.3 → 0.2.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +3 -3
  3. data/README.md +1 -25
  4. data/Rakefile +0 -1
  5. data/app/assets/images/background.png +0 -0
  6. data/app/assets/javascripts/app/controllers/alerts.js.coffee +12 -0
  7. data/app/assets/javascripts/app/controllers/breadcrumbs.js.coffee +25 -0
  8. data/app/assets/javascripts/app/controllers/collections.js.coffee +40 -0
  9. data/app/assets/javascripts/app/controllers/databases.js.coffee +39 -0
  10. data/app/assets/javascripts/app/controllers/documents.js.coffee +49 -0
  11. data/app/assets/javascripts/app/controllers/main.js.coffee +10 -0
  12. data/app/assets/javascripts/app/controllers/server_info.js.coffee +14 -0
  13. data/app/assets/javascripts/app/controllers.js.coffee +2 -0
  14. data/app/assets/javascripts/app/directives.js.coffee +20 -0
  15. data/app/assets/javascripts/app/filters.js.coffee +48 -0
  16. data/app/assets/javascripts/app/modules/dialogs.js.coffee +29 -0
  17. data/app/assets/javascripts/app/modules/pager.js.coffee +87 -0
  18. data/app/assets/javascripts/app/modules/table_filter.js.coffee +27 -0
  19. data/app/assets/javascripts/app/resources.js.coffee +22 -0
  20. data/app/assets/javascripts/app/services.js.coffee +36 -0
  21. data/app/assets/javascripts/app.js.coffee +8 -0
  22. data/app/assets/javascripts/application.js.coffee +35 -6
  23. data/app/assets/javascripts/templates/.gitkeep +0 -0
  24. data/app/assets/javascripts/templates.js.coffee +1 -0
  25. data/app/assets/javascripts/vendor.js.coffee +5 -0
  26. data/app/assets/stylesheets/application.css.scss +46 -3
  27. data/app/assets/templates/collections.html +53 -0
  28. data/app/assets/templates/databases.html +32 -0
  29. data/app/assets/templates/documents.html +45 -0
  30. data/app/assets/templates/pager.html +13 -0
  31. data/app/{views/server_info.erb → assets/templates/server_info.html} +5 -7
  32. data/app/assets/templates/table_filter.html +10 -0
  33. data/bin/mongo_browser +8 -45
  34. data/config-e2e.ru +20 -0
  35. data/grunt.js +36 -0
  36. data/lib/mongo_browser/application.rb +143 -64
  37. data/lib/mongo_browser/middleware/sprockets_base.rb +11 -0
  38. data/lib/mongo_browser/middleware/sprockets_sinatra.rb +3 -7
  39. data/lib/mongo_browser/middleware/sprockets_specs.rb +18 -0
  40. data/lib/mongo_browser/models/collection.rb +67 -0
  41. data/lib/mongo_browser/models/database.rb +52 -0
  42. data/lib/mongo_browser/models/document.rb +17 -0
  43. data/lib/mongo_browser/models/pager.rb +30 -0
  44. data/lib/mongo_browser/models/server.rb +51 -0
  45. data/lib/mongo_browser/version.rb +1 -1
  46. data/lib/mongo_browser.rb +10 -5
  47. data/mongo_browser.gemspec +4 -11
  48. data/public/index.html +47 -0
  49. data/script/ci_all +21 -0
  50. data/script/ci_e2e +11 -0
  51. data/script/ci_javascripts +4 -0
  52. data/script/ci_rspec +3 -0
  53. data/spec/features/collections_list_spec.rb +6 -49
  54. data/spec/features/documents_list_spec.rb +15 -14
  55. data/spec/features/server_info_spec.rb +3 -3
  56. data/spec/javascripts/app/controllers/alerts_spec.js.coffee +36 -0
  57. data/spec/javascripts/app/controllers/breadcrumbs_spec.js.coffee +28 -0
  58. data/spec/javascripts/app/controllers/collections_spec.js.coffee +78 -0
  59. data/spec/javascripts/app/controllers/databases_spec.js.coffee +55 -0
  60. data/spec/javascripts/app/controllers/documents_spec.js.coffee +62 -0
  61. data/spec/javascripts/app/controllers/main_spec.js.coffee +20 -0
  62. data/spec/javascripts/app/controllers/server_info_spec.js.coffee +21 -0
  63. data/spec/javascripts/app/directives_spec.js.coffee +58 -0
  64. data/spec/javascripts/app/filters_spec.js.coffee +99 -0
  65. data/spec/javascripts/app/modules/dialogs_spec.js.coffee +51 -0
  66. data/spec/javascripts/app/modules/pager_spec.js.coffee +104 -0
  67. data/spec/javascripts/app/modules/table_filter_spec.js.coffee +76 -0
  68. data/spec/javascripts/app/services_spec.js.coffee +83 -0
  69. data/spec/javascripts/config/testacular-e2e.conf.js +19 -0
  70. data/spec/javascripts/config/testacular.conf.js +43 -0
  71. data/spec/javascripts/e2e/collections_scenario.js.coffee +49 -0
  72. data/spec/javascripts/e2e/databases_scenario.js.coffee +74 -0
  73. data/spec/javascripts/e2e/documents_scenario.js.coffee +18 -0
  74. data/spec/javascripts/e2e/server_info_scenario.js.coffee +12 -0
  75. data/spec/javascripts/helpers/matchers.js.coffee +5 -0
  76. data/spec/javascripts/helpers/mocks.js.coffee +7 -0
  77. data/spec/javascripts/helpers_e2e/app_element.js.coffee +6 -0
  78. data/spec/javascripts/lib/angular-mocks.js +1740 -0
  79. data/spec/javascripts/lib/angular-scenario.js +26147 -0
  80. data/spec/javascripts/lib/jasmine-html.js +681 -0
  81. data/spec/javascripts/lib/jasmine.css +82 -0
  82. data/spec/javascripts/lib/jasmine.js +2600 -0
  83. data/spec/javascripts/runner.html +54 -0
  84. data/spec/javascripts/runner_e2e.html +10 -0
  85. data/spec/javascripts/spec.js.coffee +2 -0
  86. data/spec/javascripts/spec_e2e.js.coffee +2 -0
  87. data/spec/lib/models/collection_spec.rb +80 -0
  88. data/spec/lib/models/database_spec.rb +75 -0
  89. data/spec/lib/models/document_spec.rb +17 -0
  90. data/spec/lib/models/pager_spec.rb +64 -0
  91. data/spec/lib/models/server_spec.rb +76 -0
  92. data/spec/lib/mongo_browser_spec.rb +1 -1
  93. data/spec/spec_helper.rb +2 -19
  94. data/spec/support/feature_example_group.rb +8 -3
  95. data/spec/support/fixtures/databases.json +8 -0
  96. data/spec/support/fixtures.rb +20 -3
  97. data/spec/support/matchers/have_flash_message.rb +1 -1
  98. data/spec/support/mongod.rb +37 -21
  99. data/spec/support/mongodb.conf +47 -0
  100. data/vendor/assets/javascripts/angular/angular-bootstrap.js +166 -0
  101. data/vendor/assets/javascripts/angular/angular-resource.js +435 -0
  102. data/vendor/assets/javascripts/angular/angular-sanitize.js +535 -0
  103. data/vendor/assets/javascripts/angular/angular.js +14531 -0
  104. data/vendor/assets/javascripts/underscore.js +1200 -0
  105. metadata +136 -148
  106. data/app/assets/javascripts/app/table_filter.js.coffee +0 -50
  107. data/app/assets/javascripts/ujs.js.coffee +0 -23
  108. data/app/views/collections/index.erb +0 -59
  109. data/app/views/databases/index.erb +0 -29
  110. data/app/views/documents/index.erb +0 -61
  111. data/app/views/layout/_flash_messages.erb +0 -10
  112. data/app/views/layout/_navbar.erb +0 -22
  113. data/app/views/layout.erb +0 -20
  114. data/app/views/shared/_filter.erb +0 -14
  115. data/features/mongo_browser.feature +0 -18
  116. data/features/step_definitions/mongo_browser_steps.rb +0 -1
  117. data/features/support/env.rb +0 -18
  118. data/spec/features/databases_list_spec.rb +0 -65
@@ -6,22 +6,65 @@
6
6
  body {
7
7
  position: relative;
8
8
  padding-top: 40px;
9
- background-color: #fff;
9
+ background-color: #d3d3d3;
10
10
  background-repeat: repeat-x;
11
11
  background-position: 0 40px;
12
12
  }
13
13
 
14
+ section.container {
15
+ background-color: white;
16
+ margin-top: 16px;
17
+ border: 1px solid #AAA;
18
+ border-radius: 4px 4px 0px 0px;
19
+ padding-left: 20px;
20
+ padding-right: 20px;
21
+
22
+ section {
23
+ margin-top: 20px;
24
+
25
+ header {
26
+ background-color: #f5f5f5;
27
+ border-bottom: 1px solid #DDD;
28
+ border-radius: 4px 4px 0px 0px;
29
+ margin: -20px -20px 20px;
30
+ padding-left: 20px;
31
+
32
+ h2 {
33
+ font-family: "Rokkitt", serif;
34
+ font-size: 24px;
35
+ margin: 0px;
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ #alerts {
42
+ margin-left: auto;
43
+ margin-right: auto;
44
+ margin-top: 20px;
45
+ max-width: 980px;
46
+ }
47
+
14
48
  table.table {
15
49
  tr {
16
- &.document pre {
50
+ &.document td.data pre {
17
51
  background: none;
18
52
  border: 0px;
19
53
  padding: 0px;
20
54
  display: inline;
55
+
56
+ // syntax higlight for json document
57
+ span {
58
+ &.string { color: green; }
59
+ &.number { color: darkorange; }
60
+ &.boolean { color: blue; }
61
+ &.null { color: magenta; }
62
+ &.key { color: red; }
63
+ }
21
64
  }
22
65
 
23
66
  th.actions {
24
- min-width: 90px;
67
+ width: 90px;
25
68
  }
26
69
  }
27
70
  }
@@ -0,0 +1,53 @@
1
+ <header>
2
+ <h2>{{dbName}} collections</h2>
3
+ </header>
4
+
5
+ <div class="tabbable">
6
+ <div class="tab-pane" title="Collections" ng-hide="isLoading()">
7
+ <table-filter value="filterValue.name" placeholder="Enter collection name"></table-filter>
8
+
9
+ <table ng-show="(collections | filter:filterValue).length" class="table table-striped table-hover collections">
10
+ <thead>
11
+ <tr>
12
+ <th>Name</th>
13
+ <th>Documents</th>
14
+ <th class="actions">&nbsp;</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <tr ng-repeat="collection in collections | orderBy:'name' | filter:filterValue">
19
+ <td>
20
+ <a href="{{collection | documentsPath}}">
21
+ {{collection.name}}
22
+ </a>
23
+ </td>
24
+ <td>{{collection.size}}</td>
25
+ <td class="actions">
26
+ <delete-button ng-click="delete(collection)" />
27
+ </td>
28
+ </tr>
29
+ </tbody>
30
+ </table>
31
+
32
+ <div ng-hide="(collections | filter:filterValue).length" class="filter alert">
33
+ Nothing has been found.
34
+ </div>
35
+ </div>
36
+
37
+ <div class="tab-pane" title="Database stats">
38
+ <table class="table table-striped table-hover">
39
+ <thead>
40
+ <tr>
41
+ <th>Property</th>
42
+ <th>Value</th>
43
+ </tr>
44
+ </thead>
45
+ <tbody>
46
+ <tr ng-repeat="(property, value) in dbStats">
47
+ <td>{{property}}</td>
48
+ <td>{{value}}</td>
49
+ </tr>
50
+ </tbody>
51
+ </table>
52
+ </div>
53
+ </div>
@@ -0,0 +1,32 @@
1
+ <header>
2
+ <h2>localhost databases</h2>
3
+ </header>
4
+
5
+ <div ng-hide="isLoading()">
6
+ <table-filter value="filterValue.name" placeholder="Enter database name"></table-filter>
7
+
8
+ <table ng-show="(databases | filter:filterValue).length" class="table table-striped table-hover databases">
9
+ <thead>
10
+ <tr>
11
+ <th>Name</th>
12
+ <th>Collections</th>
13
+ <th>Size</th>
14
+ <th class="actions">&nbsp;</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <tr ng-repeat="database in databases | orderBy:'name' | filter:filterValue">
19
+ <td><a href="{{database | collectionsPath}}">{{database.name}}</a></td>
20
+ <td>{{database.count}}</td>
21
+ <td>{{database.size | humanSize}}</td>
22
+ <td class="actions">
23
+ <delete-button ng-click="delete(database)" />
24
+ </td>
25
+ </tr>
26
+ </tbody>
27
+ </table>
28
+
29
+ <div ng-hide="(databases | filter:filterValue).length" class="filter alert">
30
+ Nothing has been found.
31
+ </div>
32
+ </div>
@@ -0,0 +1,45 @@
1
+ <header>
2
+ <h2>{{collectionName}} documents</h2>
3
+ </header>
4
+
5
+ <div class="tabbable">
6
+ <div class="tab-pane" title="Documents">
7
+ <pager page="page" total-pages="totalPages"></pager>
8
+
9
+ <table class="table table-striped table-hover documents">
10
+ <thead>
11
+ <tr>
12
+ <th>Data</th>
13
+ <th class="actions">&nbsp;</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr ng-repeat="document in documents" class="document id-{{document.id}}">
18
+ <td class="data" ng-bind-html="document.data | jsonDocument"></td>
19
+ <td class="actions">
20
+ <delete-button ng-click="delete(document)" />
21
+ </td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+
26
+ <pager page="page" total-pages="totalPages"></pager>
27
+ </div>
28
+
29
+ <div class="tab-pane" title="Collection stats">
30
+ <table class="table table-striped table-hover">
31
+ <thead>
32
+ <tr>
33
+ <th>Property</th>
34
+ <th>Value</th>
35
+ </tr>
36
+ </thead>
37
+ <tbody>
38
+ <tr ng-repeat="(property, value) in collectionStats">
39
+ <td>{{property}}</td>
40
+ <td>{{value}}</td>
41
+ </tr>
42
+ </tbody>
43
+ </table>
44
+ </div>
45
+ </div>
@@ -0,0 +1,13 @@
1
+ <div class="pagination" ng-show="display()">
2
+ <ul>
3
+ <li ng-class="{disabled: !hasPrev()}"><a href="#" ng-click="prev()">Prev</a></li>
4
+ <li ng-class="{disabled: !hasNext()}"><a href="#" ng-click="next()">Next</a></li>
5
+
6
+ <li ng-repeat="number in windowedPageNumbers"
7
+ ng-class="{active: number == page}"
8
+ ng-class="{disabled: !number}">
9
+
10
+ <a ng-click="setPage(number)" href="#">{{number || "…"}}</a>
11
+ </li>
12
+ </ul>
13
+ </div>
@@ -1,6 +1,6 @@
1
- <div class="page-header">
1
+ <header>
2
2
  <h2>server info</h2>
3
- </div>
3
+ </header>
4
4
 
5
5
  <table class="table table-striped table-hover">
6
6
  <thead>
@@ -10,11 +10,9 @@
10
10
  </tr>
11
11
  </thead>
12
12
  <tbody>
13
- <% @server_info.each do |property, value| %>
14
- <tr>
15
- <td><%= property %></td>
16
- <td><%= value %></td>
13
+ <tr ng-repeat="(property, value) in serverInfo">
14
+ <td>{{property}}</td>
15
+ <td>{{value}}</td>
17
16
  </tr>
18
- <% end %>
19
17
  </tbody>
20
18
  </table>
@@ -0,0 +1,10 @@
1
+ <form class="filter">
2
+ <div class="input-append">
3
+ <input ng-model="value" on-esc="clear()" type="text" class="span3" placeholder="{{placeholder}}">
4
+
5
+ <button ng-click="clear()" type="button" class="btn ng-class: {disabled: isEmpty()}">
6
+ <i class="icon-remove-circle"></i>Clear
7
+ </button>
8
+ </div>
9
+ <span class="help-block">Press ESC to clear the filter</span>
10
+ </form>
data/bin/mongo_browser CHANGED
@@ -1,53 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "optparse"
4
- require "methadone"
3
+ require "vegas"
5
4
  require "mongo_browser"
6
- require "forever"
7
-
8
- class App
9
- include Methadone::Main
10
- include Methadone::CLILogging
11
-
12
- main do
13
- app_port = options[:port] || 4567
14
- info("Running on the master node #{MongoBrowser.mongodb_host}:#{MongoBrowser.mongodb_port}")
15
- info("Application is accessible at http://localhost:#{app_port}")
16
-
17
- if options[:demonize]
18
- Forever.run do
19
- pid '/tmp/mongo_browser.pid'
20
- log '/tmp/mongo_browser.log'
21
-
22
- on_ready do
23
- MongoBrowser::Application.run!(port: app_port)
24
- end
25
- end
26
- else
27
- MongoBrowser::Application.run!(port: app_port)
28
- end
29
- end
30
-
31
- version MongoBrowser::VERSION
32
-
33
- on("--port PORT", "MongoBrowser port",
34
- "(Default: 4567)")
35
-
36
- on("--mongodb-host HOST", "Mongodb database host",
37
- "(Default: #{MongoBrowser.mongodb_host})") do |host|
38
-
39
- MongoBrowser.mongodb_host = host
40
- end
41
-
42
- on("--mongodb-port PORT", "Mongodb database port",
43
- "(Default: #{MongoBrowser.mongodb_port})") do |port|
44
5
 
6
+ Vegas::Runner.new(MongoBrowser::Application, "mongo_browser") do |runner, opts, app|
7
+ opts.on("--mongodb-port PORT", "Specify mongodb port") do |port|
8
+ runner.logger.info "Using mongodb port #{port}"
45
9
  MongoBrowser.mongodb_port = port.to_i
46
10
  end
47
11
 
48
- on("--demonize", "Run the app in the background")
49
-
50
- use_log_level_option
51
-
52
- go!
12
+ opts.on("--mongodb-host HOST", "Specify mongodb host") do |host|
13
+ runner.logger.info "Using mongodb host #{host}"
14
+ MongoBrowser.mongodb_host = host.to_i
15
+ end
53
16
  end
data/config-e2e.ru ADDED
@@ -0,0 +1,20 @@
1
+ require "mongo_browser"
2
+
3
+ require File.expand_path("spec/support/mongod")
4
+ require File.expand_path("spec/support/fixtures")
5
+
6
+ test_server = Mongod.instance
7
+ fixtures = Fixtures.instance
8
+
9
+ test_server.start! do |port|
10
+ MongoBrowser.mongodb_host = "127.0.0.1"
11
+ MongoBrowser.mongodb_port = port
12
+ end
13
+
14
+ fixtures.load!
15
+
16
+ run MongoBrowser::Application
17
+
18
+ at_exit do
19
+ test_server.shutdown!
20
+ end
data/grunt.js ADDED
@@ -0,0 +1,36 @@
1
+ module.exports = function(grunt) {
2
+
3
+ grunt.initConfig({
4
+ watch: {
5
+ templates: {
6
+ files: 'app/assets/templates/*.html',
7
+ tasks: 'html2js:directives'
8
+ }
9
+ },
10
+
11
+ html2js: {
12
+ directives: ['app/assets/templates/*.html']
13
+ }
14
+ });
15
+
16
+ var TPL = 'angular.module("<%= file %>", []).run(function($templateCache) {\n' + ' $templateCache.put("<%= path %>",\n "<%= content %>");\n' + '});\n';
17
+
18
+ var escapeContent = function(content) {
19
+ return content.replace(/"/g, '\\"').replace(/\n/g, '" +\n "');
20
+ };
21
+
22
+ grunt.registerMultiTask('html2js', 'Generate js version of html template.', function() {
23
+ var files = grunt._watch_changed_files || grunt.file.expand(this.data);
24
+
25
+ files.forEach(function(file) {
26
+ var parts = file.split("/");
27
+ var name = parts[parts.length - 1];
28
+
29
+ grunt.file.write("app/assets/javascripts/templates/" + name + '.js', grunt.template.process(TPL, {
30
+ file: file,
31
+ path: "/ng/templates/" + file.split("/").pop(),
32
+ content: escapeContent(grunt.file.read(file))
33
+ }));
34
+ });
35
+ });
36
+ };
@@ -1,7 +1,6 @@
1
1
  require "sinatra"
2
2
  require "sinatra/reloader"
3
- require "sinatra/flash"
4
- require "will_paginate-bootstrap"
3
+ require "sinatra/respond_with"
5
4
 
6
5
  require "sprockets"
7
6
  require "sass"
@@ -11,109 +10,189 @@ require "mongo_browser/middleware/sprockets_sinatra"
11
10
 
12
11
  module MongoBrowser
13
12
  class Application < Sinatra::Base
13
+ include Models
14
+
14
15
  configure :development do
15
16
  register Sinatra::Reloader
16
17
  end
17
18
 
18
19
  enable :sessions
19
- register Sinatra::Flash
20
20
 
21
21
  set :root, File.join(File.dirname(__FILE__), "../../app")
22
+ set :public_folder, File.join(settings.root, "../public")
23
+
22
24
  set :method_override, true
23
25
 
26
+ register Sinatra::RespondWith
27
+
24
28
  use Middleware::SprocketsSinatra, :root => File.join(settings.root, "..")
25
- register WillPaginate::Sinatra
26
29
 
27
- # Databases list
28
- get "/" do
29
- @databases = connection.database_info
30
- erb :"databases/index"
30
+ if settings.test?
31
+ require File.join(settings.root, "../spec/support/fixtures")
32
+
33
+ require "mongo_browser/middleware/sprockets_specs"
34
+ use Middleware::SprocketsSpecs, :root => File.join(settings.root, "..")
35
+
36
+ get "/jasmine" do
37
+ File.read(File.join(settings.root, "../spec/javascripts/runner.html"))
38
+ end
39
+
40
+ # Execute e2e runner
41
+ get "/e2e" do
42
+ File.read(File.join(settings.root, "../spec/javascripts/runner_e2e.html"))
43
+ end
44
+
45
+ # Load database fixtures
46
+ get "/e2e/load_fixtures" do
47
+ Fixtures.instance.load!
48
+
49
+ respond_to do |format|
50
+ format.json { true }
51
+ end
52
+ end
31
53
  end
32
54
 
33
- # Collections list
34
- get "/databases/:db_name" do |db_name|
35
- database = connection.db(db_name)
36
- @collections = database.collections
37
- @stats = database.stats
55
+ # Loads given template from assets/templates directory
56
+ get "/ng/templates/:name.html" do |template_name|
57
+ send_file File.join(settings.root, "assets/templates/#{template_name}.html")
58
+ end
59
+
60
+ # Welcome page
61
+ # All routes without `/api` prefix
62
+ get /^(?!\/api).+/ do
63
+ File.read(File.join(settings.public_folder, "index.html"))
64
+ end
65
+
66
+ # Databases list
67
+ get "/api/databases.json" do
68
+ databases = server.databases.map do |db|
69
+ {
70
+ id: db.id,
71
+ name: db.name,
72
+ size: db.size,
73
+ count: db.count
74
+ }
75
+ end
38
76
 
39
- erb :"collections/index"
77
+ respond_to do |format|
78
+ format.json { databases.to_json }
79
+ end
40
80
  end
41
81
 
42
82
  # Delete a database
43
- delete "/databases/:db_name" do |db_name|
44
- connection.drop_database(db_name)
83
+ delete "/api/databases.json" do
84
+ database = server.database(params[:id])
85
+ database.drop!
45
86
 
46
- flash[:info] = "Database #{db_name} has been deleted."
47
- redirect "/"
87
+ respond_to do |format|
88
+ format.json { true }
89
+ end
48
90
  end
49
91
 
50
- # Documents list
51
- get "/databases/:db_name/collections/:collection_name" do |db_name, collection_name|
52
- database = connection.db(db_name)
53
- collection = database.collection(collection_name)
92
+ # Database stats
93
+ get "/api/databases/:db_name/stats.json" do |db_name|
94
+ database = server.database(db_name)
54
95
 
55
- @stats = collection.stats
56
- @documents, @pagination = paginate_documents_for(collection, params[:page])
96
+ respond_to do |format|
97
+ format.json { database.stats.to_json }
98
+ end
99
+ end
57
100
 
58
- erb :"documents/index"
101
+ # Collections list
102
+ get "/api/databases/:db_name/collections.json" do |db_name|
103
+ database = server.database(db_name)
104
+ collections = database.collections.map do |collection|
105
+ {
106
+ dbName: collection.db_name,
107
+ name: collection.name,
108
+ size: collection.size
109
+ }
110
+ end
111
+
112
+ respond_to do |format|
113
+ format.json { collections.to_json }
114
+ end
59
115
  end
60
116
 
61
117
  # Delete a collection
62
- delete "/databases/:db_name/collections/:collection_name" do |db_name, collection_name|
63
- begin
64
- database = connection.db(db_name)
65
- database.drop_collection(collection_name)
66
-
67
- flash[:info] = "Collection #{collection_name} has been deleted."
118
+ delete "/api/databases/:db_name/collections.json" do |db_name|
119
+ success = begin
120
+ collection = server.database(db_name).collection(params[:id])
121
+ collection.drop!
122
+ true
68
123
  rescue Mongo::OperationFailure => e
69
- flash[:error] = e.message
124
+ false
70
125
  end
71
126
 
72
- redirect "/databases/#{db_name}"
127
+ respond_to do |format|
128
+ format.json { success }
129
+ end
73
130
  end
74
131
 
75
- # Delete a document
76
- delete "/databases/:db_name/collections/:collection_name/:id" do |db_name, collection_name, id|
77
- database = connection.db(db_name)
78
- collection = database.collection(collection_name)
79
-
80
- id = BSON::ObjectId(id)
81
- collection.remove(_id: id)
132
+ # Collection stats
133
+ get "/api/databases/:db_name/collections/:collection_name/stats.json" do |db_name, collection_name|
134
+ collection = server.database(db_name).collection(collection_name)
82
135
 
83
- flash[:info] = "Document #{id} has been deleted."
84
- redirect "/databases/#{db_name}/collections/#{collection_name}"
136
+ respond_to do |format|
137
+ format.json { collection.stats.to_json }
138
+ end
85
139
  end
86
140
 
87
- # Server info
88
- get "/server_info" do
89
- @server_info = connection.server_info
90
- erb :"server_info"
91
- end
141
+ # Documents list
142
+ get "/api/databases/:db_name/collections/:collection_name/documents.json" do |db_name, collection_name|
143
+ collection = server.database(db_name).collection(collection_name)
144
+ documents, pagination = collection.documents_with_pagination(params[:page])
145
+
146
+ documents.map! do |doc|
147
+ {
148
+ id: doc.id.to_s,
149
+ data: doc.data
150
+ }
151
+ end
92
152
 
93
- private
153
+ respond_to do |format|
154
+ format.json do
155
+ {
156
+ documents: documents,
157
+ size: pagination.size,
158
+ page: pagination.current_page,
159
+ totalPages: pagination.total_pages
160
+ }.to_json
161
+ end
162
+ end
163
+ end
94
164
 
95
- def paginate_documents_for(collection, page = 1)
96
- per_page = 25
165
+ # Delete a document
166
+ delete "/api/databases/:db_name/collections/:collection_name/documents.json" do |db_name, collection_name|
167
+ collection = server.database(db_name).collection(collection_name)
168
+ document = collection.find(params[:id])
169
+ collection.remove!(document)
97
170
 
98
- count = collection.count
99
- total_pages = (count.to_f / per_page).ceil
171
+ respond_to do |format|
172
+ format.json { true }
173
+ end
174
+ end
100
175
 
101
- page = if page.to_i <= 0 then 1
102
- else
103
- [page.to_i, total_pages].min
104
- end
176
+ get "/api/server_info.json" do
177
+ server_info = server.info
105
178
 
106
- offset = (page - 1) * per_page
107
- documents = collection.find.skip(offset).limit(per_page)
108
- pagination = OpenStruct.new \
109
- total_pages: total_pages,
110
- current_page: page
179
+ respond_to do |format|
180
+ format.json { server_info.to_json }
181
+ end
182
+ end
111
183
 
112
- return documents, pagination
184
+ get "/api/version.json" do
185
+ respond_to do |format|
186
+ format.json do
187
+ { version: MongoBrowser::VERSION }.to_json
188
+ end
189
+ end
113
190
  end
114
191
 
115
- def connection
116
- @connection ||= Mongo::Connection.new(MongoBrowser.mongodb_host, MongoBrowser.mongodb_port)
192
+ private
193
+
194
+ def server
195
+ @server ||= Server.current
117
196
  end
118
197
  end
119
198
  end
@@ -0,0 +1,11 @@
1
+ module MongoBrowser
2
+ module Middleware
3
+ class SprocketsBase
4
+ def call(env)
5
+ return @app.call(env) unless @matcher =~ env["PATH_INFO"]
6
+ env["PATH_INFO"].sub!(@matcher, "")
7
+ @environment.call(env)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,8 @@
1
+ require "mongo_browser/middleware/sprockets_base"
2
+
1
3
  module MongoBrowser
2
4
  module Middleware
3
- class SprocketsSinatra
5
+ class SprocketsSinatra < SprocketsBase
4
6
  def initialize(app, options = {})
5
7
  @app = app
6
8
  @root = options[:root]
@@ -18,12 +20,6 @@ module MongoBrowser
18
20
  @environment.append_path "vendor/assets/stylesheets"
19
21
  @environment.append_path "vendor/assets/images"
20
22
  end
21
-
22
- def call(env)
23
- return @app.call(env) unless @matcher =~ env["PATH_INFO"]
24
- env["PATH_INFO"].sub!(@matcher, "")
25
- @environment.call(env)
26
- end
27
23
  end
28
24
  end
29
25
  end