Fix Step and Result file previews [SCI-3539]

This commit is contained in:
Oleksii Kriuchykhin 2019-07-01 23:30:20 +02:00
parent 5acb16d43e
commit 4ea6b56582
11 changed files with 46 additions and 219 deletions

View file

@ -1,102 +0,0 @@
/* global animateSpinner FilePreviewModal */
function setupAssetsLoading() {
var DELAY = 2500;
var REPETITIONS = 60;
var cntr = 0;
var intervalId;
function refreshAssets() {
var elements = $("[data-status='asset-loading']");
if (!elements.length) {
return false;
}
$.each(elements, function(_, el) {
var $el = $(el);
// Perform an AJAX call to present URL
// to check if file already exists
$.ajax({
url: $el.data('present-url'),
type: 'GET',
dataType: 'json',
success: function(data) {
if (data.processing === true) {
return;
}
if (data.processing === false) {
$el.html(data.placeholder_html);
$el.attr('data-status', 'asset-loaded');
return;
}
$el.attr('data-status', 'asset-loaded');
$el.find('img').hide();
$el.next().hide();
$el.html('');
if (data.type === 'image') {
$el.html(
"<a class='file-preview-link' id='modal_link"
+ data['asset-id'] + "' data-status='asset-present' "
+ "href='" + data['download-url'] + "' data-preview-url='" + data['preview-url'] + "'>"
+ "<img src='" + data['image-tag-url'] + "'><p>" + data.filename + '</p></a>'
);
} else {
$el.html(
"<a class='file-preview-link' id='modal_link"
+ data['asset-id'] + "' data-status='asset-present' "
+ "href='" + data['download-url'] + "' data-preview-url='"
+ data['preview-url'] + "'><p>" + data.filename + '</p></a>'
);
}
animateSpinner(null, false);
FilePreviewModal.init();
},
error: function(data) {
if (data.status === 403) {
$el.find('img').hide();
$el.next().hide();
// Image/file exists, but user doesn't have
// rights to download it
if (data.type === 'image') {
$el.html(
"<img src='" + data['image-tag-url'] + "'><p>" + data.filename + '</p>'
);
} else {
$el.html('<p>' + data.filename + '</p>');
}
} else {
// Do nothing, file is not yet present
animateSpinner(null, false);
}
}
});
});
return true;
}
function finalizeAssets() {
var elements = $("[data-status='asset-loading']");
$.each(elements, function(_, el) {
var $el = $(el);
$el.attr('data-status', 'asset-failed');
if ($el.data('filename')) {
$el.html($el.data('filename'));
}
});
}
intervalId = window.setInterval(function() {
cntr += 1;
if (cntr >= REPETITIONS || !refreshAssets()) {
finalizeAssets();
window.clearInterval(intervalId);
}
}, DELAY);
}

View file

@ -1,5 +1,3 @@
//= require assets
(function(global) { (function(global) {
'use strict'; 'use strict';
@ -111,7 +109,6 @@
}); });
_renderTable($(result).find('div.step-result-hot-table')); _renderTable($(result).find('div.step-result-hot-table'));
animateSpinner(null, false); animateSpinner(null, false);
setupAssetsLoading();
} }
function _renderTable(table) { function _renderTable(table) {

View file

@ -1,6 +1,5 @@
//= require Sortable.min //= require Sortable.min
//= require canvas-to-blob.min //= require canvas-to-blob.min
//= require assets
(function(global) { (function(global) {
'use strict'; 'use strict';
@ -246,7 +245,6 @@
$new_step.find("[data-role='step-hot-table']").each(function() { $new_step.find("[data-role='step-hot-table']").each(function() {
renderTable($(this)); renderTable($(this));
}); });
setupAssetsLoading();
}) })
.on("ajax:error", function(e, xhr, status, error) { .on("ajax:error", function(e, xhr, status, error) {
$form.renderFormErrors('step', xhr.responseJSON, true, e); $form.renderFormErrors('step', xhr.responseJSON, true, e);
@ -609,7 +607,6 @@
$(this).handsontable("render"); $(this).handsontable("render");
}); });
animateSpinner(null, false); animateSpinner(null, false);
setupAssetsLoading();
DragNDropSteps.clearFiles(); DragNDropSteps.clearFiles();
FilePreviewModal.init(); FilePreviewModal.init();
$.initTooltips(); $.initTooltips();
@ -680,7 +677,6 @@
initCallBacks(); initCallBacks();
initHandsOnTable($(document)); initHandsOnTable($(document));
expandAllSteps(); expandAllSteps();
setupAssetsLoading();
FilePreviewModal.init(); FilePreviewModal.init();
TinyMCE.highlight(); TinyMCE.highlight();
SmartAnnotation.preventPropagation('.atwho-user-popover'); SmartAnnotation.preventPropagation('.atwho-user-popover');

View file

@ -1,8 +1,7 @@
/* eslint no-underscore-dangle: ["error", { "allowAfterThis": true }]*/ /* eslint no-underscore-dangle: ["error", { "allowAfterThis": true }]*/
/* eslint no-use-before-define: ["error", { "functions": false }]*/ /* eslint no-use-before-define: ["error", { "functions": false }]*/
/* eslint-disable no-underscore-dangle */ /* eslint-disable no-underscore-dangle */
/* global Uint8Array fabric tui animateSpinner setupAssetsLoading I18n PerfectScrollbar*/ /* global Uint8Array fabric tui animateSpinner I18n PerfectScrollbar*/
//= require assets
var FilePreviewModal = (function() { var FilePreviewModal = (function() {
'use strict'; 'use strict';
@ -396,7 +395,6 @@ var FilePreviewModal = (function() {
processData: false, processData: false,
success: function(res) { success: function(res) {
$('#modal_link' + data.id).parent().html(res.html); $('#modal_link' + data.id).parent().html(res.html);
setupAssetsLoading();
} }
}).done(function() { }).done(function() {
animateSpinner(null, false); animateSpinner(null, false);

View file

@ -10,62 +10,15 @@ class AssetsController < ApplicationController
include FileIconsHelper include FileIconsHelper
before_action :load_vars, except: :create_wopi_file before_action :load_vars, except: :create_wopi_file
before_action :check_read_permission, except: :file_present before_action :check_read_permission
before_action :check_edit_permission, only: :edit before_action :check_edit_permission, only: :edit
def file_present
respond_to do |format|
format.json do
if @asset.file.processing?
render json: {}, status: 404
else
# Only if file is present,
# check_read_permission
check_read_permission
# If check_read_permission already rendered error,
# stop execution
return if performed?
# If check permission passes, return :ok
render json: {
'asset-id' => @asset.id,
'image-tag-url' => @asset.url(:medium),
'preview-url' => asset_file_preview_path(@asset),
'filename' => truncate(escape_input(@asset.file_file_name),
length: Constants::FILENAME_TRUNCATION_LENGTH),
'download-url' => download_asset_path(@asset),
'type' => asset_data_type(@asset)
}, status: 200
end
end
end
end
def step_file_present
respond_to do |format|
format.json do
if @asset.file.processing?
render json: { processing: true }
else
render json: {
placeholder_html: render_to_string(
partial: 'steps/attachments/placeholder.html.erb',
locals: { asset: @asset, edit_page: false }
),
processing: false
}
end
end
end
end
def file_preview def file_preview
response_json = { response_json = {
'id' => @asset.id, 'id' => @asset.id,
'type' => (@asset.image? ? 'image' : 'file'), 'type' => (@asset.image? ? 'image' : 'file'),
'filename' => truncate(escape_input(@asset.file_file_name), 'filename' => truncate(escape_input(@asset.file_name),
length: Constants::FILENAME_TRUNCATION_LENGTH), length: Constants::FILENAME_TRUNCATION_LENGTH),
'download-url' => download_asset_path(@asset, timestamp: Time.now.to_i) 'download-url' => download_asset_path(@asset, timestamp: Time.now.to_i)
} }
@ -85,18 +38,11 @@ class AssetsController < ApplicationController
response_json.merge!( response_json.merge!(
'editable' => @asset.editable_image? && can_edit, 'editable' => @asset.editable_image? && can_edit,
'mime-type' => @asset.file.content_type, 'mime-type' => @asset.file.content_type,
'processing' => @asset.file.processing?, 'large-preview-url' => @asset.large_preview
'large-preview-url' => @asset.url(:large),
'processing-img' => image_tag('medium/processing.gif')
) )
else else
response_json.merge!( response_json['preview-icon'] = render_to_string(partial: 'shared/file_preview_icon.html.erb',
'processing' => @asset.file.processing?, locals: { asset: @asset })
'preview-icon' => render_to_string(
partial: 'shared/file_preview_icon.html.erb',
locals: { asset: @asset }
)
)
end end
if wopi_enabled? && wopi_file?(@asset) if wopi_enabled? && wopi_file?(@asset)
@ -120,7 +66,7 @@ class AssetsController < ApplicationController
# Check whether the wopi file can be edited and return appropriate response # Check whether the wopi file can be edited and return appropriate response
def wopi_file_edit_button_status def wopi_file_edit_button_status
file_ext = @asset.file_file_name.split('.').last file_ext = @asset.file_name.split('.').last
if Constants::WOPI_EDITABLE_FORMATS.include?(file_ext) if Constants::WOPI_EDITABLE_FORMATS.include?(file_ext)
edit_supported = true edit_supported = true
title = '' title = ''
@ -138,20 +84,16 @@ class AssetsController < ApplicationController
end end
def download def download
if !@asset.file_present if !@asset.file.attached?
render_404 and return render_404
elsif @asset.file.is_stored_on_s3?
redirect_to @asset.presigned_url(download: true), status: 307
else else
send_file @asset.file.path, filename: URI.unescape(@asset.file_file_name), redirect_to rails_blob_path(@asset.file, disposition: 'attachment')
type: @asset.file_content_type
end end
end end
def edit def edit
action = @asset.file_file_size.zero? && !@asset.locked? ? 'editnew' : 'edit' action = @asset.file_size.zero? && !@asset.locked? ? 'editnew' : 'edit'
@action_url = append_wd_params(@asset @action_url = append_wd_params(@asset.get_action_url(current_user, action, false))
.get_action_url(current_user, action, false))
@favicon_url = @asset.favicon_url('edit') @favicon_url = @asset.favicon_url('edit')
tkn = current_user.get_wopi_token tkn = current_user.get_wopi_token
@token = tkn.token @token = tkn.token
@ -164,8 +106,7 @@ class AssetsController < ApplicationController
end end
def view def view
@action_url = append_wd_params(@asset @action_url = append_wd_params(@asset.get_action_url(current_user, 'view', false))
.get_action_url(current_user, 'view', false))
@favicon_url = @asset.favicon_url('view') @favicon_url = @asset.favicon_url('view')
tkn = current_user.get_wopi_token tkn = current_user.get_wopi_token
@token = tkn.token @token = tkn.token
@ -176,12 +117,11 @@ class AssetsController < ApplicationController
def update_image def update_image
@asset = Asset.find(params[:id]) @asset = Asset.find(params[:id])
orig_file_size = @asset.file_file_size orig_file_size = @asset.file_size
orig_file_name = @asset.file_file_name orig_file_name = @asset.file_name
return render_403 unless can_read_team?(@asset.team) return render_403 unless can_read_team?(@asset.team)
@asset.file = params[:image] @asset.file.attach(io: params.require(:image), filename: orig_file_name)
@asset.file_file_name = orig_file_name
@asset.save! @asset.save!
# release previous image space # release previous image space
@asset.team.release_space(orig_file_size) @asset.team.release_space(orig_file_size)
@ -225,10 +165,10 @@ class AssetsController < ApplicationController
render_403 && return unless %w(docx xlsx pptx).include?(params[:file_type]) render_403 && return unless %w(docx xlsx pptx).include?(params[:file_type])
# Asset validation # Asset validation
file = Paperclip.io_adapters.for(StringIO.new) asset = Asset.new(created_by: current_user)
file.original_filename = "#{params[:file_name]}.#{params[:file_type]}" asset.file.attach(io: StringIO.new,
file.content_type = wopi_content_type(params[:file_type]) filename: "#{params[:file_name]}.#{params[:file_type]}",
asset = Asset.new(file: file, created_by: current_user, file_present: true) content_type: wopi_content_type(params[:file_type]))
unless asset.valid?(:wopi_file_creation) unless asset.valid?(:wopi_file_creation)
render json: { render json: {
@ -315,9 +255,7 @@ class AssetsController < ApplicationController
end end
def asset_params def asset_params
params.permit( params.permit(:file)
:file
)
end end
def asset_data_type(asset) def asset_data_type(asset)

View file

@ -194,10 +194,10 @@ class ResultAssetsController < ApplicationController
success = true success = true
results = [] results = []
params[:results_files].values.each_with_index do |file, index| params[:results_files].values.each_with_index do |file, index|
asset = Asset.new(file: file, asset = Asset.new(created_by: current_user,
created_by: current_user,
last_modified_by: current_user, last_modified_by: current_user,
team: current_team) team: current_team)
asset.file.attach(file)
result = Result.new(user: current_user, result = Result.new(user: current_user,
my_module: @my_module, my_module: @my_module,
name: params[:results_names][index.to_s], name: params[:results_names][index.to_s],

View file

@ -1,11 +1,12 @@
module FileIconsHelper module FileIconsHelper
def wopi_file?(asset) def wopi_file?(asset)
file_ext = asset.file_file_name.split('.').last file_ext = asset.file_name.split('.').last
%w(csv ods xls xlsb xlsm xlsx odp pot potm potx pps ppsm ppsx ppt pptm pptx doc docm docx dot dotm dotx odt rtf).include?(file_ext) %w(csv ods xls xlsb xlsm xlsx odp pot potm potx pps ppsm
ppsx ppt pptm pptx doc docm docx dot dotm dotx odt rtf).include?(file_ext)
end end
def file_fa_icon_class(asset) def file_fa_icon_class(asset)
file_ext = asset.file_file_name.split('.').last file_ext = asset.file_name.split('.').last
if Extends::FILE_FA_ICON_MAPPINGS[file_ext] # Check for custom mappings or possible overrides if Extends::FILE_FA_ICON_MAPPINGS[file_ext] # Check for custom mappings or possible overrides
return Extends::FILE_FA_ICON_MAPPINGS[file_ext] return Extends::FILE_FA_ICON_MAPPINGS[file_ext]
@ -28,7 +29,7 @@ module FileIconsHelper
# For showing next to file # For showing next to file
def file_extension_icon(asset) def file_extension_icon(asset)
file_ext = asset.file_file_name.split('.').last file_ext = asset.file_name.split('.').last
if Constants::FILE_TEXT_FORMATS.include?(file_ext) if Constants::FILE_TEXT_FORMATS.include?(file_ext)
image_link = 'office/Word-docx_20x20x32.png' image_link = 'office/Word-docx_20x20x32.png'
elsif Constants::FILE_TABLE_FORMATS.include?(file_ext) elsif Constants::FILE_TABLE_FORMATS.include?(file_ext)
@ -38,9 +39,7 @@ module FileIconsHelper
end end
# Now check for custom mappings or possible overrides # Now check for custom mappings or possible overrides
if Extends::FILE_ICON_MAPPINGS[file_ext] image_link = Extends::FILE_ICON_MAPPINGS[file_ext] if Extends::FILE_ICON_MAPPINGS[file_ext]
image_link = Extends::FILE_ICON_MAPPINGS[file_ext]
end
if image_link if image_link
image_tag image_link image_tag image_link

View file

@ -204,6 +204,8 @@ class Asset < ApplicationRecord
end end
def previewable? def previewable?
return false unless file.attached?
previewable_document? || previewable_image? previewable_document? || previewable_image?
end end
@ -222,10 +224,14 @@ class Asset < ApplicationRecord
end end
def file_name def file_name
return '' unless file.attached?
file.blob&.filename&.to_s file.blob&.filename&.to_s
end end
def file_size def file_size
return 0 unless file.attached?
file.blob&.byte_size file.blob&.byte_size
end end
@ -247,7 +253,7 @@ class Asset < ApplicationRecord
def text? def text?
Constants::TEXT_EXTRACT_FILE_TYPES.any? do |v| Constants::TEXT_EXTRACT_FILE_TYPES.any? do |v|
file_content_type.start_with? v file.content_type.start_with? v
end end
end end
@ -530,10 +536,10 @@ class Asset < ApplicationRecord
private private
def previewable_document? def previewable_document?
previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(file.blob&.content_type) previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(file.content_type)
filename = file.blob&.filename filename = file.filename.to_s
content_type = file.blob&.content_type content_type = file.content_type
extensions = %w(.xlsx .docx .pptx .xls .doc .ppt) extensions = %w(.xlsx .docx .pptx .xls .doc .ppt)
# Mimetype sometimes recognizes Office files as zip files # Mimetype sometimes recognizes Office files as zip files

View file

@ -2,18 +2,14 @@
class: 'file-preview-link', class: 'file-preview-link',
id: "modal_link#{asset.id}", id: "modal_link#{asset.id}",
data: { no_turbolink: true, id: true, status: 'asset-present', 'preview-url': asset_file_preview_path(asset) } do %> data: { no_turbolink: true, id: true, status: 'asset-present', 'preview-url': asset_file_preview_path(asset) } do %>
<% if asset.image? && display_image_tag %> <% if display_image_tag && asset.previewable? %>
<%= image_tag asset.medium_preview %> <%= image_tag asset.medium_preview %>
<% end %>
<% if display_image_tag %>
<p> <p>
<%= truncate(asset.file_file_name, <%= truncate(asset.file_name, length: Constants::FILENAME_TRUNCATION_LENGTH) %>
length: Constants::FILENAME_TRUNCATION_LENGTH) %>
</p> </p>
<% else %> <% else %>
<span> <span>
<%= truncate(asset.file_file_name, <%= truncate(asset.file_name, length: Constants::FILENAME_TRUNCATION_LENGTH) %>
length: Constants::FILENAME_TRUNCATION_LENGTH) %>
</span> </span>
<% end %> <% end %>
<% end %> <% end %>

View file

@ -1,5 +1,5 @@
<div> <div>
<% if asset.file.previewable_document? %> <% if asset.previewable? %>
<%= image_tag(asset.large_preview) %> <%= image_tag(asset.large_preview) %>
<% else %> <% else %>
<i class="fas fa-10x <%= file_fa_icon_class(asset) %>"></i> <i class="fas fa-10x <%= file_fa_icon_class(asset) %>"></i>

View file

@ -76,7 +76,6 @@ Rails.application.config.assets.precompile += %w(canvas-to-blob.min.js)
Rails.application.config.assets.precompile += %w(Sortable.min.js) Rails.application.config.assets.precompile += %w(Sortable.min.js)
Rails.application.config.assets.precompile += %w(reports_pdf.css) Rails.application.config.assets.precompile += %w(reports_pdf.css)
Rails.application.config.assets.precompile += %w(jszip.min.js) Rails.application.config.assets.precompile += %w(jszip.min.js)
Rails.application.config.assets.precompile += %w(assets.js)
Rails.application.config.assets.precompile += %w(comments.js) Rails.application.config.assets.precompile += %w(comments.js)
Rails.application.config.assets.precompile += %w(projects/show.js) Rails.application.config.assets.precompile += %w(projects/show.js)
Rails.application.config.assets.precompile += %w(notifications.js) Rails.application.config.assets.precompile += %w(notifications.js)