##// END OF EJS Templates
Enumerations can now have custom fields defined on them. #4077...
Eric Davis -
r2831:ac4937a76755
parent child
Show More
@@ -0,0 +1,23
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 class DocumentCategoryCustomField < CustomField
19 def type_name
20 :enumeration_doc_categories
21 end
22 end
23
@@ -0,0 +1,23
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 class IssuePriorityCustomField < CustomField
19 def type_name
20 :enumeration_issue_priorities
21 end
22 end
23
@@ -0,0 +1,23
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 class TimeEntryActivityCustomField < CustomField
19 def type_name
20 :enumeration_time_entry_activities
21 end
22 end
23
@@ -1,84 +1,87
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class EnumerationsController < ApplicationController
19 19 before_filter :require_admin
20
21 helper :custom_fields
22 include CustomFieldsHelper
20 23
21 24 def index
22 25 list
23 26 render :action => 'list'
24 27 end
25 28
26 29 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
27 30 verify :method => :post, :only => [ :destroy, :create, :update ],
28 31 :redirect_to => { :action => :list }
29 32
30 33 def list
31 34 end
32 35
33 36 def new
34 37 begin
35 38 @enumeration = params[:type].constantize.new
36 39 rescue NameError
37 40 @enumeration = Enumeration.new
38 41 end
39 42 end
40 43
41 44 def create
42 45 @enumeration = Enumeration.new(params[:enumeration])
43 46 @enumeration.type = params[:enumeration][:type]
44 47 if @enumeration.save
45 48 flash[:notice] = l(:notice_successful_create)
46 49 redirect_to :action => 'list', :type => @enumeration.type
47 50 else
48 51 render :action => 'new'
49 52 end
50 53 end
51 54
52 55 def edit
53 56 @enumeration = Enumeration.find(params[:id])
54 57 end
55 58
56 59 def update
57 60 @enumeration = Enumeration.find(params[:id])
58 61 @enumeration.type = params[:enumeration][:type] if params[:enumeration][:type]
59 62 if @enumeration.update_attributes(params[:enumeration])
60 63 flash[:notice] = l(:notice_successful_update)
61 64 redirect_to :action => 'list', :type => @enumeration.type
62 65 else
63 66 render :action => 'edit'
64 67 end
65 68 end
66 69
67 70 def destroy
68 71 @enumeration = Enumeration.find(params[:id])
69 72 if !@enumeration.in_use?
70 73 # No associated objects
71 74 @enumeration.destroy
72 75 redirect_to :action => 'index'
73 76 elsif params[:reassign_to_id]
74 77 if reassign_to = Enumeration.find_by_type_and_id(@enumeration.type, params[:reassign_to_id])
75 78 @enumeration.destroy(reassign_to)
76 79 redirect_to :action => 'index'
77 80 end
78 81 end
79 82 @enumerations = Enumeration.find(:all, :conditions => ['type = (?)', @enumeration.type]) - [@enumeration]
80 83 #rescue
81 84 # flash[:error] = 'Unable to delete enumeration'
82 85 # redirect_to :action => 'index'
83 86 end
84 87 end
@@ -1,89 +1,92
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 module CustomFieldsHelper
19 19
20 20 def custom_fields_tabs
21 21 tabs = [{:name => 'IssueCustomField', :partial => 'custom_fields/index', :label => :label_issue_plural},
22 22 {:name => 'TimeEntryCustomField', :partial => 'custom_fields/index', :label => :label_spent_time},
23 23 {:name => 'ProjectCustomField', :partial => 'custom_fields/index', :label => :label_project_plural},
24 24 {:name => 'UserCustomField', :partial => 'custom_fields/index', :label => :label_user_plural},
25 {:name => 'GroupCustomField', :partial => 'custom_fields/index', :label => :label_group_plural}
25 {:name => 'GroupCustomField', :partial => 'custom_fields/index', :label => :label_group_plural},
26 {:name => 'TimeEntryActivityCustomField', :label => TimeEntryActivity::OptionName},
27 {:name => 'IssuePriorityCustomField', :label => IssuePriority::OptionName},
28 {:name => 'DocumentCategoryCustomField', :label => DocumentCategory::OptionName}
26 29 ]
27 30 end
28 31
29 32 # Return custom field html tag corresponding to its format
30 33 def custom_field_tag(name, custom_value)
31 34 custom_field = custom_value.custom_field
32 35 field_name = "#{name}[custom_field_values][#{custom_field.id}]"
33 36 field_id = "#{name}_custom_field_values_#{custom_field.id}"
34 37
35 38 case custom_field.field_format
36 39 when "date"
37 40 text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) +
38 41 calendar_for(field_id)
39 42 when "text"
40 43 text_area_tag(field_name, custom_value.value, :id => field_id, :rows => 3, :style => 'width:90%')
41 44 when "bool"
42 45 hidden_field_tag(field_name, '0') + check_box_tag(field_name, '1', custom_value.true?, :id => field_id)
43 46 when "list"
44 47 blank_option = custom_field.is_required? ?
45 48 (custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') :
46 49 '<option></option>'
47 50 select_tag(field_name, blank_option + options_for_select(custom_field.possible_values, custom_value.value), :id => field_id)
48 51 else
49 52 text_field_tag(field_name, custom_value.value, :id => field_id)
50 53 end
51 54 end
52 55
53 56 # Return custom field label tag
54 57 def custom_field_label_tag(name, custom_value)
55 58 content_tag "label", custom_value.custom_field.name +
56 59 (custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
57 60 :for => "#{name}_custom_field_values_#{custom_value.custom_field.id}",
58 61 :class => (custom_value.errors.empty? ? nil : "error" )
59 62 end
60 63
61 64 # Return custom field tag with its label tag
62 65 def custom_field_tag_with_label(name, custom_value)
63 66 custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
64 67 end
65 68
66 69 # Return a string used to display a custom value
67 70 def show_value(custom_value)
68 71 return "" unless custom_value
69 72 format_value(custom_value.value, custom_value.custom_field.field_format)
70 73 end
71 74
72 75 # Return a string used to display a custom value
73 76 def format_value(value, field_format)
74 77 return "" unless value && !value.empty?
75 78 case field_format
76 79 when "date"
77 80 begin; format_date(value.to_date); rescue; value end
78 81 when "bool"
79 82 l(value == "1" ? :general_text_Yes : :general_text_No)
80 83 else
81 84 value
82 85 end
83 86 end
84 87
85 88 # Return an array of custom field formats which can be used in select_tag
86 89 def custom_field_formats_for_select
87 90 CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
88 91 end
89 92 end
@@ -1,131 +1,132
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Enumeration < ActiveRecord::Base
19 19 acts_as_list :scope => 'type = \'#{type}\''
20 acts_as_customizable
20 21
21 22 before_destroy :check_integrity
22 23
23 24 validates_presence_of :name
24 25 validates_uniqueness_of :name, :scope => [:type]
25 26 validates_length_of :name, :maximum => 30
26 27
27 28 # Backwards compatiblity named_scopes.
28 29 # Can be removed post-0.9
29 30 named_scope :priorities, :conditions => { :type => "IssuePriority" }, :order => 'position' do
30 31 ActiveSupport::Deprecation.warn("Enumeration#priorities is deprecated, use the IssuePriority class. (#{Redmine::Info.issue(3007)})")
31 32 def default
32 33 find(:first, :conditions => { :is_default => true })
33 34 end
34 35 end
35 36
36 37 named_scope :document_categories, :conditions => { :type => "DocumentCategory" }, :order => 'position' do
37 38 ActiveSupport::Deprecation.warn("Enumeration#document_categories is deprecated, use the DocumentCategories class. (#{Redmine::Info.issue(3007)})")
38 39 def default
39 40 find(:first, :conditions => { :is_default => true })
40 41 end
41 42 end
42 43
43 44 named_scope :activities, :conditions => { :type => "TimeEntryActivity" }, :order => 'position' do
44 45 ActiveSupport::Deprecation.warn("Enumeration#activities is deprecated, use the TimeEntryActivity class. (#{Redmine::Info.issue(3007)})")
45 46 def default
46 47 find(:first, :conditions => { :is_default => true })
47 48 end
48 49 end
49 50
50 51 named_scope :values, lambda {|type| { :conditions => { :type => type }, :order => 'position' } } do
51 52 def default
52 53 find(:first, :conditions => { :is_default => true })
53 54 end
54 55 end
55 56
56 57 named_scope :all, :order => 'position'
57 58
58 59 def self.default
59 60 # Creates a fake default scope so Enumeration.default will check
60 61 # it's type. STI subclasses will automatically add their own
61 62 # types to the finder.
62 63 if self.descends_from_active_record?
63 64 find(:first, :conditions => { :is_default => true, :type => 'Enumeration' })
64 65 else
65 66 # STI classes are
66 67 find(:first, :conditions => { :is_default => true })
67 68 end
68 69 end
69 70
70 71 # Overloaded on concrete classes
71 72 def option_name
72 73 nil
73 74 end
74 75
75 76 # Backwards compatiblity. Can be removed post-0.9
76 77 def opt
77 78 ActiveSupport::Deprecation.warn("Enumeration#opt is deprecated, use the STI classes now. (#{Redmine::Info.issue(3007)})")
78 79 return OptName
79 80 end
80 81
81 82 def before_save
82 83 if is_default? && is_default_changed?
83 84 Enumeration.update_all("is_default = #{connection.quoted_false}", {:type => type})
84 85 end
85 86 end
86 87
87 88 # Overloaded on concrete classes
88 89 def objects_count
89 90 0
90 91 end
91 92
92 93 def in_use?
93 94 self.objects_count != 0
94 95 end
95 96
96 97 alias :destroy_without_reassign :destroy
97 98
98 99 # Destroy the enumeration
99 100 # If a enumeration is specified, objects are reassigned
100 101 def destroy(reassign_to = nil)
101 102 if reassign_to && reassign_to.is_a?(Enumeration)
102 103 self.transfer_relations(reassign_to)
103 104 end
104 105 destroy_without_reassign
105 106 end
106 107
107 108 def <=>(enumeration)
108 109 position <=> enumeration.position
109 110 end
110 111
111 112 def to_s; name end
112 113
113 114 # Returns the Subclasses of Enumeration. Each Subclass needs to be
114 115 # required in development mode.
115 116 #
116 117 # Note: subclasses is protected in ActiveRecord
117 118 def self.get_subclasses
118 119 @@subclasses[Enumeration]
119 120 end
120 121
121 122 private
122 123 def check_integrity
123 124 raise "Can't delete enumeration" if self.in_use?
124 125 end
125 126
126 127 end
127 128
128 129 # Force load the subclasses in development mode
129 130 require_dependency 'time_entry_activity'
130 131 require_dependency 'document_category'
131 132 require_dependency 'issue_priority'
@@ -1,100 +1,103
1 1 <%= error_messages_for 'custom_field' %>
2 2
3 3 <script type="text/javascript">
4 4 //<![CDATA[
5 5 function toggle_custom_field_format() {
6 6 format = $("custom_field_field_format");
7 7 p_length = $("custom_field_min_length");
8 8 p_regexp = $("custom_field_regexp");
9 9 p_values = $("custom_field_possible_values");
10 10 p_searchable = $("custom_field_searchable");
11 11 p_default = $("custom_field_default_value");
12 12
13 13 p_default.setAttribute('type','text');
14 14 Element.show(p_default.parentNode);
15 15
16 16 switch (format.value) {
17 17 case "list":
18 18 Element.hide(p_length.parentNode);
19 19 Element.hide(p_regexp.parentNode);
20 20 if (p_searchable) Element.show(p_searchable.parentNode);
21 21 Element.show(p_values);
22 22 break;
23 23 case "bool":
24 24 p_default.setAttribute('type','checkbox');
25 25 Element.hide(p_length.parentNode);
26 26 Element.hide(p_regexp.parentNode);
27 27 if (p_searchable) Element.hide(p_searchable.parentNode);
28 28 Element.hide(p_values);
29 29 break;
30 30 case "date":
31 31 Element.hide(p_length.parentNode);
32 32 Element.hide(p_regexp.parentNode);
33 33 if (p_searchable) Element.hide(p_searchable.parentNode);
34 34 Element.hide(p_values);
35 35 break;
36 36 case "float":
37 37 case "int":
38 38 Element.show(p_length.parentNode);
39 39 Element.show(p_regexp.parentNode);
40 40 if (p_searchable) Element.hide(p_searchable.parentNode);
41 41 Element.hide(p_values);
42 42 break;
43 43 default:
44 44 Element.show(p_length.parentNode);
45 45 Element.show(p_regexp.parentNode);
46 46 if (p_searchable) Element.show(p_searchable.parentNode);
47 47 Element.hide(p_values);
48 48 break;
49 49 }
50 50 }
51 51
52 52 //]]>
53 53 </script>
54 54
55 55 <div class="box">
56 56 <p><%= f.text_field :name, :required => true %></p>
57 57 <p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();",
58 58 :disabled => !@custom_field.new_record? %></p>
59 59 <p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label>
60 60 <%= f.text_field :min_length, :size => 5, :no_label => true %> -
61 61 <%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p>
62 62 <p><%= f.text_field :regexp, :size => 50 %><br>(<%=l(:text_regexp_info)%>)</p>
63 63 <p id="custom_field_possible_values"><%= f.text_area :possible_values, :value => @custom_field.possible_values.to_a.join("\n"),
64 64 :cols => 20,
65 65 :rows => 15 %>
66 66 <br /><em><%= l(:text_custom_field_possible_values_info) %></em></p>
67 67 <p><%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %></p>
68 68 <%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %>
69 69 </div>
70 70
71 71 <div class="box">
72 72 <% case @custom_field.class.name
73 73 when "IssueCustomField" %>
74 74
75 75 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
76 76 <% for tracker in @trackers %>
77 77 <%= check_box_tag "custom_field[tracker_ids][]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %>
78 78 <% end %>
79 79 <%= hidden_field_tag "custom_field[tracker_ids][]", '' %>
80 80 </fieldset>
81 81 &nbsp;
82 82 <p><%= f.check_box :is_required %></p>
83 83 <p><%= f.check_box :is_for_all %></p>
84 84 <p><%= f.check_box :is_filter %></p>
85 85 <p><%= f.check_box :searchable %></p>
86 86
87 87 <% when "UserCustomField" %>
88 88 <p><%= f.check_box :is_required %></p>
89 89 <p><%= f.check_box :editable %></p>
90 90
91 91 <% when "ProjectCustomField" %>
92 92 <p><%= f.check_box :is_required %></p>
93 93
94 94 <% when "TimeEntryCustomField" %>
95 95 <p><%= f.check_box :is_required %></p>
96 96
97 <% else %>
98 <p><%= f.check_box :is_required %></p>
99
97 100 <% end %>
98 101 <%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %>
99 102 </div>
100 103 <%= javascript_tag "toggle_custom_field_format();" %>
@@ -1,12 +1,16
1 1 <%= error_messages_for 'enumeration' %>
2 2 <div class="box">
3 3 <!--[form:optvalue]-->
4 4 <%= hidden_field 'enumeration', 'type' %>
5 5
6 6 <p><label for="enumeration_name"><%=l(:field_name)%></label>
7 7 <%= text_field 'enumeration', 'name' %></p>
8 8
9 9 <p><label for="enumeration_is_default"><%=l(:field_is_default)%></label>
10 10 <%= check_box 'enumeration', 'is_default' %></p>
11 11 <!--[eoform:optvalue]-->
12
13 <% @enumeration.custom_field_values.each do |value| %>
14 <p><%= custom_field_tag_with_label :enumeration, value %></p>
15 <% end %>
12 16 </div> No newline at end of file
@@ -1,90 +1,103
1 1 ---
2 2 custom_fields_001:
3 3 name: Database
4 4 min_length: 0
5 5 regexp: ""
6 6 is_for_all: true
7 7 is_filter: true
8 8 type: IssueCustomField
9 9 max_length: 0
10 10 possible_values:
11 11 - MySQL
12 12 - PostgreSQL
13 13 - Oracle
14 14 id: 1
15 15 is_required: false
16 16 field_format: list
17 17 default_value: ""
18 18 editable: true
19 19 custom_fields_002:
20 20 name: Searchable field
21 21 min_length: 1
22 22 regexp: ""
23 23 is_for_all: true
24 24 type: IssueCustomField
25 25 max_length: 100
26 26 possible_values: ""
27 27 id: 2
28 28 is_required: false
29 29 field_format: string
30 30 searchable: true
31 31 default_value: "Default string"
32 32 editable: true
33 33 custom_fields_003:
34 34 name: Development status
35 35 min_length: 0
36 36 regexp: ""
37 37 is_for_all: false
38 38 is_filter: true
39 39 type: ProjectCustomField
40 40 max_length: 0
41 41 possible_values:
42 42 - Stable
43 43 - Beta
44 44 - Alpha
45 45 - Planning
46 46 id: 3
47 47 is_required: true
48 48 field_format: list
49 49 default_value: ""
50 50 editable: true
51 51 custom_fields_004:
52 52 name: Phone number
53 53 min_length: 0
54 54 regexp: ""
55 55 is_for_all: false
56 56 type: UserCustomField
57 57 max_length: 0
58 58 possible_values: ""
59 59 id: 4
60 60 is_required: false
61 61 field_format: string
62 62 default_value: ""
63 63 editable: true
64 64 custom_fields_005:
65 65 name: Money
66 66 min_length: 0
67 67 regexp: ""
68 68 is_for_all: false
69 69 type: UserCustomField
70 70 max_length: 0
71 71 possible_values: ""
72 72 id: 5
73 73 is_required: false
74 74 field_format: float
75 75 default_value: ""
76 76 editable: true
77 77 custom_fields_006:
78 78 name: Float field
79 79 min_length: 0
80 80 regexp: ""
81 81 is_for_all: true
82 82 type: IssueCustomField
83 83 max_length: 0
84 84 possible_values: ""
85 85 id: 6
86 86 is_required: false
87 87 field_format: float
88 88 default_value: ""
89 89 editable: true
90 No newline at end of file
90 custom_fields_007:
91 name: Billable
92 min_length: 0
93 regexp: ""
94 is_for_all: false
95 is_filter: true
96 type: TimeEntryActivityCustomField
97 max_length: 0
98 possible_values: ""
99 id: 7
100 is_required: false
101 field_format: bool
102 default_value: ""
103 editable: true
@@ -1,86 +1,91
1 1 ---
2 2 custom_values_006:
3 3 customized_type: Issue
4 4 custom_field_id: 2
5 5 customized_id: 3
6 6 id: 6
7 7 value: "125"
8 8 custom_values_007:
9 9 customized_type: Project
10 10 custom_field_id: 3
11 11 customized_id: 1
12 12 id: 7
13 13 value: Stable
14 14 custom_values_001:
15 15 customized_type: Principal
16 16 custom_field_id: 4
17 17 customized_id: 3
18 18 id: 1
19 19 value: ""
20 20 custom_values_002:
21 21 customized_type: Principal
22 22 custom_field_id: 4
23 23 customized_id: 4
24 24 id: 2
25 25 value: 01 23 45 67 89
26 26 custom_values_003:
27 27 customized_type: Principal
28 28 custom_field_id: 4
29 29 customized_id: 2
30 30 id: 3
31 31 value: ""
32 32 custom_values_004:
33 33 customized_type: Issue
34 34 custom_field_id: 2
35 35 customized_id: 1
36 36 id: 4
37 37 value: "125"
38 38 custom_values_005:
39 39 customized_type: Issue
40 40 custom_field_id: 2
41 41 customized_id: 2
42 42 id: 5
43 43 value: ""
44 44 custom_values_008:
45 45 customized_type: Issue
46 46 custom_field_id: 1
47 47 customized_id: 3
48 48 id: 8
49 49 value: "MySQL"
50 50 custom_values_009:
51 51 customized_type: Issue
52 52 custom_field_id: 2
53 53 customized_id: 3
54 54 id: 9
55 55 value: "this is a stringforcustomfield search"
56 56 custom_values_010:
57 57 customized_type: Issue
58 58 custom_field_id: 6
59 59 customized_id: 1
60 60 id: 10
61 61 value: "2.1"
62 62 custom_values_011:
63 63 customized_type: Issue
64 64 custom_field_id: 6
65 65 customized_id: 2
66 66 id: 11
67 67 value: "2.05"
68 68 custom_values_012:
69 69 customized_type: Issue
70 70 custom_field_id: 6
71 71 customized_id: 3
72 72 id: 12
73 73 value: "11.65"
74 74 custom_values_013:
75 75 customized_type: Issue
76 76 custom_field_id: 6
77 77 customized_id: 7
78 78 id: 13
79 79 value: ""
80 80 custom_values_014:
81 81 customized_type: Issue
82 82 custom_field_id: 6
83 83 customized_id: 5
84 84 id: 14
85 85 value: "-7.6"
86 No newline at end of file
86 custom_values_015:
87 customized_type: TimeEntryActivity
88 custom_field_id: 7
89 customized_id: 10
90 id: 15
91 value: true
@@ -1,84 +1,89
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class EnumerationTest < ActiveSupport::TestCase
21 fixtures :enumerations, :issues
21 fixtures :enumerations, :issues, :custom_fields, :custom_values
22 22
23 23 def setup
24 24 end
25 25
26 26 def test_objects_count
27 27 # low priority
28 28 assert_equal 5, Enumeration.find(4).objects_count
29 29 # urgent
30 30 assert_equal 0, Enumeration.find(7).objects_count
31 31 end
32 32
33 33 def test_in_use
34 34 # low priority
35 35 assert Enumeration.find(4).in_use?
36 36 # urgent
37 37 assert !Enumeration.find(7).in_use?
38 38 end
39 39
40 40 def test_default
41 41 e = Enumeration.default
42 42 assert e.is_a?(Enumeration)
43 43 assert e.is_default?
44 44 assert_equal 'Default Enumeration', e.name
45 45 end
46 46
47 47 def test_create
48 48 e = Enumeration.new(:name => 'Not default', :is_default => false)
49 49 e.type = 'Enumeration'
50 50 assert e.save
51 51 assert_equal 'Default Enumeration', Enumeration.default.name
52 52 end
53 53
54 54 def test_create_as_default
55 55 e = Enumeration.new(:name => 'Very urgent', :is_default => true)
56 56 e.type = 'Enumeration'
57 57 assert e.save
58 58 assert_equal e, Enumeration.default
59 59 end
60 60
61 61 def test_update_default
62 62 e = Enumeration.default
63 63 e.update_attributes(:name => 'Changed', :is_default => true)
64 64 assert_equal e, Enumeration.default
65 65 end
66 66
67 67 def test_update_default_to_non_default
68 68 e = Enumeration.default
69 69 e.update_attributes(:name => 'Changed', :is_default => false)
70 70 assert_nil Enumeration.default
71 71 end
72 72
73 73 def test_change_default
74 74 e = Enumeration.find_by_name('Default Enumeration')
75 75 e.update_attributes(:name => 'Changed Enumeration', :is_default => true)
76 76 assert_equal e, Enumeration.default
77 77 end
78 78
79 79 def test_destroy_with_reassign
80 80 Enumeration.find(4).destroy(Enumeration.find(6))
81 81 assert_nil Issue.find(:first, :conditions => {:priority_id => 4})
82 82 assert_equal 5, Enumeration.find(6).objects_count
83 83 end
84
85 def test_should_be_customizable
86 assert Enumeration.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
87 end
88
84 89 end
@@ -1,36 +1,85
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class TimeEntryActivityTest < ActiveSupport::TestCase
21 21 fixtures :enumerations, :time_entries
22 22
23 23 def test_should_be_an_enumeration
24 24 assert TimeEntryActivity.ancestors.include?(Enumeration)
25 25 end
26 26
27 27 def test_objects_count
28 28 assert_equal 3, TimeEntryActivity.find_by_name("Design").objects_count
29 29 assert_equal 1, TimeEntryActivity.find_by_name("Development").objects_count
30 30 end
31 31
32 32 def test_option_name
33 33 assert_equal :enumeration_activities, TimeEntryActivity.new.option_name
34 34 end
35
36 def test_create_with_custom_field
37 field = TimeEntryActivityCustomField.find_by_name('Billable')
38 e = TimeEntryActivity.new(:name => 'Custom Data')
39 e.custom_field_values = {field.id => "1"}
40 assert e.save
41
42 e.reload
43 assert_equal "1", e.custom_value_for(field).value
44 end
45
46 def test_create_without_required_custom_field_should_fail
47 field = TimeEntryActivityCustomField.find_by_name('Billable')
48 field.update_attribute(:is_required, true)
49
50 e = TimeEntryActivity.new(:name => 'Custom Data')
51 assert !e.save
52 assert_equal I18n.translate('activerecord.errors.messages.invalid'), e.errors.on(:custom_values)
53 end
54
55 def test_create_with_required_custom_field_should_succeed
56 field = TimeEntryActivityCustomField.find_by_name('Billable')
57 field.update_attribute(:is_required, true)
58
59 e = TimeEntryActivity.new(:name => 'Custom Data')
60 e.custom_field_values = {field.id => "1"}
61 assert e.save
62 end
63
64 def test_update_issue_with_required_custom_field_change
65 field = TimeEntryActivityCustomField.find_by_name('Billable')
66 field.update_attribute(:is_required, true)
67
68 e = TimeEntryActivity.find(10)
69 assert e.available_custom_fields.include?(field)
70 # No change to custom field, record can be saved
71 assert e.save
72 # Blanking custom field, save should fail
73 e.custom_field_values = {field.id => ""}
74 assert !e.save
75 assert e.errors.on(:custom_values)
76
77 # Update custom field to valid value, save should succeed
78 e.custom_field_values = {field.id => "0"}
79 assert e.save
80 e.reload
81 assert_equal "0", e.custom_value_for(field).value
82 end
83
35 84 end
36 85
General Comments 0
You need to be logged in to leave comments. Login now