Project

General

Profile

Feature #31472 » 31472-add-file-upload.patch

Yuichi HARADA, 2019-12-18 02:21

View differences:

app/controllers/documents_controller.rb
75 75
    @document.safe_attributes = params[:document]
76 76
    if @document.save
77 77
      flash[:notice] = l(:notice_successful_update)
78
      redirect_to document_path(@document)
78
      add_attachment
79 79
    else
80 80
      render :action => 'edit'
81 81
    end
app/models/document.rb
31 31
                :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
32 32
  acts_as_activity_provider :scope => preload(:project)
33 33

  
34
  attr_writer :deleted_attachment_ids
35

  
34 36
  validates_presence_of :project, :title, :category
35 37
  validates_length_of :title, :maximum => 255
36 38

  
39
  after_save :delete_selected_attachments
37 40
  after_create_commit :send_notification
38 41

  
39 42
  scope :visible, lambda {|*args|
......
42 45
  }
43 46

  
44 47
  safe_attributes 'category_id', 'title', 'description', 'custom_fields', 'custom_field_values'
48
  safe_attributes(
49
    'deleted_attachment_ids',
50
    :if => lambda {|document, user| document.attachments_deletable?(user)}
51
  )
45 52

  
46 53
  def visible?(user=User.current)
47 54
    !user.nil? && user.allowed_to?(:view_documents, project)
......
66 73
    project.notified_users.reject {|user| !visible?(user)}
67 74
  end
68 75

  
76
  def deleted_attachment_ids
77
    Array(@deleted_attachment_ids).map(&:to_i)
78
  end
79

  
69 80
  private
70 81

  
82
  def delete_selected_attachments
83
    deleted_ids = deleted_attachment_ids
84
    return if deleted_ids.blank?
85
    objects = attachments.where(:id => deleted_ids)
86
    attachments.delete(objects) if objects.exists?
87
  end
88

  
71 89
  def send_notification
72 90
    if Setting.notified_events.include?('document_added')
73 91
      Mailer.deliver_document_added(self, User.current)
app/views/documents/_form.html.erb
13 13
<% @document.custom_field_values.each do |value| %>
14 14
  <p><%= custom_field_tag_with_label :document, value %></p>
15 15
<% end %>
16
</div>
17 16

  
18 17
<%= wikitoolbar_for 'document_description' %>
19 18

  
20
<% if @document.new_record? %>
21
<div class="box tabular">
22
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form', :locals => {:container => @document} %></p>
19
<fieldset>
20
<legend><%=l(:label_attachment_plural)%></legend>
21
<% if @document.attachments.any? && @document.safe_attribute?('deleted_attachment_ids') %>
22
<div class="contextual"><%= link_to l(:label_edit_attachments), '#', :onclick => "$('#existing-attachments').toggle(); return false;" %></div>
23
<div id="existing-attachments" style="<%= 'display:none;' if @document.deleted_attachment_ids.blank? %>">
24
  <% @document.attachments.each do |attachment| %>
25
  <span class="existing-attachment">
26
    <%= text_field_tag '', attachment.filename, :class => "icon icon-attachment filename", :disabled => true %>
27
    <label class='inline'>
28
      <%= check_box_tag 'document[deleted_attachment_ids][]',
29
                        attachment.id,
30
                        @document.deleted_attachment_ids.include?(attachment.id),
31
                        :id => nil, :class => "deleted_attachment" %>&nbsp;<%= l(:button_delete) %>
32
    </label>
33
  </span>
34
  <% end %>
35
  <hr />
23 36
</div>
24 37
<% end %>
38
<div id="new-attachments" style="display:inline-block;">
39
  <%= render :partial => 'attachments/form', :locals => {:container => @document} %>
40
</div>
41
</fieldset>
42
</div>
test/functional/documents_controller_test.rb
207 207
  end
208 208

  
209 209
  def test_update
210
    set_tmp_attachments_directory
210 211
    @request.session[:user_id] = 2
211
    put :update, :params => {
212
        :id => 1,
213
        :document => {
214
          :title => 'test_update'
212
    assert_difference 'Attachment.count' do
213
      put :update, :params => {
214
          :id => 1,
215
          :document => {
216
            :title => 'test_update'
217
          },
218
          :attachments => {
219
            '1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}
220
          }
215 221
        }
216
      }
222
    end
217 223
    assert_redirected_to '/documents/1'
218 224
    document = Document.find(1)
219 225
    assert_equal 'test_update', document.title
220 226
  end
221 227

  
222 228
  def test_update_with_failure
229
    set_tmp_attachments_directory
230
    @request.session[:user_id] = 2
231
    assert_no_difference 'Attachment.count' do
232
      put :update, :params => {
233
          :id => 1,
234
          :document => {
235
            :title => ''
236
          },
237
          :attachments => {
238
            '1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}
239
          }
240
        }
241
    end
242
    assert_response :success
243
    assert_select_error /title cannot be blank/i
244
  end
245

  
246
  def test_update_with_deleted_attachment_ids
247
    set_tmp_attachments_directory
223 248
    @request.session[:user_id] = 2
224
    put :update, :params => {
249
    document = Document.find(1)
250
    attachment = document.attachments.first
251
    assert_difference 'Attachment.count', -1 do
252
      put :update, :params => {
225 253
        :id => 1,
226 254
        :document => {
227
          :title => ''
255
          :title => 'test_update',
256
          :deleted_attachment_ids => [attachment.id]
228 257
        }
229 258
      }
230
    assert_response :success
231
    assert_select_error /title cannot be blank/i
259
    end
260
    document.reload
261
    refute_includes document.attachments, attachment
262
  end
263

  
264
  def test_update_with_deleted_attachment_ids_and_failure_should_preserve_selected_attachments
265
    set_tmp_attachments_directory
266
    @request.session[:user_id] = 2
267
    document = Document.find(1)
268
    attachment = document.attachments.first
269
    assert_no_difference 'Attachment.count' do
270
      put :update, :params => {
271
        :id => 1,
272
        :document => {
273
          :title => '',
274
          :deleted_attachment_ids => [attachment.id]
275
        }
276
      }
277
    end
278
    document.reload
279
    assert_includes document.attachments, attachment
232 280
  end
233 281

  
234 282
  def test_destroy
(2-2/4)