##// END OF EJS Templates
Added several more plugin hooks:...
Eric Davis -
r2535:451ef7f21f41
parent child
Show More
@@ -1,58 +1,60
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2009 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 CustomFieldsController < ApplicationController
19 19 before_filter :require_admin
20 20
21 21 def index
22 22 @custom_fields_by_type = CustomField.find(:all).group_by {|f| f.class.name }
23 23 @tab = params[:tab] || 'IssueCustomField'
24 24 end
25 25
26 26 def new
27 27 @custom_field = begin
28 28 if params[:type].to_s.match(/.+CustomField$/)
29 29 params[:type].to_s.constantize.new(params[:custom_field])
30 30 end
31 31 rescue
32 32 end
33 33 redirect_to(:action => 'index') and return unless @custom_field.is_a?(CustomField)
34 34
35 35 if request.post? and @custom_field.save
36 36 flash[:notice] = l(:notice_successful_create)
37 call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
37 38 redirect_to :action => 'index', :tab => @custom_field.class.name
38 39 end
39 40 @trackers = Tracker.find(:all, :order => 'position')
40 41 end
41 42
42 43 def edit
43 44 @custom_field = CustomField.find(params[:id])
44 45 if request.post? and @custom_field.update_attributes(params[:custom_field])
45 46 flash[:notice] = l(:notice_successful_update)
47 call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
46 48 redirect_to :action => 'index', :tab => @custom_field.class.name
47 49 end
48 50 @trackers = Tracker.find(:all, :order => 'position')
49 51 end
50 52
51 53 def destroy
52 54 @custom_field = CustomField.find(params[:id]).destroy
53 55 redirect_to :action => 'index', :tab => @custom_field.class.name
54 56 rescue
55 57 flash[:error] = "Unable to delete custom field"
56 58 redirect_to :action => 'index'
57 59 end
58 60 end
@@ -1,98 +1,100
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 <%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %>
68 69 </div>
69 70
70 71 <div class="box">
71 72 <% case @custom_field.class.name
72 73 when "IssueCustomField" %>
73 74
74 75 <fieldset><legend><%=l(:label_tracker_plural)%></legend>
75 76 <% for tracker in @trackers %>
76 77 <%= check_box_tag "custom_field[tracker_ids][]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %>
77 78 <% end %>
78 79 <%= hidden_field_tag "custom_field[tracker_ids][]", '' %>
79 80 </fieldset>
80 81 &nbsp;
81 82 <p><%= f.check_box :is_required %></p>
82 83 <p><%= f.check_box :is_for_all %></p>
83 84 <p><%= f.check_box :is_filter %></p>
84 85 <p><%= f.check_box :searchable %></p>
85 86
86 87 <% when "UserCustomField" %>
87 88 <p><%= f.check_box :is_required %></p>
88 89 <p><%= f.check_box :editable %></p>
89 90
90 91 <% when "ProjectCustomField" %>
91 92 <p><%= f.check_box :is_required %></p>
92 93
93 94 <% when "TimeEntryCustomField" %>
94 95 <p><%= f.check_box :is_required %></p>
95 96
96 97 <% end %>
98 <%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %>
97 99 </div>
98 100 <%= javascript_tag "toggle_custom_field_format();" %>
@@ -1,15 +1,17
1 1 <%= error_messages_for 'issue_status' %>
2 2
3 3 <div class="box">
4 4 <!--[form:issue_status]-->
5 5 <p><label for="issue_status_name"><%=l(:field_name)%><span class="required"> *</span></label>
6 6 <%= text_field 'issue_status', 'name' %></p>
7 7
8 8 <p><label for="issue_status_is_closed"><%=l(:field_is_closed)%></label>
9 9 <%= check_box 'issue_status', 'is_closed' %></p>
10 10
11 11 <p><label for="issue_status_is_default"><%=l(:field_is_default)%></label>
12 12 <%= check_box 'issue_status', 'is_default' %></p>
13 13
14 <%= call_hook(:view_issue_statuses_form, :issue_status => @issue_status) %>
15
14 16 <!--[eoform:issue_status]-->
15 </div> No newline at end of file
17 </div>
@@ -1,125 +1,127
1 1 <div class="contextual">
2 2 <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
3 3 <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time-add' %>
4 4 <%= watcher_tag(@issue, User.current) %>
5 5 <%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %>
6 6 <%= link_to_if_authorized l(:button_move), {:controller => 'issues', :action => 'move', :id => @issue }, :class => 'icon icon-move' %>
7 7 <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
8 8 </div>
9 9
10 10 <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
11 11
12 12 <div class="<%= css_issue_classes(@issue) %> details">
13 13 <%= avatar(@issue.author, :size => "64") %>
14 14 <h3><%=h @issue.subject %></h3>
15 15 <p class="author">
16 16 <%= authoring @issue.created_on, @issue.author %>.
17 17 <%= l(:label_updated_time, distance_of_time_in_words(Time.now, @issue.updated_on)) + '.' if @issue.created_on != @issue.updated_on %>
18 18 </p>
19 19
20 20 <table width="100%">
21 21 <tr>
22 22 <td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status"><%= @issue.status.name %></td>
23 23 <td style="width:15%" class="start-date"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td>
24 24 </tr>
25 25 <tr>
26 26 <td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority"><%= @issue.priority.name %></td>
27 27 <td class="due-date"><b><%=l(:field_due_date)%>:</b></td><td class="due-date"><%= format_date(@issue.due_date) %></td>
28 28 </tr>
29 29 <tr>
30 30 <td class="assigned-to"><b><%=l(:field_assigned_to)%>:</b></td><td><%= avatar(@issue.assigned_to, :size => "14") %><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
31 31 <td class="progress"><b><%=l(:field_done_ratio)%>:</b></td><td class="progress"><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
32 32 </tr>
33 33 <tr>
34 34 <td class="category"><b><%=l(:field_category)%>:</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td>
35 35 <% if User.current.allowed_to?(:view_time_entries, @project) %>
36 36 <td class="spent-time"><b><%=l(:label_spent_time)%>:</b></td>
37 37 <td class="spent-hours"><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}) : "-" %></td>
38 38 <% end %>
39 39 </tr>
40 40 <tr>
41 41 <td class="fixed-version"><b><%=l(:field_fixed_version)%>:</b></td><td><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
42 42 <% if @issue.estimated_hours %>
43 43 <td class="estimated-hours"><b><%=l(:field_estimated_hours)%>:</b></td><td><%= l_hours(@issue.estimated_hours) %></td>
44 44 <% end %>
45 45 </tr>
46 46 <tr>
47 47 <% n = 0 -%>
48 48 <% @issue.custom_values.each do |value| -%>
49 49 <td valign="top"><b><%=h value.custom_field.name %>:</b></td><td valign="top"><%= simple_format(h(show_value(value))) %></td>
50 50 <% n = n + 1
51 51 if (n > 1)
52 52 n = 0 %>
53 53 </tr><tr>
54 54 <%end
55 55 end %>
56 56 </tr>
57 57 <%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
58 58 </table>
59 59 <hr />
60 60
61 61 <div class="contextual">
62 62 <%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %>
63 63 </div>
64 64
65 65 <p><strong><%=l(:field_description)%></strong></p>
66 66 <div class="wiki">
67 67 <%= textilizable @issue, :description, :attachments => @issue.attachments %>
68 68 </div>
69 69
70 70 <%= link_to_attachments @issue %>
71 71
72 <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
73
72 74 <% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
73 75 <hr />
74 76 <div id="relations">
75 77 <%= render :partial => 'relations' %>
76 78 </div>
77 79 <% end %>
78 80
79 81 <% if User.current.allowed_to?(:add_issue_watchers, @project) ||
80 82 (@issue.watchers.any? && User.current.allowed_to?(:view_issue_watchers, @project)) %>
81 83 <hr />
82 84 <div id="watchers">
83 85 <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %>
84 86 </div>
85 87 <% end %>
86 88
87 89 </div>
88 90
89 91 <% if @changesets.any? && User.current.allowed_to?(:view_changesets, @project) %>
90 92 <div id="issue-changesets">
91 93 <h3><%=l(:label_associated_revisions)%></h3>
92 94 <%= render :partial => 'changesets', :locals => { :changesets => @changesets} %>
93 95 </div>
94 96 <% end %>
95 97
96 98 <% if @journals.any? %>
97 99 <div id="history">
98 100 <h3><%=l(:label_history)%></h3>
99 101 <%= render :partial => 'history', :locals => { :journals => @journals } %>
100 102 </div>
101 103 <% end %>
102 104 <div style="clear: both;"></div>
103 105
104 106 <% if authorize_for('issues', 'edit') %>
105 107 <div id="update" style="display:none;">
106 108 <h3><%= l(:button_update) %></h3>
107 109 <%= render :partial => 'edit' %>
108 110 </div>
109 111 <% end %>
110 112
111 113 <% other_formats_links do |f| %>
112 114 <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
113 115 <%= f.link_to 'PDF' %>
114 116 <% end %>
115 117
116 118 <% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
117 119
118 120 <% content_for :sidebar do %>
119 121 <%= render :partial => 'issues/sidebar' %>
120 122 <% end %>
121 123
122 124 <% content_for :header_tags do %>
123 125 <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %>
124 126 <%= stylesheet_link_tag 'scm' %>
125 127 <% end %>
@@ -1,59 +1,60
1 1 <div class="contextual">
2 2 <%= link_to(l(:button_change_password), :action => 'password') unless @user.auth_source_id %>
3 3 </div>
4 4 <h2><%=l(:label_my_account)%></h2>
5 5 <%= error_messages_for 'user' %>
6 6
7 7 <% form_for :user, @user, :url => { :action => "account" },
8 8 :builder => TabularFormBuilder,
9 9 :lang => current_language,
10 10 :html => { :id => 'my_account_form' } do |f| %>
11 11 <div class="splitcontentleft">
12 12 <h3><%=l(:label_information_plural)%></h3>
13 13 <div class="box tabular">
14 14 <p><%= f.text_field :firstname, :required => true %></p>
15 15 <p><%= f.text_field :lastname, :required => true %></p>
16 16 <p><%= f.text_field :mail, :required => true %></p>
17 17 <p><%= f.select :language, lang_options_for_select %></p>
18 18 <% if Setting.openid? %>
19 19 <p><%= f.text_field :identity_url %></p>
20 20 <% end %>
21 21
22 22 <% @user.custom_field_values.select(&:editable?).each do |value| %>
23 23 <p><%= custom_field_tag_with_label :user, value %></p>
24 24 <% end %>
25 <%= call_hook(:view_my_account, :user => @user, :form => f) %>
25 26 </div>
26 27
27 28 <%= submit_tag l(:button_save) %>
28 29 </div>
29 30
30 31 <div class="splitcontentright">
31 32 <h3><%=l(:field_mail_notification)%></h3>
32 33 <div class="box">
33 34 <%= select_tag 'notification_option', options_for_select(@notification_options, @notification_option),
34 35 :onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
35 36 <% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %>
36 37 <p><% User.current.projects.each do |project| %>
37 38 <label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
38 39 <% end %></p>
39 40 <p><em><%= l(:text_user_mail_option) %></em></p>
40 41 <% end %>
41 42 <p><label><%= check_box_tag 'no_self_notified', 1, @user.pref[:no_self_notified] %> <%= l(:label_user_mail_no_self_notified) %></label></p>
42 43 </div>
43 44
44 45 <h3><%=l(:label_preferences)%></h3>
45 46 <div class="box tabular">
46 47 <% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
47 48 <p><%= pref_fields.check_box :hide_mail %></p>
48 49 <p><%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
49 50 <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
50 51 <% end %>
51 52 </div>
52 53 </div>
53 54 <% end %>
54 55
55 56 <% content_for :sidebar do %>
56 57 <%= render :partial => 'sidebar' %>
57 58 <% end %>
58 59
59 60 <% html_title(l(:label_my_account)) -%>
@@ -1,34 +1,35
1 1 <%= error_messages_for 'user' %>
2 2
3 3 <!--[form:user]-->
4 4 <div class="box">
5 5 <p><%= f.text_field :login, :required => true, :size => 25 %></p>
6 6 <p><%= f.text_field :firstname, :required => true %></p>
7 7 <p><%= f.text_field :lastname, :required => true %></p>
8 8 <p><%= f.text_field :mail, :required => true %></p>
9 9 <p><%= f.select :language, lang_options_for_select %></p>
10 10 <% if Setting.openid? %>
11 11 <p><%= f.text_field :identity_url %></p>
12 12 <% end %>
13 13
14 14 <% @user.custom_field_values.each do |value| %>
15 15 <p><%= custom_field_tag_with_label :user, value %></p>
16 16 <% end %>
17 17
18 18 <p><%= f.check_box :admin, :disabled => (@user == User.current) %></p>
19 <%= call_hook(:view_users_form, :user => @user, :form => f) %>
19 20 </div>
20 21
21 22 <div class="box">
22 23 <h3><%=l(:label_authentication)%></h3>
23 24 <% unless @auth_sources.empty? %>
24 25 <p><%= f.select :auth_source_id, ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }), {}, :onchange => "if (this.value=='') {Element.show('password_fields');} else {Element.hide('password_fields');}" %></p>
25 26 <% end %>
26 27 <div id="password_fields" style="<%= 'display:none;' if @user.auth_source %>">
27 28 <p><label for="password"><%=l(:field_password)%><span class="required"> *</span></label>
28 29 <%= password_field_tag 'password', nil, :size => 25 %><br />
29 30 <em><%= l(:text_caracters_minimum, 4) %></em></p>
30 31 <p><label for="password_confirmation"><%=l(:field_password_confirmation)%><span class="required"> *</span></label>
31 32 <%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
32 33 </div>
33 34 </div>
34 35 <!--[eoform:user]-->
General Comments 0
You need to be logged in to leave comments. Login now