Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

652: added Document (file) media type #668

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/assets/images/media/document.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion app/assets/javascripts/legacy/views/question_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
selected_type == "signature" ||
selected_type == "sketch" ||
selected_type == "audio" ||
selected_type == "video"
selected_type == "video" ||
selected_type == "document"
);
$(".question_fields .question_key").css('display', hide_key_q ? 'none' : 'flex');

Expand Down
1 change: 1 addition & 0 deletions app/controllers/media/objects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def media_class(type)
when "audios" then Media::Audio
when "videos" then Media::Video
when "images" then Media::Image
when "documents" then Media::Document
else raise "A valid media type must be specified"
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/decorators/odk/question_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Odk
class QuestionDecorator < ApplicationDecorator
delegate_all

URI_DIRS_BY_TYPE = {video: "video", audio: "audio", image: "images"}.freeze
URI_DIRS_BY_TYPE = {video: "video", audio: "audio", image: "images", document: "document"}.freeze
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ODK document media prompts aren't supported then this should be removed too.


# Make media prompt file name unique to curb collisions and duplications
def unique_media_prompt_filename
Expand Down
1 change: 1 addition & 0 deletions app/decorators/odk/subqing_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def media_type
when "image", "annotated_image", "sketch", "signature" then "image/*"
when "audio" then "audio/*"
when "video" then "video/*"
when "document" then "document/*"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this been tested in ODK Collect? What does it do? I know that image, audio, and video have specific meanings in Collect but I haven't heard of "document" in that context. If it's not supported by ODK then we should not be rendering this question type when rendering for Collect, and this deliberate omission should be tested in the form_rendering_spec.rb

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @smoyth. Yes, we've tested in ODK collect and also in Nemo web interface. I've tested by uploading a document (pdf, odt, doc) in the collect, the answer was saved and after I could download/preview that document in the answer screen. This also worked in the web interface.

end
end

Expand Down
21 changes: 11 additions & 10 deletions app/helpers/forms_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,17 @@ def allow_incomplete?

# Question types not listed here use PNGs instead of FA icons.
FORM_ITEM_ICON_CLASSES = {
'long_text' => 'fa-align-left',
'date' => 'fa-calendar',
'time' => 'fa-clock-o',
'location' => 'fa-map-marker',
'group' => 'fa-folder-open-o',
'image' => 'fa-image',
'sketch' => 'fa-pencil-square-o',
'audio' => 'fa-volume-up',
'video' => 'fa-film',
'counter' => 'fa-plus'
"long_text" => "fa-align-left",
"date" => "fa-calendar",
"time" => "fa-clock-o",
"location" => "fa-map-marker",
"group" => "fa-folder-open-o",
"image" => "fa-image",
"sketch" => "fa-pencil-square-o",
"audio" => "fa-volume-up",
"video" => "fa-film",
"counter" => "fa-plus",
"document" => "fa-file"
}

def form_item_icon(type)
Expand Down
15 changes: 13 additions & 2 deletions app/models/concerns/odk/mediable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@ module Mediable
extend ActiveSupport::Concern

# video/ogg is needed for audio OGG files for some weird reason.
# application/x-ole-storage is needed sometimes due to issue: https://github.com/minad/mimemagic/issues/50
ODK_MEDIA_MIME_TYPES = %w[audio/mpeg audio/ogg audio/wave audio/wav audio/x-wav audio/x-pn-wav
audio/flac video/ogg application/ogg video/mp4 image/png image/jpeg].freeze
ODK_MEDIA_EXTS = {audio: %w[mp3 ogg wav flac], video: %w[mp4], image: %w[png jpg jpeg]}.freeze
audio/flac video/ogg application/ogg video/mp4 image/png image/jpeg
application/msword application/vnd.oasis.opendocument.spreadsheet
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.oasis.opendocument.text application/pdf
application/vnd.ms-powerpoint text/csv application/rtf text/plain
application/vnd.oasis.opendocument.presentation
application/x-ole-storage].freeze
ODK_MEDIA_EXTS = {audio: %w[mp3 ogg wav flac], video: %w[mp4], image: %w[png jpg jpeg],
document: %w[pdf xls xlsx ods doc docx odt rtf ppt pptx odp csv txt]}.freeze
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ODK doesn't support the document type then all of this can be removed, yes?


class_methods do
def odk_media_attachment(col_name)
Expand Down
57 changes: 57 additions & 0 deletions app/models/media/document.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

# rubocop:disable Metrics/LineLength
# == Schema Information
#
# Table name: media_objects
#
# id :uuid not null, primary key
# item_content_type :string(255) not null
# item_file_name :string(255) not null
# item_file_size :integer not null
# item_updated_at :datetime not null
# type :string(255) not null
# created_at :datetime not null
# updated_at :datetime not null
# answer_id :uuid
#
# Indexes
#
# index_media_objects_on_answer_id (answer_id)
#
# Foreign Keys
#
# media_objects_answer_id_fkey (answer_id => answers.id) ON DELETE => restrict ON UPDATE => restrict
#
# rubocop:enable Metrics/LineLength

module Media
# Document-type Answer attachment.
class Document < ::Media::Object
# A note on validation:
# We no longer validate file extensions because we can't anticipate what extensions folks
# will be sending from ODK Collect (since the platform changes over time)
# and there is no easy way to allow the user to correct behavior on validation fail-we just have to
# discard the file. So for that we reason we limit to mime type validation only since that still
# provides some security but is less restrictive and less superficial.
validates_attachment_content_type :item, content_type: [
"text/csv", "text/plain", "application/pdf", "application/rtf",
viniciuscb marked this conversation as resolved.
Show resolved Hide resolved
"application/msword", "application/vnd.ms-excel", "application/vnd.ms-powerpoint",
"application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.text",
"application/vnd.oasis.opendocument.presentation",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
viniciuscb marked this conversation as resolved.
Show resolved Hide resolved
# sometimes mimemagic returns x-ole-storage for msoffice files: https://github.com/minad/mimemagic/issues/50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment!

"application/x-ole-storage"
]

def static_thumb_path
"media/document.png"
end

def kind
"document"
end
end
end
1 change: 1 addition & 0 deletions app/models/odk/answer_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def media_class(qtype_name)
when "image", "annotated_image", "sketch", "signature" then Media::Image
when "audio" then Media::Audio
when "video" then Media::Video
when "document" then Media::Document
end
end
end
Expand Down
6 changes: 5 additions & 1 deletion app/models/question_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class QuestionType
name: "video",
odk_name: "binary",
properties: %w[multimedia]
}, {
name: "document",
odk_name: "binary",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe don't need this?

properties: %w[multimedia]
}]

# looks up a question type by name
Expand Down Expand Up @@ -124,7 +128,7 @@ def human_name
def media_type
case name
when "image", "annotated_image", "signature", "sketch" then "image"
when "audio", "video" then name
when "audio", "video", "document" then name
end
end
end
15 changes: 8 additions & 7 deletions app/models/report/standard_form_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ class Report::StandardFormReport < Report::Report

# question types that we leave off this report (stored as a hash for better performance)
EXCLUDED_TYPES = {
'location' => true,
'image' => true,
'annotated_image' => true,
'signature' => true,
'sketch' => true,
'video' => true,
'audio' => true
"location" => true,
"image" => true,
"annotated_image" => true,
"signature" => true,
"sketch" => true,
"video" => true,
"audio" => true,
"document" => true
}

# options for the question_order attrib
Expand Down
2 changes: 1 addition & 1 deletion app/views/responses/answers/_single_editable.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
class: "form-control") %>
<% end %>

<% when "image", "annotated_image", "signature", "sketch", "audio", "video" %>
<% when "image", "annotated_image", "signature", "sketch", "audio", "video", "document" %>

<%= render("responses/answers/media_editable", answer: answer, context: context) %>

Expand Down
2 changes: 1 addition & 1 deletion app/views/responses/answers/_single_read_only.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

<%= content_tag(:div, answer.value) %>

<% when "image", "annotated_image", "signature", "sketch", "audio", "video" %>
<% when "image", "annotated_image", "signature", "sketch", "audio", "video", "document" %>

<%= media_link answer.media_object %>

Expand Down
10 changes: 10 additions & 0 deletions config/initializers/mime_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@

# Add new mime types for use in respond_to blocks:
Mime::Type.register("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx)

# Avoid Paperclip to handle newer office files (docx/xlsx/pptx) as application/zip
# https://github.com/thoughtbot/paperclip/issues/896#issuecomment-538136513
[
["application/vnd.openxmlformats-officedocument.presentationml.presentation", [[0..2000, "ppt/"]]],
["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", [[0..2000, "xl/"]]],
["application/vnd.openxmlformats-officedocument.wordprocessingml.document", [[0..2000, "word/"]]]
].each do |magic|
viniciuscb marked this conversation as resolved.
Show resolved Hide resolved
MimeMagic.add(magic[0], magic: magic[1])
end
3 changes: 3 additions & 0 deletions config/locales/en/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,7 @@ en:
sketch: "Sketch"
audio: "Audio"
video: "Video"
document: "Document"

recaptcha:
errors:
Expand Down Expand Up @@ -1751,11 +1752,13 @@ en:
image: "Are you sure you want to delete this image?"
audio: "Are you sure you want to delete this audio?"
video: "Are you sure you want to delete this video?"
document: "Are you sure you want to delete this document?"
drop_more_info: "More info"
drop_hint:
image: "The image should be at most 5 MB in size. Accepted formats are: jpg, png."
video: "The video should be at most 25 MB in size. Accepted formats are: 3gp, mp4, webm, mpg, wmv, avi."
audio: "The audio should be at most 10 MB in size. Accepted formats are: mp3, ogg, webm, wav."
document: "The document should be at most 10 MB in size. Accepted formats are: pdf, doc(x), xls(x), ppt(x), ods, odt, odp, csv, rtf, txt."
csv_headers:
response_id: "ResponseID"
reviewed: "Reviewed"
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
end
end

namespace :media, type: /audios|images|videos/ do
namespace :media, type: /audios|images|videos|documents/ do
resources :objects, path: ":type", only: %i[show create destroy]
end

Expand Down
56 changes: 56 additions & 0 deletions spec/factories/media_objects.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,61 @@
item { media_fixture("video/jupiter.ogv") }
end
end

factory :media_document, class: "Media::Document" do
pdf

trait :csv do
item { media_fixture("document/document.csv") }
end

trait :doc do
item { media_fixture("document/document.doc") }
end

trait :docx do
item { media_fixture("document/document.docx") }
end

trait :odp do
item { media_fixture("document/document.odp") }
end

trait :ods do
item { media_fixture("document/document.ods") }
end

trait :odt do
item { media_fixture("document/document.odt") }
end

trait :pdf do
item { media_fixture("document/document.pdf") }
end

trait :ppt do
item { media_fixture("document/document.ppt") }
end

trait :pptx do
item { media_fixture("document/document.pptx") }
end

trait :rtf do
item { media_fixture("document/document.rtf") }
end

trait :txt do
item { media_fixture("document/document.txt") }
end

trait :xls do
item { media_fixture("document/document.xls") }
end

trait :xlsx do
item { media_fixture("document/document.xlsx") }
end
end
end
end
3 changes: 2 additions & 1 deletion spec/features/forms/question/question_form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"Signature" => %i[],
"Sketch" => %i[],
"Audio" => %i[],
"Video" => %i[]
"Video" => %i[],
"Document" => %i[]
}.freeze

FIELD_NAMES = {
Expand Down
Loading