Merged trunk r1773.
git-svn-id: http://redmine.rubyforge.org/svn/branches/work@1774 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'coderay'
|
||||
require 'coderay/helpers/file_type'
|
||||
|
||||
module ApplicationHelper
|
||||
include Redmine::WikiFormatting::Macros::Definitions
|
||||
|
||||
@@ -31,6 +34,12 @@ module ApplicationHelper
|
||||
def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
|
||||
link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
|
||||
end
|
||||
|
||||
# Display a link to remote if user is authorized
|
||||
def link_to_remote_if_authorized(name, options = {}, html_options = nil)
|
||||
url = options[:url] || {}
|
||||
link_to_remote(name, options, html_options) if authorize_for(url[:controller] || params[:controller], url[:action])
|
||||
end
|
||||
|
||||
# Display a link to user's account page
|
||||
def link_to_user(user)
|
||||
@@ -38,9 +47,23 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def link_to_issue(issue, options={})
|
||||
options[:class] ||= ''
|
||||
options[:class] << ' issue'
|
||||
options[:class] << ' closed' if issue.closed?
|
||||
link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
|
||||
end
|
||||
|
||||
# Generates a link to an attachment.
|
||||
# Options:
|
||||
# * :text - Link text (default to attachment filename)
|
||||
# * :download - Force download (default: false)
|
||||
def link_to_attachment(attachment, options={})
|
||||
text = options.delete(:text) || attachment.filename
|
||||
action = options.delete(:download) ? 'download' : 'show'
|
||||
|
||||
link_to(h(text), {:controller => 'attachments', :action => action, :id => attachment, :filename => attachment.filename }, options)
|
||||
end
|
||||
|
||||
def toggle_link(name, id, options={})
|
||||
onclick = "Element.toggle('#{id}'); "
|
||||
onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
|
||||
@@ -48,14 +71,6 @@ module ApplicationHelper
|
||||
link_to(name, "#", :onclick => onclick)
|
||||
end
|
||||
|
||||
def show_and_goto_link(name, id, options={})
|
||||
onclick = "Element.show('#{id}'); "
|
||||
onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
|
||||
onclick << "Element.scrollTo('#{id}'); "
|
||||
onclick << "return false;"
|
||||
link_to(name, "#", options.merge(:onclick => onclick))
|
||||
end
|
||||
|
||||
def image_to_function(name, function, html_options = {})
|
||||
html_options.symbolize_keys!
|
||||
tag(:input, html_options.merge({
|
||||
@@ -80,23 +95,25 @@ module ApplicationHelper
|
||||
return nil unless time
|
||||
time = time.to_time if time.is_a?(String)
|
||||
zone = User.current.time_zone
|
||||
if time.utc?
|
||||
local = zone ? zone.adjust(time) : time.getlocal
|
||||
else
|
||||
local = zone ? zone.adjust(time.getutc) : time
|
||||
end
|
||||
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.utc_to_local : 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
|
||||
|
||||
# Truncates and returns the string as a single line
|
||||
def truncate_single_line(string, *args)
|
||||
truncate(string, *args).gsub(%r{[\r\n]+}m, ' ')
|
||||
end
|
||||
|
||||
def html_hours(text)
|
||||
text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
|
||||
end
|
||||
|
||||
def authoring(created, author)
|
||||
time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
|
||||
l(:label_added_time_by, author || 'Anonymous', time_tag)
|
||||
author_tag = (author.is_a?(User) && !author.anonymous?) ? link_to(h(author), :controller => 'account', :action => 'show', :id => author) : h(author || 'Anonymous')
|
||||
l(:label_added_time_by, author_tag, time_tag)
|
||||
end
|
||||
|
||||
def l_or_humanize(s)
|
||||
@@ -111,6 +128,15 @@ module ApplicationHelper
|
||||
l(:actionview_datehelper_select_month_names).split(',')[month-1]
|
||||
end
|
||||
|
||||
def syntax_highlight(name, content)
|
||||
type = CodeRay::FileType[name]
|
||||
type ? CodeRay.scan(content, type).html : h(content)
|
||||
end
|
||||
|
||||
def to_path_param(path)
|
||||
path.to_s.split(%r{[/\\]}).select {|p| !p.blank?}
|
||||
end
|
||||
|
||||
def pagination_links_full(paginator, count=nil, options={})
|
||||
page_param = options.delete(:page_param) || :page
|
||||
url_param = params.dup
|
||||
@@ -157,7 +183,8 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def breadcrumb(*args)
|
||||
content_tag('p', args.join(' » ') + ' » ', :class => 'breadcrumb')
|
||||
elements = args.flatten
|
||||
elements.any? ? content_tag('p', args.join(' » ') + ' » ', :class => 'breadcrumb') : nil
|
||||
end
|
||||
|
||||
def html_title(*args)
|
||||
@@ -185,7 +212,7 @@ module ApplicationHelper
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
case args.size
|
||||
when 1
|
||||
obj = nil
|
||||
obj = options[:object]
|
||||
text = args.shift
|
||||
when 2
|
||||
obj = args.shift
|
||||
@@ -225,12 +252,12 @@ module ApplicationHelper
|
||||
case options[:wiki_links]
|
||||
when :local
|
||||
# used for local links to html files
|
||||
format_wiki_link = Proc.new {|project, title| "#{title}.html" }
|
||||
format_wiki_link = Proc.new {|project, title, anchor| "#{title}.html" }
|
||||
when :anchor
|
||||
# used for single-file wiki export
|
||||
format_wiki_link = Proc.new {|project, title| "##{title}" }
|
||||
format_wiki_link = Proc.new {|project, title, anchor| "##{title}" }
|
||||
else
|
||||
format_wiki_link = Proc.new {|project, title| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title) }
|
||||
format_wiki_link = Proc.new {|project, title, anchor| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title, :anchor => anchor) }
|
||||
end
|
||||
|
||||
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
|
||||
@@ -256,9 +283,14 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
if link_project && link_project.wiki
|
||||
# extract anchor
|
||||
anchor = nil
|
||||
if page =~ /^(.+?)\#(.+)$/
|
||||
page, anchor = $1, $2
|
||||
end
|
||||
# check if page exists
|
||||
wiki_page = link_project.wiki.find_page(page)
|
||||
link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)),
|
||||
link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page), anchor),
|
||||
:class => ('wiki-page' + (wiki_page ? '' : ' new')))
|
||||
else
|
||||
# project or wiki doesn't exist
|
||||
@@ -293,7 +325,9 @@ module ApplicationHelper
|
||||
# source:some/file#L120 -> Link to line 120 of the file
|
||||
# source:some/file@52#L120 -> Link to line 120 of the file's revision 52
|
||||
# export:some/file -> Force the download of the file
|
||||
text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
|
||||
# Forum messages:
|
||||
# message#1218 -> Link to message with id 1218
|
||||
text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export|message)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|\s|<|$)}) do |m|
|
||||
leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
|
||||
link = nil
|
||||
if esc.nil?
|
||||
@@ -301,7 +335,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(changeset.comments, 100))
|
||||
:title => truncate_single_line(changeset.comments, 100))
|
||||
end
|
||||
elsif sep == '#'
|
||||
oid = oid.to_i
|
||||
@@ -323,6 +357,16 @@ module ApplicationHelper
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
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,
|
||||
:controller => 'messages',
|
||||
:action => 'show',
|
||||
:board_id => message.board,
|
||||
:id => message.root,
|
||||
:anchor => (message.parent ? "message-#{message.id}" : nil)},
|
||||
:class => 'message'
|
||||
end
|
||||
end
|
||||
elsif sep == ':'
|
||||
# removes the double quotes if any
|
||||
@@ -340,13 +384,16 @@ module ApplicationHelper
|
||||
end
|
||||
when 'commit'
|
||||
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(changeset.comments, 100)
|
||||
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)
|
||||
end
|
||||
when 'source', 'export'
|
||||
if project && project.repository
|
||||
name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
|
||||
path, rev, anchor = $1, $3, $5
|
||||
link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :path => path,
|
||||
link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
|
||||
:path => to_path_param(path),
|
||||
:rev => rev,
|
||||
:anchor => anchor,
|
||||
:format => (prefix == 'export' ? 'raw' : nil)},
|
||||
@@ -428,7 +475,8 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def back_url_hidden_field_tag
|
||||
hidden_field_tag 'back_url', (params[:back_url] || request.env['HTTP_REFERER'])
|
||||
back_url = params[:back_url] || request.env['HTTP_REFERER']
|
||||
hidden_field_tag('back_url', back_url) unless back_url.blank?
|
||||
end
|
||||
|
||||
def check_all_links(form_name)
|
||||
|
||||
@@ -22,4 +22,8 @@ module AttachmentsHelper
|
||||
render :partial => 'attachments/links', :locals => {:attachments => attachments, :options => options}
|
||||
end
|
||||
end
|
||||
|
||||
def to_utf8(str)
|
||||
str
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,6 +19,7 @@ module CustomFieldsHelper
|
||||
|
||||
def custom_fields_tabs
|
||||
tabs = [{:name => 'IssueCustomField', :label => :label_issue_plural},
|
||||
{:name => 'TimeEntryCustomField', :label => :label_spent_time},
|
||||
{:name => 'ProjectCustomField', :label => :label_project_plural},
|
||||
{:name => 'UserCustomField', :label => :label_user_plural},
|
||||
{:name => 'GroupCustomField', :label => :label_group_plural}
|
||||
@@ -26,37 +27,40 @@ module CustomFieldsHelper
|
||||
end
|
||||
|
||||
# Return custom field html tag corresponding to its format
|
||||
def custom_field_tag(custom_value)
|
||||
def custom_field_tag(name, custom_value)
|
||||
custom_field = custom_value.custom_field
|
||||
field_name = "custom_fields[#{custom_field.id}]"
|
||||
field_id = "custom_fields_#{custom_field.id}"
|
||||
field_name = "#{name}[custom_field_values][#{custom_field.id}]"
|
||||
field_id = "#{name}_custom_field_values_#{custom_field.id}"
|
||||
|
||||
case custom_field.field_format
|
||||
when "date"
|
||||
text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) +
|
||||
text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) +
|
||||
calendar_for(field_id)
|
||||
when "text"
|
||||
text_area 'custom_value', 'value', :name => field_name, :id => field_id, :rows => 3, :style => 'width:99%'
|
||||
text_area_tag(field_name, custom_value.value, :id => field_id, :rows => 3, :style => 'width:90%')
|
||||
when "bool"
|
||||
check_box 'custom_value', 'value', :name => field_name, :id => field_id
|
||||
check_box_tag(field_name, '1', custom_value.true?, :id => field_id) + hidden_field_tag(field_name, '0')
|
||||
when "list"
|
||||
select 'custom_value', 'value', custom_field.possible_values, { :include_blank => true }, :name => field_name, :id => field_id
|
||||
blank_option = custom_field.is_required? ?
|
||||
(custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') :
|
||||
'<option></option>'
|
||||
select_tag(field_name, blank_option + options_for_select(custom_field.possible_values, custom_value.value), :id => field_id)
|
||||
else
|
||||
text_field 'custom_value', 'value', :name => field_name, :id => field_id
|
||||
text_field_tag(field_name, custom_value.value, :id => field_id)
|
||||
end
|
||||
end
|
||||
|
||||
# Return custom field label tag
|
||||
def custom_field_label_tag(custom_value)
|
||||
def custom_field_label_tag(name, custom_value)
|
||||
content_tag "label", custom_value.custom_field.name +
|
||||
(custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
|
||||
:for => "custom_fields_#{custom_value.custom_field.id}",
|
||||
:for => "#{name}_custom_field_values_#{custom_value.custom_field.id}",
|
||||
:class => (custom_value.errors.empty? ? nil : "error" )
|
||||
end
|
||||
|
||||
# Return custom field tag with its label tag
|
||||
def custom_field_tag_with_label(custom_value)
|
||||
custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
|
||||
def custom_field_tag_with_label(name, custom_value)
|
||||
custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
|
||||
end
|
||||
|
||||
# Return a string used to display a custom value
|
||||
|
||||
@@ -54,9 +54,15 @@ module IssuesHelper
|
||||
when 'due_date', 'start_date'
|
||||
value = format_date(detail.value.to_date) if detail.value
|
||||
old_value = format_date(detail.old_value.to_date) if detail.old_value
|
||||
when 'project_id'
|
||||
p = Project.find_by_id(detail.value) and value = p.name if detail.value
|
||||
p = Project.find_by_id(detail.old_value) and old_value = p.name if detail.old_value
|
||||
when 'status_id'
|
||||
s = IssueStatus.find_by_id(detail.value) and value = s.name if detail.value
|
||||
s = IssueStatus.find_by_id(detail.old_value) and old_value = s.name if detail.old_value
|
||||
when 'tracker_id'
|
||||
t = Tracker.find_by_id(detail.value) and value = t.name if detail.value
|
||||
t = Tracker.find_by_id(detail.old_value) and old_value = t.name if detail.old_value
|
||||
when 'assigned_to_id'
|
||||
u = User.find_by_id(detail.value) and value = u.name if detail.value
|
||||
u = User.find_by_id(detail.old_value) and old_value = u.name if detail.old_value
|
||||
@@ -69,6 +75,9 @@ module IssuesHelper
|
||||
when 'fixed_version_id'
|
||||
v = Version.find_by_id(detail.value) and value = v.name if detail.value
|
||||
v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
|
||||
when 'estimated_hours'
|
||||
value = "%0.02f" % detail.value.to_f unless detail.value.blank?
|
||||
old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
|
||||
end
|
||||
when 'cf'
|
||||
custom_field = CustomField.find_by_id(detail.prop_key)
|
||||
@@ -89,9 +98,9 @@ module IssuesHelper
|
||||
label = content_tag('strong', label)
|
||||
old_value = content_tag("i", h(old_value)) if detail.old_value
|
||||
old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
|
||||
if detail.property == 'attachment' && !value.blank? && Attachment.find_by_id(detail.prop_key)
|
||||
if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
|
||||
# Link to the attachment if it has not been removed
|
||||
value = link_to(value, :controller => 'attachments', :action => 'download', :id => detail.prop_key)
|
||||
value = link_to_attachment(a)
|
||||
else
|
||||
value = content_tag("i", h(value)) if value
|
||||
end
|
||||
@@ -120,6 +129,7 @@ module IssuesHelper
|
||||
|
||||
def issues_to_csv(issues, project = nil)
|
||||
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
||||
decimal_separator = l(:general_csv_decimal_separator)
|
||||
export = StringIO.new
|
||||
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
|
||||
# csv header fields
|
||||
@@ -142,7 +152,7 @@ module IssuesHelper
|
||||
]
|
||||
# Export project custom fields if project is given
|
||||
# otherwise export custom fields marked as "For all projects"
|
||||
custom_fields = project.nil? ? IssueCustomField.for_all : project.all_custom_fields
|
||||
custom_fields = project.nil? ? IssueCustomField.for_all : project.all_issue_custom_fields
|
||||
custom_fields.each {|f| headers << f.name}
|
||||
# Description in the last column
|
||||
headers << l(:field_description)
|
||||
@@ -162,7 +172,7 @@ module IssuesHelper
|
||||
format_date(issue.start_date),
|
||||
format_date(issue.due_date),
|
||||
issue.done_ratio,
|
||||
issue.estimated_hours,
|
||||
issue.estimated_hours.to_s.gsub('.', decimal_separator),
|
||||
format_time(issue.created_on),
|
||||
format_time(issue.updated_on)
|
||||
]
|
||||
|
||||
@@ -19,13 +19,16 @@ module JournalsHelper
|
||||
def render_notes(journal, options={})
|
||||
content = ''
|
||||
editable = journal.editable_by?(User.current)
|
||||
if editable && !journal.notes.blank?
|
||||
links = []
|
||||
links = []
|
||||
if !journal.notes.blank?
|
||||
links << link_to_remote(image_tag('comment.png'),
|
||||
{ :url => {:controller => 'issues', :action => 'reply', :id => journal.journalized, :journal_id => journal} },
|
||||
:title => l(:button_quote)) if options[:reply_links]
|
||||
links << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes",
|
||||
{ :controller => 'journals', :action => 'edit', :id => journal },
|
||||
:title => l(:button_edit))
|
||||
content << content_tag('div', links.join(' '), :class => 'contextual')
|
||||
:title => l(:button_edit)) if editable
|
||||
end
|
||||
content << content_tag('div', links.join(' '), :class => 'contextual') unless links.empty?
|
||||
content << textilizable(journal, :notes)
|
||||
content_tag('div', content, :id => "journal-#{journal.id}-notes", :class => (editable ? 'wiki editable' : 'wiki'))
|
||||
end
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# redMine - project management software
|
||||
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module MailHandlerHelper
|
||||
end
|
||||
@@ -21,18 +21,22 @@ module ProjectsHelper
|
||||
link_to h(version.name), { :controller => 'versions', :action => 'show', :id => version }, options
|
||||
end
|
||||
|
||||
def format_activity_title(text)
|
||||
h(truncate_single_line(text, 100))
|
||||
end
|
||||
|
||||
def format_activity_day(date)
|
||||
date == Date.today ? l(:label_today).titleize : format_date(date)
|
||||
end
|
||||
|
||||
def format_activity_description(text)
|
||||
h(truncate(text, 250))
|
||||
h(truncate(text.to_s, 250).gsub(%r{<(pre|code)>.*$}m, '...'))
|
||||
end
|
||||
|
||||
# Renders the member list displayed on project overview
|
||||
def render_member_list(project)
|
||||
parts = []
|
||||
memberships_by_role = project.memberships.find(:all, :include => :role, :order => 'position').group_by {|m| m.role}
|
||||
memberships_by_role = project.memberships.find(:all, :include => :role, :order => "#{Role.table_name}.position").group_by {|m| m.role}
|
||||
memberships_by_role.keys.sort.each do |role|
|
||||
role_parts = []
|
||||
# Display group name (with its 5 first users) or user name
|
||||
|
||||
@@ -15,20 +15,23 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'coderay'
|
||||
require 'coderay/helpers/file_type'
|
||||
require 'iconv'
|
||||
|
||||
module RepositoriesHelper
|
||||
def syntax_highlight(name, content)
|
||||
type = CodeRay::FileType[name]
|
||||
type ? CodeRay.scan(content, type).html : h(content)
|
||||
end
|
||||
|
||||
def format_revision(txt)
|
||||
txt.to_s[0,8]
|
||||
end
|
||||
|
||||
def render_properties(properties)
|
||||
unless properties.nil? || properties.empty?
|
||||
content = ''
|
||||
properties.keys.sort.each do |property|
|
||||
content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>")
|
||||
end
|
||||
content_tag('ul', content, :class => 'properties')
|
||||
end
|
||||
end
|
||||
|
||||
def to_utf8(str)
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
|
||||
@@ -48,10 +51,13 @@ module RepositoriesHelper
|
||||
end
|
||||
|
||||
def scm_select_tag(repository)
|
||||
container = [[]]
|
||||
REDMINE_SUPPORTED_SCM.each {|scm| container << ["Repository::#{scm}".constantize.scm_name, scm]}
|
||||
scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']]
|
||||
REDMINE_SUPPORTED_SCM.each do |scm|
|
||||
scm_options << ["Repository::#{scm}".constantize.scm_name, scm] if Setting.enabled_scm.include?(scm) || (repository && repository.class.name.demodulize == scm)
|
||||
end
|
||||
|
||||
select_tag('repository_scm',
|
||||
options_for_select(container, repository.class.name.demodulize),
|
||||
options_for_select(scm_options, repository.class.name.demodulize),
|
||||
:disabled => (repository && !repository.new_record?),
|
||||
:onchange => remote_function(:url => { :controller => 'repositories', :action => 'edit', :id => @project }, :method => :get, :with => "Form.serialize(this.form)")
|
||||
)
|
||||
@@ -95,4 +101,8 @@ module RepositoriesHelper
|
||||
def bazaar_field_tags(form, repository)
|
||||
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?)))
|
||||
end
|
||||
|
||||
def filesystem_field_tags(form, repository)
|
||||
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
module SearchHelper
|
||||
def highlight_tokens(text, tokens)
|
||||
return text unless text && tokens && !tokens.empty?
|
||||
regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE
|
||||
re_tokens = tokens.collect {|t| Regexp.escape(t)}
|
||||
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
|
||||
result = ''
|
||||
text.split(regexp).each_with_index do |words, i|
|
||||
if result.length > 1200
|
||||
@@ -35,4 +36,28 @@ module SearchHelper
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def type_label(t)
|
||||
l("label_#{t.singularize}_plural")
|
||||
end
|
||||
|
||||
def project_select_tag
|
||||
options = [[l(:label_project_all), 'all']]
|
||||
options << [l(:label_my_projects), 'my_projects'] unless User.current.memberships.empty?
|
||||
options << [l(:label_and_its_subprojects, @project.name), 'subprojects'] unless @project.nil? || @project.active_children.empty?
|
||||
options << [@project.name, ''] unless @project.nil?
|
||||
select_tag('scope', options_for_select(options, params[:scope].to_s)) if options.size > 1
|
||||
end
|
||||
|
||||
def render_results_by_type(results_by_type)
|
||||
links = []
|
||||
# Sorts types by results count
|
||||
results_by_type.keys.sort {|a, b| results_by_type[b] <=> results_by_type[a]}.each do |t|
|
||||
c = results_by_type[t]
|
||||
next if c == 0
|
||||
text = "#{type_label(t)} (#{c})"
|
||||
links << link_to(text, :q => params[:q], :titles_only => params[:title_only], :all_words => params[:all_words], :scope => params[:scope], t => 1)
|
||||
end
|
||||
('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,6 +21,7 @@ module SettingsHelper
|
||||
{:name => 'authentication', :partial => 'settings/authentication', :label => :label_authentication},
|
||||
{: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 => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural}
|
||||
]
|
||||
end
|
||||
|
||||
@@ -83,7 +83,7 @@ module SortHelper
|
||||
# Use this to sort the controller's table items collection.
|
||||
#
|
||||
def sort_clause()
|
||||
session[@sort_name][:key] + ' ' + session[@sort_name][:order]
|
||||
session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
|
||||
end
|
||||
|
||||
# Returns a link which sorts by the named column.
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module TimelogHelper
|
||||
def activity_collection_for_select_options
|
||||
activities = Enumeration::get_values('ACTI')
|
||||
collection = []
|
||||
collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ] unless activities.detect(&:is_default)
|
||||
activities.each { |a| collection << [a.name, a.id] }
|
||||
collection
|
||||
end
|
||||
|
||||
def select_hours(data, criteria, value)
|
||||
data.select {|row| row[criteria] == value}
|
||||
end
|
||||
@@ -44,6 +52,8 @@ module TimelogHelper
|
||||
|
||||
def entries_to_csv(entries)
|
||||
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
||||
decimal_separator = l(:general_csv_decimal_separator)
|
||||
custom_fields = TimeEntryCustomField.find(:all)
|
||||
export = StringIO.new
|
||||
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
|
||||
# csv header fields
|
||||
@@ -57,6 +67,9 @@ module TimelogHelper
|
||||
l(:field_hours),
|
||||
l(:field_comments)
|
||||
]
|
||||
# Export custom fields
|
||||
headers += custom_fields.collect(&:name)
|
||||
|
||||
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
# csv lines
|
||||
entries.each do |entry|
|
||||
@@ -67,9 +80,11 @@ module TimelogHelper
|
||||
(entry.issue ? entry.issue.id : nil),
|
||||
(entry.issue ? entry.issue.tracker : nil),
|
||||
(entry.issue ? entry.issue.subject : nil),
|
||||
entry.hours,
|
||||
entry.hours.to_s.gsub('.', decimal_separator),
|
||||
entry.comments
|
||||
]
|
||||
fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) }
|
||||
|
||||
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,11 +16,26 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module UsersHelper
|
||||
def status_options_for_select(selected)
|
||||
def users_status_options_for_select(selected)
|
||||
user_count_by_status = User.count(:group => 'status').to_hash
|
||||
options_for_select([[l(:label_all), ''],
|
||||
[l(:status_active), 1],
|
||||
[l(:status_registered), 2],
|
||||
[l(:status_locked), 3]], selected)
|
||||
["#{l(:status_active)} (#{user_count_by_status[1].to_i})", 1],
|
||||
["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", 2],
|
||||
["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", 3]], selected)
|
||||
end
|
||||
|
||||
# Options for the new membership projects combo-box
|
||||
def projects_options_for_select(projects)
|
||||
options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---")
|
||||
projects_by_root = projects.group_by(&:root)
|
||||
projects_by_root.keys.sort.each do |root|
|
||||
options << content_tag('option', h(root.name), :value => root.id, :disabled => (!projects.include?(root)))
|
||||
projects_by_root[root].sort.each do |project|
|
||||
next if project == root
|
||||
options << content_tag('option', '» ' + h(project.name), :value => project.id)
|
||||
end
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
def change_status_link(user)
|
||||
@@ -30,8 +45,14 @@ module UsersHelper
|
||||
link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock'
|
||||
elsif user.registered?
|
||||
link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock'
|
||||
else
|
||||
elsif user != User.current
|
||||
link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :post, :class => 'icon icon-lock'
|
||||
end
|
||||
end
|
||||
|
||||
def user_settings_tabs
|
||||
tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general},
|
||||
{:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ module WatchersHelper
|
||||
return '' unless user && user.logged? && object.respond_to?('watched_by?')
|
||||
watched = object.watched_by?(user)
|
||||
url = {:controller => 'watchers',
|
||||
:action => (watched ? 'remove' : 'add'),
|
||||
:action => (watched ? 'unwatch' : 'watch'),
|
||||
:object_type => object.class.to_s.underscore,
|
||||
:object_id => object.id}
|
||||
link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
|
||||
@@ -33,4 +33,9 @@ module WatchersHelper
|
||||
:class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
|
||||
|
||||
end
|
||||
|
||||
# Returns a comma separated list of users watching the given object
|
||||
def watchers_list(object)
|
||||
object.watcher_users.collect {|u| content_tag('span', link_to_user(u), :class => 'user') }.join(",\n")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,22 @@
|
||||
|
||||
module WikiHelper
|
||||
|
||||
def render_page_hierarchy(pages, node=nil)
|
||||
content = ''
|
||||
if pages[node]
|
||||
content << "<ul class=\"pages-hierarchy\">\n"
|
||||
pages[node].each do |page|
|
||||
content << "<li>"
|
||||
content << link_to(h(page.pretty_title), {:action => 'index', :page => page.title},
|
||||
:title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
|
||||
content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id]
|
||||
content << "</li>\n"
|
||||
end
|
||||
content << "</ul>\n"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def html_diff(wdiff)
|
||||
words = wdiff.words.collect{|word| h(word)}
|
||||
words_add = 0
|
||||
|
||||
Reference in New Issue
Block a user