browse-everything 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +19 -0
  2. data/.travis.yml +6 -0
  3. data/CONTRIBUTING.md +113 -0
  4. data/Gemfile +4 -0
  5. data/HISTORY.md +2 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +164 -0
  8. data/Rakefile +10 -0
  9. data/app/.DS_Store +0 -0
  10. data/app/assets/javascripts/browse_everything.js +3 -0
  11. data/app/assets/javascripts/browse_everything/behavior.js.coffee +110 -0
  12. data/app/assets/stylesheets/browse_everything.css.scss +82 -0
  13. data/app/controllers/browse_everything_controller.rb +74 -0
  14. data/app/helpers/browse_everything_helper.rb +11 -0
  15. data/app/views/.DS_Store +0 -0
  16. data/app/views/browse_everything/_auth.html.erb +3 -0
  17. data/app/views/browse_everything/_files.html.erb +12 -0
  18. data/app/views/browse_everything/_providers.html.erb +10 -0
  19. data/app/views/browse_everything/auth.html.erb +7 -0
  20. data/app/views/browse_everything/index.html.erb +28 -0
  21. data/app/views/browse_everything/resolve.html.erb +1 -0
  22. data/app/views/browse_everything/show.html.erb +9 -0
  23. data/app/views/layouts/browse_everything.html.erb +11 -0
  24. data/browse-everything.gemspec +40 -0
  25. data/config/locales/en_browse_everything.yml +13 -0
  26. data/config/routes.rb +6 -0
  27. data/lib/browse-everything.rb +1 -0
  28. data/lib/browse_everything.rb +37 -0
  29. data/lib/browse_everything/browser.rb +25 -0
  30. data/lib/browse_everything/driver/base.rb +55 -0
  31. data/lib/browse_everything/driver/box.rb +90 -0
  32. data/lib/browse_everything/driver/drop_box.rb +74 -0
  33. data/lib/browse_everything/driver/file_system.rb +62 -0
  34. data/lib/browse_everything/driver/google_drive.rb +103 -0
  35. data/lib/browse_everything/driver/sky_drive.rb +132 -0
  36. data/lib/browse_everything/engine.rb +6 -0
  37. data/lib/browse_everything/file_entry.rb +19 -0
  38. data/lib/browse_everything/version.rb +3 -0
  39. data/spec/fixtures/file_system/dir_1/dir_3/file_3.m4v +0 -0
  40. data/spec/fixtures/file_system/dir_1/file_2.txt +1 -0
  41. data/spec/fixtures/file_system/dir_2/file_4.docx +1 -0
  42. data/spec/fixtures/file_system/file_1.pdf +0 -0
  43. data/spec/fixtures/vcr_cassettes/dropbox.yml +231 -0
  44. data/spec/rake/app_spec.rb +121 -0
  45. data/spec/spec_helper.rb +56 -0
  46. data/spec/spec_helper.rb.orig +47 -0
  47. data/spec/support/app/controllers/file_handler_controller.rb +8 -0
  48. data/spec/support/app/views/file_handler/index.html.erb +22 -0
  49. data/spec/support/config/browse_everything_providers.yml.example +15 -0
  50. data/spec/support/lib/generators/test_app_generator.rb +50 -0
  51. data/spec/unit/base_spec.rb +28 -0
  52. data/spec/unit/browser_spec.rb +76 -0
  53. data/spec/unit/drop_box_spec.rb +119 -0
  54. data/spec/unit/file_entry_spec.rb +44 -0
  55. data/spec/unit/file_system_spec.rb +85 -0
  56. data/spec/unit/sky_drive_spec.rb +58 -0
  57. data/tasks/browse-everything-dev.rake +63 -0
  58. data/tasks/ci.rake +7 -0
  59. metadata +419 -0
@@ -0,0 +1,82 @@
1
+ @import "bootstrap/variables";
2
+ @import "bootstrap/mixins";
3
+ @import "bootstrap";
4
+ @import "bootstrap-responsive";
5
+ @import "font-awesome";
6
+
7
+ @mixin border-highlight($color) {
8
+ $bl: 3;
9
+ @if $color == none {
10
+ $bl: 0
11
+ }
12
+ margin-left: #{4-$bl}px;
13
+ border-left: #{$bl}px solid $color;
14
+ padding-left: 4px;
15
+ }
16
+
17
+ @mixin ev-link {
18
+ cursor: pointer;
19
+ @include border-highlight(none);
20
+ &:hover {
21
+ @include border-highlight(gray);
22
+ }
23
+ a {
24
+ color: inherit;
25
+ background-color: inherit;
26
+ text-decoration: none;
27
+ }
28
+ }
29
+
30
+ .ev-body {
31
+ padding: 0;
32
+ }
33
+
34
+ .ev-providers {
35
+ padding: 4px;
36
+ background-color: lightgray;
37
+ }
38
+
39
+ .ev-providers, .ev-files {
40
+ li { @include ev-link; }
41
+ .ev-selected {
42
+ @include border-highlight(black);
43
+ }
44
+ }
45
+
46
+ .modal-body {
47
+ overflow: hidden;
48
+ }
49
+
50
+ .ev-files {
51
+ position: relative;
52
+ overflow-x: hidden;
53
+ overflow-y: auto;
54
+
55
+ li {
56
+ overflow: hidden;
57
+ text-overflow: ellipsis;
58
+ .ev-file-name {
59
+ // padding: 0px 6px;
60
+ white-space: nowrap;
61
+ }
62
+ border-top: none;
63
+ }
64
+
65
+ &.detail {
66
+ }
67
+
68
+ &.list ul {
69
+ @include content-columns(3);
70
+ }
71
+ }
72
+
73
+ .ev-container li {
74
+ cursor: pointer;
75
+ }
76
+
77
+ #browse-everything {
78
+ margin: 0 0 0 -37.5%;
79
+ left: 50%;
80
+ width: 75%;
81
+ height: 75%;
82
+ }
@@ -0,0 +1,74 @@
1
+ require File.expand_path('../../helpers/browse_everything_helper',__FILE__)
2
+
3
+ class BrowseEverythingController < ActionController::Base
4
+ layout 'browse_everything'
5
+ helper BrowseEverythingHelper
6
+
7
+ def index
8
+ render :layout => !request.xhr?
9
+ end
10
+
11
+ def show
12
+ render :layout => !request.xhr?
13
+ end
14
+
15
+ def auth
16
+ code = params[:code]
17
+ session["#{provider_name}_token"] = provider.connect(params,session["#{provider_name}_data"])
18
+ end
19
+
20
+ def resolve
21
+ selected_files = params[:selected_files] || []
22
+ @links = selected_files.collect { |file|
23
+ p,f = file.split(/:/)
24
+ (url,extra) = browser.providers[p].link_for(f)
25
+ result = { url: url }
26
+ result.merge!(extra) unless extra.nil?
27
+ result
28
+ }
29
+ respond_to do |format|
30
+ format.html { render :layout => false }
31
+ format.json { render :json => @links }
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def auth_link
38
+ @auth_link ||= if provider.present?
39
+ link, data = provider.auth_link
40
+ session["#{provider_name}_data"] = data
41
+ "#{link}&state=#{provider.key}"
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ def browser
48
+ if @browser.nil?
49
+ @browser = BrowseEverything::Browser.new(url_options)
50
+ @browser.providers.values.each do |p|
51
+ p.token = session["#{p.key}_token"]
52
+ end
53
+ end
54
+ @browser
55
+ end
56
+
57
+ def browse_path
58
+ @path ||= params[:path] || ''
59
+ end
60
+
61
+ def provider
62
+ @provider ||= browser.providers[provider_name]
63
+ end
64
+
65
+ def provider_name
66
+ @provider_nane ||= params[:provider] || params[:state].to_s.split(/\|/).last
67
+ end
68
+
69
+ helper_method :auth_link
70
+ helper_method :browser
71
+ helper_method :browse_path
72
+ helper_method :provider
73
+ helper_method :provider_name
74
+ end
@@ -0,0 +1,11 @@
1
+ module BrowseEverythingHelper
2
+
3
+ def array_to_hidden_fields(array,key)
4
+ fields = array.to_query(key).split(Rack::Utils::DEFAULT_SEP).collect do |pair|
5
+ key,value=pair.split('=', 2).map { |str| Rack::Utils.unescape(str) }
6
+ hidden_field_tag(key,value)
7
+ end
8
+ fields.join("\n").html_safe
9
+ end
10
+
11
+ end
Binary file
@@ -0,0 +1,3 @@
1
+ <h2><%=t('browse_everything.auth_prompt.head', provider: provider.name)%></h2>
2
+ <p><%=t('browse_everything.auth_prompt.text', provider: provider.name)%></p>
3
+ <p><%= link_to t('browse_everything.auth_prompt.button_text', provider: provider.name), auth_link, class:"btn btn-primary ev-auth", target:'blank' %></p>
@@ -0,0 +1,12 @@
1
+ <% if provider.present? %>
2
+ <ul class="unstyled">
3
+ <% provider.contents(browse_path).each do |file| %>
4
+ <li data-ev-location="<%= file.location %>" title="<%= number_to_human_size(file.size).sub(/Bytes/,'bytes') %> • <%= file.mtime.strftime('%F %R') %>">
5
+ <span class="<%=file.container? ? 'ev-container' : 'ev-file'%> ev-file-name">
6
+ <%= link_to(file.name, browse_everything_engine.contents_path(provider_name,file.id)) %>
7
+ </span>
8
+ </li>
9
+ <% end %>
10
+ </table>
11
+ <% end %>
12
+
@@ -0,0 +1,10 @@
1
+ <ul class="unstyled">
2
+ <% browser.providers.each_pair do |key, provider| %>
3
+ <li>
4
+ <span class="ev-container">
5
+ <i class="icon-<%=provider.icon%>"></i>
6
+ <%= link_to(provider.name, browse_everything_engine.contents_path(key)) %>
7
+ </span>
8
+ </li>
9
+ <% end %>
10
+ </ul>
@@ -0,0 +1,7 @@
1
+ Authorized!
2
+
3
+ <script>
4
+ var caller = $($(window.opener).document)
5
+ $('.ev-providers .ev-selected',caller).click()
6
+ window.close()
7
+ </script>
@@ -0,0 +1,28 @@
1
+ <div class="modal-header"></div>
2
+ <div class="modal-body ev-body">
3
+ <div class="ev-browser row-fluid">
4
+ <div class="span2 ev-providers nav nav-list">
5
+ <%= render :partial => 'providers' %>
6
+ </div>
7
+ <div class="span10 ev-files list">
8
+ <%= render :partial => 'files' %>
9
+ </div>
10
+ </div>
11
+ </div>
12
+ <div class="modal-footer">
13
+ <span class="pull-left ev-status">0 files selected</span>
14
+ <%= form_tag browse_everything_file_handler_path, :method => "POST", :class => "ev-submit-form form-horizontal", :data => { :resolver => browse_everything_engine.resolver_path } do %>
15
+ <button class="ev-cancel btn btn-danger"><%= t('browse_everything.modal_form.cancel')%></button>
16
+ <button class="ev-submit btn btn-primary" data-loading-text="Loading..."><%= t('browse_everything.modal_form.submit')%></button>
17
+ <% end %>
18
+ </div>
19
+ <script>
20
+ $(window).resize(function() {
21
+ var be = $('#browse-everything').outerHeight();
22
+ var he = $('#browse-everything .modal-header').outerHeight();
23
+ var fo = $('#browse-everything .modal-footer').outerHeight();
24
+ $('#browse-everything .modal-body').css('max-height','none').height(be-(he+fo));
25
+ $('#browse-everything .ev-providers').height(be-(he+fo));
26
+ })
27
+ $(window).trigger('resize');
28
+ </script>
@@ -0,0 +1 @@
1
+ <%= array_to_hidden_fields(@links,'selected_files') %>
@@ -0,0 +1,9 @@
1
+ <% if provider.present? %>
2
+ <% if provider.authorized? %>
3
+ <%= render 'files' %>
4
+ <% else %>
5
+ <%= render 'auth' %>
6
+ <% end %>
7
+
8
+ <% end %>
9
+
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ <%= javascript_include_tag 'browse_everything' %>
4
+ <%= stylesheet_link_tag 'browse_everything' %>
5
+ </head>
6
+ <body>
7
+ <div class="browse-ev">
8
+ <%= yield %>
9
+ </div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'browse_everything/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "browse-everything"
8
+ spec.version = BrowseEverything::VERSION
9
+ spec.authors = ["Carolyn Cole", "Jessie Keck", "Michael B. Klein", "Thomas Scherz", "Xiaoming Wang"]
10
+ spec.email = ["cam156@psu.edu", "jkeck@stanford.edu", "mbklein@gmail.com", "scherztc@ucmail.uc.edu", "xw5d@virginia.edu"]
11
+ spec.description = %q{AJAX/Rails engine file browser for cloud storage services}
12
+ spec.summary = %q{AJAX/Rails engine file browser for cloud storage services}
13
+ spec.homepage = "https://github.com/mbklein/browse-everything"
14
+ spec.license = "Apache 2"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rails", ">= 3.1"
22
+ spec.add_dependency "sass-rails"
23
+ spec.add_dependency "bootstrap-sass"
24
+ spec.add_dependency "font-awesome-rails"
25
+ spec.add_dependency "google_drive"
26
+ spec.add_dependency "dropbox-sdk"
27
+ spec.add_dependency "skydrive"
28
+ spec.add_dependency "ruby-box"
29
+ spec.add_dependency "google-api-client"
30
+ spec.add_development_dependency "rspec"
31
+ spec.add_development_dependency "rspec-rails"
32
+ spec.add_development_dependency "simplecov"
33
+ spec.add_development_dependency "bundler", "~> 1.3"
34
+ spec.add_development_dependency "pry"
35
+ spec.add_development_dependency "rake"
36
+ spec.add_development_dependency "webmock"
37
+ spec.add_development_dependency "vcr"
38
+ spec.add_development_dependency "sqlite3"
39
+
40
+ end
@@ -0,0 +1,13 @@
1
+ en:
2
+ browse_everything:
3
+ auth_prompt:
4
+ head: "%{provider}"
5
+ text: >
6
+ Please take a moment to authorize this application
7
+ to access your %{provider} files. You will be guided
8
+ through authorization in a popup window, and returned
9
+ here automatically when authorization is complete.
10
+ button_text: "Connect to %{provider}"
11
+ modal_form:
12
+ submit: "Submit"
13
+ cancel: "Cancel"
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ BrowseEverything::Engine.routes.draw do
2
+ get "connect", to: 'browse_everything#auth', as: 'connector_response'
3
+ match "resolve", to: 'browse_everything#resolve', as: 'resolver', via: [:get, :post]
4
+ get ":provider(/*path)", to: 'browse_everything#show', as: 'contents'
5
+ root to: 'browse_everything#index'
6
+ end
@@ -0,0 +1 @@
1
+ require 'browse_everything'
@@ -0,0 +1,37 @@
1
+ require "rails"
2
+ require "browse_everything/version"
3
+ require "browse_everything/engine"
4
+
5
+ module BrowseEverything
6
+ class InitializationError < RuntimeError; end
7
+
8
+ autoload :Browser, 'browse_everything/browser'
9
+ autoload :FileEntry, 'browse_everything/file_entry'
10
+ module Driver
11
+ autoload :Base, 'browse_everything/driver/base'
12
+ autoload :FileSystem, 'browse_everything/driver/file_system'
13
+ autoload :DropBox, 'browse_everything/driver/drop_box'
14
+ autoload :SkyDrive, 'browse_everything/driver/sky_drive'
15
+ autoload :Box, 'browse_everything/driver/box'
16
+ autoload :GoogleDrive, 'browse_everything/driver/google_drive'
17
+ end
18
+
19
+ class << self
20
+ def configure(value)
21
+ if value.nil? or value.kind_of?(Hash)
22
+ @config = value
23
+ elsif value.kind_of?(String)
24
+ @config = YAML.load(File.read(value))
25
+ else
26
+ raise InitializationError, "Unrecognized configuration: #{value.inspect}"
27
+ end
28
+ end
29
+
30
+ def config
31
+ if @config.nil?
32
+ configure(File.join(Rails.root.to_s,'config','browse_everything_providers.yml'))
33
+ end
34
+ @config
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module BrowseEverything
2
+ class Browser
3
+ attr_reader :providers
4
+
5
+ def initialize(opts = {})
6
+ url_options = {}
7
+ if opts.has_key?(:url_options)
8
+ url_options = opts.delete(:url_options)
9
+ else
10
+ url_options = opts
11
+ opts = BrowseEverything.config
12
+ end
13
+
14
+ @providers = {}
15
+ opts.each_pair do |driver,config|
16
+ begin
17
+ driver_klass = BrowseEverything::Driver.const_get(driver.to_s.camelize.to_sym)
18
+ @providers[driver] = driver_klass.new(config.merge(url_options: url_options))
19
+ rescue
20
+ Rails.logger.warn "Unknown provider: #{driver.to_s}"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ module BrowseEverything
2
+ module Driver
3
+ class Base
4
+ include BrowseEverything::Engine.routes.url_helpers
5
+
6
+ attr_reader :config
7
+ attr_accessor :token
8
+
9
+ def initialize(config,session_info={})
10
+ @config = config
11
+ validate_config
12
+ end
13
+
14
+ def key
15
+ self.class.name.split(/::/).last.underscore
16
+ end
17
+
18
+ def icon
19
+ 'unchecked'
20
+ end
21
+
22
+ def name
23
+ self.class.name.split(/::/).last.titleize
24
+ end
25
+
26
+ def validate_config
27
+ end
28
+
29
+ def contents(path)
30
+ []
31
+ end
32
+
33
+ def details(path)
34
+ nil
35
+ end
36
+
37
+ def link_for(path)
38
+ path
39
+ end
40
+
41
+ def authorized?
42
+ false
43
+ end
44
+
45
+ def auth_link
46
+ []
47
+ end
48
+
49
+ def connect(params,data)
50
+ nil
51
+ end
52
+
53
+ end
54
+ end
55
+ end