mirror of
https://github.com/redmine/redmine.git
synced 2025-11-02 11:25:55 +01:00
Adds Enumeration custom field format (#21060).
Similar to List format but stores possible values as records. git-svn-id: http://svn.redmine.org/redmine/trunk@14745 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
69
app/controllers/custom_field_enumerations_controller.rb
Normal file
69
app/controllers/custom_field_enumerations_controller.rb
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2015 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
class CustomFieldEnumerationsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_filter :require_admin
|
||||||
|
before_filter :find_custom_field
|
||||||
|
before_filter :find_enumeration, :only => :destroy
|
||||||
|
|
||||||
|
def index
|
||||||
|
@values = @custom_field.enumerations.order(:position)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@value = @custom_field.enumerations.build(params[:custom_field_enumeration])
|
||||||
|
@value.save
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to custom_field_enumerations_path(@custom_field) }
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_each
|
||||||
|
if CustomFieldEnumeration.update_each(@custom_field, params[:custom_field_enumerations])
|
||||||
|
flash[:notice] = l(:notice_successful_update)
|
||||||
|
end
|
||||||
|
redirect_to :action => 'index'
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
reassign_to = @custom_field.enumerations.find_by_id(params[:reassign_to_id])
|
||||||
|
if reassign_to.nil? && @value.in_use?
|
||||||
|
@enumerations = @custom_field.enumerations - [@value]
|
||||||
|
render :action => 'destroy'
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@value.destroy(reassign_to)
|
||||||
|
redirect_to custom_field_enumerations_path(@custom_field)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_custom_field
|
||||||
|
@custom_field = CustomField.find(params[:custom_field_id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_enumeration
|
||||||
|
@value = @custom_field.enumerations.find(params[:id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -18,6 +18,10 @@
|
|||||||
class CustomField < ActiveRecord::Base
|
class CustomField < ActiveRecord::Base
|
||||||
include Redmine::SubclassFactory
|
include Redmine::SubclassFactory
|
||||||
|
|
||||||
|
has_many :enumerations,
|
||||||
|
lambda { order(:position) },
|
||||||
|
:class_name => 'CustomFieldEnumeration',
|
||||||
|
:dependent => :delete_all
|
||||||
has_many :custom_values, :dependent => :delete_all
|
has_many :custom_values, :dependent => :delete_all
|
||||||
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
|
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
|
||||||
acts_as_list :scope => 'type = \'#{self.class}\''
|
acts_as_list :scope => 'type = \'#{self.class}\''
|
||||||
|
|||||||
74
app/models/custom_field_enumeration.rb
Normal file
74
app/models/custom_field_enumeration.rb
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2015 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
class CustomFieldEnumeration < ActiveRecord::Base
|
||||||
|
belongs_to :custom_field
|
||||||
|
attr_accessible :name, :active, :position
|
||||||
|
|
||||||
|
validates_presence_of :name, :position, :custom_field_id
|
||||||
|
validates_length_of :name, :maximum => 60
|
||||||
|
validates_numericality_of :position, :only_integer => true
|
||||||
|
before_create :set_position
|
||||||
|
|
||||||
|
scope :active, lambda { where(:active => true) }
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
name.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def objects_count
|
||||||
|
custom_values.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def in_use?
|
||||||
|
objects_count > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
alias :destroy_without_reassign :destroy
|
||||||
|
def destroy(reassign_to=nil)
|
||||||
|
if reassign_to
|
||||||
|
custom_values.update_all(:value => reassign_to.id.to_s)
|
||||||
|
end
|
||||||
|
destroy_without_reassign
|
||||||
|
end
|
||||||
|
|
||||||
|
def custom_values
|
||||||
|
custom_field.custom_values.where(:value => id.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.update_each(custom_field, attributes)
|
||||||
|
return unless attributes.is_a?(Hash)
|
||||||
|
transaction do
|
||||||
|
attributes.each do |enumeration_id, enumeration_attributes|
|
||||||
|
enumeration = custom_field.enumerations.find_by_id(enumeration_id)
|
||||||
|
if enumeration
|
||||||
|
enumeration.attributes = enumeration_attributes
|
||||||
|
unless enumeration.save
|
||||||
|
raise ActiveRecord::Rollback
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_position
|
||||||
|
max = self.class.where(:custom_field_id => custom_field_id).maximum(:position) || 0
|
||||||
|
self.position = max + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
2
app/views/custom_field_enumerations/create.js.erb
Normal file
2
app/views/custom_field_enumerations/create.js.erb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
$('#content').html('<%= escape_javascript(render(:template => 'custom_field_enumerations/index')) %>');
|
||||||
|
$('#custom_field_enumeration_name').focus();
|
||||||
14
app/views/custom_field_enumerations/destroy.html.erb
Normal file
14
app/views/custom_field_enumerations/destroy.html.erb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<%= title [l(:label_custom_field_plural), custom_fields_path],
|
||||||
|
[l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
|
||||||
|
@custom_field.name %>
|
||||||
|
|
||||||
|
<%= form_tag(custom_field_enumeration_path(@custom_field, @value), :method => :delete) do %>
|
||||||
|
<div class="box">
|
||||||
|
<p><strong><%= l(:text_enumeration_destroy_question, :name => @value.name, :count => @value.objects_count) %></strong></p>
|
||||||
|
<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
|
||||||
|
<%= select_tag('reassign_to_id', content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---", :value => '') + options_from_collection_for_select(@enumerations, 'id', 'name')) %></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= submit_tag l(:button_apply) %>
|
||||||
|
<%= link_to l(:button_cancel), custom_field_enumerations_path(@custom_field) %>
|
||||||
|
<% end %>
|
||||||
49
app/views/custom_field_enumerations/index.html.erb
Normal file
49
app/views/custom_field_enumerations/index.html.erb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<%= title [l(:label_custom_field_plural), custom_fields_path],
|
||||||
|
[l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
|
||||||
|
@custom_field.name %>
|
||||||
|
|
||||||
|
<% if @custom_field.enumerations.any? %>
|
||||||
|
<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'put' do %>
|
||||||
|
<div class="box">
|
||||||
|
<ul id="custom_field_enumerations" class="flat">
|
||||||
|
<% @custom_field.enumerations.each_with_index do |value, position| %>
|
||||||
|
<li>
|
||||||
|
<span class="sort-handle ui-icon ui-icon-arrowthick-2-n-s"></span>
|
||||||
|
<%= hidden_field_tag "custom_field_enumerations[#{value.id}][position]", position, :class => 'position' %>
|
||||||
|
<%= text_field_tag "custom_field_enumerations[#{value.id}][name]", value.name, :size => 40 %>
|
||||||
|
<%= hidden_field_tag "custom_field_enumerations[#{value.id}][active]", 0 %>
|
||||||
|
<label>
|
||||||
|
<%= check_box_tag "custom_field_enumerations[#{value.id}][active]", 1, value.active? %>
|
||||||
|
<%= l(:field_active) %>
|
||||||
|
</label>
|
||||||
|
<%= delete_link custom_field_enumeration_path(@custom_field, value) %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<%= submit_tag(l(:button_save)) %> |
|
||||||
|
<%= link_to l(:button_back), edit_custom_field_path(@custom_field) %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<p><%= l(:label_enumeration_new) %></p>
|
||||||
|
|
||||||
|
<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'post', :remote => true do %>
|
||||||
|
<p><%= text_field_tag 'custom_field_enumeration[name]', '', :size => 40 %>
|
||||||
|
<%= submit_tag(l(:button_add)) %></p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= javascript_tag do %>
|
||||||
|
$(function() {
|
||||||
|
$("#custom_field_enumerations").sortable({
|
||||||
|
handle: ".sort-handle",
|
||||||
|
update: function(event, ui) {
|
||||||
|
$("#custom_field_enumerations li").each(function(){
|
||||||
|
$(this).find("input.position").val($(this).index()+1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
<% end %>
|
||||||
12
app/views/custom_fields/formats/_enumeration.erb
Normal file
12
app/views/custom_fields/formats/_enumeration.erb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<% unless @custom_field.new_record? %>
|
||||||
|
<p>
|
||||||
|
<label><%= l(:field_possible_values) %></label>
|
||||||
|
<%= link_to l(:button_edit), custom_field_enumerations_path(@custom_field), :class => 'icon icon-edit' %>
|
||||||
|
</p>
|
||||||
|
<% if @custom_field.enumerations.active.any? %>
|
||||||
|
<p><%= f.select :default_value, @custom_field.enumerations.active.map{|v| [v.name, v.id.to_s]}, :include_blank => true %></p>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<p><%= f.text_field :url_pattern, :size => 50, :label => :label_link_values_to %></p>
|
||||||
|
<p><%= edit_tag_style_tag f %></p>
|
||||||
@@ -970,6 +970,7 @@ en:
|
|||||||
label_file_content_preview: File content preview
|
label_file_content_preview: File content preview
|
||||||
label_create_missing_values: Create missing values
|
label_create_missing_values: Create missing values
|
||||||
label_api: API
|
label_api: API
|
||||||
|
label_field_format_enumeration: Key/value list
|
||||||
|
|
||||||
button_login: Login
|
button_login: Login
|
||||||
button_submit: Submit
|
button_submit: Submit
|
||||||
|
|||||||
@@ -988,6 +988,7 @@ fr:
|
|||||||
label_file_content_preview: Aperçu du contenu du fichier
|
label_file_content_preview: Aperçu du contenu du fichier
|
||||||
label_create_missing_values: Créer les valeurs manquantes
|
label_create_missing_values: Créer les valeurs manquantes
|
||||||
label_api: API
|
label_api: API
|
||||||
|
label_field_format_enumeration: Liste clé/valeur
|
||||||
|
|
||||||
button_login: Connexion
|
button_login: Connexion
|
||||||
button_submit: Soumettre
|
button_submit: Soumettre
|
||||||
|
|||||||
@@ -311,7 +311,10 @@ Rails.application.routes.draw do
|
|||||||
post 'update_issue_done_ratio'
|
post 'update_issue_done_ratio'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :custom_fields, :except => :show
|
resources :custom_fields, :except => :show do
|
||||||
|
resources :enumerations, :controller => 'custom_field_enumerations', :except => [:show, :new, :edit]
|
||||||
|
put 'enumerations', :to => 'custom_field_enumerations#update_each'
|
||||||
|
end
|
||||||
resources :roles do
|
resources :roles do
|
||||||
collection do
|
collection do
|
||||||
match 'permissions', :via => [:get, :post]
|
match 'permissions', :via => [:get, :post]
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class CreateCustomFieldEnumerations < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :custom_field_enumerations do |t|
|
||||||
|
t.integer :custom_field_id, :null => false
|
||||||
|
t.string :name, :null => false
|
||||||
|
t.boolean :active, :default => true, :null => false
|
||||||
|
t.integer :position, :default => 1, :null => false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -539,7 +539,7 @@ module Redmine
|
|||||||
add 'list'
|
add 'list'
|
||||||
self.searchable_supported = true
|
self.searchable_supported = true
|
||||||
self.form_partial = 'custom_fields/formats/list'
|
self.form_partial = 'custom_fields/formats/list'
|
||||||
|
|
||||||
def possible_custom_value_options(custom_value)
|
def possible_custom_value_options(custom_value)
|
||||||
options = possible_values_options(custom_value.custom_field)
|
options = possible_values_options(custom_value.custom_field)
|
||||||
missing = [custom_value.value].flatten.reject(&:blank?) - options
|
missing = [custom_value.value].flatten.reject(&:blank?) - options
|
||||||
@@ -636,7 +636,6 @@ module Redmine
|
|||||||
missing = [custom_value.value_was].flatten.reject(&:blank?) - options.map(&:last)
|
missing = [custom_value.value_was].flatten.reject(&:blank?) - options.map(&:last)
|
||||||
if missing.any?
|
if missing.any?
|
||||||
options += target_class.where(:id => missing.map(&:to_i)).map {|o| [o.to_s, o.id.to_s]}
|
options += target_class.where(:id => missing.map(&:to_i)).map {|o| [o.to_s, o.id.to_s]}
|
||||||
options.sort_by!(&:first)
|
|
||||||
end
|
end
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
@@ -674,6 +673,32 @@ module Redmine
|
|||||||
protected :value_join_alias
|
protected :value_join_alias
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class EnumerationFormat < RecordList
|
||||||
|
add 'enumeration'
|
||||||
|
self.form_partial = 'custom_fields/formats/enumeration'
|
||||||
|
|
||||||
|
def label
|
||||||
|
"label_field_format_enumeration"
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_class
|
||||||
|
@target_class ||= CustomFieldEnumeration
|
||||||
|
end
|
||||||
|
|
||||||
|
def possible_values_options(custom_field, object=nil)
|
||||||
|
possible_values_records(custom_field, object).map {|u| [u.name, u.id.to_s]}
|
||||||
|
end
|
||||||
|
|
||||||
|
def possible_values_records(custom_field, object=nil)
|
||||||
|
custom_field.enumerations.active
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_from_keyword(custom_field, keyword, object)
|
||||||
|
value = custom_field.enumerations.where("LOWER(name) LIKE LOWER(?)", keyword)
|
||||||
|
value ? value.id : nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class UserFormat < RecordList
|
class UserFormat < RecordList
|
||||||
add 'user'
|
add 'user'
|
||||||
self.form_partial = 'custom_fields/formats/user'
|
self.form_partial = 'custom_fields/formats/user'
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ pre, code {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
|
|||||||
#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
|
#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
|
||||||
* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
|
* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
|
||||||
#sidebar .contextual { margin-right: 1em; }
|
#sidebar .contextual { margin-right: 1em; }
|
||||||
#sidebar ul {margin: 0; padding: 0;}
|
#sidebar ul, ul.flat {margin: 0; padding: 0;}
|
||||||
#sidebar ul li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
|
#sidebar ul li, ul.flat li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
|
||||||
|
|
||||||
#content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
|
#content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
|
||||||
* html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
|
* html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
|
||||||
@@ -483,6 +483,7 @@ select.expandable {vertical-align:top;}
|
|||||||
|
|
||||||
textarea#custom_field_possible_values {width: 95%; resize:vertical}
|
textarea#custom_field_possible_values {width: 95%; resize:vertical}
|
||||||
textarea#custom_field_default_value {width: 95%; resize:vertical}
|
textarea#custom_field_default_value {width: 95%; resize:vertical}
|
||||||
|
.sort-handle {display:inline-block; vertical-align:middle;}
|
||||||
|
|
||||||
input#content_comments {width: 99%}
|
input#content_comments {width: 99%}
|
||||||
|
|
||||||
|
|||||||
111
test/functional/custom_field_enumerations_controller_test.rb
Normal file
111
test/functional/custom_field_enumerations_controller_test.rb
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2015 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
require File.expand_path('../../test_helper', __FILE__)
|
||||||
|
|
||||||
|
class CustomFieldEnumerationsControllerTest < ActionController::TestCase
|
||||||
|
fixtures :users, :email_addresses
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@request.session[:user_id] = 1
|
||||||
|
@field = GroupCustomField.create!(:name => 'List', :field_format => 'enumeration', :is_required => false)
|
||||||
|
@foo = CustomFieldEnumeration.new(:name => 'Foo')
|
||||||
|
@bar = CustomFieldEnumeration.new(:name => 'Bar')
|
||||||
|
@field.enumerations << @foo
|
||||||
|
@field.enumerations << @bar
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_index
|
||||||
|
get :index, :custom_field_id => @field.id
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'index'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
assert_difference 'CustomFieldEnumeration.count' do
|
||||||
|
post :create, :custom_field_id => @field.id, :custom_field_enumeration => { :name => 'Baz' }
|
||||||
|
assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 3, @field.reload.enumerations.count
|
||||||
|
enum = @field.enumerations.last
|
||||||
|
assert_equal 'Baz', enum.name
|
||||||
|
assert_equal true, enum.active
|
||||||
|
assert_equal 3, enum.position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create_xhr
|
||||||
|
assert_difference 'CustomFieldEnumeration.count' do
|
||||||
|
xhr :post, :create, :custom_field_id => @field.id, :custom_field_enumeration => { :name => 'Baz' }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_each
|
||||||
|
put :update_each, :custom_field_id => @field.id, :custom_field_enumerations => {
|
||||||
|
@bar.id => {:position => "1", :name => "Baz", :active => "1"},
|
||||||
|
@foo.id => {:position => "2", :name => "Foo", :active => "0"}
|
||||||
|
}
|
||||||
|
assert_response 302
|
||||||
|
|
||||||
|
@bar.reload
|
||||||
|
assert_equal "Baz", @bar.name
|
||||||
|
assert_equal true, @bar.active
|
||||||
|
assert_equal 1, @bar.position
|
||||||
|
|
||||||
|
@foo.reload
|
||||||
|
assert_equal "Foo", @foo.name
|
||||||
|
assert_equal false, @foo.active
|
||||||
|
assert_equal 2, @foo.position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_destroy
|
||||||
|
assert_difference 'CustomFieldEnumeration.count', -1 do
|
||||||
|
delete :destroy, :custom_field_id => @field.id, :id => @foo.id
|
||||||
|
assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 1, @field.reload.enumerations.count
|
||||||
|
enum = @field.enumerations.last
|
||||||
|
assert_equal 'Bar', enum.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_destroy_enumeration_in_use_should_display_destroy_form
|
||||||
|
group = Group.generate!
|
||||||
|
group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
|
||||||
|
group.save!
|
||||||
|
|
||||||
|
assert_no_difference 'CustomFieldEnumeration.count' do
|
||||||
|
delete :destroy, :custom_field_id => @field.id, :id => @foo.id
|
||||||
|
assert_response 200
|
||||||
|
assert_template 'destroy'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_destroy_enumeration_in_use_should_destroy_and_reassign_values
|
||||||
|
group = Group.generate!
|
||||||
|
group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
|
||||||
|
group.save!
|
||||||
|
|
||||||
|
assert_difference 'CustomFieldEnumeration.count', -1 do
|
||||||
|
delete :destroy, :custom_field_id => @field.id, :id => @foo.id, :reassign_to_id => @bar.id
|
||||||
|
assert_response 302
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal @bar.id.to_s, group.reload.custom_field_value(@field)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -27,4 +27,11 @@ class RoutingCustomFieldsTest < Redmine::RoutingTest
|
|||||||
should_route 'PUT /custom_fields/2' => 'custom_fields#update', :id => '2'
|
should_route 'PUT /custom_fields/2' => 'custom_fields#update', :id => '2'
|
||||||
should_route 'DELETE /custom_fields/2' => 'custom_fields#destroy', :id => '2'
|
should_route 'DELETE /custom_fields/2' => 'custom_fields#destroy', :id => '2'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_custom_field_enumerations
|
||||||
|
should_route 'GET /custom_fields/3/enumerations' => 'custom_field_enumerations#index', :custom_field_id => '3'
|
||||||
|
should_route 'POST /custom_fields/3/enumerations' => 'custom_field_enumerations#create', :custom_field_id => '3'
|
||||||
|
should_route 'PUT /custom_fields/3/enumerations' => 'custom_field_enumerations#update_each', :custom_field_id => '3'
|
||||||
|
should_route 'DELETE /custom_fields/3/enumerations/6' => 'custom_field_enumerations#destroy', :custom_field_id => '3', :id => '6'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2015 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
require File.expand_path('../../../../../test_helper', __FILE__)
|
||||||
|
require 'redmine/field_format'
|
||||||
|
|
||||||
|
class Redmine::EnumerationFieldFormatTest < ActionView::TestCase
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@field = IssueCustomField.create!(:name => 'List', :field_format => 'enumeration', :is_required => false)
|
||||||
|
@foo = CustomFieldEnumeration.new(:name => 'Foo')
|
||||||
|
@bar = CustomFieldEnumeration.new(:name => 'Bar')
|
||||||
|
@field.enumerations << @foo
|
||||||
|
@field.enumerations << @bar
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_tag_should_contain_possible_values
|
||||||
|
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
|
||||||
|
|
||||||
|
tag = @field.format.edit_tag(self, 'id', 'name', value)
|
||||||
|
assert_select_in tag, 'select' do
|
||||||
|
assert_select 'option', 3
|
||||||
|
assert_select 'option[value=""]'
|
||||||
|
assert_select 'option[value=?]', @foo.id.to_s, :text => 'Foo'
|
||||||
|
assert_select 'option[value=?]', @bar.id.to_s, :text => 'Bar'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_tag_should_select_current_value
|
||||||
|
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => @bar.id.to_s)
|
||||||
|
|
||||||
|
tag = @field.format.edit_tag(self, 'id', 'name', value)
|
||||||
|
assert_select_in tag, 'select' do
|
||||||
|
assert_select 'option[selected=selected]', 1
|
||||||
|
assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_tag_with_multiple_should_select_current_values
|
||||||
|
@field.multiple = true
|
||||||
|
@field.save!
|
||||||
|
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => [@foo.id.to_s, @bar.id.to_s])
|
||||||
|
|
||||||
|
tag = @field.format.edit_tag(self, 'id', 'name', value)
|
||||||
|
assert_select_in tag, 'select[multiple=multiple]' do
|
||||||
|
assert_select 'option[selected=selected]', 2
|
||||||
|
assert_select 'option[value=?][selected=selected]', @foo.id.to_s, :text => 'Foo'
|
||||||
|
assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_tag_with_check_box_style_should_contain_possible_values
|
||||||
|
@field.edit_tag_style = 'check_box'
|
||||||
|
@field.save!
|
||||||
|
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
|
||||||
|
|
||||||
|
tag = @field.format.edit_tag(self, 'id', 'name', value)
|
||||||
|
assert_select_in tag, 'span' do
|
||||||
|
assert_select 'input[type=radio]', 3
|
||||||
|
assert_select 'label', :text => '(none)' do
|
||||||
|
assert_select 'input[value=""]'
|
||||||
|
end
|
||||||
|
assert_select 'label', :text => 'Foo' do
|
||||||
|
assert_select 'input[value=?]', @foo.id.to_s
|
||||||
|
end
|
||||||
|
assert_select 'label', :text => 'Bar' do
|
||||||
|
assert_select 'input[value=?]', @bar.id.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user