mongo_browser 0.1.3 → 0.2.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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