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