diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index 9889670a..1a0df425 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -74,11 +74,18 @@ class DmsfFilesController < ApplicationController member = Member.find_by(user_id: User.current.id, project_id: @file.project.id) # IE has got a tendency to cache files expires_in 0.years, 'must-revalidate' => true + # PDF preview pdf_preview = (params[:disposition] != 'attachment') && params[:filename].blank? && @file.pdf_preview filename = filename_for_content_disposition(@revision.formatted_name(member)) if pdf_preview.present? && (Setting.plugin_redmine_dmsf['office_bin'].present? || params[:preview].present?) basename = File.basename(filename, '.*') send_file pdf_preview, filename: "#{basename}.pdf", type: 'application/pdf', disposition: 'inline' + # Text preview + elsif params[:download].blank? && (@file.size <= Setting.file_max_size_displayed.to_i.kilobyte) && + (@file.text? || @file.markdown? || @file.textile?) + @content = File.read(@revision.disk_file, mode: 'rb') + render action: 'document' + # Offer the file for download else params[:disposition] = 'attachment' if params[:filename].present? send_file @revision.disk_file, diff --git a/app/helpers/dmsf_files_helper.rb b/app/helpers/dmsf_files_helper.rb index a1539436..6775b332 100644 --- a/app/helpers/dmsf_files_helper.rb +++ b/app/helpers/dmsf_files_helper.rb @@ -27,4 +27,14 @@ module DmsfFilesHelper .gsub("\n\n", '
') .gsub("\n\t", '
') end + + def render_document_content(dmsf_file, content) + if dmsf_file.markdown? + render partial: 'common/markup', locals: { markup_text_formatting: markdown_formatter, markup_text: content } + elsif dmsf_file.textile? + render partial: 'common/markup', locals: { markup_text_formatting: 'textile', markup_text: content } + else + render partial: 'common/file', locals: { content: content, filename: dmsf_file.name } + end + end end diff --git a/app/helpers/dmsf_queries_helper.rb b/app/helpers/dmsf_queries_helper.rb index e9f4a6f3..4f2569bb 100644 --- a/app/helpers/dmsf_queries_helper.rb +++ b/app/helpers/dmsf_queries_helper.rb @@ -186,14 +186,15 @@ module DmsfQueriesHelper file_view_url = url_for( { controller: :dmsf_files, action: 'view', id: item.type == 'file' ? item.id : item.revision_id } ) - content_type = Redmine::MimeType.of(value) + content_type = Redmine::MimeType.of(item.filename) content_type = 'application/octet-stream' if content_type.blank? - tag = link_to(h(value), - file_view_url, - target: '_blank', - rel: 'noopener', - class: "icon icon-file #{DmsfHelper.filetype_css(item.filename)}", - 'data-downloadurl': "#{content_type}:#{h(value)}:#{file_view_url}") + options = { class: "icon icon-file #{DmsfHelper.filetype_css(item.filename)}", + 'data-downloadurl': "#{content_type}:#{h(value)}:#{file_view_url}" } + unless previewable?(item.filename, content_type) + options[:target] = '_blank' + options[:rel] = 'noopener' + end + tag = link_to h(value), file_view_url, options tag = content_tag('span', '', class: 'dmsf-expander') + tag unless filter_any? end member = Member.find_by(user_id: User.current.id, project_id: item.project_id) @@ -279,4 +280,13 @@ module DmsfQueriesHelper end false end + + def previewable?(filename, content_type) + case content_type + when 'text/markdown', 'text/x-textile' + true + else + Redmine::MimeType.is_type?('text', filename) || Redmine::SyntaxHighlighting.filename_supported?(filename) + end + end end diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index c5cb13c1..dba47b1c 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -465,7 +465,9 @@ class DmsfFile < ApplicationRecord end def text? - Redmine::MimeType.is_type?('text', last_revision&.disk_filename) + filename = last_revision&.disk_filename + Redmine::MimeType.is_type?('text', filename) || + Redmine::SyntaxHighlighting.filename_supported?(filename) end def image? @@ -495,6 +497,14 @@ class DmsfFile < ApplicationRecord end end + def markdown? + Redmine::MimeType.of(last_revision&.disk_filename) == 'text/markdown' + end + + def textile? + Redmine::MimeType.of(last_revision&.disk_filename) == 'text/x-textile' + end + def disposition image? || pdf? || video? || html? ? 'inline' : 'attachment' end @@ -504,7 +514,7 @@ class DmsfFile < ApplicationRecord end def previewable? - office_doc? && RedmineDmsf::Preview.office_available? + office_doc? && RedmineDmsf::Preview.office_available? && size <= Setting.file_max_size_displayed.to_i.kilobyte end # Deletes all previews diff --git a/app/views/dmsf_files/document.html.erb b/app/views/dmsf_files/document.html.erb new file mode 100644 index 00000000..281cb8f9 --- /dev/null +++ b/app/views/dmsf_files/document.html.erb @@ -0,0 +1,23 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman + # + # This program is free software; you can redistribute it and/or + # modify it under the terms of the GNU General Public License + # as published by the Free Software Foundation; either version 2 + # of the License, or (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program; if not, write to the Free Software + # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +%> + +<%= render layout: 'layouts/document' do %>  + <%= render_document_content @file, @content %> +<% end %> diff --git a/app/views/layouts/_document.html.erb b/app/views/layouts/_document.html.erb new file mode 100644 index 00000000..c2062a86 --- /dev/null +++ b/app/views/layouts/_document.html.erb @@ -0,0 +1,47 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman + # + # This program is free software; you can redistribute it and/or + # modify it under the terms of the GNU General Public License + # as published by the Free Software Foundation; either version 2 + # of the License, or (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program; if not, write to the Free Software + # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +%> + +
+ <%= link_to "#{l(:button_download)} (#{number_to_human_size(@file.size)})", + static_dmsf_file_path(@file, download: @file.last_revision, filename: @file.last_revision.disk_filename), + class: 'icon icon-download', disabled: false %> +
+ +

+ <%= render partial: '/dmsf/path', locals: { folder: @file.dmsf_folder, filename: @file.title, title: nil } %> +

+ +
+

+ <%= @file.description %> + + <%= link_to_user @file.last_revision.user %>, <%= format_time @file.last_revision.updated_at %> + +

+
+
+ <%= yield %> +
+ +<% html_title @file.name %> + +<% content_for :header_tags do %> + <%= stylesheet_link_tag 'scm' %> +<% end %> diff --git a/test/helpers/dmsf_queries_helper_test.rb b/test/helpers/dmsf_queries_helper_test.rb index 19b05eeb..5f060e79 100644 --- a/test/helpers/dmsf_queries_helper_test.rb +++ b/test/helpers/dmsf_queries_helper_test.rb @@ -42,4 +42,10 @@ class DmsfQueriesHelperTest < RedmineDmsf::Test::HelperTest c_size = QueryColumn.new(:size) assert_equal '1 KB', csv_value(c_size, @folder1, 1024) end + + def test_previewable + assert previewable?('file.txt', 'text/plain') + assert previewable?('main.c', 'text/x-csrc') + assert_not previewable?('document.odt', 'application/vnd.oasis.opendocument.text') + end end diff --git a/test/unit/dmsf_file_test.rb b/test/unit/dmsf_file_test.rb index 6ac73338..6077c75a 100644 --- a/test/unit/dmsf_file_test.rb +++ b/test/unit/dmsf_file_test.rb @@ -213,6 +213,8 @@ class DmsfFileTest < RedmineDmsf::Test::UnitTest assert @file1.text? assert_not @file7.text? assert_not @file8.text? + @file1.last_revision.disk_filename = 'test.c' + assert @file1.text? end def test_pdf @@ -233,6 +235,18 @@ class DmsfFileTest < RedmineDmsf::Test::UnitTest assert @file1.html? end + def test_markdown + assert_not @file1.markdown? + @file1.last_revision.disk_filename = 'test.md' + assert @file1.markdown? + end + + def test_textile + assert_not @file1.textile? + @file1.last_revision.disk_filename = 'test.textile' + assert @file1.textile? + end + def test_findn_file_by_name assert DmsfFile.find_file_by_name(@project1, nil, 'test.txt') assert_nil DmsfFile.find_file_by_name(@project1, nil, 'test.ods')