Project

General

Profile

Feature #22483 » 0001-Show-PDF-preview-for-repository-files-and-attachment.patch

Go MAEDA, 2026-02-18 06:57

View differences:

app/assets/stylesheets/application.css
2435 2435
  box-shadow: 0 1px 2px rgba(var(--oc-gray-9-rgb), 0.05);
2436 2436
}
2437 2437

  
2438
.pdf-full-view-link { margin: 0 0 0.5em; }
2439

  
2438 2440
/* tablesort */
2439 2441
th[role=columnheader]:not(.no-sort) {
2440 2442
	cursor: pointer;
app/assets/stylesheets/scm.css
102 102

  
103 103
img.filecontent, video.filecontent { max-inline-size: 100%; }
104 104

  
105
.filecontent.pdf {
106
    inline-size: 100%;
107
    max-block-size: 80vh;
108
    overflow: hidden;
109
    position: relative;
110
}
111

  
112
.filecontent.pdf::before {
113
    content: " ";
114
    display: block;
115
    inline-size: 100%;
116
    padding-block-end: 100%;
117
}
118

  
119
.filecontent.pdf object,
120
.filecontent.pdf iframe,
121
.filecontent.pdf p {
122
    position: absolute;
123
    inset-block-start: 0;
124
    inset-inline-start: 0;
125
    inset-inline-end: 0;
126
}
127

  
128
.filecontent.pdf iframe,
129
.filecontent.pdf object {
130
    border: none;
131
    inline-size: 100%;
132
    block-size: 100%;
133
}
134

  
105 135
.previous-filename {
106 136
  font-weight: normal;
107 137
}
app/controllers/attachments_controller.rb
61 61
          render :action => 'file'
62 62
        elsif @attachment.is_image?
63 63
          render :action => 'image'
64
        elsif @attachment.is_pdf?
65
          render :action => 'pdf'
64 66
        else
65 67
          render :action => 'other'
66 68
        end
app/views/attachments/pdf.html.erb
1
<%= render :layout => 'layouts/file' do %>
2
  <%= render :partial => 'common/pdf',
3
             :locals => {:path => download_named_attachment_path(@attachment, @attachment.filename)} %>
4
<% end %>
app/views/common/_pdf.html.erb
1
<p class="pdf-full-view-link">
2
  <%= link_to l(:label_open_in_full_view, :default => l(:button_download)), path %>
3
</p>
4
<div class="filecontent pdf">
5
  <object data="<%= path %>" type="application/pdf">
6
    <%= render :partial => 'common/other' %>
7
  </object>
8
</div>
app/views/repositories/entry.html.erb
10 10

  
11 11
<% if Redmine::MimeType.is_type?('image', @path) %>
12 12
  <%= render :partial => 'common/image', :locals => {:path => @raw_url, :alt => @path} %>
13
<% elsif Redmine::MimeType.of(@path) == 'application/pdf' %>
14
  <%= render :partial => 'common/pdf', :locals => {:path => @raw_url} %>
13 15
<% elsif Redmine::MimeType.of(@path) == 'text/x-textile' %>
14 16
  <%= render :partial => 'common/markup', :locals => {:markup_text_formatting => 'textile', :markup_text => @content} %>
15 17
<% elsif Redmine::MimeType.of(@path) == 'text/markdown' %>
config/locales/en.yml
726 726
  label_no_preview: No preview available
727 727
  label_no_preview_alternative_html: No preview available. %{link} the file instead.
728 728
  label_no_preview_download: Download
729
  label_open_in_full_view: Open in full view
729 730
  label_change_status: Change status
730 731
  label_history: History
731 732
  label_attachment: File
test/functional/attachments_controller_test.rb
239 239
    assert_select 'img.filecontent', :src => attachments(:attachments_010).filename
240 240
  end
241 241

  
242
  def test_show_pdf
243
    @request.session[:user_id] = 2
244
    get(:show, :params => {:id => 23})
245
    assert_response :success
246
    assert_equal 'text/html', @response.media_type
247

  
248
    path = download_named_attachment_path(attachments(:attachments_023), attachments(:attachments_023).filename)
249
    assert_select ".filecontent.pdf object[data='#{path}']"
250
    assert_select '.nodata', :text => 'No preview available'
251
  end
252

  
242 253
  def test_show_other_with_no_preview
243 254
    @request.session[:user_id] = 2
244 255
    get(:show, :params => {:id => 6})
(8-8/8)