##// END OF EJS Templates
Resourcified custom fields....
Jean-Philippe Lang -
r8024:b127f9157d45
parent child
Show More
@@ -19,6 +19,8 class CustomFieldsController < ApplicationController
19 layout 'admin'
19 layout 'admin'
20
20
21 before_filter :require_admin
21 before_filter :require_admin
22 before_filter :build_new_custom_field, :only => [:new, :create]
23 before_filter :find_custom_field, :only => [:edit, :update, :destroy]
22
24
23 def index
25 def index
24 @custom_fields_by_type = CustomField.find(:all).group_by {|f| f.class.name }
26 @custom_fields_by_type = CustomField.find(:all).group_by {|f| f.class.name }
@@ -26,39 +28,51 class CustomFieldsController < ApplicationController
26 end
28 end
27
29
28 def new
30 def new
29 @custom_field = begin
31 end
30 if params[:type].to_s.match(/.+CustomField$/)
31 params[:type].to_s.constantize.new(params[:custom_field])
32 end
33 rescue
34 end
35 (redirect_to(:action => 'index'); return) unless @custom_field.is_a?(CustomField)
36
32
33 def create
37 if request.post? and @custom_field.save
34 if request.post? and @custom_field.save
38 flash[:notice] = l(:notice_successful_create)
35 flash[:notice] = l(:notice_successful_create)
39 call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
36 call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
40 redirect_to :action => 'index', :tab => @custom_field.class.name
37 redirect_to :action => 'index', :tab => @custom_field.class.name
41 else
38 else
42 @trackers = Tracker.find(:all, :order => 'position')
39 render :action => 'new'
43 end
40 end
44 end
41 end
45
42
46 def edit
43 def edit
47 @custom_field = CustomField.find(params[:id])
44 end
48 if request.post? and @custom_field.update_attributes(params[:custom_field])
45
46 def update
47 if request.put? and @custom_field.update_attributes(params[:custom_field])
49 flash[:notice] = l(:notice_successful_update)
48 flash[:notice] = l(:notice_successful_update)
50 call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
49 call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
51 redirect_to :action => 'index', :tab => @custom_field.class.name
50 redirect_to :action => 'index', :tab => @custom_field.class.name
52 else
51 else
53 @trackers = Tracker.find(:all, :order => 'position')
52 render :action => 'edit'
54 end
53 end
55 end
54 end
56
55
57 def destroy
56 def destroy
58 @custom_field = CustomField.find(params[:id]).destroy
57 @custom_field.destroy
59 redirect_to :action => 'index', :tab => @custom_field.class.name
58 redirect_to :action => 'index', :tab => @custom_field.class.name
60 rescue
59 rescue
61 flash[:error] = l(:error_can_not_delete_custom_field)
60 flash[:error] = l(:error_can_not_delete_custom_field)
62 redirect_to :action => 'index'
61 redirect_to :action => 'index'
63 end
62 end
63
64 private
65
66 def build_new_custom_field
67 @custom_field = CustomField.new_subclass_instance(params[:type], params[:custom_field])
68 if @custom_field.nil?
69 render_404
70 end
71 end
72
73 def find_custom_field
74 @custom_field = CustomField.find(params[:id])
75 rescue ActiveRecord::RecordNotFound
76 render_404
77 end
64 end
78 end
@@ -155,6 +155,22 class CustomField < ActiveRecord::Base
155 find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
155 find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
156 end
156 end
157
157
158 # Returns an instance of the given subclass name
159 def self.new_subclass_instance(class_name, *args)
160 klass = nil
161 begin
162 klass = class_name.to_s.classify.constantize
163 rescue
164 # invalid class name
165 end
166 unless subclasses.include? klass
167 klass = nil
168 end
169 if klass
170 klass.new(*args)
171 end
172 end
173
158 def type_name
174 def type_name
159 nil
175 nil
160 end
176 end
@@ -81,7 +81,7 function toggle_custom_field_format() {
81 when "IssueCustomField" %>
81 when "IssueCustomField" %>
82
82
83 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
83 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
84 <% for tracker in @trackers %>
84 <% Tracker.all.each do |tracker| %>
85 <%= check_box_tag "custom_field[tracker_ids][]",
85 <%= check_box_tag "custom_field[tracker_ids][]",
86 tracker.id,
86 tracker.id,
87 (@custom_field.trackers.include? tracker),
87 (@custom_field.trackers.include? tracker),
@@ -13,7 +13,7
13 <tbody>
13 <tbody>
14 <% (@custom_fields_by_type[tab[:name]] || []).sort.each do |custom_field| -%>
14 <% (@custom_fields_by_type[tab[:name]] || []).sort.each do |custom_field| -%>
15 <tr class="<%= cycle("odd", "even") %>">
15 <tr class="<%= cycle("odd", "even") %>">
16 <td><%= link_to h(custom_field.name), :action => 'edit', :id => custom_field %></td>
16 <td><%= link_to h(custom_field.name), edit_custom_field_path(custom_field) %></td>
17 <td align="center"><%= l(Redmine::CustomFieldFormat.label_for(custom_field.field_format)) %></td>
17 <td align="center"><%= l(Redmine::CustomFieldFormat.label_for(custom_field.field_format)) %></td>
18 <td align="center"><%= checked_image custom_field.is_required? %></td>
18 <td align="center"><%= checked_image custom_field.is_required? %></td>
19 <% if tab[:name] == 'IssueCustomField' %>
19 <% if tab[:name] == 'IssueCustomField' %>
@@ -22,8 +22,8
22 <% end %>
22 <% end %>
23 <td align="center" style="width:15%;"><%= reorder_links('custom_field', {:action => 'edit', :id => custom_field}) %></td>
23 <td align="center" style="width:15%;"><%= reorder_links('custom_field', {:action => 'edit', :id => custom_field}) %></td>
24 <td class="buttons">
24 <td class="buttons">
25 <%= link_to(l(:button_delete), { :action => 'destroy', :id => custom_field },
25 <%= link_to(l(:button_delete), custom_field_path(custom_field),
26 :method => :post,
26 :method => :delete,
27 :confirm => l(:text_are_you_sure),
27 :confirm => l(:text_are_you_sure),
28 :class => 'icon icon-del') %>
28 :class => 'icon icon-del') %>
29 </td>
29 </td>
@@ -32,4 +32,4
32 </tbody>
32 </tbody>
33 </table>
33 </table>
34
34
35 <p><%= link_to l(:label_custom_field_new), {:action => 'new', :type => tab[:name]}, :class => 'icon icon-add' %></p>
35 <p><%= link_to l(:label_custom_field_new), new_custom_field_path(:type => tab[:name]), :class => 'icon icon-add' %></p>
@@ -2,7 +2,7
2 &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
2 &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
3 &#187; <%=h @custom_field.name %></h2>
3 &#187; <%=h @custom_field.name %></h2>
4
4
5 <% labelled_form_for :custom_field, @custom_field, :url => { :action => "edit", :id => @custom_field } do |f| %>
5 <% labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
6 <%= render :partial => 'form', :locals => { :f => f } %>
6 <%= render :partial => 'form', :locals => { :f => f } %>
7 <%= submit_tag l(:button_save) %>
7 <%= submit_tag l(:button_save) %>
8 <% end %>
8 <% end %>
@@ -2,7 +2,7
2 &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
2 &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
3 &#187; <%= l(:label_custom_field_new) %></h2>
3 &#187; <%= l(:label_custom_field_new) %></h2>
4
4
5 <% labelled_form_for :custom_field, @custom_field, :url => { :action => "new" } do |f| %>
5 <% labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
6 <%= render :partial => 'form', :locals => { :f => f } %>
6 <%= render :partial => 'form', :locals => { :f => f } %>
7 <%= hidden_field_tag 'type', @custom_field.type %>
7 <%= hidden_field_tag 'type', @custom_field.type %>
8 <%= submit_tag l(:button_save) %>
8 <%= submit_tag l(:button_save) %>
@@ -184,6 +184,7 ActionController::Routing::Routes.draw do |map|
184
184
185 map.resources :trackers, :except => :show
185 map.resources :trackers, :except => :show
186 map.resources :issue_statuses, :except => :show, :collection => {:update_issue_done_ratio => :post}
186 map.resources :issue_statuses, :except => :show, :collection => {:update_issue_done_ratio => :post}
187 map.resources :custom_fields, :except => :show
187
188
188 #left old routes at the bottom for backwards compat
189 #left old routes at the bottom for backwards compat
189 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
190 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
@@ -37,10 +37,11 class CustomFieldsControllerTest < ActionController::TestCase
37 assert_template 'index'
37 assert_template 'index'
38 end
38 end
39
39
40 def test_get_new_issue_custom_field
40 def test_new_issue_custom_field
41 get :new, :type => 'IssueCustomField'
41 get :new, :type => 'IssueCustomField'
42 assert_response :success
42 assert_response :success
43 assert_template 'new'
43 assert_template 'new'
44 assert_tag :input, :attributes => {:name => 'custom_field[name]'}
44 assert_tag :select,
45 assert_tag :select,
45 :attributes => {:name => 'custom_field[field_format]'},
46 :attributes => {:name => 'custom_field[field_format]'},
46 :child => {
47 :child => {
@@ -55,16 +56,17 class CustomFieldsControllerTest < ActionController::TestCase
55 :attributes => {:value => 'version'},
56 :attributes => {:value => 'version'},
56 :content => 'Version'
57 :content => 'Version'
57 }
58 }
59 assert_tag :input, :attributes => {:name => 'type', :value => 'IssueCustomField'}
58 end
60 end
59
61
60 def test_get_new_with_invalid_custom_field_class_should_redirect_to_list
62 def test_new_with_invalid_custom_field_class_should_render_404
61 get :new, :type => 'UnknownCustomField'
63 get :new, :type => 'UnknownCustomField'
62 assert_redirected_to '/custom_fields'
64 assert_response 404
63 end
65 end
64
66
65 def test_post_new_list_custom_field
67 def test_create_list_custom_field
66 assert_difference 'CustomField.count' do
68 assert_difference 'CustomField.count' do
67 post :new, :type => "IssueCustomField",
69 post :create, :type => "IssueCustomField",
68 :custom_field => {:name => "test_post_new_list",
70 :custom_field => {:name => "test_post_new_list",
69 :default_value => "",
71 :default_value => "",
70 :min_length => "0",
72 :min_length => "0",
@@ -85,28 +87,47 class CustomFieldsControllerTest < ActionController::TestCase
85 assert_equal 1, field.trackers.size
87 assert_equal 1, field.trackers.size
86 end
88 end
87
89
88 def test_get_edit
90 def test_create_with_failure
91 assert_no_difference 'CustomField.count' do
92 post :create, :type => "IssueCustomField", :custom_field => {:name => ''}
93 end
94 assert_response :success
95 assert_template 'new'
96 end
97
98 def test_edit
89 get :edit, :id => 1
99 get :edit, :id => 1
90 assert_response :success
100 assert_response :success
91 assert_template 'edit'
101 assert_template 'edit'
92 assert_tag 'input', :attributes => {:name => 'custom_field[name]', :value => 'Database'}
102 assert_tag 'input', :attributes => {:name => 'custom_field[name]', :value => 'Database'}
93 end
103 end
94
104
95 def test_post_edit
105 def test_edit_invalid_custom_field_should_render_404
96 post :edit, :id => 1, :custom_field => {:name => 'New name'}
106 get :edit, :id => 99
107 assert_response 404
108 end
109
110 def test_update
111 put :update, :id => 1, :custom_field => {:name => 'New name'}
97 assert_redirected_to '/custom_fields?tab=IssueCustomField'
112 assert_redirected_to '/custom_fields?tab=IssueCustomField'
98
113
99 field = CustomField.find(1)
114 field = CustomField.find(1)
100 assert_equal 'New name', field.name
115 assert_equal 'New name', field.name
101 end
116 end
102
117
118 def test_update_with_failure
119 put :update, :id => 1, :custom_field => {:name => ''}
120 assert_response :success
121 assert_template 'edit'
122 end
123
103 def test_destroy
124 def test_destroy
104 custom_values_count = CustomValue.count(:conditions => {:custom_field_id => 1})
125 custom_values_count = CustomValue.count(:conditions => {:custom_field_id => 1})
105 assert custom_values_count > 0
126 assert custom_values_count > 0
106
127
107 assert_difference 'CustomField.count', -1 do
128 assert_difference 'CustomField.count', -1 do
108 assert_difference 'CustomValue.count', - custom_values_count do
129 assert_difference 'CustomValue.count', - custom_values_count do
109 post :destroy, :id => 1
130 delete :destroy, :id => 1
110 end
131 end
111 end
132 end
112
133
@@ -45,6 +45,15 class RoutingTest < ActionController::IntegrationTest
45
45
46 end
46 end
47
47
48 context "custom_fields" do
49 should_route :get, "/custom_fields", :controller => 'custom_fields', :action => 'index'
50 should_route :get, "/custom_fields/new", :controller => 'custom_fields', :action => 'new'
51 should_route :post, "/custom_fields", :controller => 'custom_fields', :action => 'create'
52 should_route :get, "/custom_fields/2/edit", :controller => 'custom_fields', :action => 'edit', :id => 2
53 should_route :put, "/custom_fields/2", :controller => 'custom_fields', :action => 'update', :id => 2
54 should_route :delete, "/custom_fields/2", :controller => 'custom_fields', :action => 'destroy', :id => 2
55 end
56
48 context "documents" do
57 context "documents" do
49 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
58 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
50 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
59 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
@@ -56,4 +56,23 class CustomFieldTest < ActiveSupport::TestCase
56 field = CustomField.find(1)
56 field = CustomField.find(1)
57 assert field.destroy
57 assert field.destroy
58 end
58 end
59
60 def test_new_subclass_instance_should_return_an_instance
61 f = CustomField.new_subclass_instance('IssueCustomField')
62 assert_kind_of IssueCustomField, f
63 end
64
65 def test_new_subclass_instance_should_set_attributes
66 f = CustomField.new_subclass_instance('IssueCustomField', :name => 'Test')
67 assert_kind_of IssueCustomField, f
68 assert_equal 'Test', f.name
69 end
70
71 def test_new_subclass_instance_with_invalid_class_name_should_return_nil
72 assert_nil CustomField.new_subclass_instance('WrongClassName')
73 end
74
75 def test_new_subclass_instance_with_non_subclass_name_should_return_nil
76 assert_nil CustomField.new_subclass_instance('Project')
77 end
59 end
78 end
General Comments 0
You need to be logged in to leave comments. Login now