##// END OF EJS Templates
custom_field.possible_values is now serialized (no longer pipe separated)...
Jean-Philippe Lang -
r220:8316e786672d
parent child
Show More
@@ -0,0 +1,13
1 class SerializePossiblesValues < ActiveRecord::Migration
2 def self.up
3 CustomField.find(:all).each do |field|
4 if field.possible_values and field.possible_values.is_a? String
5 field.possible_values = field.possible_values.split('|')
6 field.save
7 end
8 end
9 end
10
11 def self.down
12 end
13 end
@@ -1,77 +1,77
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module CustomFieldsHelper
18 module CustomFieldsHelper
19
19
20 # Return custom field html tag corresponding to its format
20 # Return custom field html tag corresponding to its format
21 def custom_field_tag(custom_value)
21 def custom_field_tag(custom_value)
22 custom_field = custom_value.custom_field
22 custom_field = custom_value.custom_field
23 field_name = "custom_fields[#{custom_field.id}]"
23 field_name = "custom_fields[#{custom_field.id}]"
24 field_id = "custom_fields_#{custom_field.id}"
24 field_id = "custom_fields_#{custom_field.id}"
25
25
26 case custom_field.field_format
26 case custom_field.field_format
27 when "string", "int"
27 when "string", "int"
28 text_field 'custom_value', 'value', :name => field_name, :id => field_id
28 text_field 'custom_value', 'value', :name => field_name, :id => field_id
29 when "date"
29 when "date"
30 text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) +
30 text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) +
31 calendar_for(field_id)
31 calendar_for(field_id)
32 when "text"
32 when "text"
33 text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3
33 text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3
34 when "bool"
34 when "bool"
35 check_box 'custom_value', 'value', :name => field_name, :id => field_id
35 check_box 'custom_value', 'value', :name => field_name, :id => field_id
36 when "list"
36 when "list"
37 select 'custom_value', 'value', custom_field.possible_values.split('|'), { :include_blank => true }, :name => field_name, :id => field_id
37 select 'custom_value', 'value', custom_field.possible_values, { :include_blank => true }, :name => field_name, :id => field_id
38 end
38 end
39 end
39 end
40
40
41 # Return custom field label tag
41 # Return custom field label tag
42 def custom_field_label_tag(custom_value)
42 def custom_field_label_tag(custom_value)
43 content_tag "label", custom_value.custom_field.name +
43 content_tag "label", custom_value.custom_field.name +
44 (custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
44 (custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
45 :for => "custom_fields_#{custom_value.custom_field.id}",
45 :for => "custom_fields_#{custom_value.custom_field.id}",
46 :class => (custom_value.errors.empty? ? nil : "error" )
46 :class => (custom_value.errors.empty? ? nil : "error" )
47 end
47 end
48
48
49 # Return custom field tag with its label tag
49 # Return custom field tag with its label tag
50 def custom_field_tag_with_label(custom_value)
50 def custom_field_tag_with_label(custom_value)
51 custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
51 custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
52 end
52 end
53
53
54 # Return a string used to display a custom value
54 # Return a string used to display a custom value
55 def show_value(custom_value)
55 def show_value(custom_value)
56 return "" unless custom_value
56 return "" unless custom_value
57 format_value(custom_value.value, custom_value.custom_field.field_format)
57 format_value(custom_value.value, custom_value.custom_field.field_format)
58 end
58 end
59
59
60 # Return a string used to display a custom value
60 # Return a string used to display a custom value
61 def format_value(value, field_format)
61 def format_value(value, field_format)
62 return "" unless value
62 return "" unless value
63 case field_format
63 case field_format
64 when "date"
64 when "date"
65 value.empty? ? "" : l_date(value.to_date)
65 value.empty? ? "" : l_date(value.to_date)
66 when "bool"
66 when "bool"
67 l_YesNo(value == "1")
67 l_YesNo(value == "1")
68 else
68 else
69 value
69 value
70 end
70 end
71 end
71 end
72
72
73 # Return an array of custom field formats which can be used in select_tag
73 # Return an array of custom field formats which can be used in select_tag
74 def custom_field_formats_for_select
74 def custom_field_formats_for_select
75 CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
75 CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
76 end
76 end
77 end
77 end
@@ -1,43 +1,60
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class CustomField < ActiveRecord::Base
18 class CustomField < ActiveRecord::Base
19 has_many :custom_values, :dependent => :delete_all
19 has_many :custom_values, :dependent => :delete_all
20
20 serialize :possible_values
21
21 FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
22 FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
22 "text" => { :name => :label_text, :order => 2 },
23 "text" => { :name => :label_text, :order => 2 },
23 "int" => { :name => :label_integer, :order => 3 },
24 "int" => { :name => :label_integer, :order => 3 },
24 "list" => { :name => :label_list, :order => 4 },
25 "list" => { :name => :label_list, :order => 4 },
25 "date" => { :name => :label_date, :order => 5 },
26 "date" => { :name => :label_date, :order => 5 },
26 "bool" => { :name => :label_boolean, :order => 6 }
27 "bool" => { :name => :label_boolean, :order => 6 }
27 }.freeze
28 }.freeze
28
29
29 validates_presence_of :name, :field_format
30 validates_presence_of :name, :field_format
30 validates_uniqueness_of :name
31 validates_uniqueness_of :name
31 validates_format_of :name, :with => /^[\w\s\'\-]*$/i
32 validates_format_of :name, :with => /^[\w\s\'\-]*$/i
32 validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys
33 validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys
33 validates_presence_of :possible_values, :if => Proc.new { |field| field.field_format == "list" }
34
35 def initialize(attributes = nil)
36 super
37 self.possible_values ||= []
38 end
39
40 def before_validation
41 # remove empty values
42 self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
43 end
44
45 def validate
46 if self.field_format == "list"
47 errors.add(:possible_values, :activerecord_error_blank) if self.possible_values.nil? || self.possible_values.empty?
48 errors.add(:possible_values, :activerecord_error_invalid) unless self.possible_values.is_a? Array
49 end
50 end
34
51
35 # to move in project_custom_field
52 # to move in project_custom_field
36 def self.for_all
53 def self.for_all
37 find(:all, :conditions => ["is_for_all=?", true])
54 find(:all, :conditions => ["is_for_all=?", true])
38 end
55 end
39
56
40 def type_name
57 def type_name
41 nil
58 nil
42 end
59 end
43 end
60 end
@@ -1,38 +1,38
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class CustomValue < ActiveRecord::Base
18 class CustomValue < ActiveRecord::Base
19 belongs_to :custom_field
19 belongs_to :custom_field
20 belongs_to :customized, :polymorphic => true
20 belongs_to :customized, :polymorphic => true
21
21
22 protected
22 protected
23 def validate
23 def validate
24 errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty?
24 errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty?
25 errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp)
25 errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp)
26 errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0
26 errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0
27 errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
27 errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
28 case custom_field.field_format
28 case custom_field.field_format
29 when "int"
29 when "int"
30 errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/
30 errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/
31 when "date"
31 when "date"
32 errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
32 errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
33 when "list"
33 when "list"
34 errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.split('|').include? value or value.empty?
34 errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty?
35 end
35 end
36 end
36 end
37 end
37 end
38
38
@@ -1,70 +1,95
1 <%= error_messages_for 'custom_field' %>
1 <%= error_messages_for 'custom_field' %>
2
2
3 <script>
3 <script type="text/javascript">
4 //<![CDATA[
4 function toggle_custom_field_format() {
5 function toggle_custom_field_format() {
5 format = $("custom_field_field_format");
6 format = $("custom_field_field_format");
6 p_length = $("custom_field_min_length");
7 p_length = $("custom_field_min_length");
7 p_regexp = $("custom_field_regexp");
8 p_regexp = $("custom_field_regexp");
8 p_values = $("custom_field_possible_values");
9 p_values = $("custom_field_possible_values");
9 switch (format.value) {
10 switch (format.value) {
10 case "list":
11 case "list":
11 Element.hide(p_length.parentNode);
12 Element.hide(p_length.parentNode);
12 Element.hide(p_regexp.parentNode);
13 Element.hide(p_regexp.parentNode);
13 Element.show(p_values.parentNode);
14 Element.show(p_values);
14 break;
15 break;
15 case "int":
16 case "int":
16 case "string":
17 case "string":
17 case "text":
18 case "text":
18 Element.show(p_length.parentNode);
19 Element.show(p_length.parentNode);
19 Element.show(p_regexp.parentNode);
20 Element.show(p_regexp.parentNode);
20 Element.hide(p_values.parentNode);
21 Element.hide(p_values);
21 break;
22 break;
22 case "date":
23 case "date":
23 case "bool":
24 case "bool":
24 Element.hide(p_length.parentNode);
25 Element.hide(p_length.parentNode);
25 Element.hide(p_regexp.parentNode);
26 Element.hide(p_regexp.parentNode);
26 Element.hide(p_values.parentNode);
27 Element.hide(p_values);
27 break;
28 break;
28 default:
29 default:
29 Element.show(p_length.parentNode);
30 Element.show(p_length.parentNode);
30 Element.show(p_regexp.parentNode);
31 Element.show(p_regexp.parentNode);
31 Element.show(p_values.parentNode);
32 Element.show(p_values);
32 break;
33 break;
33 }
34 }
34 }
35 }
36
37 function addValueField() {
38 var f = $$('p#custom_field_possible_values span');
39 p = document.getElementById("custom_field_possible_values");
40 var v = f[0].cloneNode(true);
41 v.childNodes[0].value = "";
42 p.appendChild(v);
43 }
44
45 function deleteValueField(e) {
46 var f = $$('p#custom_field_possible_values span');
47 if (f.length == 1) {
48 e.parentNode.childNodes[0].value = "";
49 } else {
50 Element.remove(e.parentNode);
51 }
52 }
53
54 //]]>
35 </script>
55 </script>
36
56
37 <!--[form:custom_field]-->
57 <!--[form:custom_field]-->
38 <div class="box">
58 <div class="box">
39 <p><%= f.text_field :name, :required => true %></p>
59 <p><%= f.text_field :name, :required => true %></p>
40 <p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p>
60 <p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p>
41 <p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label>
61 <p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label>
42 <%= f.text_field :min_length, :size => 5, :no_label => true %> -
62 <%= f.text_field :min_length, :size => 5, :no_label => true %> -
43 <%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p>
63 <%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p>
44 <p><%= f.text_field :regexp, :size => 50 %><br>(<%=l(:text_regexp_info)%>)</p>
64 <p><%= f.text_field :regexp, :size => 50 %><br>(<%=l(:text_regexp_info)%>)</p>
45 <p><%= f.text_area :possible_values, :rows => 5, :cols => 60 %><br>(<%=l(:text_possible_values_info)%>)</p>
65 <p id="custom_field_possible_values"><label><%= l(:field_possible_values) %> <%= image_to_function "add.png", "addValueField();return false" %></label>
66 <% (@custom_field.possible_values.to_a + [""]).each do |value| %>
67 <span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span>
68 <% end %>
69
70 </p>
46 </div>
71 </div>
47 <%= javascript_tag "toggle_custom_field_format();" %>
72 <%= javascript_tag "toggle_custom_field_format();" %>
48 <!--[eoform:custom_field]-->
73 <!--[eoform:custom_field]-->
49
74
50 <div class="box">
75 <div class="box">
51 <% case @custom_field.type.to_s
76 <% case @custom_field.type.to_s
52 when "IssueCustomField" %>
77 when "IssueCustomField" %>
53
78
54 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
79 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
55 <% for tracker in @trackers %>
80 <% for tracker in @trackers %>
56 <%= check_box_tag "tracker_ids[]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %>
81 <%= check_box_tag "tracker_ids[]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %>
57 <% end %>
82 <% end %>
58 </fieldset>
83 </fieldset>
59 &nbsp;
84 &nbsp;
60 <p><%= f.check_box :is_required %></p>
85 <p><%= f.check_box :is_required %></p>
61 <p><%= f.check_box :is_for_all %></p>
86 <p><%= f.check_box :is_for_all %></p>
62
87
63 <% when "UserCustomField" %>
88 <% when "UserCustomField" %>
64 <p><%= f.check_box :is_required %></p>
89 <p><%= f.check_box :is_required %></p>
65
90
66 <% when "ProjectCustomField" %>
91 <% when "ProjectCustomField" %>
67 <p><%= f.check_box :is_required %></p>
92 <p><%= f.check_box :is_required %></p>
68
93
69 <% end %>
94 <% end %>
70 </div>
95 </div>
General Comments 0
You need to be logged in to leave comments. Login now