Commit fe28193e authored by Jean-Philippe Lang's avatar Jean-Philippe Lang

Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2493 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent 9a986ac0
......@@ -19,6 +19,13 @@ require 'uri'
require 'cgi'
class ApplicationController < ActionController::Base
include Redmine::I18n
# In case the cookie store secret changes
rescue_from CGI::Session::CookieStore::TamperedWithCookie do |exception|
render :text => 'Your session was invalid and has been reset. Please, reload this page.', :status => 500
end
layout 'base'
before_filter :user_setup, :check_if_login_required, :set_localization
......@@ -64,20 +71,18 @@ class ApplicationController < ActionController::Base
end
def set_localization
User.current.language = nil unless User.current.logged?
lang = begin
if !User.current.language.blank? && GLoc.valid_language?(User.current.language)
User.current.language
elsif request.env['HTTP_ACCEPT_LANGUAGE']
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
if !accept_lang.blank? && (GLoc.valid_language?(accept_lang) || GLoc.valid_language?(accept_lang = accept_lang.split('-').first))
User.current.language = accept_lang
end
lang = nil
if User.current.logged?
lang = find_language(User.current.language)
end
if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
if !accept_lang.blank?
lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
end
rescue
nil
end || Setting.default_language
set_language_if_valid(lang)
end
lang ||= Setting.default_language
set_language_if_valid(lang)
end
def require_login
......@@ -152,7 +157,7 @@ class ApplicationController < ActionController::Base
def render_error(msg)
flash.now[:error] = msg
render :nothing => true, :layout => !request.xhr?, :status => 500
render :text => '', :layout => !request.xhr?, :status => 500
end
def render_feed(items, options={})
......@@ -225,6 +230,8 @@ class ApplicationController < ActionController::Base
tmp.collect!{|val, q| val}
end
return tmp
rescue
nil
end
# Returns a string that can be used as filename value in Content-Disposition header
......
......@@ -258,7 +258,9 @@ class IssuesController < ApplicationController
if unsaved_issue_ids.empty?
flash[:notice] = l(:notice_successful_update) unless @issues.empty?
else
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, @issues.size, '#' + unsaved_issue_ids.join(', #'))
flash[:error] = l(:notice_failed_to_save_issues, :count => unsaved_issue_ids.size,
:total => @issues.size,
:ids => '#' + unsaved_issue_ids.join(', #'))
end
redirect_to(params[:back_to] || {:controller => 'issues', :action => 'index', :project_id => @project})
return
......@@ -291,7 +293,9 @@ class IssuesController < ApplicationController
if unsaved_issue_ids.empty?
flash[:notice] = l(:notice_successful_update) unless @issues.empty?
else
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, @issues.size, '#' + unsaved_issue_ids.join(', #'))
flash[:error] = l(:notice_failed_to_save_issues, :count => unsaved_issue_ids.size,
:total => @issues.size,
:ids => '#' + unsaved_issue_ids.join(', #'))
end
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
return
......
......@@ -238,8 +238,7 @@ private
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
fields = []
month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
graph = SVG::Graph::Bar.new(
:height => 300,
......
......@@ -22,6 +22,7 @@ require 'cgi'
module ApplicationHelper
include Redmine::WikiFormatting::Macros::Definitions
include Redmine::I18n
include GravatarHelper::PublicMethods
extend Forwardable
......@@ -89,26 +90,9 @@ module ApplicationHelper
html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
link_to name, {}, html_options
end
def format_date(date)
return nil unless date
# "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
date.strftime(@date_format)
end
def format_time(time, include_date = true)
return nil unless time
time = time.to_time if time.is_a?(String)
zone = User.current.time_zone
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
@time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
end
def format_activity_title(text)
h(truncate_single_line(text, 100))
h(truncate_single_line(text, :length => 100))
end
def format_activity_day(date)
......@@ -116,14 +100,7 @@ module ApplicationHelper
end
def format_activity_description(text)
h(truncate(text.to_s, 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
end
def distance_of_date_in_words(from_date, to_date = 0)
from_date = from_date.to_date if from_date.respond_to?(:to_date)
to_date = to_date.to_date if to_date.respond_to?(:to_date)
distance_in_days = (to_date - from_date).abs
lwr(:actionview_datehelper_time_in_words_day, distance_in_days)
h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
end
def due_date_distance_in_words(date)
......@@ -235,20 +212,7 @@ module ApplicationHelper
{:controller => 'projects', :action => 'activity', :id => @project, :from => created.to_date},
:title => format_time(created))
author_tag = (author.is_a?(User) && !author.anonymous?) ? link_to(h(author), :controller => 'account', :action => 'show', :id => author) : h(author || 'Anonymous')
l(options[:label] || :label_added_time_by, author_tag, time_tag)
end
def l_or_humanize(s, options={})
k = "#{options[:prefix]}#{s}".to_sym
l_has_string?(k) ? l(k) : s.to_s.humanize
end
def day_name(day)
l(:general_day_names).split(',')[day-1]
end
def month_name(month)
l(:actionview_datehelper_select_month_names).split(',')[month-1]
l(options[:label] || :label_added_time_by, :author => author_tag, :age => time_tag)
end
def syntax_highlight(name, content)
......@@ -308,9 +272,9 @@ module ApplicationHelper
end
def other_formats_links(&block)
concat('<p class="other-formats">' + l(:label_export_to), block.binding)
concat('<p class="other-formats">' + l(:label_export_to))
yield Redmine::Views::OtherFormatsBuilder.new(self)
concat('</p>', block.binding)
concat('</p>')
end
def page_header_title
......@@ -479,7 +443,7 @@ module ApplicationHelper
if project && (changeset = project.changesets.find_by_revision(oid))
link = link_to("r#{oid}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => oid},
:class => 'changeset',
:title => truncate_single_line(changeset.comments, 100))
:title => truncate_single_line(changeset.comments, :length => 100))
end
elsif sep == '#'
oid = oid.to_i
......@@ -488,7 +452,7 @@ module ApplicationHelper
if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current))
link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
:class => (issue.closed? ? 'issue closed' : 'issue'),
:title => "#{truncate(issue.subject, 100)} (#{issue.status.name})")
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
link = content_tag('del', link) if issue.closed?
end
when 'document'
......@@ -503,7 +467,7 @@ module ApplicationHelper
end
when 'message'
if message = Message.find_by_id(oid, :include => [:parent, {:board => :project}], :conditions => Project.visible_by(User.current))
link = link_to h(truncate(message.subject, 60)), {:only_path => only_path,
link = link_to h(truncate(message.subject, :length => 60)), {:only_path => only_path,
:controller => 'messages',
:action => 'show',
:board_id => message.board,
......@@ -530,7 +494,7 @@ module ApplicationHelper
if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
:class => 'changeset',
:title => truncate_single_line(changeset.comments, 100)
:title => truncate_single_line(changeset.comments, :length => 100)
end
when 'source', 'export'
if project && project.repository
......@@ -565,46 +529,9 @@ module ApplicationHelper
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
end
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_variable_get("@#{object_name}")
if object && !object.errors.empty?
# build full_messages here with controller current language
full_messages = []
object.errors.each do |attr, msg|
next if msg.nil?
msg = [msg] unless msg.is_a?(Array)
if attr == "base"
full_messages << l(*msg)
else
full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(*msg) unless attr == "custom_values"
end
end
# retrieve custom values error messages
if object.errors[:custom_values]
object.custom_values.each do |v|
v.errors.each do |attr, msg|
next if msg.nil?
msg = [msg] unless msg.is_a?(Array)
full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(*msg)
end
end
end
content_tag("div",
content_tag(
options[:header_tag] || "span", lwr(:gui_validation_error, full_messages.length) + ":"
) +
content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
)
else
""
end
end
def lang_options_for_select(blank=true)
(blank ? [["(auto)", ""]] : []) +
GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
end
def label_tag_for(name, option_tags = nil, options = {})
......
......@@ -119,7 +119,7 @@ module IssuesHelper
case detail.property
when 'attr', 'cf'
if !detail.old_value.blank?
label + " " + l(:text_journal_changed, old_value, value)
label + " " + l(:text_journal_changed, :old => old_value, :new => value)
else
label + " " + l(:text_journal_set_to, value)
end
......
......@@ -19,7 +19,7 @@ module MessagesHelper
def link_to_message(message)
return '' unless message
link_to h(truncate(message.subject, 60)), :controller => 'messages',
link_to h(truncate(message.subject, :length => 60)), :controller => 'messages',
:action => 'show',
:board_id => message.board_id,
:id => message.root,
......
......@@ -22,8 +22,8 @@ module SettingsHelper
{:name => 'authentication', :partial => 'settings/authentication', :label => :label_authentication},
{:name => 'projects', :partial => 'settings/projects', :label => :label_project_plural},
{:name => 'issues', :partial => 'settings/issues', :label => :label_issue_tracking},
{:name => 'notifications', :partial => 'settings/notifications', :label => l(:field_mail_notification)},
{:name => 'mail_handler', :partial => 'settings/mail_handler', :label => l(:label_incoming_emails)},
{:name => 'notifications', :partial => 'settings/notifications', :label => :field_mail_notification},
{:name => 'mail_handler', :partial => 'settings/mail_handler', :label => :label_incoming_emails},
{:name => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural}
]
end
......
......@@ -109,7 +109,7 @@ class Changeset < ActiveRecord::Base
if self.scmid && (! (csettext =~ /^r[0-9]+$/))
csettext = "commit:\"#{self.scmid}\""
end
journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext))
journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, csettext))
issue.status = fix_status
issue.done_ratio = done_ratio if done_ratio
issue.save
......
......@@ -48,14 +48,14 @@ class CustomField < ActiveRecord::Base
def validate
if self.field_format == "list"
errors.add(:possible_values, :activerecord_error_blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :activerecord_error_invalid) unless self.possible_values.is_a? Array
errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
end
# validate default value
v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil)
v.custom_field.is_required = false
errors.add(:default_value, :activerecord_error_invalid) unless v.valid?
errors.add(:default_value, :invalid) unless v.valid?
end
# Makes possible_values accept a multiline string
......
......@@ -45,22 +45,22 @@ class CustomValue < ActiveRecord::Base
protected
def validate
if value.blank?
errors.add(:value, :activerecord_error_blank) if custom_field.is_required? and value.blank?
errors.add(:value, :blank) if custom_field.is_required? and value.blank?
else
errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.blank? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length
errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
errors.add(:value, :invalid) unless custom_field.regexp.blank? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length
errors.add(:value, :too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
# Format specific validations
case custom_field.field_format
when 'int'
errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[+-]?\d+$/
errors.add(:value, :not_a_number) unless value =~ /^[+-]?\d+$/
when 'float'
begin; Kernel.Float(value); rescue; errors.add(:value, :activerecord_error_invalid) end
begin; Kernel.Float(value); rescue; errors.add(:value, :invalid) end
when 'date'
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/
errors.add(:value, :not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/
when 'list'
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include?(value)
errors.add(:value, :inclusion) unless custom_field.possible_values.include?(value)
end
end
end
......
......@@ -129,20 +129,20 @@ class Issue < ActiveRecord::Base
def validate
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :activerecord_error_not_a_date
errors.add :due_date, :not_a_date
end
if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date
errors.add :due_date, :greater_than_start_date
end
if start_date && soonest_start && start_date < soonest_start
errors.add :start_date, :activerecord_error_invalid
errors.add :start_date, :invalid
end
end
def validate_on_create
errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
errors.add :tracker_id, :invalid unless project.trackers.include?(tracker)
end
def before_create
......
......@@ -39,9 +39,9 @@ class IssueRelation < ActiveRecord::Base
def validate
if issue_from && issue_to
errors.add :issue_to_id, :activerecord_error_invalid if issue_from_id == issue_to_id
errors.add :issue_to_id, :activerecord_error_not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations?
errors.add_to_base :activerecord_error_circular_dependency if issue_to.all_dependent_issues.include? issue_from
errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id
errors.add :issue_to_id, :not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations?
errors.add_to_base :circular_dependency if issue_to.all_dependent_issues.include? issue_from
end
end
......
......@@ -236,4 +236,9 @@ class MailHandler < ActionMailer::Base
end
@plain_text_body.strip!
end
def self.full_sanitizer
@full_sanitizer ||= HTML::FullSanitizer.new
end
end
......@@ -21,6 +21,7 @@ class Mailer < ActionMailer::Base
helper :custom_fields
include ActionController::UrlWriter
include Redmine::I18n
def issue_add(issue)
redmine_headers 'Project' => issue.project.identifier,
......
......@@ -24,7 +24,7 @@ class Member < ActiveRecord::Base
validates_uniqueness_of :user_id, :scope => :project_id
def validate
errors.add :role_id, :activerecord_error_invalid if role && !role.member?
errors.add :role_id, :invalid if role && !role.member?
end
def name
......
......@@ -306,7 +306,7 @@ class Project < ActiveRecord::Base
protected
def validate
errors.add(:identifier, :activerecord_error_invalid) if !identifier.blank? && identifier.match(/^\d*$/)
errors.add(:identifier, :invalid) if !identifier.blank? && identifier.match(/^\d*$/)
end
private
......
......@@ -17,7 +17,7 @@
class QueryColumn
attr_accessor :name, :sortable, :default_order
include GLoc
include Redmine::I18n
def initialize(name, options={})
self.name = name
......@@ -26,7 +26,6 @@ class QueryColumn
end
def caption
set_language_if_valid(User.current.language)
l("field_#{name}")
end
end
......@@ -113,7 +112,6 @@ class Query < ActiveRecord::Base
def initialize(attributes = nil)
super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
set_language_if_valid(User.current.language)
end
def after_initialize
......@@ -123,7 +121,7 @@ class Query < ActiveRecord::Base
def validate
filters.each_key do |field|
errors.add label_for(field), :activerecord_error_blank unless
errors.add label_for(field), :blank unless
# filter requires one or more values
(values_for(field) and !values_for(field).first.blank?) or
# filter doesn't require any value
......
......@@ -25,7 +25,7 @@ class Repository < ActiveRecord::Base
before_destroy :clear_changesets
# Checks if the SCM is enabled when creating a repository
validate_on_create { |r| r.errors.add(:type, :activerecord_error_invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
# Removes leading and trailing whitespace
def url=(arg)
......
......@@ -26,13 +26,13 @@ class TimeEntry < ActiveRecord::Base
attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek
acts_as_customizable
acts_as_event :title => Proc.new {|o| "#{o.user}: #{lwr(:label_f_hour, o.hours)} (#{(o.issue || o.project).event_title})"},
acts_as_event :title => Proc.new {|o| "#{o.user}: #{l_hours(o.hours)} (#{(o.issue || o.project).event_title})"},
:url => Proc.new {|o| {:controller => 'timelog', :action => 'details', :project_id => o.project}},
:author => :user,
:description => :comments
validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
validates_numericality_of :hours, :allow_nil => true, :message => :activerecord_error_invalid
validates_numericality_of :hours, :allow_nil => true, :message => :invalid
validates_length_of :comments, :maximum => 255, :allow_nil => true
def after_initialize
......@@ -48,9 +48,9 @@ class TimeEntry < ActiveRecord::Base
end
def validate
errors.add :hours, :activerecord_error_invalid if hours && (hours < 0 || hours >= 1000)
errors.add :project_id, :activerecord_error_invalid if project.nil?
errors.add :issue_id, :activerecord_error_invalid if (issue_id && !issue) || (issue && project!=issue.project)
errors.add :hours, :invalid if hours && (hours < 0 || hours >= 1000)
errors.add :project_id, :invalid if project.nil?
errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project)
end
def hours=(h)
......
......@@ -25,7 +25,7 @@ class Version < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]
validates_length_of :name, :maximum => 60
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => 'activerecord_error_not_a_date', :allow_nil => true
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
def start_date
effective_date
......
......@@ -25,6 +25,6 @@ class Watcher < ActiveRecord::Base
protected
def validate
errors.add :user_id, :activerecord_error_invalid unless user.nil? || user.active?
errors.add :user_id, :invalid unless user.nil? || user.active?
end
end
......@@ -129,9 +129,9 @@ class WikiPage < ActiveRecord::Base
protected
def validate
errors.add(:parent_title, :activerecord_error_invalid) if !@parent_title.blank? && parent.nil?
errors.add(:parent_title, :activerecord_error_circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
errors.add(:parent_title, :activerecord_error_not_same_project) if parent && (parent.wiki_id != wiki_id)
errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
end
end
......
......@@ -20,7 +20,7 @@ while day <= calendar.enddt %>
image_tag('arrow_to.png')
end %>
<%= h("#{i.project} -") unless @project && @project == i.project %>
<%= link_to_issue i %>: <%= h(truncate(i.subject, 30)) %>
<%= link_to_issue i %>: <%= h(truncate(i.subject, :length => 30)) %>
<span class="tip"><%= render_issue_tooltip i %></span>
</div>
<% else %>
......
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.title truncate_single_line(@title, 100)
xml.title truncate_single_line(@title, :length => 100)
xml.link "rel" => "self", "href" => url_for(params.merge({:format => nil, :only_path => false}))
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
xml.id url_for(:controller => 'welcome', :only_path => false)
......@@ -11,9 +11,9 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.entry do
url = url_for(item.event_url(:only_path => false))
if @project
xml.title truncate_single_line(item.event_title, 100)
xml.title truncate_single_line(item.event_title, :length => 100)
else
xml.title truncate_single_line("#{item.project} - #{item.event_title}", 100)
xml.title truncate_single_line("#{item.project} - #{item.event_title}", :length => 100)
end
xml.link "rel" => "alternate", "href" => url
xml.id url
......
......@@ -35,7 +35,7 @@
<td align="center"><%= image_tag 'true.png' if custom_field.is_required? %></td>
<% if tab[:name] == 'IssueCustomField' %>
<td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td>
<td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td>
<td align="center"><%= l(:label_x_projects, :count => custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td>
<% end %>
<td align="center" style="width:15%;">
<%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => custom_field, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %>
......
<p><%= link_to h(document.title), :controller => 'documents', :action => 'show', :id => document %><br />
<% unless document.description.blank? %><%=h(truncate(document.description, 250)) %><br /><% end %>
<% unless document.description.blank? %><%=h(truncate(document.description, :length => 250)) %><br /><% end %>
<em><%= format_time(document.created_on) %></em></p>
\ No newline at end of file
......@@ -10,7 +10,7 @@
<table style="width:100%">