Skip to content

Commit

Permalink
Thumbnails on file list
Browse files Browse the repository at this point in the history
  • Loading branch information
eanders committed Feb 17, 2018
1 parent bb2c990 commit ef8c5df
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 18 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ gem 'memoist', require: false

# File processing
gem 'carrierwave'
gem 'ruby-filemagic'
gem 'mini_magick'
gem 'acts-as-taggable-on', '~> 4.0'
# this doesn't install cleanly on a Mac
# We aren't currently using this anyway
Expand Down
18 changes: 10 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,10 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
carrierwave (0.11.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
json (>= 1.7)
carrierwave (1.2.2)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
mimemagic (>= 0.3.0)
charlock_holmes (0.7.5)
choice (0.2.0)
chronic (0.10.2)
Expand Down Expand Up @@ -247,7 +245,7 @@ GEM
htmlentities (4.3.4)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (0.9.1)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
jmespath (1.3.1)
Expand Down Expand Up @@ -301,8 +299,9 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_magick (4.8.0)
mini_portile2 (2.3.0)
minitest (5.10.3)
minitest (5.11.3)
minitest-reporters (1.1.13)
ansi
builder
Expand Down Expand Up @@ -440,6 +439,7 @@ GEM
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
ruby-filemagic (0.7.2)
ruby-graphviz (1.2.2)
ruby-prof (0.16.2)
ruby-progressbar (1.8.1)
Expand Down Expand Up @@ -499,7 +499,7 @@ GEM
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.7)
tzinfo (1.2.4)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (3.0.4)
execjs (>= 0.3.0, < 3)
Expand Down Expand Up @@ -590,6 +590,7 @@ DEPENDENCIES
lograge
memoist
memory_profiler
mini_magick
minitest-reporters
net-sftp
newrelic_rpm
Expand All @@ -612,6 +613,7 @@ DEPENDENCIES
roo
rspec-mocks
rspec-rails
ruby-filemagic
ruby-prof
ruby-progressbar
ruby_parser
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ There is a simple script to setup a development environment in `bin/setup`. To m
* A running Ruby 2.3+ environment with bundler 1.11+ installed.
* A local install of postgresql 9.4+ allowing your user to create new databases.
* A local install of redis for caching. redis-server should be running on the default port
* libmagic

Once these are in place, `bin/setup` should:

Expand Down
4 changes: 4 additions & 0 deletions app/assets/stylesheets/modules/_client.scss
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,8 @@ $client-match-action-row-height: 22px;
padding: 1em 0.5em;
display: inline-block;
padding: 0.5em 0.5em;
}
.file-thumbnail
{
width: 100px;
}
4 changes: 2 additions & 2 deletions app/controllers/clients/files_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ def create
file: file,
client_id: @client.id,
user_id: current_user.id,
content_type: file&.content_type,
# content_type: file&.content_type,
content: file&.read,
visible_in_window: allowed_params[:visible_in_window],
note: allowed_params[:note],
name: allowed_params[:name],
consent_form_signed_on: allowed_params[:consent_form_signed_on],
consent_form_confirmed: allowed_params[:consent_form_confirmed]
consent_form_confirmed: allowed_params[:consent_form_confirmed],
)
tag_list = allowed_params[:tag_list].select(&:present?)
@file.tag_list.add(tag_list)
Expand Down
35 changes: 33 additions & 2 deletions app/controllers/window/clients/files_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ class FilesController < ApplicationController
include WindowClientPathGenerator

before_action :require_window_file_access!
before_action :set_client, only: [:index, :show, :new, :create, :edit, :update]
before_action :set_client, only: [:index, :show, :new, :create, :edit, :update, :preview, :thumb, :has_thumb]
before_action :set_files, only: [:index]
before_action :set_file, only: [:show, :edit, :update]
before_action :set_file, only: [:show, :edit, :update, :preview, :thumb, :has_thumb]

def index
@consent_form_url = GrdaWarehouse::Config.get(:url_of_blank_consent_form)
Expand Down Expand Up @@ -66,6 +66,37 @@ def destroy
end
redirect_to polymorphic_path(files_path_generator, client_id: @client.id)
end

def preview
if stale?(etag: @file, last_modified: @file.updated_at)
@preview = @file.file&.preview
head :ok and return unless @preview.present?
headers['Content-Security-Policy'] = "default-src 'none'; object-src 'self'; style-src 'unsafe-inline'; plugin-types application/pdf;"
send_data @preview.file.read, filename: @file.name, disposition: :inline, content_type: @preview.file.content_type
else
logger.debug 'used browser cache'
end
end

def thumb
if stale?(etag: @file, last_modified: @file.updated_at)
@thumb = @file.file&.thumb
head :ok and return unless @thumb.present?
headers['Content-Security-Policy'] = "default-src 'none'; object-src 'self'; style-src 'unsafe-inline'; plugin-types application/pdf;"
send_data @thumb.file.read, filename: @file.name, disposition: :inline, content_type: @thumb.file.content_type
else
logger.debug 'used browser cache'
end
end

def has_thumb
@thumb = @file.file&.thumb
if @thumb.present?
head :ok and return
else
head :not_found and return
end
end

def download
send_data(@file.content, type: @file.content_type, filename: File.basename(@file.file.to_s))
Expand Down
81 changes: 78 additions & 3 deletions app/uploaders/file_uploader.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# encoding: utf-8
require 'carrierwave/uploader/magic_mime_whitelist'

class FileUploader < CarrierWave::Uploader::Base
# more robust check of the bytes in the upload using libmagic
include CarrierWave::Uploader::MagicMimeWhitelist
# we will use mini magics API to process attachments
include CarrierWave::MiniMagick

# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
Expand Down Expand Up @@ -39,12 +44,82 @@ class FileUploader < CarrierWave::Uploader::Base
# version :thumb do
# process :resize_to_fit => [50, 50]
# end
#
process :extract_file_metadata!

version :preview do
process :create_preview
end
version :thumb do
process :create_thumb
end

def create_thumb
create_preview(size: '400x400')
end

def create_preview size: '1920x1080'
# https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Efficiently-converting-image-formats#changing-the-format
manipulate! do |img|
img.format('jpg') do |c|
c.auto_orient
c.auto_level #FIXME: we probably only want to do this for DICOM images.
end
img.strip
img.resize size
img
end
end

# NOTE if you make changes here it would be a good idea to update test/uploaders/attachment_uploader_test.rb
WHITELIST = IceNine.deep_freeze(%w(
image/jpeg
image/png
image/gif
application/pdf
application/msword
application/vnd.openxmlformats-officedocument.wordprocessingml.document
text/csv
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
))

# normal content_type handling uses this
# this is mostly to provide user feedback if they send
# a content_type value with the upload
def content_type_whitelist
WHITELIST+%w(application/octet-stream)
end

# MagicMimeWhitelist content_type handling uses
# this list (Regexp actually is what they want)
# this is checked againts the actual uploaded data bytes
# so a client cannot lie about the bytes sent
# this should be very restrictive and is what we use to
# decided what processing we are willing to try running
def whitelist_mime_type_pattern
Regexp.union WHITELIST
end

# Extracts the file metadata into the model fields
# size and mime_type are forced to the
# actual data, name defaults to thethe original_filename
# if its not already set in the model
def extract_file_metadata!
model.name ||= file&.filename
model.size = file&.size
model.content_type = content_type_from_bytes(file) # use magic for this and NOT ruby's built in lookup
end

private def content_type_from_bytes(file_to_test = file)
extract_content_type(file_to_test) rescue nil
end

# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(pdf jpg jpeg doc docx xls xlsx gif png txt rtf)
end
# def extension_white_list
# %w(pdf jpg jpeg doc docx xls xlsx gif png txt rtf)
# end

# Provide a range of file sizes which are allowed to be uploaded
# NOT WORKING
Expand Down
2 changes: 2 additions & 0 deletions app/views/clients/files/_file_list.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
%th(colspan=6)
%th.text-center(colspan=2 style='background-color: #eee') Consent Form
%tr
%th
%th File
%th Contains
%th Note
Expand All @@ -20,6 +21,7 @@
%tbody
- @files.each do |file|
%tr{ class: "client-file-#{file.id}"}
%td.jThumb{data: {file: file.id}}
%td
- if file.content.present?
= link_to polymorphic_path(file_path_generator, id: file.id) do
Expand Down
17 changes: 17 additions & 0 deletions app/views/clients/files/index.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,20 @@

= render 'window/clients/files/file_upload'
= render 'file_list'

= content_for :page_js do
:javascript
(function($) {
$('.jThumb').each(function(e) {
var thumb = $(this);
var file_id = $(this).data('file')
var url = window.location.pathname + '/' + file_id + '/has_thumb';
$.get(url).done(function(data) {
var url = window.location.pathname + '/' + file_id + '/thumb';
thumb.append('<img src="' + url + '" class="file-thumbnail" />');
}).fail(function() {

});

});
})(jQuery);
12 changes: 10 additions & 2 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ def sub_populations
delete :destroy_file
end
end
resources :files, controller: 'clients/files'
resources :files, controller: 'clients/files' do
get :preview, on: :member
get :thumb, on: :member
get :has_thumb, on: :member
end
resources :notes, only: [:index, :destroy, :create], controller: 'clients/notes'
resource :eto_api, only: [:show, :update], controller: 'clients/eto_api'
resources :users, only: [:index, :create, :update, :destroy], controller: 'clients/users'
Expand Down Expand Up @@ -234,7 +238,11 @@ def sub_populations
delete :destroy_file
end
end
resources :files, controller: 'clients/files'
resources :files, controller: 'clients/files' do
get :preview, on: :member
get :thumb, on: :member
get :has_thumb, on: :member
end
resources :notes, only: [:index, :create, :destroy], controller: 'clients/notes'
resource :eto_api, only: [:show, :update], controller: 'clients/eto_api'
resources :users, only: [:index, :create, :update, :destroy], controller: 'clients/users'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddAttributesToFiles < ActiveRecord::Migration
def change
add_column :files, :size, :float
end
end
3 changes: 2 additions & 1 deletion db/warehouse/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20180215212401) do
ActiveRecord::Schema.define(version: 20180216221704) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -1106,6 +1106,7 @@
t.integer "vispdat_id"
t.date "consent_form_signed_on"
t.boolean "consent_form_confirmed"
t.float "size"
end

add_index "files", ["type"], name: "index_files_on_type", using: :btree
Expand Down

0 comments on commit ef8c5df

Please sign in to comment.