##// END OF EJS Templates
Removed User#display_name (replaced by User#name)....
Jean-Philippe Lang -
r575:65be9d3c86f5
parent child
Show More
@@ -1,277 +1,277
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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 RedCloth
19 19 # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet.
20 20 # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
21 21 def hard_break( text )
22 22 text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks
23 23 end
24 24 end
25 25
26 26 module ApplicationHelper
27 27
28 28 # Return current logged in user or nil
29 29 def loggedin?
30 30 @logged_in_user
31 31 end
32 32
33 33 # Return true if user is logged in and is admin, otherwise false
34 34 def admin_loggedin?
35 35 @logged_in_user and @logged_in_user.admin?
36 36 end
37 37
38 38 # Return true if user is authorized for controller/action, otherwise false
39 39 def authorize_for(controller, action)
40 40 # check if action is allowed on public projects
41 41 if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ]
42 42 return true
43 43 end
44 44 # check if user is authorized
45 45 if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project) ) )
46 46 return true
47 47 end
48 48 return false
49 49 end
50 50
51 51 # Display a link if user is authorized
52 52 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
53 53 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action])
54 54 end
55 55
56 56 # Display a link to user's account page
57 57 def link_to_user(user)
58 link_to user.display_name, :controller => 'account', :action => 'show', :id => user
58 link_to user.name, :controller => 'account', :action => 'show', :id => user
59 59 end
60 60
61 61 def link_to_issue(issue)
62 62 link_to "#{issue.tracker.name} ##{issue.id}", :controller => "issues", :action => "show", :id => issue
63 63 end
64 64
65 65 def toggle_link(name, id, options={})
66 66 onclick = "Element.toggle('#{id}'); "
67 67 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
68 68 onclick << "return false;"
69 69 link_to(name, "#", :onclick => onclick)
70 70 end
71 71
72 72 def image_to_function(name, function, html_options = {})
73 73 html_options.symbolize_keys!
74 74 tag(:input, html_options.merge({
75 75 :type => "image", :src => image_path(name),
76 76 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
77 77 }))
78 78 end
79 79
80 80 def format_date(date)
81 81 l_date(date) if date
82 82 end
83 83
84 84 def format_time(time)
85 85 l_datetime((time.is_a? String) ? time.to_time : time) if time
86 86 end
87 87
88 88 def day_name(day)
89 89 l(:general_day_names).split(',')[day-1]
90 90 end
91 91
92 92 def month_name(month)
93 93 l(:actionview_datehelper_select_month_names).split(',')[month-1]
94 94 end
95 95
96 96 def pagination_links_full(paginator, options={}, html_options={})
97 97 page_param = options.delete(:page_param) || :page
98 98
99 99 html = ''
100 100 html << link_to_remote(('&#171; ' + l(:label_previous)),
101 101 {:update => "content", :url => options.merge(page_param => paginator.current.previous)},
102 102 {:href => url_for(:params => options.merge(page_param => paginator.current.previous))}) + ' ' if paginator.current.previous
103 103
104 104 html << (pagination_links_each(paginator, options) do |n|
105 105 link_to_remote(n.to_s,
106 106 {:url => {:params => options.merge(page_param => n)}, :update => 'content'},
107 107 {:href => url_for(:params => options.merge(page_param => n))})
108 108 end || '')
109 109
110 110 html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
111 111 {:update => "content", :url => options.merge(page_param => paginator.current.next)},
112 112 {:href => url_for(:params => options.merge(page_param => paginator.current.next))}) if paginator.current.next
113 113 html
114 114 end
115 115
116 116 # textilize text according to system settings and RedCloth availability
117 117 def textilizable(text, options = {})
118 118 return "" if text.blank?
119 119
120 120 # different methods for formatting wiki links
121 121 case options[:wiki_links]
122 122 when :local
123 123 # used for local links to html files
124 124 format_wiki_link = Proc.new {|title| "#{title}.html" }
125 125 when :anchor
126 126 # used for single-file wiki export
127 127 format_wiki_link = Proc.new {|title| "##{title}" }
128 128 else
129 129 if @project
130 130 format_wiki_link = Proc.new {|title| url_for :controller => 'wiki', :action => 'index', :id => @project, :page => title }
131 131 else
132 132 format_wiki_link = Proc.new {|title| title }
133 133 end
134 134 end
135 135
136 136 # turn wiki links into textile links:
137 137 # example:
138 138 # [[link]] -> "link":link
139 139 # [[link|title]] -> "title":link
140 140 text = text.gsub(/\[\[([^\]\|]+)(\|([^\]\|]+))?\]\]/) {|m| "\"#{$3 || $1}\":" + format_wiki_link.call(Wiki.titleize($1)) }
141 141
142 142 # turn issue ids into links
143 143 # example:
144 144 # #52 -> <a href="/issues/show/52">#52</a>
145 145 text = text.gsub(/#(\d+)(?=\b)/) {|m| link_to "##{$1}", :controller => 'issues', :action => 'show', :id => $1}
146 146
147 147 # turn revision ids into links (@project needed)
148 148 # example:
149 149 # r52 -> <a href="/repositories/revision/6?rev=52">r52</a> (@project.id is 6)
150 150 text = text.gsub(/(?=\b)r(\d+)(?=\b)/) {|m| link_to "r#{$1}", :controller => 'repositories', :action => 'revision', :id => @project.id, :rev => $1} if @project
151 151
152 152 # when using an image link, try to use an attachment, if possible
153 153 attachments = options[:attachments]
154 154 if attachments
155 155 text = text.gsub(/!([<>=]*)(\S+\.(gif|jpg|jpeg|png))!/) do |m|
156 156 align = $1
157 157 filename = $2
158 158 rf = Regexp.new(filename, Regexp::IGNORECASE)
159 159 # search for the picture in attachments
160 160 if found = attachments.detect { |att| att.filename =~ rf }
161 161 image_url = url_for :controller => 'attachments', :action => 'show', :id => found.id
162 162 "!#{align}#{image_url}!"
163 163 else
164 164 "!#{align}#{filename}!"
165 165 end
166 166 end
167 167 end
168 168
169 169 # finally textilize text
170 170 @do_textilize ||= (Setting.text_formatting == 'textile') && (ActionView::Helpers::TextHelper.method_defined? "textilize")
171 171 text = @do_textilize ? auto_link(RedCloth.new(text, [:hard_breaks]).to_html) : simple_format(auto_link(h(text)))
172 172 end
173 173
174 174 def error_messages_for(object_name, options = {})
175 175 options = options.symbolize_keys
176 176 object = instance_variable_get("@#{object_name}")
177 177 if object && !object.errors.empty?
178 178 # build full_messages here with controller current language
179 179 full_messages = []
180 180 object.errors.each do |attr, msg|
181 181 next if msg.nil?
182 182 msg = msg.first if msg.is_a? Array
183 183 if attr == "base"
184 184 full_messages << l(msg)
185 185 else
186 186 full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
187 187 end
188 188 end
189 189 # retrieve custom values error messages
190 190 if object.errors[:custom_values]
191 191 object.custom_values.each do |v|
192 192 v.errors.each do |attr, msg|
193 193 next if msg.nil?
194 194 msg = msg.first if msg.is_a? Array
195 195 full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
196 196 end
197 197 end
198 198 end
199 199 content_tag("div",
200 200 content_tag(
201 201 options[:header_tag] || "h2", lwr(:gui_validation_error, full_messages.length) + " :"
202 202 ) +
203 203 content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
204 204 "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
205 205 )
206 206 else
207 207 ""
208 208 end
209 209 end
210 210
211 211 def lang_options_for_select(blank=true)
212 212 (blank ? [["(auto)", ""]] : []) +
213 213 GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.first <=> y.first }
214 214 end
215 215
216 216 def label_tag_for(name, option_tags = nil, options = {})
217 217 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
218 218 content_tag("label", label_text)
219 219 end
220 220
221 221 def labelled_tabular_form_for(name, object, options, &proc)
222 222 options[:html] ||= {}
223 223 options[:html].store :class, "tabular"
224 224 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
225 225 end
226 226
227 227 def check_all_links(form_name)
228 228 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
229 229 " | " +
230 230 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
231 231 end
232 232
233 233 def calendar_for(field_id)
234 234 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
235 235 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
236 236 end
237 237
238 238 def wikitoolbar_for(field_id)
239 239 return '' unless Setting.text_formatting == 'textile'
240 240 javascript_include_tag('jstoolbar') + javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.draw();")
241 241 end
242 242 end
243 243
244 244 class TabularFormBuilder < ActionView::Helpers::FormBuilder
245 245 include GLoc
246 246
247 247 def initialize(object_name, object, template, options, proc)
248 248 set_language_if_valid options.delete(:lang)
249 249 @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
250 250 end
251 251
252 252 (field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector|
253 253 src = <<-END_SRC
254 254 def #{selector}(field, options = {})
255 255 return super if options.delete :no_label
256 256 label_text = l(options[:label]) if options[:label]
257 257 label_text ||= l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym)
258 258 label_text << @template.content_tag("span", " *", :class => "required") if options.delete(:required)
259 259 label = @template.content_tag("label", label_text,
260 260 :class => (@object && @object.errors[field] ? "error" : nil),
261 261 :for => (@object_name.to_s + "_" + field.to_s))
262 262 label + super
263 263 end
264 264 END_SRC
265 265 class_eval src, __FILE__, __LINE__
266 266 end
267 267
268 268 def select(field, choices, options = {}, html_options = {})
269 269 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
270 270 label = @template.content_tag("label", label_text,
271 271 :class => (@object && @object.errors[field] ? "error" : nil),
272 272 :for => (@object_name.to_s + "_" + field.to_s))
273 273 label + super
274 274 end
275 275
276 276 end
277 277
@@ -1,34 +1,34
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Member < ActiveRecord::Base
19 19 belongs_to :user
20 20 belongs_to :role
21 21 belongs_to :project
22 22
23 23 validates_presence_of :role, :user, :project
24 24 validates_uniqueness_of :user_id, :scope => :project_id
25 25
26 26 def name
27 self.user.display_name
27 self.user.name
28 28 end
29 29
30 30 def before_destroy
31 31 # remove category based auto assignments for this member
32 32 project.issue_categories.update_all "assigned_to_id = NULL", ["assigned_to_id = ?", self.user.id]
33 33 end
34 34 end
@@ -1,167 +1,163
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require "digest/sha1"
19 19
20 20 class User < ActiveRecord::Base
21 21 # Account statuses
22 22 STATUS_ACTIVE = 1
23 23 STATUS_REGISTERED = 2
24 24 STATUS_LOCKED = 3
25 25
26 26 has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name", :dependent => :delete_all
27 27 has_many :projects, :through => :memberships
28 28 has_many :custom_values, :dependent => :delete_all, :as => :customized
29 29 has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
30 30 has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
31 31 has_one :rss_key, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
32 32 belongs_to :auth_source
33 33
34 34 attr_accessor :password, :password_confirmation
35 35 attr_accessor :last_before_login_on
36 36 # Prevents unauthorized assignments
37 37 attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
38 38
39 39 validates_presence_of :login, :firstname, :lastname, :mail
40 40 validates_uniqueness_of :login, :mail
41 41 # Login must contain lettres, numbers, underscores only
42 42 validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
43 43 validates_length_of :login, :maximum => 30
44 44 validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
45 45 validates_length_of :firstname, :lastname, :maximum => 30
46 46 validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
47 47 validates_length_of :mail, :maximum => 60
48 48 # Password length between 4 and 12
49 49 validates_length_of :password, :in => 4..12, :allow_nil => true
50 50 validates_confirmation_of :password, :allow_nil => true
51 51 validates_associated :custom_values, :on => :update
52 52
53 53 def before_save
54 54 # update hashed_password if password was set
55 55 self.hashed_password = User.hash_password(self.password) if self.password
56 56 end
57 57
58 58 def self.active
59 59 with_scope :find => { :conditions => [ "status = ?", STATUS_ACTIVE ] } do
60 60 yield
61 61 end
62 62 end
63 63
64 64 def self.find_active(*args)
65 65 active do
66 66 find(*args)
67 67 end
68 68 end
69 69
70 70 # Returns the user that matches provided login and password, or nil
71 71 def self.try_to_login(login, password)
72 72 user = find(:first, :conditions => ["login=?", login])
73 73 if user
74 74 # user is already in local database
75 75 return nil if !user.active?
76 76 if user.auth_source
77 77 # user has an external authentication method
78 78 return nil unless user.auth_source.authenticate(login, password)
79 79 else
80 80 # authentication with local password
81 81 return nil unless User.hash_password(password) == user.hashed_password
82 82 end
83 83 else
84 84 # user is not yet registered, try to authenticate with available sources
85 85 attrs = AuthSource.authenticate(login, password)
86 86 if attrs
87 87 onthefly = new(*attrs)
88 88 onthefly.login = login
89 89 onthefly.language = Setting.default_language
90 90 if onthefly.save
91 91 user = find(:first, :conditions => ["login=?", login])
92 92 logger.info("User '#{user.login}' created on the fly.") if logger
93 93 end
94 94 end
95 95 end
96 96 user.update_attribute(:last_login_on, Time.now) if user
97 97 user
98 98
99 99 rescue => text
100 100 raise text
101 101 end
102 102
103 103 # Return user's full name for display
104 def display_name
105 firstname + " " + lastname
106 end
107
108 104 def name
109 display_name
105 "#{firstname} #{lastname}"
110 106 end
111 107
112 108 def active?
113 109 self.status == STATUS_ACTIVE
114 110 end
115 111
116 112 def registered?
117 113 self.status == STATUS_REGISTERED
118 114 end
119 115
120 116 def locked?
121 117 self.status == STATUS_LOCKED
122 118 end
123 119
124 120 def check_password?(clear_password)
125 121 User.hash_password(clear_password) == self.hashed_password
126 122 end
127 123
128 124 def role_for_project(project)
129 125 return nil unless project
130 126 member = memberships.detect {|m| m.project_id == project.id}
131 127 member ? member.role : nil
132 128 end
133 129
134 130 def authorized_to(project, action)
135 131 return true if self.admin?
136 132 role = role_for_project(project)
137 133 role && Permission.allowed_to_role(action, role)
138 134 end
139 135
140 136 def pref
141 137 self.preference ||= UserPreference.new(:user => self)
142 138 end
143 139
144 140 def get_or_create_rss_key
145 141 self.rss_key || Token.create(:user => self, :action => 'feeds')
146 142 end
147 143
148 144 def self.find_by_rss_key(key)
149 145 token = Token.find_by_value(key)
150 146 token && token.user.active? ? token.user : nil
151 147 end
152 148
153 149 def self.find_by_autologin_key(key)
154 150 token = Token.find_by_action_and_value('autologin', key)
155 151 token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
156 152 end
157 153
158 154 def <=>(user)
159 155 lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname
160 156 end
161 157
162 158 private
163 159 # Return password digest
164 160 def self.hash_password(clear_password)
165 161 Digest::SHA1.hexdigest(clear_password || "")
166 162 end
167 163 end
@@ -1,28 +1,28
1 <h2><%= @user.display_name %></h2>
1 <h2><%=h @user.name %></h2>
2 2
3 3 <p>
4 4 <%= mail_to @user.mail unless @user.pref.hide_mail %>
5 5 <ul>
6 6 <li><%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %></li>
7 7 <% for custom_value in @custom_values %>
8 8 <% if !custom_value.value.empty? %>
9 9 <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
10 10 <% end %>
11 11 <% end %>
12 12 </ul>
13 13 </p>
14 14
15 15 <% unless @memberships.empty? %>
16 16 <h3><%=l(:label_project_plural)%></h3>
17 17 <ul>
18 18 <% for membership in @memberships %>
19 19 <li><%= link_to membership.project.name, :controller => 'projects', :action => 'show', :id => membership.project %>
20 20 (<%= membership.role.name %>, <%= format_date(membership.created_on) %>)</li>
21 21 <% end %>
22 22 </ul>
23 23 <% end %>
24 24
25 25 <h3><%=l(:label_activity)%></h3>
26 26 <p>
27 27 <%=l(:label_reported_issues)%>: <%= Issue.count(["author_id=?", @user.id]) %>
28 28 </p> No newline at end of file
@@ -1,13 +1,13
1 1 <div class="attachments">
2 2 <% for attachment in attachments %>
3 3 <p><%= link_to attachment.filename, {:controller => 'attachments', :action => 'download', :id => attachment }, :class => 'icon icon-attachment' %>
4 4 (<%= number_to_human_size attachment.filesize %>)
5 5 <% unless options[:no_author] %>
6 <em><%= attachment.author.display_name %>, <%= format_date(attachment.created_on) %></em>
6 <em><%= attachment.author.name %>, <%= format_date(attachment.created_on) %></em>
7 7 <% end %>
8 8 <% if options[:delete_url] %>
9 9 <%= link_to image_tag('delete.png'), options[:delete_url].update({:attachment_id => attachment}), :confirm => l(:text_are_you_sure), :method => :post %>
10 10 <% end %>
11 11 </p>
12 12 <% end %>
13 13 </div>
@@ -1,36 +1,36
1 1 <div class="contextual">
2 2 <%= link_to_if_authorized l(:button_edit), {:controller => 'documents', :action => 'edit', :id => @document}, :class => 'icon icon-edit' %>
3 3 <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
4 4 </div>
5 5
6 6 <h2><%= @document.title %></h2>
7 7
8 8 <p><em><%= @document.category.name %><br />
9 9 <%= format_date @document.created_on %></em></p>
10 10 <%= textilizable @document.description, :attachments => @document.attachments %>
11 11 <br />
12 12
13 13 <h3><%= l(:label_attachment_plural) %></h3>
14 14 <ul class="documents">
15 15 <% for attachment in @attachments %>
16 16 <li>
17 17 <div class="contextual">
18 18 <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy_attachment', :id => @document, :attachment_id => attachment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
19 19 </div>
20 20 <%= link_to attachment.filename, :action => 'download', :id => @document, :attachment_id => attachment %>
21 21 (<%= number_to_human_size attachment.filesize %>)<br />
22 <em><%= attachment.author.display_name %>, <%= format_date(attachment.created_on) %></em><br />
22 <em><%= attachment.author.name %>, <%= format_date(attachment.created_on) %></em><br />
23 23 <%= lwr(:label_download, attachment.downloads) %>
24 24 </li>
25 25 <% end %>
26 26 </ul>
27 27 <br />
28 28
29 29
30 30 <% if authorize_for('documents', 'add_attachment') %>
31 31 <p><%= toggle_link l(:label_attachment_new), "add_attachment_form" %></p>
32 32 <% form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :class => "tabular", :id => "add_attachment_form", :style => "display:none;") do %>
33 33 <%= render :partial => 'attachments/form' %>
34 34 <%= submit_tag l(:button_add) %>
35 35 <% end %>
36 36 <% end %>
@@ -1,8 +1,8
1 1 <%=l(:label_issue)%> #<%= issue.id %> - <%= issue.subject %>
2 <%=l(:field_author)%>: <%= issue.author.display_name %>
2 <%=l(:field_author)%>: <%= issue.author.name %>
3 3 <%=l(:field_assigned_to)%>: <%= issue.assigned_to ? issue.assigned_to.name : "-" %>
4 4 <%=l(:field_status)%>: <%= issue.status.name %>
5 5
6 6 <%= issue.description %>
7 7
8 8 http://<%= Setting.host_name %>/issues/show/<%= issue.id %> No newline at end of file
@@ -1,32 +1,32
1 1 <div class="contextual">
2 2 <%= link_to_if_authorized l(:button_edit), {:controller => 'news', :action => 'edit', :id => @news}, :class => 'icon icon-edit' %>
3 3 <%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy', :id => @news}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
4 4 </div>
5 5
6 6 <h2><%=h @news.title %></h2>
7 7
8 8 <p><em><% unless @news.summary.empty? %><%=h @news.summary %><br /><% end %>
9 <%= @news.author.display_name %>, <%= format_time(@news.created_on) %></em></p>
9 <%= @news.author.name %>, <%= format_time(@news.created_on) %></em></p>
10 10 <br />
11 11 <%= textilizable(@news.description) %>
12 12 <br />
13 13
14 14 <div id="comments" style="margin-bottom:16px;">
15 15 <h3 class="icon22 icon22-comment"><%= l(:label_comment_plural) %></h3>
16 16 <% @news.comments.each do |comment| %>
17 17 <% next if comment.new_record? %>
18 18 <h4><%= format_time(comment.created_on) %> - <%= comment.author.name %></h4>
19 19 <div class="contextual">
20 20 <%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy_comment', :id => @news, :comment_id => comment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
21 21 </div>
22 22 <%= simple_format(auto_link(h comment.comments))%>
23 23 <% end if @news.comments_count > 0 %>
24 24 </div>
25 25
26 26 <% if authorize_for 'news', 'add_comment' %>
27 27 <p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %></p>
28 28 <% form_tag({:action => 'add_comment', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
29 29 <%= text_area 'comment', 'comments', :cols => 60, :rows => 6 %>
30 30 <p><%= submit_tag l(:button_add) %></p>
31 31 <% end %>
32 32 <% end %> No newline at end of file
@@ -1,43 +1,43
1 1 <%= error_messages_for 'member' %>
2 2 <% roles = Role.find(:all, :order => 'position') %>
3 3 <% users = User.find_active(:all) - @project.users %>
4 4
5 5 <table class="list">
6 6 <thead>
7 7 <th><%= l(:label_user) %></th>
8 8 <th><%= l(:label_role) %></th>
9 9 <th style="width:15%"></th>
10 10 </thead>
11 11 <tbody>
12 12 <% @project.members.find(:all, :include => [:role, :user]).sort{|x,y| x.role.position <=> y.role.position}.each do |member| %>
13 13 <% next if member.new_record? %>
14 14 <tr class="<%= cycle 'odd', 'even' %>">
15 <td><%= member.user.display_name %></td>
15 <td><%= member.name %></td>
16 16 <td align="center">
17 17 <% if authorize_for('members', 'edit') %>
18 18 <% remote_form_for(:member, member, :url => {:controller => 'members', :action => 'edit', :id => member}, :method => :post) do |f| %>
19 19 <%= f.select :role_id, roles.collect{|role| [role.name, role.id]}, {}, :class => "small" %>
20 20 <%= submit_tag l(:button_change), :class => "small" %>
21 21 <% end %>
22 22 <% end %>
23 23 </td>
24 24 <td align="center">
25 25 <small><%= link_to_remote l(:button_delete), { :url => {:controller => 'members', :action => 'destroy', :id => member},
26 26 :method => :post
27 27 }, :title => l(:button_delete),
28 28 :class => 'icon icon-del' %></small>
29 29 </td>
30 30 </tr>
31 31 </tbody>
32 32 <% end; reset_cycle %>
33 33 </table>
34 34 &nbsp;
35 35
36 36 <% if authorize_for('projects', 'add_member') && !users.empty? %>
37 37 <% remote_form_for(:member, @member, :url => {:controller => 'projects', :action => 'add_member', :tab => 'members', :id => @project}, :method => :post) do |f| %>
38 38 <p><label for="member_user_id"><%=l(:label_member_new)%></label><br />
39 39 <%= f.select :user_id, users.collect{|user| [user.name, user.id]} %>
40 40 <%= l(:label_role) %>: <%= f.select :role_id, roles.collect{|role| [role.name, role.id]}, :selected => nil %>
41 41 <%= submit_tag l(:button_add) %></p>
42 42 <% end %>
43 43 <% end %>
@@ -1,13 +1,13
1 1 <h2><%=l(:label_member_plural)%></h2>
2 2
3 3 <% if @members.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %>
4 4
5 5 <% members = @members.group_by {|m| m.role } %>
6 6 <% members.keys.sort{|x,y| x.position <=> y.position}.each do |role| %>
7 7 <h3><%= role.name %></h3>
8 8 <ul>
9 9 <% members[role].each do |m| %>
10 <li><%= link_to m.user.display_name, :controller => 'account', :action => 'show', :id => m.user %> (<%= format_date m.created_on %>)</li>
10 <li><%= link_to m.name, :controller => 'account', :action => 'show', :id => m.user %> (<%= format_date m.created_on %>)</li>
11 11 <% end %>
12 12 </ul>
13 13 <% end %>
General Comments 0
You need to be logged in to leave comments. Login now