browse-everything 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +105 -30
- data/.gitignore +4 -2
- data/.rubocop.yml +54 -34
- data/.rubocop_todo.yml +0 -5
- data/.tool-versions +2 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +41 -33
- data/README.md +66 -31
- data/Rakefile +9 -1
- data/app/assets/javascripts/browse_everything/behavior.js +45 -31
- data/app/assets/javascripts/browse_everything.js +1 -1
- data/app/assets/javascripts/treetable.webpack.js +687 -0
- data/app/controllers/browse_everything_controller.rb +60 -60
- data/app/helpers/browse_everything_helper.rb +4 -0
- data/app/views/browse_everything/_files.html.erb +3 -2
- data/bin/rails +14 -0
- data/browse-everything.gemspec +13 -12
- data/lib/browse_everything/auth/google/credentials.rb +5 -5
- data/lib/browse_everything/auth/google/request_parameters.rb +38 -38
- data/lib/browse_everything/driver/base.rb +15 -14
- data/lib/browse_everything/driver/box.rb +56 -56
- data/lib/browse_everything/driver/dropbox.rb +44 -41
- data/lib/browse_everything/driver/file_system.rb +31 -18
- data/lib/browse_everything/driver/google_drive.rb +38 -38
- data/lib/browse_everything/driver/s3.rb +61 -61
- data/lib/browse_everything/engine.rb +10 -3
- data/lib/browse_everything/file_entry.rb +1 -1
- data/lib/browse_everything/retriever.rb +69 -69
- data/lib/browse_everything/version.rb +1 -1
- data/lib/browse_everything.rb +1 -1
- data/spec/dummy_test_app/Rakefile +6 -0
- data/spec/dummy_test_app/app/assets/config/manifest.js +3 -0
- data/spec/dummy_test_app/app/assets/images/.keep +0 -0
- data/spec/dummy_test_app/app/assets/javascripts/application.js +25 -0
- data/spec/dummy_test_app/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy_test_app/app/assets/javascripts/channels/.keep +0 -0
- data/spec/dummy_test_app/app/assets/stylesheets/application.scss +18 -0
- data/spec/dummy_test_app/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy_test_app/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy_test_app/app/controllers/application_controller.rb +3 -0
- data/spec/dummy_test_app/app/controllers/concerns/.keep +0 -0
- data/spec/{support → dummy_test_app}/app/controllers/file_handler_controller.rb +0 -0
- data/spec/dummy_test_app/app/helpers/application_helper.rb +2 -0
- data/spec/dummy_test_app/app/jobs/application_job.rb +2 -0
- data/spec/dummy_test_app/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy_test_app/app/models/application_record.rb +3 -0
- data/spec/dummy_test_app/app/models/concerns/.keep +0 -0
- data/spec/dummy_test_app/app/views/file_handler/index.html.erb +10 -0
- data/spec/{support → dummy_test_app}/app/views/file_handler/main.html.erb +6 -3
- data/spec/dummy_test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy_test_app/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy_test_app/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy_test_app/bin/bundle +3 -0
- data/spec/dummy_test_app/bin/rails +4 -0
- data/spec/dummy_test_app/bin/rake +4 -0
- data/spec/dummy_test_app/bin/setup +38 -0
- data/spec/dummy_test_app/bin/update +29 -0
- data/spec/dummy_test_app/bin/yarn +11 -0
- data/spec/dummy_test_app/config/application.rb +27 -0
- data/spec/dummy_test_app/config/boot.rb +5 -0
- data/spec/dummy_test_app/config/browse_everything_providers.yml +25 -0
- data/spec/dummy_test_app/config/cable.yml +10 -0
- data/spec/dummy_test_app/config/database.yml +25 -0
- data/spec/dummy_test_app/config/environment.rb +5 -0
- data/spec/dummy_test_app/config/environments/development.rb +54 -0
- data/spec/dummy_test_app/config/environments/production.rb +91 -0
- data/spec/dummy_test_app/config/environments/test.rb +42 -0
- data/spec/dummy_test_app/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy_test_app/config/initializers/assets.rb +14 -0
- data/spec/dummy_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy_test_app/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy_test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy_test_app/config/initializers/inflections.rb +16 -0
- data/spec/dummy_test_app/config/initializers/mime_types.rb +4 -0
- data/spec/dummy_test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy_test_app/config/locales/en.yml +33 -0
- data/spec/dummy_test_app/config/puma.rb +56 -0
- data/spec/dummy_test_app/config/routes.rb +9 -0
- data/spec/dummy_test_app/config/secrets.yml +32 -0
- data/spec/dummy_test_app/config/spring.rb +6 -0
- data/spec/dummy_test_app/config.ru +5 -0
- data/spec/dummy_test_app/lib/assets/.keep +0 -0
- data/spec/dummy_test_app/log/.keep +0 -0
- data/spec/dummy_test_app/package.json +5 -0
- data/spec/dummy_test_app/public/404.html +67 -0
- data/spec/dummy_test_app/public/422.html +67 -0
- data/spec/dummy_test_app/public/500.html +66 -0
- data/spec/dummy_test_app/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy_test_app/public/apple-touch-icon.png +0 -0
- data/spec/dummy_test_app/public/favicon.ico +0 -0
- data/spec/dummy_test_app/tmp/.gitkeep +0 -0
- data/spec/features/select_files_spec.rb +1 -0
- data/spec/features/test_compiling_stylesheets_spec.rb +1 -1
- data/spec/lib/browse_everything/driver_spec.rb +43 -3
- data/spec/spec_helper.rb +3 -28
- data/tasks/ci.rake +1 -1
- metadata +180 -94
- data/karma.conf.js +0 -71
- data/spec/javascripts/behavior_spec.js +0 -7
- data/spec/javascripts/helpers/jasmine-jquery.js +0 -838
- data/spec/javascripts/helpers/jquery.js +0 -11008
- data/spec/javascripts/karma_spec.rb +0 -16
- data/spec/support/app/views/file_handler/index.html.erb +0 -6
- data/spec/test_app_templates/Gemfile.extra +0 -9
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +0 -61
@@ -9,13 +9,17 @@ module BrowseEverything
|
|
9
9
|
|
10
10
|
def validate_config
|
11
11
|
raise BrowseEverything::InitializationError, 'FileSystem driver requires a :home argument' if config[:home].blank?
|
12
|
+
|
13
|
+
unless config[:home].start_with?("/") || config[:allow_relative_home] == true
|
14
|
+
raise BrowseEverything::InitializationError, 'FileSystem driver :home argument must be absolute unless :allow_relative_home is set'
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
# Retrieve the contents of a directory
|
15
19
|
# @param path [String] the path to a file system resource
|
16
20
|
# @return [Array<BrowseEverything::FileEntry>]
|
17
21
|
def contents(path = '')
|
18
|
-
real_path = File.join(
|
22
|
+
real_path = File.join(home_path, path)
|
19
23
|
values = if File.directory?(real_path)
|
20
24
|
make_directory_entry real_path
|
21
25
|
else
|
@@ -55,25 +59,34 @@ module BrowseEverything
|
|
55
59
|
|
56
60
|
private
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
def home_path
|
63
|
+
@home_path ||= if config[:allow_relative_home] == true
|
64
|
+
# expand relative to Rails.root, mainly test CI use-case
|
65
|
+
File.expand_path(config[:home], Rails.root)
|
66
|
+
else
|
67
|
+
config[:home]
|
68
|
+
end
|
69
|
+
end
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
# Construct an array of FileEntry objects for the contents of a
|
72
|
+
# directory
|
73
|
+
# @param real_path [String] path to the file system directory
|
74
|
+
# @return [Array<BrowseEverything::FileEntry>]
|
75
|
+
def make_directory_entry(real_path)
|
76
|
+
entries = []
|
77
|
+
entries + Dir[File.join(real_path, '*')].collect { |f| details(f) }
|
78
|
+
end
|
70
79
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
80
|
+
def make_pathname(path)
|
81
|
+
Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(home_path))
|
82
|
+
end
|
83
|
+
|
84
|
+
def file_size(path)
|
85
|
+
File.size(path).to_i
|
86
|
+
rescue StandardError => error
|
87
|
+
Rails.logger.error "Failed to find the file size for #{path}: #{error}"
|
88
|
+
0
|
89
|
+
end
|
77
90
|
end
|
78
91
|
end
|
79
92
|
end
|
@@ -191,50 +191,50 @@ module BrowseEverything
|
|
191
191
|
|
192
192
|
private
|
193
193
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
}
|
194
|
+
def client_secrets
|
195
|
+
{
|
196
|
+
Google::Auth::ClientId::WEB_APP => {
|
197
|
+
Google::Auth::ClientId::CLIENT_ID => config[:client_id],
|
198
|
+
Google::Auth::ClientId::CLIENT_SECRET => config[:client_secret]
|
200
199
|
}
|
201
|
-
|
200
|
+
}
|
201
|
+
end
|
202
202
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
203
|
+
# This is required for using the googleauth Gem
|
204
|
+
# @see http://www.rubydoc.info/gems/googleauth/Google/Auth/Stores/FileTokenStore FileTokenStore for googleauth
|
205
|
+
# @return [Tempfile] temporary file within which to cache credentials
|
206
|
+
def file_token_store_path
|
207
|
+
Tempfile.new('gdrive.yaml')
|
208
|
+
end
|
209
209
|
|
210
|
-
|
211
|
-
|
212
|
-
|
210
|
+
def scope
|
211
|
+
Google::Apis::DriveV3::AUTH_DRIVE
|
212
|
+
end
|
213
213
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
214
|
+
# Provides the user ID for caching access tokens
|
215
|
+
# (This is a hack which attempts to anonymize the access tokens)
|
216
|
+
# @return [String] the ID for the user
|
217
|
+
def user_id
|
218
|
+
'current_user'
|
219
|
+
end
|
220
220
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
221
|
+
# Please see https://developers.google.com/drive/v3/web/manage-downloads
|
222
|
+
# @param id [String] the ID for the Google Drive File
|
223
|
+
# @return [String] the URL for the file download
|
224
|
+
def download_url(id)
|
225
|
+
"https://www.googleapis.com/drive/v3/files/#{id}?alt=media"
|
226
|
+
end
|
227
227
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
228
|
+
# Restore the credentials for the Google API
|
229
|
+
# @param access_token [String] the access token redeemed using an authorization code
|
230
|
+
# @return Credentials credentials restored from a cached access token
|
231
|
+
def restore_credentials(access_token)
|
232
|
+
client = Auth::Google::Credentials.new
|
233
|
+
client.client_id = client_id.id
|
234
|
+
client.client_secret = client_id.secret
|
235
|
+
client.update_token!('access_token' => access_token)
|
236
|
+
@credentials = client
|
237
|
+
end
|
238
238
|
end
|
239
239
|
end
|
240
240
|
end
|
@@ -79,79 +79,79 @@ module BrowseEverything
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
def strip(path)
|
83
|
+
path.sub %r{^/?(.+?)/?$}, '\1'
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
def from_base(key)
|
87
|
+
Pathname.new(key).relative_path_from(Pathname.new(config[:base].to_s)).to_s
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
def full_path(path)
|
91
|
+
config[:base].present? ? File.join(config[:base], path) : path
|
92
|
+
end
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
94
|
+
def aws_config
|
95
|
+
result = {}
|
96
|
+
result[:credentials] = Aws::Credentials.new(config[:app_key], config[:app_secret]) if config[:app_key].present?
|
97
|
+
result[:region] = config[:region] if config.key?(:region)
|
98
|
+
result
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
101
|
+
def session
|
102
|
+
AuthenticationFactory.new(
|
103
|
+
self.class.authentication_klass,
|
104
|
+
aws_config
|
105
|
+
)
|
106
|
+
end
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
def authenticate
|
109
|
+
session.authenticate
|
110
|
+
end
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
def client
|
113
|
+
@client ||= authenticate
|
114
|
+
end
|
115
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
116
|
+
# Construct a BrowseEverything::FileEntry object
|
117
|
+
# @param name [String]
|
118
|
+
# @param size [String]
|
119
|
+
# @param date [DateTime]
|
120
|
+
# @param dir [String]
|
121
|
+
# @return [BrowseEverything::FileEntry]
|
122
|
+
def entry_for(name, size, date, dir)
|
123
|
+
BrowseEverything::FileEntry.new(name, [key, name].join(':'), File.basename(name), size, date, dir)
|
124
|
+
end
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
126
|
+
# Populate the entries with FileEntry objects from an S3 listing
|
127
|
+
# @param listing [Seahorse::Client::Response]
|
128
|
+
def add_directories(listing)
|
129
|
+
listing.common_prefixes.each do |prefix|
|
130
|
+
new_entry = entry_for(from_base(prefix.prefix), 0, Time.current, true)
|
131
|
+
@entries << new_entry unless new_entry.nil?
|
133
132
|
end
|
133
|
+
end
|
134
134
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
135
|
+
# Given a listing and a S3 listing and path, populate the entries
|
136
|
+
# @param listing [Seahorse::Client::Response]
|
137
|
+
# @param path [String]
|
138
|
+
def add_files(listing, path)
|
139
|
+
listing.contents.each do |entry|
|
140
|
+
key = from_base(entry.key)
|
141
|
+
new_entry = entry_for(key, entry.size, entry.last_modified, false)
|
142
|
+
@entries << new_entry unless strip(key) == strip(path) || new_entry.nil?
|
144
143
|
end
|
144
|
+
end
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
146
|
+
# For a given path to a S3 resource, retrieve the listing object and
|
147
|
+
# construct the file entries
|
148
|
+
# @param path [String]
|
149
|
+
def generate_listing(path)
|
150
|
+
client
|
151
|
+
listing = client.list_objects(bucket: config[:bucket], delimiter: '/', prefix: full_path(path))
|
152
|
+
add_directories(listing)
|
153
|
+
add_files(listing, path)
|
154
|
+
end
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|
@@ -2,8 +2,15 @@
|
|
2
2
|
|
3
3
|
module BrowseEverything
|
4
4
|
class Engine < ::Rails::Engine
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# As of Rails 7, sprockets is optional in Rails. If you don't have sprockets-rails
|
6
|
+
# installed, you don't have a config.assets. Without sprockets, you may
|
7
|
+
# or may not be able to figure out how to get browse-everything JS and CSS to load,
|
8
|
+
# but we should at least let you load the engine and try, so we don't try
|
9
|
+
# to configure sprockets unless it is installed...
|
10
|
+
if config.respond_to?(:assets)
|
11
|
+
config.assets.paths << config.root.join('vendor', 'assets', 'javascripts')
|
12
|
+
config.assets.paths << config.root.join('vendor', 'assets', 'stylesheets')
|
13
|
+
config.assets.precompile += %w[browse_everything.js browse_everything.css]
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
@@ -89,81 +89,81 @@ module BrowseEverything
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
# This avoids the potential for a KeyError
|
99
|
-
headers = options.fetch('headers', {}) || {}
|
100
|
-
|
101
|
-
file_size_value = options.fetch('file_size', 0)
|
102
|
-
file_size = file_size_value.to_i
|
103
|
-
|
104
|
-
output = {
|
105
|
-
url: ::Addressable::URI.parse(url),
|
106
|
-
headers: headers,
|
107
|
-
file_size: file_size
|
108
|
-
}
|
109
|
-
|
110
|
-
output[:file_size] = get_file_size(output) if output[:file_size] < 1
|
111
|
-
output
|
112
|
-
end
|
92
|
+
# Extract and parse options used to download a file or resource from an HTTP API
|
93
|
+
# @param options [Hash]
|
94
|
+
# @return [Hash]
|
95
|
+
def extract_download_options(options)
|
96
|
+
url = options.fetch('url')
|
113
97
|
|
114
|
-
#
|
115
|
-
|
116
|
-
def retrieve_file(options)
|
117
|
-
file_uri = options.fetch(:url)
|
118
|
-
file_size = options.fetch(:file_size)
|
119
|
-
|
120
|
-
retrieved = 0
|
121
|
-
File.open(file_uri.path, 'rb') do |f|
|
122
|
-
until f.eof?
|
123
|
-
chunk = f.read(chunk_size)
|
124
|
-
retrieved += chunk.length
|
125
|
-
yield(chunk, retrieved, file_size)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
98
|
+
# This avoids the potential for a KeyError
|
99
|
+
headers = options.fetch('headers', {}) || {}
|
129
100
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
101
|
+
file_size_value = options.fetch('file_size', 0)
|
102
|
+
file_size = file_size_value.to_i
|
103
|
+
|
104
|
+
output = {
|
105
|
+
url: ::Addressable::URI.parse(url),
|
106
|
+
headers: headers,
|
107
|
+
file_size: file_size
|
108
|
+
}
|
109
|
+
|
110
|
+
output[:file_size] = get_file_size(output) if output[:file_size] < 1
|
111
|
+
output
|
112
|
+
end
|
113
|
+
|
114
|
+
# Retrieve the file from the file system
|
115
|
+
# @param options [Hash]
|
116
|
+
def retrieve_file(options)
|
117
|
+
file_uri = options.fetch(:url)
|
118
|
+
file_size = options.fetch(:file_size)
|
119
|
+
|
120
|
+
retrieved = 0
|
121
|
+
File.open(file_uri.path, 'rb') do |f|
|
122
|
+
until f.eof?
|
123
|
+
chunk = f.read(chunk_size)
|
124
|
+
retrieved += chunk.length
|
144
125
|
yield(chunk, retrieved, file_size)
|
145
126
|
end
|
146
|
-
request.run
|
147
127
|
end
|
128
|
+
end
|
148
129
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
when /https?/
|
161
|
-
response = Typhoeus.head(url.to_s, headers: headers)
|
162
|
-
length_value = response.headers['Content-Length'] || file_size
|
163
|
-
length_value.to_i
|
164
|
-
else
|
165
|
-
raise URI::BadURIError, "Unknown URI scheme: #{url.scheme}"
|
166
|
-
end
|
130
|
+
# Retrieve a resource over the HTTP
|
131
|
+
# @param options [Hash]
|
132
|
+
def retrieve_http(options)
|
133
|
+
file_size = options.fetch(:file_size)
|
134
|
+
headers = options.fetch(:headers)
|
135
|
+
url = options.fetch(:url)
|
136
|
+
retrieved = 0
|
137
|
+
|
138
|
+
request = Typhoeus::Request.new(url.to_s, method: :get, headers: headers)
|
139
|
+
request.on_headers do |response|
|
140
|
+
raise DownloadError.new("#{self.class}: Failed to download #{url}: Status Code: #{response.code}", response) unless response.code == 200
|
167
141
|
end
|
142
|
+
request.on_body do |chunk|
|
143
|
+
retrieved += chunk.bytesize
|
144
|
+
yield(chunk, retrieved, file_size)
|
145
|
+
end
|
146
|
+
request.run
|
147
|
+
end
|
148
|
+
|
149
|
+
# Retrieve the file size
|
150
|
+
# @param options [Hash]
|
151
|
+
# @return [Integer] the size of the requested file
|
152
|
+
def get_file_size(options)
|
153
|
+
url = options.fetch(:url)
|
154
|
+
headers = options.fetch(:headers)
|
155
|
+
file_size = options.fetch(:file_size)
|
156
|
+
|
157
|
+
case url.scheme
|
158
|
+
when 'file'
|
159
|
+
File.size(url.path)
|
160
|
+
when /https?/
|
161
|
+
response = Typhoeus.head(url.to_s, headers: headers)
|
162
|
+
length_value = response.headers['Content-Length'] || file_size
|
163
|
+
length_value.to_i
|
164
|
+
else
|
165
|
+
raise URI::BadURIError, "Unknown URI scheme: #{url.scheme}"
|
166
|
+
end
|
167
|
+
end
|
168
168
|
end
|
169
169
|
end
|
data/lib/browse_everything.rb
CHANGED
@@ -55,7 +55,7 @@ module BrowseEverything
|
|
55
55
|
begin
|
56
56
|
config_file_content = File.read(value)
|
57
57
|
config_file_template = ERB.new(config_file_content)
|
58
|
-
config_values = YAML.safe_load(config_file_template.result, [Symbol])
|
58
|
+
config_values = YAML.safe_load(config_file_template.result, permitted_classes: [Symbol])
|
59
59
|
@config = ActiveSupport::HashWithIndifferentAccess.new config_values
|
60
60
|
@config.deep_symbolize_keys
|
61
61
|
rescue Errno::ENOENT
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
|
14
|
+
// We want to test with turbolinks, which our code also requires rails-ujs to deal with:
|
15
|
+
|
16
|
+
//= require rails-ujs
|
17
|
+
//= require turbolinks
|
18
|
+
|
19
|
+
// Actual stack required for current browse-everything JS
|
20
|
+
|
21
|
+
//= require jquery3
|
22
|
+
//= require bootstrap
|
23
|
+
//= require browse_everything
|
24
|
+
|
25
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
|
3
|
+
//
|
4
|
+
//= require action_cable
|
5
|
+
//= require_self
|
6
|
+
//= require_tree ./channels
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
this.App || (this.App = {});
|
10
|
+
|
11
|
+
App.cable = ActionCable.createConsumer();
|
12
|
+
|
13
|
+
}).call(this);
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
16
|
+
|
17
|
+
@import "bootstrap";
|
18
|
+
@import "browse_everything/browse_everything_bootstrap4";
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<div class="panel panel-default">
|
2
|
+
<div class="panel-body">
|
3
|
+
<a href="main" class="btn btn-large btn-primary" role="button">Enter Test App (Turbolinks)</a>
|
4
|
+
|
5
|
+
<%# this doesn't REALLY test no Turbolinks, as there will still be a `window.Turbolinks` object,
|
6
|
+
and a `turbolinks:load` event. It just tests as if the page we are navigating to were the FIRST
|
7
|
+
page loaded under turbolinks %>
|
8
|
+
<a href="main" class="btn btn-large btn-primary" role="button" data-turbolinks="false" data-no-turbolink>Enter Test App (No Turbolinks)</a>
|
9
|
+
</div>
|
10
|
+
</div>
|