]> source.dussan.org Git - redmine.git/commitdiff
Create custom field by copy (#34307).
authorGo MAEDA <maeda@farend.jp>
Sat, 26 Dec 2020 01:36:19 +0000 (01:36 +0000)
committerGo MAEDA <maeda@farend.jp>
Sat, 26 Dec 2020 01:36:19 +0000 (01:36 +0000)
Patch by Takenori TAKAKI.

git-svn-id: http://svn.redmine.org/redmine/trunk@20692 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/custom_fields_controller.rb
app/models/custom_field.rb
app/views/custom_fields/_index.html.erb
app/views/custom_fields/new.html.erb
test/functional/custom_fields_controller_test.rb
test/unit/custom_field_test.rb

index 893bc481985e53c767a1cf89dfa64a58ad17e0f2..41a41ebe96c362e0089f5e2a636e92b749abc0b1 100644 (file)
@@ -98,6 +98,9 @@ class CustomFieldsController < ApplicationController
     if @custom_field.nil?
       render :action => 'select_type'
     else
+      if params[:copy].present? && (@copy_from = CustomField.find_by(id: params[:copy]))
+        @custom_field.copy_from(@copy_from)
+      end
       @custom_field.safe_attributes = params[:custom_field]
     end
   end
index e0ea10cc8b1b993a09d2a86039be6d8b87098237..816a52fb81ecfb049cc94e34844728699a46287e 100644 (file)
@@ -102,6 +102,26 @@ class CustomField < ActiveRecord::Base
     'extensions_allowed',
     'full_width_layout')
 
+  def copy_from(arg, options={})
+    return if arg.blank?
+
+    custom_field = arg.is_a?(CustomField) ? arg : CustomField.find_by(id: arg.to_s)
+    self.attributes = custom_field.attributes.dup.except('id', 'name', 'position')
+    custom_field.enumerations.each do |e|
+      new_enumeration = self.enumerations.build
+      new_enumeration.attributes = e.attributes.except('id')
+    end
+    self.default_value = nil if custom_field.enumerations.any?
+    if %w(IssueCustomField TimeEntryCustomField ProjectCustomField VersionCustomField).include?(self.class.name)
+      self.role_ids = custom_field.role_ids.dup
+    end
+    if self.is_a?(IssueCustomField)
+      self.tracker_ids = custom_field.tracker_ids.dup
+      self.project_ids = custom_field.project_ids.dup
+    end
+    self
+  end
+
   def format
     @format ||= Redmine::FieldFormat.find(field_format)
   end
index 04d4aa21d4c690fb57b553058cdb01a96582ca02..81fe21404341bbee495e540e5c274fbd8e8f9cae 100644 (file)
@@ -22,6 +22,7 @@
       <% end %>
       <td class="buttons">
         <%= reorder_handle(custom_field, :url => custom_field_path(custom_field), :param => 'custom_field') %>
+        <%= link_to_function l(:button_copy), "location.href = '#{new_custom_field_path(:copy => custom_field)}&type=' + encodeURIComponent(($('.tabs a.selected').attr('id')||'').split('tab-').pop())", :class => 'icon icon-copy' %>
         <%= delete_link custom_field_path(custom_field) %>
       </td>
     </tr>
index db422296b3c170cdceb5b5160fcff03f418599ec..45b5cc0cf2c6506fc26053628c99e4784cad0b6e 100644 (file)
@@ -3,6 +3,7 @@
 <%= labelled_form_for :custom_field, @custom_field, :url => custom_fields_path, :html => {:id => 'custom_field_form'} do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= hidden_field_tag 'type', @custom_field.type %>
+<%= hidden_field_tag 'copy', @copy_from.id if @copy_from %>
 <% end %>
 
 <%= javascript_tag do %>
index fd042dea68d1e1ab16d0c2ac00cebf1ea8e5028d..a2ca380835e5d440486e9d87ae2989aa88859524 100644 (file)
@@ -325,6 +325,56 @@ class CustomFieldsControllerTest < Redmine::ControllerTest
     assert_select 'input[type=radio][name=type]'
   end
 
+  def test_new_with_copy
+    role_ids = [1, 2]
+    tracker_ids = [1, 2]
+    project_ids = [1, 2, 3]
+
+    copy_from = CustomField.find(1)
+    copy_from.role_ids = role_ids
+    copy_from.tracker_ids = tracker_ids
+    copy_from.project_ids = project_ids
+    copy_from.save
+
+    get :new, :params => {:copy => copy_from.id.to_s, :type => IssueCustomField}
+    assert_response :success
+
+    assert_select 'form' do
+      # field_format selected
+      assert_select 'select[name=?]', 'custom_field[field_format]' do
+        assert_select "option[value=\"#{copy_from.field_format}\"][selected=selected]"
+      end
+      # blank name
+      assert_select 'input[name=?][value=""]', 'custom_field[name]'
+      # description copied
+      assert_select 'textarea[name=?]', 'custom_field[description]', :text => copy_from.description
+      # role checked
+      role_ids.each do |role_id|
+        assert_select "input[type=checkbox][name=?][value=#{role_id}][checked=checked]", 'custom_field[role_ids][]'
+      end
+      # role not checked
+      (Role.givable.pluck(:id) - role_ids).each do |role_id|
+        assert_select "input[type=checkbox][name=?][value=#{role_id}]", 'custom_field[role_ids][]'
+      end
+      # tracker checked
+      tracker_ids.each do |tracker_id|
+        assert_select "input[type=checkbox][name=?][value=#{tracker_id}][checked=checked]", 'custom_field[tracker_ids][]'
+      end
+      # tracker not checked
+      (Tracker.all.pluck(:id) - tracker_ids).each do |tracker_id|
+        assert_select "input[type=checkbox][name=?][value=#{tracker_id}]", 'custom_field[tracker_ids][]'
+      end
+      # project checked
+      project_ids.each do |project_id|
+        assert_select "input[type=checkbox][name=?][value=#{project_id}][checked=checked]", 'custom_field[project_ids][]'
+      end
+      # project not checked
+      (Project.all.pluck(:id) - project_ids).each do |project_id|
+        assert_select "input[type=checkbox][name=?][value=#{project_id}]", 'custom_field[project_ids][]'
+      end
+    end
+  end
+
   def test_create_list_custom_field
     field = new_record(IssueCustomField) do
       post(
@@ -449,6 +499,29 @@ class CustomFieldsControllerTest < Redmine::ControllerTest
     assert_select 'input[type=radio][name=type]'
   end
 
+  def test_create_with_enumerations
+    custom_field = IssueCustomField.create(:field_format => 'enumeration', :name => 'IssueCustomField')
+    custom_field.enumerations.build(:name => 'enumeration1', :position => 1)
+    custom_field.enumerations.build(:name => 'enumeration2', :position => 2)
+    assert custom_field.save
+
+    assert_difference 'CustomField.count' do
+      post(
+        :create,
+        :params => {
+          :type => 'IssueCustomField',
+          :copy => custom_field.id,
+          :custom_field => {:name => 'Copy'}
+        }
+      )
+      assert_response 302
+    end
+    field = IssueCustomField.order('id desc').first
+    assert_equal 'Copy', field.name
+    assert_equal ['enumeration1', 'enumeration2'], field.enumerations.pluck(:name).sort
+    assert_equal [1, 2], field.enumerations.pluck(:position).sort
+  end
+
   def test_edit
     get(
       :edit,
index f5d8e80276e9fffaeec141255ca3bb7da5e37987..3e18512d6dc3a60dbf6bd19358a135ad7eb19db2 100644 (file)
@@ -372,4 +372,53 @@ class CustomFieldTest < ActiveSupport::TestCase
     field2 = IssueCustomField.create!(:name => 'Another long text', :field_format => 'text')
     assert !field2.full_text_formatting?
   end
+
+  def test_copy_from
+    custom_field = CustomField.find(1)
+    copy = CustomField.new.copy_from(custom_field)
+
+    assert_nil copy.id
+    assert_equal '', copy.name
+    assert_nil copy.position
+    (custom_field.attribute_names - ['id', 'name', 'position']).each do |attribute_name|
+      assert_equal custom_field.send(attribute_name).to_s, copy.send(attribute_name).to_s
+    end
+
+    copy.name = 'Copy'
+    assert copy.save
+  end
+
+  def test_copy_from_should_copy_enumerations
+    custom_field = CustomField.create(:field_format => 'enumeration', :name => 'CustomField')
+    custom_field.enumerations.build(:name => 'enumeration1', :position => 1)
+    custom_field.enumerations.build(:name => 'enumeration2', :position => 2)
+    assert custom_field.save
+
+    copy = CustomField.new.copy_from(custom_field)
+    copy.name = 'Copy'
+    assert copy.save
+    assert_equal ['enumeration1', 'enumeration2'], copy.enumerations.pluck(:name)
+    assert_equal [1, 2], copy.enumerations.pluck(:position)
+  end
+
+  def test_copy_from_should_copy_roles
+    %w(IssueCustomField TimeEntryCustomField ProjectCustomField VersionCustomField).each do |klass_name|
+      klass = klass_name.constantize
+      custom_field = klass.new(:name => klass_name, :role_ids => [1, 2, 3, 4, 5])
+      copy = klass.new.copy_from(custom_field)
+      assert_equal [1, 2, 3, 4, 5], copy.role_ids.sort
+    end
+  end
+
+  def test_copy_from_should_copy_trackers
+    issue_custom_field = IssueCustomField.new(:name => 'IssueCustomField', :tracker_ids => [1, 2, 3])
+    copy = IssueCustomField.new.copy_from(issue_custom_field)
+    assert_equal [1, 2, 3], copy.tracker_ids
+  end
+
+  def test_copy_from_should_copy_projects
+    issue_custom_field = IssueCustomField.new(:name => 'IssueCustomField', :project_ids => [1, 2, 3, 4, 5, 6])
+    copy = IssueCustomField.new.copy_from(issue_custom_field)
+    assert_equal [1, 2, 3, 4, 5, 6], copy.project_ids
+  end
 end