Compare commits

...

35 Commits
1.4.1 ... 0.8.1

Author SHA1 Message Date
Jean-Philippe Lang
ed6151b4d2 tagged version 0.8.1
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/tags/0.8.1@2471 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-15 09:27:21 +00:00
Jean-Philippe Lang
3d1bd79ffb Set version to 0.8.1
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2470 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-15 09:08:26 +00:00
Jean-Philippe Lang
7f957653ad Merged r2463, r2465, r2467, r2468 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2469 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-15 09:04:24 +00:00
Jean-Philippe Lang
9a9141041e Merged r2461 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2462 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-13 17:32:27 +00:00
Jean-Philippe Lang
bc4249e3d3 Merged r2270, r2344, r2359, r2360, r2362, r2363, r2415, r2423, r2424 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2425 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-09 18:46:00 +00:00
Jean-Philippe Lang
fae04f3ae1 Merged r2246 and r2248 from trunk (#2456).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2310 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-24 13:01:31 +00:00
Jean-Philippe Lang
b13ef64794 Merged r2265 from trunk (#2523).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2309 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-24 12:27:56 +00:00
Jean-Philippe Lang
683e1c5d73 Merged r2266 from trunk (#2522).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2308 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-24 12:13:16 +00:00
Jean-Philippe Lang
1c1755d278 Merged r2280 from trunk (#2506).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2307 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-24 12:11:52 +00:00
Jean-Philippe Lang
5e6ff86f47 Merged r2302 from trunk (#2466).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2306 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-24 12:10:24 +00:00
Jean-Philippe Lang
764393aa6a Merged r2250 and r2251 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2252 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-10 10:51:59 +00:00
Jean-Philippe Lang
3155b8ccad Merged r2226 and r2233 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2245 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-05 18:16:14 +00:00
Jean-Philippe Lang
567c8ed9b0 Fixed: Darcs adapter works on Win32 only (wrong quotes in commands #2402).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2231 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-04 13:24:56 +00:00
Jean-Philippe Lang
49b6f9e4dd Merged r2218 to r2225 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2230 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-04 13:10:16 +00:00
Jean-Philippe Lang
c9d4d3a2be Merged r2209 to r2211 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2229 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-01-04 13:03:34 +00:00
Jean-Philippe Lang
31178553f3 Merged r2116, r2117 and r2187 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2217 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-31 11:40:03 +00:00
Jean-Philippe Lang
dea10c54f9 Merged r2164 to r2167, r2188 and r2189 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2216 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-31 11:31:02 +00:00
Jean-Philippe Lang
6abd32be9e Merged r2212 to r2214 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2215 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-31 10:47:19 +00:00
Jean-Philippe Lang
56318aab53 Merged r2202 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2205 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-30 10:01:34 +00:00
Jean-Philippe Lang
babb14dd94 Doc updates for 0.8.0 final release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2204 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-30 09:52:49 +00:00
Jean-Philippe Lang
3b90141543 Translation updates.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2200 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-29 15:50:08 +00:00
Jean-Philippe Lang
bce764d9bc Merged r2191 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2198 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-29 15:27:29 +00:00
Jean-Philippe Lang
b65d546245 Merged r2195 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2197 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-29 15:26:17 +00:00
Jean-Philippe Lang
9f12151ac0 Merged r2192 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2193 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-28 13:41:03 +00:00
Jean-Philippe Lang
78cac6f02b Merged r2183 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2184 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-27 14:07:00 +00:00
Jean-Philippe Lang
16b85bda32 Merged r2178 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2179 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-24 13:32:59 +00:00
Jean-Philippe Lang
733987fbb6 Merged r2168 to r2171 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2172 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-24 11:23:17 +00:00
Jean-Philippe Lang
7389b4bed0 Merged r2109, r2118, r2130, r2131, r2134, r2135, r2136 and r2139 to r2145 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2146 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-19 11:45:33 +00:00
Jean-Philippe Lang
4570fcb7a2 Merged r2137 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2138 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-15 20:20:56 +00:00
Jean-Philippe Lang
0a709660d2 Merged r2119 to r2127 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2133 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-14 15:32:11 +00:00
Jean-Philippe Lang
633e026e44 Merged r2110 to r2112 (diff limit) from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2132 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-12 19:49:22 +00:00
Jean-Philippe Lang
618ab6004e Merged r2114 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2115 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-08 18:30:00 +00:00
Jean-Philippe Lang
644f03b834 Set version to stable.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2107 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-07 10:01:10 +00:00
Jean-Philippe Lang
1154141ee7 Merge from trunk up to r2105.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2106 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-07 10:00:40 +00:00
Jean-Philippe Lang
bf42d9b706 0.8 branch added
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2099 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-12-06 22:41:47 +00:00
159 changed files with 3304 additions and 2103 deletions

View File

@@ -27,7 +27,7 @@ class AdminController < ApplicationController
def projects
sort_init 'name', 'asc'
sort_update
sort_update %w(name is_public created_on)
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -86,6 +86,7 @@ class AdminController < ApplicationController
@flags = {
:default_admin_changed => User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?,
:file_repository_writable => File.writable?(Attachment.storage_path),
:plugin_assets_writable => File.writable?(Engines.public_directory),
:rmagick_available => Object.const_defined?(:Magick)
}
end

View File

@@ -126,10 +126,14 @@ class ApplicationController < ActionController::Base
def redirect_back_or_default(default)
back_url = CGI.unescape(params[:back_url].to_s)
if !back_url.blank?
uri = URI.parse(back_url)
# do not redirect user to another host or to the login or register page
if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
redirect_to(back_url) and return
begin
uri = URI.parse(back_url)
# do not redirect user to another host or to the login or register page
if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
redirect_to(back_url) and return
end
rescue URI::InvalidURIError
# redirect to default
end
end
redirect_to default
@@ -171,6 +175,7 @@ class ApplicationController < ActionController::Base
# TODO: move to model
def attach_files(obj, attachments)
attached = []
unsaved = []
if attachments && attachments.is_a?(Hash)
attachments.each_value do |attachment|
file = attachment['file']
@@ -179,7 +184,10 @@ class ApplicationController < ActionController::Base
:file => file,
:description => attachment['description'].to_s.strip,
:author => User.current)
attached << a unless a.new_record?
a.new_record? ? (unsaved << a) : (attached << a)
end
if unsaved.any?
flash[:warning] = l(:warning_attachments_not_saved, unsaved.size)
end
end
attached

View File

@@ -1,5 +1,5 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
# 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
@@ -17,7 +17,11 @@
class AttachmentsController < ApplicationController
before_filter :find_project
before_filter :read_authorize, :except => :destroy
before_filter :delete_authorize, :only => :destroy
verify :method => :post, :only => :destroy
def show
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@@ -31,25 +35,40 @@ class AttachmentsController < ApplicationController
end
def download
@attachment.increment_download if @attachment.container.is_a?(Version)
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => @attachment.content_type,
:disposition => (@attachment.image? ? 'inline' : 'attachment')
end
def destroy
# Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment)
redirect_to :back
rescue ::ActionController::RedirectBackError
redirect_to :controller => 'projects', :action => 'show', :id => @project
end
private
def find_project
@attachment = Attachment.find(params[:id])
# Show 404 if the filename in the url is wrong
raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
@project = @attachment.project
permission = @attachment.container.is_a?(Version) ? :view_files : "view_#{@attachment.container.class.name.underscore.pluralize}".to_sym
allowed = User.current.allowed_to?(permission, @project)
allowed ? true : (User.current.logged? ? render_403 : require_login)
rescue ActiveRecord::RecordNotFound
render_404
end
def read_authorize
@attachment.visible? ? true : deny_access
end
def delete_authorize
@attachment.deletable? ? true : deny_access
end
end

View File

@@ -35,12 +35,14 @@ class BoardsController < ApplicationController
end
def show
sort_init "#{Message.table_name}.updated_on", "desc"
sort_update
sort_init 'updated_on', 'desc'
sort_update 'created_on' => "#{Message.table_name}.created_on",
'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "#{Message.table_name}.updated_on"
@topic_count = @board.topics.count
@topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
@topics = @board.topics.find :all, :order => "#{Message.table_name}.sticky DESC, #{sort_clause}",
@topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '),
:include => [:author, {:last_reply => :author}],
:limit => @topic_pages.items_per_page,
:offset => @topic_pages.current.offset

View File

@@ -35,6 +35,7 @@ class DocumentsController < ApplicationController
else
@grouped = documents.group_by(&:category)
end
@document = @project.documents.build
render :layout => false if request.xhr?
end
@@ -70,11 +71,6 @@ class DocumentsController < ApplicationController
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('document_added')
redirect_to :action => 'show', :id => @document
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @document
end
private
def find_project

View File

@@ -18,7 +18,7 @@
class IssuesController < ApplicationController
menu_item :new_issue, :only => :new
before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
before_filter :find_issue, :only => [:show, :edit, :reply]
before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
before_filter :find_project, :only => [:new, :update_form, :preview]
before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :update_form, :context_menu]
@@ -30,8 +30,6 @@ class IssuesController < ApplicationController
include ProjectsHelper
helper :custom_fields
include CustomFieldsHelper
helper :ifpdf
include IfpdfHelper
helper :issue_relations
include IssueRelationsHelper
helper :watchers
@@ -43,11 +41,13 @@ class IssuesController < ApplicationController
include SortHelper
include IssuesHelper
helper :timelog
include Redmine::Export::PDF
def index
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
sort_init 'id', 'desc'
sort_update({'id' => "#{Issue.table_name}.id"}.merge(@query.columns.inject({}) {|h, c| h[c.name.to_s] = c.sortable; h}))
if @query.valid?
limit = per_page_option
respond_to do |format|
@@ -67,7 +67,7 @@ class IssuesController < ApplicationController
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(issues_to_csv(@issues, @project).read, :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(render(:template => 'issues/index.rfpdf', :layout => false), :type => 'application/pdf', :filename => 'export.pdf') }
format.pdf { send_data(issues_to_pdf(@issues, @project), :type => 'application/pdf', :filename => 'export.pdf') }
end
else
# Send html if the query is not valid
@@ -78,9 +78,10 @@ class IssuesController < ApplicationController
end
def changes
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
sort_init 'id', 'desc'
sort_update({'id' => "#{Issue.table_name}.id"}.merge(@query.columns.inject({}) {|h, c| h[c.name.to_s] = c.sortable; h}))
if @query.valid?
@journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
:conditions => @query.statement,
@@ -104,7 +105,7 @@ class IssuesController < ApplicationController
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
end
end
@@ -121,7 +122,10 @@ class IssuesController < ApplicationController
render :nothing => true, :layout => true
return
end
@issue.attributes = params[:issue]
if params[:issue].is_a?(Hash)
@issue.attributes = params[:issue]
@issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
end
@issue.author = User.current
default_status = IssueStatus.default
@@ -143,7 +147,8 @@ class IssuesController < ApplicationController
attach_files(@issue, params[:attachments])
flash[:notice] = l(:notice_successful_create)
Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added')
redirect_to :controller => 'issues', :action => 'show', :id => @issue
redirect_to(params[:continue] ? { :action => 'new', :tracker_id => @issue.tracker } :
{ :action => 'show', :id => @issue })
return
end
end
@@ -181,7 +186,7 @@ class IssuesController < ApplicationController
if (@time_entry.hours.nil? || @time_entry.valid?) && @issue.save
# Log spend time
if current_role.allowed_to?(:log_time)
if User.current.allowed_to?(:log_time, @project)
@time_entry.save
end
if !journal.new_record?
@@ -313,17 +318,6 @@ class IssuesController < ApplicationController
@issues.each(&:destroy)
redirect_to :action => 'index', :project_id => @project
end
def destroy_attachment
a = @issue.attachments.find(params[:attachment_id])
a.destroy
journal = @issue.init_journal(User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:old_value => a.filename)
journal.save
redirect_to :action => 'show', :id => @issue
end
def gantt
@gantt = Redmine::Helpers::Gantt.new(params)
@@ -352,7 +346,7 @@ class IssuesController < ApplicationController
respond_to do |format|
format.html { render :template => "issues/gantt.rhtml", :layout => !request.xhr? }
format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{@project.identifier}-gantt.png") } if @gantt.respond_to?('to_image')
format.pdf { send_data(render(:template => "issues/gantt.rfpdf", :layout => false), :type => 'application/pdf', :filename => "#{@project.nil? ? '' : "#{@project.identifier}-" }gantt.pdf") }
format.pdf { send_data(gantt_to_pdf(@gantt, @project), :type => 'application/pdf', :filename => "#{@project.nil? ? '' : "#{@project.identifier}-" }gantt.pdf") }
end
end

View File

@@ -22,6 +22,7 @@ class JournalsController < ApplicationController
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params})
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
format.js { render :action => 'update' }

View File

@@ -33,8 +33,6 @@ class ProjectsController < ApplicationController
include SortHelper
helper :custom_fields
include CustomFieldsHelper
helper :ifpdf
include IfpdfHelper
helper :issues
helper IssuesHelper
helper :queries
@@ -84,6 +82,11 @@ class ProjectsController < ApplicationController
# Show @project
def show
if params[:jump]
# try to redirect to the requested menu item
redirect_to_project_menu_item(@project, params[:jump]) && return
end
@members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role}
@subprojects = @project.children.find(:all, :conditions => Project.visible_by(User.current))
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@@ -188,18 +191,26 @@ class ProjectsController < ApplicationController
def add_file
if request.post?
@version = @project.versions.find_by_id(params[:version_id])
attachments = attach_files(@version, params[:attachments])
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('file_added')
container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
attachments = attach_files(container, params[:attachments])
if !attachments.empty? && Setting.notified_events.include?('file_added')
Mailer.deliver_attachments_added(attachments)
end
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
return
end
@versions = @project.versions.sort
end
def list_files
sort_init "#{Attachment.table_name}.filename", "asc"
sort_update
@versions = @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
sort_init 'filename', 'asc'
sort_update 'filename' => "#{Attachment.table_name}.filename",
'created_on' => "#{Attachment.table_name}.created_on",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
@containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
@containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
render :layout => !request.xhr?
end

View File

@@ -51,8 +51,9 @@ class RepositoriesController < ApplicationController
@users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
@users.compact!
@users.sort!
if request.post?
@repository.committer_ids = params[:committers]
if request.post? && params[:committers].is_a?(Hash)
# Build a hash with repository usernames as keys and corresponding user ids as values
@repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'committers', :id => @project
end
@@ -126,6 +127,9 @@ class RepositoriesController < ApplicationController
end
def annotate
@entry = @repository.entry(@path, @rev)
show_error_not_found and return unless @entry
@annotate = @repository.scm.annotate(@path, @rev)
render_error l(:error_scm_annotate) and return if @annotate.nil? || @annotate.empty?
end

View File

@@ -40,7 +40,7 @@ class SettingsController < ApplicationController
@options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
@deliveries = ActionMailer::Base.perform_deliveries
@guessed_host_and_path = request.host_with_port
@guessed_host_and_path = request.host_with_port.dup
@guessed_host_and_path << ('/'+ request.relative_url_root.gsub(%r{^\/}, '')) unless request.relative_url_root.blank?
end

View File

@@ -138,7 +138,12 @@ class TimelogController < ApplicationController
def details
sort_init 'spent_on', 'desc'
sort_update
sort_update 'spent_on' => 'spent_on',
'user' => 'user_id',
'activity' => 'activity_id',
'project' => "#{Project.table_name}.name",
'issue' => 'issue_id',
'hours' => 'hours'
cond = ARCondition.new
if @project.nil?

View File

@@ -30,7 +30,7 @@ class UsersController < ApplicationController
def list
sort_init 'login', 'asc'
sort_update
sort_update %w(login firstname lastname mail admin created_on last_login_on)
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])

View File

@@ -37,12 +37,6 @@ class VersionsController < ApplicationController
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end
def destroy_file
@version.attachments.find(params[:attachment_id]).destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
def status_by
respond_to do |format|
format.html { render :action => 'show' }

View File

@@ -19,8 +19,9 @@ require 'diff'
class WikiController < ApplicationController
before_filter :find_wiki, :authorize
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index }
helper :attachments
include AttachmentsHelper
@@ -91,8 +92,7 @@ class WikiController < ApplicationController
# rename a page
def rename
@page = @wiki.find_page(params[:page])
return render_403 unless editable?
return render_403 unless editable?
@page.redirect_existing_links = true
# used to display the *original* title if some AR validation errors occur
@original_title = @page.pretty_title
@@ -103,15 +103,12 @@ class WikiController < ApplicationController
end
def protect
page = @wiki.find_page(params[:page])
page.update_attribute :protected, params[:protected]
redirect_to :action => 'index', :id => @project, :page => page.title
@page.update_attribute :protected, params[:protected]
redirect_to :action => 'index', :id => @project, :page => @page.title
end
# show page history
def history
@page = @wiki.find_page(params[:page])
@version_count = @page.content.versions.count
@version_pages = Paginator.new self, @version_count, per_page_option, params['p']
# don't load text
@@ -125,21 +122,19 @@ class WikiController < ApplicationController
end
def diff
@page = @wiki.find_page(params[:page])
@diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff
end
def annotate
@page = @wiki.find_page(params[:page])
@annotate = @page.annotate(params[:version])
render_404 unless @annotate
end
# remove a wiki page and its history
def destroy
@page = @wiki.find_page(params[:page])
return render_403 unless editable?
@page.destroy if @page
return render_403 unless editable?
@page.destroy
redirect_to :action => 'special', :id => @project, :page => 'Page_index'
end
@@ -181,19 +176,11 @@ class WikiController < ApplicationController
end
def add_attachment
@page = @wiki.find_page(params[:page])
return render_403 unless editable?
attach_files(@page, params[:attachments])
redirect_to :action => 'index', :page => @page.title
end
def destroy_attachment
@page = @wiki.find_page(params[:page])
return render_403 unless editable?
@page.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'index', :page => @page.title
end
private
def find_wiki
@@ -204,6 +191,12 @@ private
render_404
end
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:page])
render_404 if @page.nil?
end
# Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page)
page.editable_by?(User.current)

View File

@@ -18,6 +18,7 @@
require 'coderay'
require 'coderay/helpers/file_type'
require 'forwardable'
require 'cgi'
module ApplicationHelper
include Redmine::WikiFormatting::Macros::Definitions
@@ -47,8 +48,8 @@ module ApplicationHelper
end
# Display a link to user's account page
def link_to_user(user)
(user && !user.anonymous?) ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
def link_to_user(user, options={})
(user && !user.anonymous?) ? link_to(user.name(options[:format]), :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
end
def link_to_issue(issue, options={})
@@ -146,6 +147,15 @@ module ApplicationHelper
end
content
end
# Renders flash messages
def render_flash_messages
s = ''
flash.each do |k,v|
s << content_tag('div', v, :class => "flash #{k}")
end
s
end
# Truncates and returns the string as a single line
def truncate_single_line(string, *args)
@@ -281,16 +291,15 @@ module ApplicationHelper
attachments = attachments.sort_by(&:created_on).reverse
text = text.gsub(/!((\<|\=|\>)?(\([^\)]+\))?(\[[^\]]+\])?(\{[^\}]+\})?)(\S+\.(bmp|gif|jpg|jpeg|png))!/i) do |m|
style = $1
filename = $6
rf = Regexp.new(Regexp.escape(filename), Regexp::IGNORECASE)
filename = $6.downcase
# search for the picture in attachments
if found = attachments.detect { |att| att.filename =~ rf }
if found = attachments.detect { |att| att.filename.downcase == filename }
image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
desc = found.description.to_s.gsub(/^([^\(\)]*).*$/, "\\1")
alt = desc.blank? ? nil : "(#{desc})"
"!#{style}#{image_url}#{alt}!"
else
"!#{style}#{filename}!"
m
end
end
end
@@ -525,7 +534,8 @@ module ApplicationHelper
def back_url_hidden_field_tag
back_url = params[:back_url] || request.env['HTTP_REFERER']
hidden_field_tag('back_url', back_url) unless back_url.blank?
back_url = CGI.unescape(back_url.to_s)
hidden_field_tag('back_url', CGI.escape(back_url)) unless back_url.blank?
end
def check_all_links(form_name)

View File

@@ -16,10 +16,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AttachmentsHelper
# displays the links to a collection of attachments
def link_to_attachments(attachments, options = {})
if attachments.any?
render :partial => 'attachments/links', :locals => {:attachments => attachments, :options => options}
# Displays view/delete links to the attachments of the given object
# Options:
# :author -- author names are not displayed if set to false
def link_to_attachments(container, options = {})
options.assert_valid_keys(:author)
if container.attachments.any?
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
render :partial => 'attachments/links', :locals => {:attachments => container.attachments, :options => options}
end
end

View File

@@ -1,85 +0,0 @@
# redMine - project management software
# Copyright (C) 2006 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.
require 'iconv'
require 'rfpdf/chinese'
module IfpdfHelper
class IFPDF < FPDF
include GLoc
attr_accessor :footer_date
def initialize(lang)
super()
set_language_if_valid lang
case current_language.to_s
when 'ja'
extend(PDF_Japanese)
AddSJISFont()
@font_for_content = 'SJIS'
@font_for_footer = 'SJIS'
when 'zh'
extend(PDF_Chinese)
AddGBFont()
@font_for_content = 'GB'
@font_for_footer = 'GB'
when 'zh-tw'
extend(PDF_Chinese)
AddBig5Font()
@font_for_content = 'Big5'
@font_for_footer = 'Big5'
else
@font_for_content = 'Arial'
@font_for_footer = 'Helvetica'
end
SetCreator(Redmine::Info.app_name)
SetFont(@font_for_content)
end
def SetFontStyle(style, size)
SetFont(@font_for_content, style, size)
end
def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
@ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
# these quotation marks are not correctly rendered in the pdf
txt = txt.gsub(/[“”]/, '"') if txt
txt = begin
# 0x5c char handling
txtar = txt.split('\\')
txtar << '' if txt[-1] == ?\\
txtar.collect {|x| @ic.iconv(x)}.join('\\').gsub(/\\/, "\\\\\\\\")
rescue
txt
end || ''
super w,h,txt,border,ln,align,fill,link
end
def Footer
SetFont(@font_for_footer, 'I', 8)
SetY(-15)
SetX(15)
Cell(0, 5, @footer_date, 0, 0, 'L')
SetY(-15)
SetX(-30)
Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
end
end
end

View File

@@ -33,6 +33,14 @@ module IssuesHelper
"<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
end
# Returns a string of css classes that apply to the given issue
def css_issue_classes(issue)
s = "issue status-#{issue.status.position} priority-#{issue.priority.position}"
s << ' closed' if issue.closed?
s << ' overdue' if issue.overdue?
s
end
def sidebar_queries
unless @sidebar_queries
# User can see public queries and his own queries

View File

@@ -22,8 +22,8 @@ module QueriesHelper
end
def column_header(column)
column.sortable ? sort_header_tag(column.sortable, :caption => column.caption,
:default_order => column.default_order) :
column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption,
:default_order => column.default_order) :
content_tag('th', column.caption)
end

View File

@@ -67,23 +67,31 @@ module SortHelper
# Updates the sort state. Call this in the controller prior to calling
# sort_clause.
#
def sort_update()
if params[:sort_key]
sort = {:key => params[:sort_key], :order => params[:sort_order]}
# sort_keys can be either an array or a hash of allowed keys
def sort_update(sort_keys)
sort_key = params[:sort_key]
sort_key = nil unless (sort_keys.is_a?(Array) ? sort_keys.include?(sort_key) : sort_keys[sort_key])
sort_order = (params[:sort_order] == 'desc' ? 'DESC' : 'ASC')
if sort_key
sort = {:key => sort_key, :order => sort_order}
elsif session[@sort_name]
sort = session[@sort_name] # Previous sort.
else
sort = @sort_default
end
session[@sort_name] = sort
sort_column = (sort_keys.is_a?(Hash) ? sort_keys[sort[:key]] : sort[:key])
@sort_clause = (sort_column.blank? ? nil : "#{sort_column} #{sort[:order]}")
end
# Returns an SQL sort clause corresponding to the current sort state.
# Use this to sort the controller's table items collection.
#
def sort_clause()
session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
@sort_clause
end
# Returns a link which sorts by the named column.

View File

@@ -16,6 +16,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module TimelogHelper
include ApplicationHelper
def render_timelog_breadcrumb
links = []
links << link_to(l(:label_project_all), {:project_id => nil, :issue_id => nil})
@@ -81,7 +83,7 @@ module TimelogHelper
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
# csv lines
entries.each do |entry|
fields = [l_date(entry.spent_on),
fields = [format_date(entry.spent_on),
entry.user,
entry.activity,
entry.project,

View File

@@ -98,6 +98,14 @@ class Attachment < ActiveRecord::Base
container.project
end
def visible?(user=User.current)
container.attachments_visible?(user)
end
def deletable?(user=User.current)
container.attachments_deletable?(user)
end
def image?
self.filename =~ /\.(jpe?g|gif|png)$/i
end

View File

@@ -18,7 +18,7 @@
class Document < ActiveRecord::Base
belongs_to :project
belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id"
has_many :attachments, :as => :container, :dependent => :destroy
acts_as_attachable :delete_permission => :manage_documents
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
@@ -28,4 +28,10 @@ class Document < ActiveRecord::Base
validates_presence_of :project, :title, :category
validates_length_of :title, :maximum => 60
def after_initialize
if new_record?
self.category ||= Enumeration.default('DCAT')
end
end
end

View File

@@ -44,7 +44,9 @@ class Enumeration < ActiveRecord::Base
end
def before_save
Enumeration.update_all("is_default = #{connection.quoted_false}", {:opt => opt}) if is_default?
if is_default? && is_default_changed?
Enumeration.update_all("is_default = #{connection.quoted_false}", {:opt => opt})
end
end
def objects_count

View File

@@ -26,13 +26,13 @@ class Issue < ActiveRecord::Base
belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
has_many :journals, :as => :journalized, :dependent => :destroy
has_many :attachments, :as => :container, :dependent => :destroy
has_many :time_entries, :dependent => :delete_all
has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
acts_as_attachable :after_remove => :attachment_removed
acts_as_customizable
acts_as_watchable
acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"],
@@ -45,7 +45,7 @@ class Issue < ActiveRecord::Base
acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]},
:author_key => :author_id
validates_presence_of :subject, :description, :priority, :project, :tracker, :author, :status
validates_presence_of :subject, :priority, :project, :tracker, :author, :status
validates_length_of :subject, :maximum => 255
validates_inclusion_of :done_ratio, :in => 0..100
validates_numericality_of :estimated_hours, :allow_nil => true
@@ -195,6 +195,11 @@ class Issue < ActiveRecord::Base
self.status.is_closed?
end
# Returns true if the issue is overdue
def overdue?
!due_date.nil? && (due_date < Date.today)
end
# Users the issue can be assigned to
def assignable_users
project.assignable_users
@@ -261,4 +266,15 @@ class Issue < ActiveRecord::Base
def to_s
"#{tracker} ##{id}: #{subject}"
end
private
# Callback on attachment deletion
def attachment_removed(obj)
journal = init_journal(User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => obj.id,
:old_value => obj.filename)
journal.save
end
end

View File

@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandler < ActionMailer::Base
include ActionView::Helpers::SanitizeHelper
class UnauthorizedAction < StandardError; end
class MissingInformation < StandardError; end
@@ -88,15 +89,21 @@ class MailHandler < ActionMailer::Base
issue.status = status
end
issue.subject = email.subject.chomp.toutf8
issue.description = email.plain_text_body.chomp
issue.description = plain_text_body
# custom fields
issue.custom_field_values = issue.available_custom_fields.inject({}) do |h, c|
if value = get_keyword(c.name, :override => true)
h[c.id] = value
end
h
end
issue.save!
add_attachments(issue)
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
# send notification before adding watchers since they were cc'ed
Mailer.deliver_issue_add(issue) if Setting.notified_events.include?('issue_added')
# add To and Cc as watchers
add_watchers(issue)
# send notification after adding watchers so that they can reply to Redmine
Mailer.deliver_issue_add(issue) if Setting.notified_events.include?('issue_added')
issue
end
@@ -120,7 +127,7 @@ class MailHandler < ActionMailer::Base
raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project)
# add the note
journal = issue.init_journal(user, email.plain_text_body.chomp)
journal = issue.init_journal(user, plain_text_body)
add_attachments(issue)
# check workflow
if status && issue.new_statuses_allowed_to(user).include?(status)
@@ -155,22 +162,31 @@ class MailHandler < ActionMailer::Base
end
end
def get_keyword(attr)
if @@handler_options[:allow_override].include?(attr.to_s) && email.plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i
def get_keyword(attr, options={})
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i
$1.strip
elsif !@@handler_options[:issue][attr].blank?
@@handler_options[:issue][attr]
end
end
end
class TMail::Mail
# Returns body of the first plain text part found if any
# Returns the text/plain part of the email
# If not found (eg. HTML-only email), returns the body with tags removed
def plain_text_body
return @plain_text_body unless @plain_text_body.nil?
p = self.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten
plain = p.detect {|c| c.content_type == 'text/plain'}
@plain_text_body = plain.nil? ? self.body : plain.body
parts = @email.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten
if parts.empty?
parts << @email
end
plain_text_part = parts.detect {|p| p.content_type == 'text/plain'}
if plain_text_part.nil?
# no text/plain part found, assuming html-only email
# strip html tags and remove doctype directive
@plain_text_body = strip_tags(@email.body.to_s)
@plain_text_body.gsub! %r{^<!DOCTYPE .*$}, ''
else
@plain_text_body = plain_text_part.body.to_s
end
@plain_text_body.strip!
end
end

View File

@@ -28,6 +28,7 @@ class Mailer < ActionMailer::Base
'Issue-Author' => issue.author.login
redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
recipients issue.recipients
cc(issue.watcher_recipients - @recipients)
subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
body :issue => issue,
:issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
@@ -39,6 +40,7 @@ class Mailer < ActionMailer::Base
'Issue-Id' => issue.id,
'Issue-Author' => issue.author.login
redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
@author = journal.user
recipients issue.recipients
# Watchers in cc
cc(issue.watcher_recipients - @recipients)
@@ -57,7 +59,7 @@ class Mailer < ActionMailer::Base
subject l(:mail_subject_reminder, issues.size)
body :issues => issues,
:days => days,
:issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'issues.due_date', :sort_order => 'asc')
:issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc')
end
def document_added(document)
@@ -73,6 +75,9 @@ class Mailer < ActionMailer::Base
added_to = ''
added_to_url = ''
case container.class.name
when 'Project'
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
added_to = "#{l(:label_project)}: #{container}"
when 'Version'
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
added_to = "#{l(:label_version)}: #{container.name}"
@@ -205,9 +210,10 @@ class Mailer < ActionMailer::Base
def create_mail
# Removes the current user from the recipients and cc
# if he doesn't want to receive notifications about what he does
if User.current.pref[:no_self_notified]
recipients.delete(User.current.mail) if recipients
cc.delete(User.current.mail) if cc
@author ||= User.current
if @author.pref[:no_self_notified]
recipients.delete(@author.mail) if recipients
cc.delete(@author.mail) if cc
end
# Blind carbon copy recipients
if Setting.bcc_recipients?

View File

@@ -19,11 +19,11 @@ class Message < ActiveRecord::Base
belongs_to :board
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
has_many :attachments, :as => :container, :dependent => :destroy
acts_as_attachable
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
acts_as_searchable :columns => ['subject', 'content'],
:include => {:board, :project},
:include => {:board => :project},
:project_key => 'project_id',
:date_column => "#{table_name}.created_on"
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},

View File

@@ -44,6 +44,8 @@ class Project < ActiveRecord::Base
:association_foreign_key => 'custom_field_id'
acts_as_tree :order => "name", :counter_cache => true
acts_as_attachable :view_permission => :view_files,
:delete_permission => :manage_files
acts_as_customizable
acts_as_searchable :columns => ['name', 'description'], :project_key => 'id', :permission => nil
@@ -58,7 +60,7 @@ class Project < ActiveRecord::Base
validates_associated :repository, :wiki
validates_length_of :name, :maximum => 30
validates_length_of :homepage, :maximum => 255
validates_length_of :identifier, :in => 3..20
validates_length_of :identifier, :in => 2..20
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
before_destroy :delete_all_members

View File

@@ -31,9 +31,9 @@ class Role < ActiveRecord::Base
raise "Can not copy workflow from a #{role.class}" unless role.is_a?(Role)
raise "Can not copy workflow from/to an unsaved role" if proxy_owner.new_record? || role.new_record?
clear
connection.insert "INSERT INTO workflows (tracker_id, old_status_id, new_status_id, role_id)" +
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, old_status_id, new_status_id, role_id)" +
" SELECT tracker_id, old_status_id, new_status_id, #{proxy_owner.id}" +
" FROM workflows" +
" FROM #{Workflow.table_name}" +
" WHERE role_id = #{role.id}"
end
end

View File

@@ -32,7 +32,7 @@ class TimeEntry < ActiveRecord::Base
:description => :comments
validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
validates_numericality_of :hours, :allow_nil => true
validates_numericality_of :hours, :allow_nil => true, :message => :activerecord_error_invalid
validates_length_of :comments, :maximum => 255, :allow_nil => true
def after_initialize
@@ -54,7 +54,7 @@ class TimeEntry < ActiveRecord::Base
end
def hours=(h)
write_attribute :hours, (h.is_a?(String) ? h.to_hours : h)
write_attribute :hours, (h.is_a?(String) ? (h.to_hours || h) : h)
end
# tyear, tmonth, tweek assigned where setting spent_on attributes

View File

@@ -23,9 +23,9 @@ class Tracker < ActiveRecord::Base
raise "Can not copy workflow from a #{tracker.class}" unless tracker.is_a?(Tracker)
raise "Can not copy workflow from/to an unsaved tracker" if proxy_owner.new_record? || tracker.new_record?
clear
connection.insert "INSERT INTO workflows (tracker_id, old_status_id, new_status_id, role_id)" +
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, old_status_id, new_status_id, role_id)" +
" SELECT #{proxy_owner.id}, old_status_id, new_status_id, role_id" +
" FROM workflows" +
" FROM #{Workflow.table_name}" +
" WHERE tracker_id = #{tracker.id}"
end
end

View File

@@ -144,7 +144,7 @@ class User < ActiveRecord::Base
end
def time_zone
@time_zone ||= (self.pref.time_zone.blank? ? nil : TimeZone[self.pref.time_zone])
@time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
end
def wants_comments_in_reverse_order?
@@ -178,6 +178,11 @@ class User < ActiveRecord::Base
token = Token.find_by_action_and_value('autologin', key)
token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
end
# Makes find_by_mail case-insensitive
def self.find_by_mail(mail)
find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
end
# Sort users by their display names
def <=>(user)

View File

@@ -19,7 +19,8 @@ class Version < ActiveRecord::Base
before_destroy :check_integrity
belongs_to :project
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
has_many :attachments, :as => :container, :dependent => :destroy
acts_as_attachable :view_permission => :view_files,
:delete_permission => :manage_files
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]

View File

@@ -21,7 +21,7 @@ require 'enumerator'
class WikiPage < ActiveRecord::Base
belongs_to :wiki
has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
has_many :attachments, :as => :container, :dependent => :destroy
acts_as_attachable :delete_permission => :delete_wiki_pages_attachments
acts_as_tree :order => 'title'
acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"},
@@ -111,6 +111,10 @@ class WikiPage < ActiveRecord::Base
def editable_by?(usr)
!protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
end
def attachments_deletable?(usr=User.current)
editable_by?(usr) && super(usr)
end
def parent_title
@parent_title || (self.parent && self.parent.pretty_title)

View File

@@ -4,7 +4,8 @@
<table class="list">
<tr class="odd"><td><%= l(:text_default_administrator_account_changed) %></td><td><%= image_tag (@flags[:default_admin_changed] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr>
<tr class="even"><td><%= l(:text_file_repository_writable) %></td><td><%= image_tag (@flags[:file_repository_writable] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr>
<tr class="even"><td><%= l(:text_file_repository_writable) %> (<%= Attachment.storage_path %>)</td><td><%= image_tag (@flags[:file_repository_writable] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr>
<tr class="even"><td><%= l(:text_plugin_assets_writable) %> (<%= Engines.public_directory %>)</td><td><%= image_tag (@flags[:plugin_assets_writable] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr>
<tr class="odd"><td><%= l(:text_rmagick_available) %></td><td><%= image_tag (@flags[:rmagick_available] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr>
</table>

View File

@@ -3,14 +3,14 @@
<p><%= link_to_attachment attachment, :class => 'icon icon-attachment' -%>
<%= h(" - #{attachment.description}") unless attachment.description.blank? %>
<span class="size">(<%= number_to_human_size attachment.filesize %>)</span>
<% if options[:delete_url] %>
<%= link_to image_tag('delete.png'), options[:delete_url].update({:attachment_id => attachment}),
<% if options[:deletable] %>
<%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'destroy', :id => attachment},
:confirm => l(:text_are_you_sure),
:method => :post,
:class => 'delete',
:title => l(:button_delete) %>
<% end %>
<% unless options[:no_author] %>
<% if options[:author] %>
<span class="author"><%= attachment.author %>, <%= format_time(attachment.created_on) %></span>
<% end %>
</p>

View File

@@ -33,9 +33,9 @@
<thead><tr>
<th><%= l(:field_subject) %></th>
<th><%= l(:field_author) %></th>
<%= sort_header_tag("#{Message.table_name}.created_on", :caption => l(:field_created_on)) %>
<%= sort_header_tag("#{Message.table_name}.replies_count", :caption => l(:label_reply_plural)) %>
<%= sort_header_tag("#{Message.table_name}.updated_on", :caption => l(:label_message_last)) %>
<%= sort_header_tag('created_on', :caption => l(:field_created_on)) %>
<%= sort_header_tag('replies', :caption => l(:label_reply_plural)) %>
<%= sort_header_tag('updated_on', :caption => l(:label_message_last)) %>
</tr></thead>
<tbody>
<% @topics.each do |topic| %>

View File

@@ -1,4 +1,5 @@
<% Redmine::UnifiedDiff.new(diff, diff_type).each do |table_file| -%>
<% diff = Redmine::UnifiedDiff.new(diff, :type => diff_type, :max_lines => Setting.diff_max_lines_displayed.to_i) -%>
<% diff.each do |table_file| -%>
<div class="autoscroll">
<% if diff_type == 'sbs' -%>
<table class="filecontent CodeRay">
@@ -62,3 +63,5 @@
</div>
<% end -%>
<%= l(:text_diff_truncated) if diff.truncated? %>

View File

@@ -12,7 +12,7 @@
</div>
<h3><%= l(:label_attachment_plural) %></h3>
<%= link_to_attachments @attachments, :delete_url => (authorize_for('documents', 'destroy_attachment') ? {:controller => 'documents', :action => 'destroy_attachment', :id => @document} : nil) %>
<%= link_to_attachments @document %>
<% if authorize_for('documents', 'add_attachment') %>
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",

View File

@@ -8,7 +8,7 @@
<div id="issue_descr_fields" <%= 'style="display:none"' unless @issue.new_record? || @issue.errors.any? %>>
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
<p><%= f.text_area :description, :required => true,
<p><%= f.text_area :description,
:cols => 60,
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
:accesskey => accesskey(:edit),
@@ -24,11 +24,13 @@
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), :required => true %></p>
<p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p>
<% unless @project.issue_categories.empty? %>
<p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %>
<%= prompt_to_remote(l(:label_issue_category_new),
l(:label_issue_category_new), 'category[name]',
{:controller => 'projects', :action => 'add_issue_category', :id => @project},
:class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
<% end %>
<%= content_tag('p', f.select(:fixed_version_id,
(@project.versions.sort.collect {|v| [v.name, v.id]}),
{ :include_blank => true })) unless @project.versions.empty? %>
@@ -48,6 +50,14 @@
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
<% end %>
<% if @issue.new_record? && User.current.allowed_to?(:add_issue_watchers, @project) -%>
<p><label><%= l(:label_issue_watchers) %></label>
<% @issue.project.users.sort.each do |user| -%>
<label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, @issue.watcher_user_ids.include?(user.id) %> <%=h user %></label>
<% end -%>
</p>
<% end %>
<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %>
<%= wikitoolbar_for 'issue_description' %>

View File

@@ -4,14 +4,14 @@
<th><%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;',
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %>
</th>
<%= sort_header_tag("#{Issue.table_name}.id", :caption => '#', :default_order => 'desc') %>
<%= sort_header_tag('id', :caption => '#', :default_order => 'desc') %>
<% query.columns.each do |column| %>
<%= column_header(column) %>
<% end %>
</tr></thead>
<tbody>
<% issues.each do |issue| -%>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= css_issue_classes(issue) %>">
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
<td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
<% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %>

View File

@@ -8,7 +8,7 @@
</tr></thead>
<tbody>
<% for issue in issues %>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= css_issue_classes(issue) %>">
<td class="id">
<%= check_box_tag("ids[]", issue.id, false, :style => 'display:none;') %>
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>

View File

@@ -10,7 +10,8 @@
<table style="width:100%">
<% @issue.relations.each do |relation| %>
<tr>
<td><%= l(relation.label_for(@issue)) %> <%= "(#{lwr(:actionview_datehelper_time_in_words_day, relation.delay)})" if relation.delay && relation.delay != 0 %> <%= link_to_issue relation.other_issue(@issue) %></td>
<td><%= l(relation.label_for(@issue)) %> <%= "(#{lwr(:actionview_datehelper_time_in_words_day, relation.delay)})" if relation.delay && relation.delay != 0 %>
<%= h(relation.other_issue(@issue).project) + ' - ' if Setting.cross_project_issue_relations? %> <%= link_to_issue relation.other_issue(@issue) %></td>
<td><%=h relation.other_issue(@issue).subject %></td>
<td><%= relation.other_issue(@issue).status.name %></td>
<td><%= format_date(relation.other_issue(@issue).start_date) %></td>

View File

@@ -20,7 +20,7 @@
<h3><%= l(:label_query_plural) %></h3>
<% sidebar_queries.each do |query| -%>
<%= link_to query.name, :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %><br />
<%= link_to(h(query.name), :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query) %><br />
<% end -%>
<%= call_hook(:view_issues_sidebar_queries_bottom) %>
<% end -%>

View File

@@ -44,6 +44,7 @@
<fieldset><legend><%= l(:field_notes) %></legend>
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
<%= wikitoolbar_for 'notes' %>
</fieldset>
</div>
<p><%= submit_tag l(:button_submit) %>

View File

@@ -1,188 +0,0 @@
<%
pdf=IfpdfHelper::IFPDF.new(current_language)
pdf.SetTitle("#{l(:label_gantt)} #{@project}")
pdf.AliasNbPages
pdf.footer_date = format_date(Date.today)
pdf.AddPage("L")
pdf.SetFontStyle('B',12)
pdf.SetX(15)
pdf.Cell(70, 20, @project.to_s)
pdf.Ln
pdf.SetFontStyle('B',9)
subject_width = 70
header_heigth = 5
headers_heigth = header_heigth
show_weeks = false
show_days = false
if @gantt.months < 7
show_weeks = true
headers_heigth = 2*header_heigth
if @gantt.months < 3
show_days = true
headers_heigth = 3*header_heigth
end
end
g_width = 210
zoom = (g_width) / (@gantt.date_to - @gantt.date_from + 1)
g_height = 120
t_height = g_height + headers_heigth
y_start = pdf.GetY
#
# Months headers
#
month_f = @gantt.date_from
left = subject_width
height = header_heigth
@gantt.months.times do
width = ((month_f >> 1) - month_f) * zoom
pdf.SetY(y_start)
pdf.SetX(left)
pdf.Cell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
left = left + width
month_f = month_f >> 1
end
#
# Weeks headers
#
if show_weeks
left = subject_width
height = header_heigth
if @gantt.date_from.cwday == 1
# @gantt.date_from is monday
week_f = @gantt.date_from
else
# find next monday after @gantt.date_from
week_f = @gantt.date_from + (7 - @gantt.date_from.cwday + 1)
width = (7 - @gantt.date_from.cwday + 1) * zoom-1
pdf.SetY(y_start + header_heigth)
pdf.SetX(left)
pdf.Cell(width + 1, height, "", "LTR")
left = left + width+1
end
while week_f <= @gantt.date_to
width = (week_f + 6 <= @gantt.date_to) ? 7 * zoom : (@gantt.date_to - week_f + 1) * zoom
pdf.SetY(y_start + header_heigth)
pdf.SetX(left)
pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
left = left + width
week_f = week_f+7
end
end
#
# Days headers
#
if show_days
left = subject_width
height = header_heigth
wday = @gantt.date_from.cwday
pdf.SetFontStyle('B',7)
(@gantt.date_to - @gantt.date_from + 1).to_i.times do
width = zoom
pdf.SetY(y_start + 2 * header_heigth)
pdf.SetX(left)
pdf.Cell(width, height, day_name(wday).first, "LTR", 0, "C")
left = left + width
wday = wday + 1
wday = 1 if wday > 7
end
end
pdf.SetY(y_start)
pdf.SetX(15)
pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
#
# Tasks
#
top = headers_heigth + y_start
pdf.SetFontStyle('B',7)
@gantt.events.each do |i|
pdf.SetY(top)
pdf.SetX(15)
if i.is_a? Issue
pdf.Cell(subject_width-15, 5, "#{i.tracker.name} #{i.id}: #{i.subject}".sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), "LR")
else
pdf.Cell(subject_width-15, 5, "#{l(:label_version)}: #{i.name}", "LR")
end
pdf.SetY(top)
pdf.SetX(subject_width)
pdf.Cell(g_width, 5, "", "LR")
pdf.SetY(top+1.5)
if i.is_a? Issue
i_start_date = (i.start_date >= @gantt.date_from ? i.start_date : @gantt.date_from )
i_end_date = (i.due_before <= @gantt.date_to ? i.due_before : @gantt.date_to )
i_done_date = i.start_date + ((i.due_before - i.start_date+1)*i.done_ratio/100).floor
i_done_date = (i_done_date <= @gantt.date_from ? @gantt.date_from : i_done_date )
i_done_date = (i_done_date >= @gantt.date_to ? @gantt.date_to : i_done_date )
i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
i_left = ((i_start_date - @gantt.date_from)*zoom)
i_width = ((i_end_date - i_start_date + 1)*zoom)
d_width = ((i_done_date - i_start_date)*zoom)
l_width = ((i_late_date - i_start_date+1)*zoom) if i_late_date
l_width ||= 0
pdf.SetX(subject_width + i_left)
pdf.SetFillColor(200,200,200)
pdf.Cell(i_width, 2, "", 0, 0, "", 1)
if l_width > 0
pdf.SetY(top+1.5)
pdf.SetX(subject_width + i_left)
pdf.SetFillColor(255,100,100)
pdf.Cell(l_width, 2, "", 0, 0, "", 1)
end
if d_width > 0
pdf.SetY(top+1.5)
pdf.SetX(subject_width + i_left)
pdf.SetFillColor(100,100,255)
pdf.Cell(d_width, 2, "", 0, 0, "", 1)
end
pdf.SetY(top+1.5)
pdf.SetX(subject_width + i_left + i_width)
pdf.Cell(30, 2, "#{i.status.name} #{i.done_ratio}%")
else
i_left = ((i.start_date - @gantt.date_from)*zoom)
pdf.SetX(subject_width + i_left)
pdf.SetFillColor(50,200,50)
pdf.Cell(2, 2, "", 0, 0, "", 1)
pdf.SetY(top+1.5)
pdf.SetX(subject_width + i_left + 3)
pdf.Cell(30, 2, "#{i.name}")
end
top = top + 5
pdf.SetDrawColor(200, 200, 200)
pdf.Line(15, top, subject_width+g_width, top)
if pdf.GetY() > 180
pdf.AddPage("L")
top = 20
pdf.Line(15, top, subject_width+g_width, top)
end
pdf.SetDrawColor(0, 0, 0)
end
pdf.Line(15, top, subject_width+g_width, top)
%>
<%= pdf.Output %>

View File

@@ -1,50 +0,0 @@
<% pdf=IfpdfHelper::IFPDF.new(current_language)
title = @project ? "#{@project.name} - #{l(:label_issue_plural)}" : "#{l(:label_issue_plural)}"
pdf.SetTitle(title)
pdf.AliasNbPages
pdf.footer_date = format_date(Date.today)
pdf.AddPage("L")
row_height = 7
#
# title
#
pdf.SetFontStyle('B',11)
pdf.Cell(190,10, title)
pdf.Ln
#
# headers
#
pdf.SetFontStyle('B',10)
pdf.SetFillColor(230, 230, 230)
pdf.Cell(15, row_height, "#", 0, 0, 'L', 1)
pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
pdf.Cell(40, row_height, l(:field_assigned_to), 0, 0, 'L', 1)
pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1)
pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1)
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
pdf.Ln
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
pdf.SetY(pdf.GetY() + 1)
#
# rows
#
pdf.SetFontStyle('',9)
pdf.SetFillColor(255, 255, 255)
@issues.each do |issue|
pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'L', 1)
pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
pdf.Cell(40, row_height, issue.assigned_to ? issue.assigned_to.name : '', 0, 0, 'L', 1)
pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}"))
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
pdf.SetY(pdf.GetY() + 1)
end
%>
<%= pdf.Output %>

View File

@@ -7,6 +7,7 @@
<%= render :partial => 'issues/form', :locals => {:f => f} %>
</div>
<%= submit_tag l(:button_create) %>
<%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
<%= link_to_remote l(:label_preview),
{ :url => { :controller => 'issues', :action => 'preview', :project_id => @project },
:method => 'post',
@@ -14,6 +15,12 @@
:with => "Form.serialize('issue-form')",
:complete => "Element.scrollTo('preview')"
}, :accesskey => accesskey(:preview) %>
<%= javascript_tag "Form.Element.focus('issue_subject');" %>
<% end %>
<div id="preview" class="wiki"></div>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'scm' %>
<% end %>

View File

@@ -1,126 +0,0 @@
<% pdf=IfpdfHelper::IFPDF.new(current_language)
pdf.SetTitle("#{@project.name} - ##{@issue.tracker.name} #{@issue.id}")
pdf.AliasNbPages
pdf.footer_date = format_date(Date.today)
pdf.AddPage
pdf.SetFontStyle('B',11)
pdf.Cell(190,10, "#{@issue.project} - #{@issue.tracker} # #{@issue.id}: #{@issue.subject}")
pdf.Ln
y0 = pdf.GetY
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_status) + ":","LT")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, @issue.status.name,"RT")
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_priority) + ":","LT")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, @issue.priority.name,"RT")
pdf.Ln
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_author) + ":","L")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, @issue.author.name,"R")
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_category) + ":","L")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, (@issue.category ? @issue.category.name : "-"),"R")
pdf.Ln
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_created_on) + ":","L")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, format_date(@issue.created_on),"R")
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_assigned_to) + ":","L")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, (@issue.assigned_to ? @issue.assigned_to.name : "-"),"R")
pdf.Ln
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_updated_on) + ":","LB")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, format_date(@issue.updated_on),"RB")
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_due_date) + ":","LB")
pdf.SetFontStyle('',9)
pdf.Cell(60,5, format_date(@issue.due_date),"RB")
pdf.Ln
for custom_value in @issue.custom_values
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
pdf.SetFontStyle('',9)
pdf.MultiCell(155,5, (show_value custom_value),"R")
end
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_subject) + ":","LTB")
pdf.SetFontStyle('',9)
pdf.Cell(155,5, @issue.subject,"RTB")
pdf.Ln
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_description) + ":")
pdf.SetFontStyle('',9)
pdf.MultiCell(155,5, @issue.description,"BR")
pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
pdf.Ln
if @issue.changesets.any? && User.current.allowed_to?(:view_changesets, @issue.project)
pdf.SetFontStyle('B',9)
pdf.Cell(190,5, l(:label_associated_revisions), "B")
pdf.Ln
for changeset in @issue.changesets
pdf.SetFontStyle('B',8)
pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.author.to_s)
pdf.Ln
unless changeset.comments.blank?
pdf.SetFontStyle('',8)
pdf.MultiCell(190,5, changeset.comments)
end
pdf.Ln
end
end
pdf.SetFontStyle('B',9)
pdf.Cell(190,5, l(:label_history), "B")
pdf.Ln
for journal in @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
pdf.SetFontStyle('B',8)
pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
pdf.Ln
pdf.SetFontStyle('I',8)
for detail in journal.details
pdf.Cell(190,5, "- " + show_detail(detail, true))
pdf.Ln
end
if journal.notes?
pdf.SetFontStyle('',8)
pdf.MultiCell(190,5, journal.notes)
end
pdf.Ln
end
if @issue.attachments.any?
pdf.SetFontStyle('B',9)
pdf.Cell(190,5, l(:label_attachment_plural), "B")
pdf.Ln
for attachment in @issue.attachments
pdf.SetFontStyle('',8)
pdf.Cell(80,5, attachment.filename)
pdf.Cell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
pdf.Cell(25,5, format_date(attachment.created_on),0,0,"R")
pdf.Cell(65,5, attachment.author.name,0,0,"R")
pdf.Ln
end
end
%>
<%= pdf.Output %>

View File

@@ -9,7 +9,7 @@
<h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
<div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>">
<div class="<%= css_issue_classes(@issue) %>">
<%= avatar(@issue.author, :size => "64") %>
<h3><%=h @issue.subject %></h3>
<p class="author">
@@ -19,11 +19,11 @@
<table width="100%">
<tr>
<td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status status-<%= @issue.status.name %>"><%= @issue.status.name %></td>
<td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status"><%= @issue.status.name %></td>
<td style="width:15%" class="start-date"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td>
</tr>
<tr>
<td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority priority-<%= @issue.priority.name %>"><%= @issue.priority.name %></td>
<td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority"><%= @issue.priority.name %></td>
<td class="due-date"><b><%=l(:field_due_date)%>:</b></td><td class="due-date"><%= format_date(@issue.due_date) %></td>
</tr>
<tr>
@@ -59,7 +59,7 @@ end %>
<hr />
<div class="contextual">
<%= link_to_remote_if_authorized l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment' %>
<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %>
</div>
<p><strong><%=l(:field_description)%></strong></p>
@@ -67,9 +67,7 @@ end %>
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
</div>
<% if @issue.attachments.any? %>
<%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %>
<% end %>
<%= link_to_attachments @issue %>
<% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
<hr />

View File

@@ -1,6 +1,7 @@
<% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %>
<%= text_area_tag :notes, @journal.notes, :class => 'wiki-edit',
:rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %>
<%= text_area_tag :notes, h(@journal.notes), :class => 'wiki-edit',
:rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %>
<%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %>
<p><%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " +
"Element.show('journal-#{@journal.id}-notes'); return false;" %></p>

View File

@@ -6,3 +6,5 @@ else
page.show "journal-#{@journal.id}-notes"
page.remove "journal-#{@journal.id}-form"
end
call_hook(:view_journals_update_rjs_bottom, { :page => page, :journal => @journal })

View File

@@ -3,10 +3,10 @@
<option selected="selected"><%= l(:label_jump_to_a_project) %></option>
<option disabled="disabled">---</option>
<% user_projects_by_root.keys.sort.each do |root| %>
<%= content_tag('option', h(root.name), :value => url_for(:controller => 'projects', :action => 'show', :id => root)) %>
<%= content_tag('option', h(root.name), :value => url_for(:controller => 'projects', :action => 'show', :id => root, :jump => current_menu_item)) %>
<% user_projects_by_root[root].sort.each do |project| %>
<% next if project == root %>
<%= content_tag('option', ('&#187; ' + h(project.name)), :value => url_for(:controller => 'projects', :action => 'show', :id => project)) %>
<%= content_tag('option', ('&#187; ' + h(project.name)), :value => url_for(:controller => 'projects', :action => 'show', :id => project, :jump => current_menu_item)) %>
<% end %>
<% end %>
</select>

View File

@@ -24,7 +24,7 @@
<div id="account">
<%= render_menu :account_menu -%>
</div>
<%= content_tag('div', "#{l(:label_logged_as)} #{User.current.login}", :id => 'loggedas') if User.current.logged? %>
<%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}", :id => 'loggedas') if User.current.logged? %>
<%= render_menu :top_menu -%>
</div>
@@ -50,8 +50,7 @@
</div>
<div id="content">
<%= content_tag('div', flash[:error], :class => 'flash error') if flash[:error] %>
<%= content_tag('div', flash[:notice], :class => 'flash notice') if flash[:notice] %>
<%= render_flash_messages %>
<%= yield %>
</div>
</div>

View File

@@ -6,17 +6,12 @@ body {
font-size: 0.8em;
color:#484848;
}
h1 {
font-family: "Trebuchet MS", Verdana, sans-serif;
font-size: 1.2em;
margin: 0px;
}
a, a:link, a:visited {
color: #2A5685;
}
a:hover, a:active {
color: #c61a1a;
}
h1, h2, h3 { font-family: "Trebuchet MS", Verdana, sans-serif; margin: 0px; }
h1 { font-size: 1.2em; }
h2, h3 { font-size: 1.1em; }
a, a:link, a:visited { color: #2A5685;}
a:hover, a:active { color: #c61a1a; }
a.wiki-anchor { display: none; }
hr {
width: 100%;
height: 1px;

View File

@@ -15,7 +15,7 @@
<div class="wiki">
<%= textilizable(@topic.content, :attachments => @topic.attachments) %>
</div>
<%= link_to_attachments @topic.attachments, :no_author => true %>
<%= link_to_attachments @topic, :author => false %>
</div>
<br />
@@ -31,7 +31,7 @@
<div class="message reply">
<h4><%=h message.subject %> - <%= authoring message.created_on, message.author %></h4>
<div class="wiki"><%= textilizable message, :content, :attachments => message.attachments %></div>
<%= link_to_attachments message.attachments, :no_author => true %>
<%= link_to_attachments message, :author => false %>
</div>
<% end %>
<% end %>

View File

@@ -38,7 +38,7 @@
<div class="box tabular">
<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
<p><%= pref_fields.check_box :hide_mail %></p>
<p><%= pref_fields.select :time_zone, TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
<p><%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
<p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
<% end %>
</div>

View File

@@ -47,6 +47,6 @@ entries_by_day = entries.group_by(&:spent_on)
</tr>
<% end -%>
<% end -%>
</tbdoy>
</tbody>
</table>
<% end %>

View File

@@ -11,7 +11,7 @@
<p><%= f.text_area :description, :rows => 5, :class => 'wiki-edit' %></p>
<p><%= f.text_field :identifier, :required => true, :disabled => @project.identifier_frozen? %>
<% unless @project.identifier_frozen? %>
<br /><em><%= l(:text_length_between, 3, 20) %> <%= l(:text_project_identifier_info) %></em>
<br /><em><%= l(:text_length_between, 2, 20) %> <%= l(:text_project_identifier_info) %></em>
<% end %></p>
<p><%= f.text_field :homepage, :size => 60 %></p>
<p><%= f.check_box :is_public %></p>

View File

@@ -4,10 +4,13 @@
<div class="box">
<% form_tag({ :action => 'add_file', :id => @project }, :multipart => true, :class => "tabular") do %>
<p><label for="version_id"><%=l(:field_version)%> <span class="required">*</span></label>
<%= select_tag "version_id", options_from_collection_for_select(@versions, "id", "name") %></p>
<% if @versions.any? %>
<p><label for="version_id"><%=l(:field_version)%></label>
<%= select_tag "version_id", content_tag('option', '') +
options_from_collection_for_select(@versions, "id", "name") %></p>
<% end %>
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
</div>
<%= submit_tag l(:button_add) %>
<% end %>
<% end %>

View File

@@ -4,39 +4,37 @@
<h2><%=l(:label_attachment_plural)%></h2>
<% delete_allowed = authorize_for('versions', 'destroy_file') %>
<% delete_allowed = User.current.allowed_to?(:manage_files, @project) %>
<table class="list">
<thead><tr>
<th><%=l(:field_version)%></th>
<%= sort_header_tag("#{Attachment.table_name}.filename", :caption => l(:field_filename)) %>
<%= sort_header_tag("#{Attachment.table_name}.created_on", :caption => l(:label_date), :default_order => 'desc') %>
<%= sort_header_tag("#{Attachment.table_name}.filesize", :caption => l(:field_filesize), :default_order => 'desc') %>
<%= sort_header_tag("#{Attachment.table_name}.downloads", :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
<%= sort_header_tag('filename', :caption => l(:field_filename)) %>
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
<%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %>
<%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
<th>MD5</th>
<% if delete_allowed %><th></th><% end %>
<th></th>
</tr></thead>
<tbody>
<% for version in @versions %>
<% unless version.attachments.empty? %>
<tr><th colspan="7" align="left"><span class="icon icon-package"><b><%= version.name %></b></span></th></tr>
<% for file in version.attachments %>
<% @containers.each do |container| %>
<% next if container.attachments.empty? -%>
<% if container.is_a?(Version) -%>
<tr><th colspan="6" align="left"><span class="icon icon-package"><b><%=h container %></b></span></th></tr>
<% end -%>
<% container.attachments.each do |file| %>
<tr class="<%= cycle("odd", "even") %>">
<td></td>
<td><%= link_to_attachment file, :download => true, :title => file.description %></td>
<td align="center"><%= format_time(file.created_on) %></td>
<td align="center"><%= number_to_human_size(file.filesize) %></td>
<td align="center"><%= file.downloads %></td>
<td align="center"><small><%= file.digest %></small></td>
<% if delete_allowed %>
<td align="center">
<%= link_to_if_authorized image_tag('delete.png'), {:controller => 'versions', :action => 'destroy_file', :id => version, :attachment_id => file}, :confirm => l(:text_are_you_sure), :method => :post %>
<%= link_to(image_tag('delete.png'), {:controller => 'attachments', :action => 'destroy', :id => file},
:confirm => l(:text_are_you_sure), :method => :post) if delete_allowed %>
</td>
<% end %>
</tr>
<% end
reset_cycle %>
<% end %>
<% end %>
</tbody>
</table>

View File

@@ -17,7 +17,6 @@
<td><%= link_to(version.wiki_page_title, :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
<td align="center"><%= link_to_if_authorized l(:button_edit), { :controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %></td>
<td align="center"><%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></td>
</td>
</tr>
<% end; reset_cycle %>
</tbody>

View File

@@ -0,0 +1,10 @@
<p>
<% if @repository.supports_cat? %>
<%= link_to_if action_name != 'entry', l(:button_view), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev } %> |
<% end %>
<% if @repository.supports_annotate? %>
<%= link_to_if action_name != 'annotate', l(:button_annotate), {:action => 'annotate', :id => @project, :path => to_path_param(@path), :rev => @rev } %> |
<% end %>
<%= link_to(l(:button_download), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev, :format => 'raw' }) if @repository.supports_cat? %>
<%= "(#{number_to_human_size(@entry.size)})" if @entry.size %>
</p>

View File

@@ -1,5 +1,7 @@
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2>
<p><%= render :partial => 'link_to_functions' %></p>
<% colors = Hash.new {|k,v| k[v] = (k.size % 12) } %>
<div class="autoscroll">

View File

@@ -1,15 +1,6 @@
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %></h2>
<p>
<% if @repository.supports_cat? %>
<%= link_to l(:button_view), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev } %> |
<% end %>
<% if @repository.supports_annotate? %>
<%= link_to l(:button_annotate), {:action => 'annotate', :id => @project, :path => to_path_param(@path), :rev => @rev } %> |
<% end %>
<%= link_to(l(:button_download), {:action => 'entry', :id => @project, :path => to_path_param(@path), :rev => @rev, :format => 'raw' }) if @repository.supports_cat? %>
<%= "(#{number_to_human_size(@entry.size)})" if @entry.size %>
</p>
<p><%= render :partial => 'link_to_functions' %></p>
<%= render_properties(@properties) %>

View File

@@ -15,11 +15,16 @@
</tr>
</thead>
<tbody>
<% i = 0 -%>
<% @committers.each do |committer, user_id| -%>
<tr class="<%= cycle 'odd', 'even' %>">
<td><%=h committer %></td>
<td><%= select_tag "committers[#{committer}]", content_tag('option', "-- #{l :actionview_instancetag_blank_option} --", :value => '') + options_from_collection_for_select(@users, 'id', 'name', user_id.to_i) %></td>
<td>
<%= hidden_field_tag "committers[#{i}][]", committer %>
<%= select_tag "committers[#{i}][]", content_tag('option', "-- #{l :actionview_instancetag_blank_option} --", :value => '') + options_from_collection_for_select(@users, 'id', 'name', user_id.to_i) %>
</td>
</tr>
<% i += 1 -%>
<% end -%>
</tbody>
</table>

View File

@@ -1,5 +1,7 @@
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2>
<p><%= render :partial => 'link_to_functions' %></p>
<%= render :partial => 'common/file', :locals => {:filename => @path, :content => @content} %>
<% content_for :header_tags do %>

View File

@@ -48,6 +48,9 @@
<p><label><%= l(:setting_feeds_limit) %></label>
<%= text_field_tag 'settings[feeds_limit]', Setting.feeds_limit, :size => 6 %></p>
<p><label><%= l(:setting_diff_max_lines_displayed) %></label>
<%= text_field_tag 'settings[diff_max_lines_displayed]', Setting.diff_max_lines_displayed, :size => 6 %></p>
<p><label><%= l(:setting_gravatar_enabled) %></label>
<%= check_box_tag 'settings[gravatar_enabled]', 1, Setting.gravatar_enabled? %><%= hidden_field_tag 'settings[gravatar_enabled]', 0 %></p>
</div>

View File

@@ -2,10 +2,10 @@
<thead>
<tr>
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
<%= sort_header_tag("#{Project.table_name}.name", :caption => l(:label_project)) %>
<%= sort_header_tag('issue_id', :caption => l(:label_issue), :default_order => 'desc') %>
<%= sort_header_tag('user', :caption => l(:label_member)) %>
<%= sort_header_tag('activity', :caption => l(:label_activity)) %>
<%= sort_header_tag('project', :caption => l(:label_project)) %>
<%= sort_header_tag('issue', :caption => l(:label_issue), :default_order => 'desc') %>
<th><%= l(:field_comments) %></th>
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
<th></th>

View File

@@ -20,7 +20,7 @@
<th class="line-num"><%= line_num %></th>
<td class="revision"><%= link_to line[0], :controller => 'wiki', :action => 'index', :id => @project, :page => @page.title, :version => line[0] %></td>
<td class="author"><%= h(line[1]) %></td>
<td class="line-code"><pre><%= line[2] %></pre></td>
<td class="line-code"><pre><%=h line[2] %></pre></td>
</tr>
<% line_num += 1 %>
<% end -%>

View File

@@ -5,7 +5,7 @@
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
body { font:80% Verdana,Tahoma,Arial,sans-serif; }
h1, h2, h3, h4 { font-family: Trebuchet MS,Georgia,"Times New Roman",serif; }
h1, h2, h3, h4 { font-family: "Trebuchet MS",Georgia,"Times New Roman",serif; }
ul.toc { padding: 4px; margin-left: 0; }
ul.toc li { list-style-type:none; }
ul.toc li.heading2 { margin-left: 1em; }

View File

@@ -5,7 +5,7 @@
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
body { font:80% Verdana,Tahoma,Arial,sans-serif; }
h1, h2, h3, h4 { font-family: Trebuchet MS,Georgia,"Times New Roman",serif; }
h1, h2, h3, h4 { font-family: "Trebuchet MS",Georgia,"Times New Roman",serif; }
</style>
</head>
<body>

View File

@@ -28,7 +28,7 @@
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
<%= link_to_attachments @page.attachments, :delete_url => ((@editable && authorize_for('wiki', 'destroy_attachment')) ? {:controller => 'wiki', :action => 'destroy_attachment', :page => @page.title} : nil) %>
<%= link_to_attachments @page %>
<% if @editable && authorize_for('wiki', 'add_attachment') %>
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",

View File

@@ -5,7 +5,7 @@
# ENV['RAILS_ENV'] ||= 'production'
# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')

View File

@@ -61,6 +61,9 @@ protocol:
feeds_limit:
format: int
default: 15
diff_max_lines_displayed:
format: int
default: 1500
enabled_scm:
serialized: true
default:

View File

@@ -2,9 +2,10 @@ class SetTopicAuthorsAsWatchers < ActiveRecord::Migration
def self.up
# Sets active users who created/replied a topic as watchers of the topic
# so that the new watch functionality at topic level doesn't affect notifications behaviour
Message.connection.execute("INSERT INTO watchers (watchable_type, watchable_id, user_id)" +
" SELECT DISTINCT 'Message', COALESCE(messages.parent_id, messages.id), messages.author_id FROM messages, users" +
" WHERE messages.author_id = users.id AND users.status = 1")
Message.connection.execute("INSERT INTO #{Watcher.table_name} (watchable_type, watchable_id, user_id)" +
" SELECT DISTINCT 'Message', COALESCE(m.parent_id, m.id), m.author_id" +
" FROM #{Message.table_name} m, #{User.table_name} u" +
" WHERE m.author_id = u.id AND u.status = 1")
end
def self.down

View File

@@ -1,10 +1,227 @@
== Redmine changelog
Redmine - project management software
Copyright (C) 2006-2008 Jean-Philippe Lang
Copyright (C) 2006-2009 Jean-Philippe Lang
http://www.redmine.org/
== 2009-02-15 v0.8.1
* Select watchers on new issue form
* Issue description is no longer a required field
* Files module: ability to add files without version
* Jump to the current tab when using the project quick-jump combo
* Display a warning if some attachments were not saved
* Import custom fields values from emails on issue creation
* Show view/annotate/download links on entry and annotate views
* Admin Info Screen: Display if plugin assets directory is writable
* Adds a 'Create and continue' button on the new issue form
* IMAP: add options to move received emails
* Do not show Category field when categories are not defined
* Lower the project identifier limit to a minimum of two characters
* Add "closed" html class to closed entries in issue list
* Fixed: broken redirect URL on login failure
* Fixed: Deleted files are shown when using Darcs
* Fixed: Darcs adapter works on Win32 only
* Fixed: syntax highlight doesn't appear in new ticket preview
* Fixed: email notification for changes I make still occurs when running Repository.fetch_changesets
* Fixed: no error is raised when entering invalid hours on the issue update form
* Fixed: Details time log report CSV export doesn't honour date format from settings
* Fixed: invalid css classes on issue details
* Fixed: Trac importer creates duplicate custom values
* Fixed: inline attached image should not match partial filename
== 2008-12-30 v0.8.0
* Setting added in order to limit the number of diff lines that should be displayed
* Makes logged-in username in topbar linking to
* Mail handler: strip tags when receiving a html-only email
* Mail handler: add watchers before sending notification
* Adds a css class (overdue) to overdue issues on issue lists and detail views
* Fixed: project activity truncated after viewing user's activity
* Fixed: email address entered for password recovery shouldn't be case-sensitive
* Fixed: default flag removed when editing a default enumeration
* Fixed: default category ignored when adding a document
* Fixed: error on repository user mapping when a repository username is blank
* Fixed: Firefox cuts off large diffs
* Fixed: CVS browser should not show dead revisions (deleted files)
* Fixed: escape double-quotes in image titles
* Fixed: escape textarea content when editing a issue note
* Fixed: JS error on context menu with IE
* Fixed: bold syntax around single character in series doesn't work
* Fixed several XSS vulnerabilities
* Fixed a SQL injection vulnerability
== 2008-12-07 v0.8.0-rc1
* Wiki page protection
* Wiki page hierarchy. Parent page can be assigned on the Rename screen
* Adds support for issue creation via email
* Adds support for free ticket filtering and custom queries on Gantt chart and calendar
* Cross-project search
* Ability to search a project and its subprojects
* Ability to search the projects the user belongs to
* Adds custom fields on time entries
* Adds boolean and list custom fields for time entries as criteria on time report
* Cross-project time reports
* Display latest user's activity on account/show view
* Show last connexion time on user's page
* Obfuscates email address on user's account page using javascript
* wiki TOC rendered as an unordered list
* Adds the ability to search for a user on the administration users list
* Adds the ability to search for a project name or identifier on the administration projects list
* Redirect user to the previous page after logging in
* Adds a permission 'view wiki edits' so that wiki history can be hidden to certain users
* Adds permissions for viewing the watcher list and adding new watchers on the issue detail view
* Adds permissions to let users edit and/or delete their messages
* Link to activity view when displaying dates
* Hide Redmine version in atom feeds and pdf properties
* Maps repository users to Redmine users. Users with same username or email are automatically mapped. Mapping can be manually adjusted in repository settings. Multiple usernames can be mapped to the same Redmine user.
* Sort users by their display names so that user dropdown lists are sorted alphabetically
* Adds estimated hours to issue filters
* Switch order of current and previous revisions in side-by-side diff
* Render the commit changes list as a tree
* Adds watch/unwatch functionality at forum topic level
* When moving an issue to another project, reassign it to the category with same name if any
* Adds child_pages macro for wiki pages
* Use GET instead of POST on roadmap (#718), gantt and calendar forms
* Search engine: display total results count and count by result type
* Email delivery configuration moved to an unversioned YAML file (config/email.yml, see the sample file)
* Adds icons on search results
* Adds 'Edit' link on account/show for admin users
* Adds Lock/Unlock/Activate link on user edit screen
* Adds user count in status drop down on admin user list
* Adds multi-levels blockquotes support by using > at the beginning of lines
* Adds a Reply link to each issue note
* Adds plain text only option for mail notifications
* Gravatar support for issue detail, user grid, and activity stream (disabled by default)
* Adds 'Delete wiki pages attachments' permission
* Show the most recent file when displaying an inline image
* Makes permission screens localized
* AuthSource list: display associated users count and disable 'Delete' buton if any
* Make the 'duplicates of' relation asymmetric
* Adds username to the password reminder email
* Adds links to forum messages using message#id syntax
* Allow same name for custom fields on different object types
* One-click bulk edition using the issue list context menu within the same project
* Adds support for commit logs reencoding to UTF-8 before insertion in the database. Source encoding of commit logs can be selected in Application settings -> Repositories.
* Adds checkboxes toggle links on permissions report
* Adds Trac-Like anchors on wiki headings
* Adds support for wiki links with anchor
* Adds category to the issue context menu
* Adds a workflow overview screen
* Appends the filename to the attachment url so that clients that ignore content-disposition http header get the real filename
* Dots allowed in custom field name
* Adds posts quoting functionality
* Adds an option to generate sequential project identifiers
* Adds mailto link on the user administration list
* Ability to remove enumerations (activities, priorities, document categories) that are in use. Associated objects can be reassigned to another value
* Gantt chart: display issues that don't have a due date if they are assigned to a version with a date
* Change projects homepage limit to 255 chars
* Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes
* Adds "please select" to activity select box if no activity is set as default
* Do not silently ignore timelog validation failure on issue edit
* Adds a rake task to send reminder emails
* Allow empty cells in wiki tables
* Makes wiki text formatter pluggable
* Adds back textile acronyms support
* Remove pre tag attributes
* Plugin hooks
* Pluggable admin menu
* Plugins can provide activity content
* Moves plugin list to its own administration menu item
* Adds url and author_url plugin attributes
* Adds Plugin#requires_redmine method so that plugin compatibility can be checked against current Redmine version
* Adds atom feed on time entries details
* Adds project name to issues feed title
* Adds a css class on menu items in order to apply item specific styles (eg. icons)
* Adds a Redmine plugin generators
* Adds timelog link to the issue context menu
* Adds links to the user page on various views
* Turkish translation by Ismail Sezen
* Catalan translation
* Vietnamese translation
* Slovak translation
* Better naming of activity feed if only one kind of event is displayed
* Enable syntax highlight on issues, messages and news
* Add target version to the issue list context menu
* Hide 'Target version' filter if no version is defined
* Add filters on cross-project issue list for custom fields marked as 'For all projects'
* Turn ftp urls into links
* Hiding the View Differences button when a wiki page's history only has one version
* Messages on a Board can now be sorted by the number of replies
* Adds a class ('me') to events of the activity view created by current user
* Strip pre/code tags content from activity view events
* Display issue notes in the activity view
* Adds links to changesets atom feed on repository browser
* Track project and tracker changes in issue history
* Adds anchor to atom feed messages links
* Adds a key in lang files to set the decimal separator (point or comma) in csv exports
* Makes importer work with Trac 0.8.x
* Upgraded to Prototype 1.6.0.1
* File viewer for attached text files
* Menu mapper: add support for :before, :after and :last options to #push method and add #delete method
* Removed inconsistent revision numbers on diff view
* CVS: add support for modules names with spaces
* Log the user in after registration if account activation is not needed
* Mercurial adapter improvements
* Trac importer: read session_attribute table to find user's email and real name
* Ability to disable unused SCM adapters in application settings
* Adds Filesystem adapter
* Clear changesets and changes with raw sql when deleting a repository for performance
* Redmine.pm now uses the 'commit access' permission defined in Redmine
* Reposman can create any type of scm (--scm option)
* Reposman creates a repository if the 'repository' module is enabled at project level only
* Display svn properties in the browser, svn >= 1.5.0 only
* Reduces memory usage when importing large git repositories
* Wider SVG graphs in repository stats
* SubversionAdapter#entries performance improvement
* SCM browser: ability to download raw unified diffs
* More detailed error message in log when scm command fails
* Adds support for file viewing with Darcs 2.0+
* Check that git changeset is not in the database before creating it
* Unified diff viewer for attached files with .patch or .diff extension
* File size display with Bazaar repositories
* Git adapter: use commit time instead of author time
* Prettier url for changesets
* Makes changes link to entries on the revision view
* Adds a field on the repository view to browse at specific revision
* Adds new projects atom feed
* Added rake tasks to generate rcov code coverage reports
* Add Redcloth's :block_markdown_rule to allow horizontal rules in wiki
* Show the project hierarchy in the drop down list for new membership on user administration screen
* Split user edit screen into tabs
* Renames bundled RedCloth to RedCloth3 to avoid RedCloth 4 to be loaded instead
* Fixed: Roadmap crashes when a version has a due date > 2037
* Fixed: invalid effective date (eg. 99999-01-01) causes an error on version edition screen
* Fixed: login filter providing incorrect back_url for Redmine installed in sub-directory
* Fixed: logtime entry duplicated when edited from parent project
* Fixed: wrong digest for text files under Windows
* Fixed: associated revisions are displayed in wrong order on issue view
* Fixed: Git Adapter date parsing ignores timezone
* Fixed: Printing long roadmap doesn't split across pages
* Fixes custom fields display order at several places
* Fixed: urls containing @ are parsed as email adress by the wiki formatter
* Fixed date filters accuracy with SQLite
* Fixed: tokens not escaped in highlight_tokens regexp
* Fixed Bazaar shared repository browsing
* Fixes platform determination under JRuby
* Fixed: Estimated time in issue's journal should be rounded to two decimals
* Fixed: 'search titles only' box ignored after one search is done on titles only
* Fixed: non-ASCII subversion path can't be displayed
* Fixed: Inline images don't work if file name has upper case letters or if image is in BMP format
* Fixed: document listing shows on "my page" when viewing documents is disabled for the role
* Fixed: Latest news appear on the homepage for projects with the News module disabled
* Fixed: cross-project issue list should not show issues of projects for which the issue tracking module was disabled
* Fixed: the default status is lost when reordering issue statuses
* Fixes error with Postgresql and non-UTF8 commit logs
* Fixed: textile footnotes no longer work
* Fixed: http links containing parentheses fail to reder correctly
* Fixed: GitAdapter#get_rev should use current branch instead of hardwiring master
== 2008-07-06 v0.7.3
* Allow dot in firstnames and lastnames

View File

@@ -7,7 +7,7 @@ http://www.redmine.org/
== Requirements
* Ruby on Rails 2.1
* Ruby on Rails 2.1.2
* A database:
* MySQL (tested with MySQL 5)
* PostgreSQL (tested with PostgreSQL 8.1)

View File

@@ -22,7 +22,7 @@ http://www.redmine.org/
== Notes
1. Rails 2.0.2 is required for version 0.7 and later.
1. Rails 2.1.2 is required for version 0.8.
2. When upgrading your code with svn update, don't forget to clear
the application cache (RAILS_ROOT/tmp/cache) before restarting.

View File

@@ -694,3 +694,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -695,3 +695,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -699,3 +699,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -695,3 +695,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -223,6 +223,7 @@ setting_mail_handler_api_enabled: Abruf eingehender E-Mails aktivieren
setting_mail_handler_api_key: API-Schlüssel
setting_sequential_project_identifiers: Fortlaufende Projektkennungen generieren
setting_gravatar_enabled: Gravatar Benutzerbilder benutzen
setting_diff_max_lines_displayed: Maximale Anzahl anzuzeigender Diff-Zeilen
permission_edit_project: Projekt bearbeiten
permission_select_project_modules: Projektmodule auswählen
@@ -344,6 +345,7 @@ label_last_updates_plural: %d zuletzt aktualisierten
label_registered_on: Angemeldet am
label_activity: Aktivität
label_overall_activity: Aktivität aller Projekte anzeigen
label_user_activity: "Aktivität von %s"
label_new: Neu
label_logged_as: Angemeldet als
label_environment: Environment
@@ -543,6 +545,7 @@ label_send_test_email: Test-E-Mail senden
label_feeds_access_key_created_on: Atom-Zugriffsschlüssel vor %s erstellt
label_module_plural: Module
label_added_time_by: Von %s vor %s hinzugefügt
label_updated_time_by: Von %s vor %s aktualisiert
label_updated_time: Vor %s aktualisiert
label_jump_to_a_project: Zu einem Projekt springen...
label_file_plural: Dateien
@@ -668,6 +671,7 @@ text_enumeration_destroy_question: '%d Objekte sind diesem Wert zugeordnet.'
text_enumeration_category_reassign_to: 'Die Objekte stattdessen diesem Wert zuordnen:'
text_email_delivery_not_configured: "Der SMTP-Server ist nicht konfiguriert und Mailbenachrichtigungen sind ausgeschaltet.\nNehmen Sie die Einstellungen für Ihren SMTP-Server in config/email.yml vor und starten Sie die Applikation neu."
text_repository_usernames_mapping: "Bitte legen Sie die Zuordnung der Redmine-Benutzer zu den Benutzernamen der Commit-Log-Meldungen des Projektarchivs fest.\nBenutzer mit identischen Redmine- und Projektarchiv-Benutzernamen oder -E-Mail-Adressen werden automatisch zugeordnet."
text_diff_truncated: '... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.'
default_role_manager: Manager
default_role_developper: Entwickler
@@ -694,5 +698,6 @@ default_activity_development: Entwicklung
enumeration_issue_priorities: Ticket-Prioritäten
enumeration_doc_categories: Dokumentenkategorien
enumeration_activities: Aktivitäten (Zeiterfassung)
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -85,6 +85,8 @@ error_scm_command_failed: "An error occurred when trying to access the repositor
error_scm_annotate: "The entry does not exist or can not be annotated."
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
warning_attachments_not_saved: "%d file(s) could not be saved."
mail_subject_lost_password: Your %s password
mail_body_lost_password: 'To change your password, click on the following link:'
mail_subject_register: Your %s account activation
@@ -223,6 +225,7 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
setting_mail_handler_api_key: API key
setting_sequential_project_identifiers: Generate sequential project identifiers
setting_gravatar_enabled: Use Gravatar user icons
setting_diff_max_lines_displayed: Max number of diff lines displayed
permission_edit_project: Edit project
permission_select_project_modules: Select project modules
@@ -589,6 +592,7 @@ button_check_all: Check all
button_uncheck_all: Uncheck all
button_delete: Delete
button_create: Create
button_create_and_continue: Create and continue
button_test: Test
button_edit: Edit
button_add: Add
@@ -659,7 +663,8 @@ text_status_changed_by_changeset: Applied in changeset %s.
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s) ?'
text_select_project_modules: 'Select modules to enable for this project:'
text_default_administrator_account_changed: Default administrator account changed
text_file_repository_writable: File repository writable
text_file_repository_writable: Attachments directory writable
text_plugin_assets_writable: Plugin assets directory writable
text_rmagick_available: RMagick available (optional)
text_destroy_time_entries_question: %.02f hours were reported on the issues you are about to delete. What do you want to do ?
text_destroy_time_entries: Delete reported hours
@@ -670,6 +675,7 @@ text_enumeration_destroy_question: '%d objects are assigned to this value.'
text_enumeration_category_reassign_to: 'Reassign them to this value:'
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
default_role_manager: Manager
default_role_developper: Developer

View File

@@ -19,11 +19,11 @@ actionview_datehelper_time_in_words_second_less_than_plural: menos de %d segundo
actionview_instancetag_blank_option: Por favor seleccione
activerecord_error_accepted: debe ser aceptado
activerecord_error_blank: no puede estar en blanco
activerecord_error_circular_dependency: Esta relación podría crear una dependencia anidada
activerecord_error_circular_dependency: Esta relación podría crear una dependencia circular
activerecord_error_confirmation: la confirmación no coincide
activerecord_error_empty: no puede estar vacío
activerecord_error_exclusion: está reservado
activerecord_error_greater_than_start_date: debe ser la fecha mayor que del comienzo
activerecord_error_greater_than_start_date: debe ser posterior a la fecha de comienzo
activerecord_error_inclusion: no está incluído en la lista
activerecord_error_invalid: no es válido
activerecord_error_not_a_date: no es una fecha válida
@@ -140,11 +140,11 @@ field_is_default: Estado por defecto
field_is_filter: Usado como filtro
field_is_for_all: Para todos los proyectos
field_is_in_chlog: Consultar las peticiones en el histórico
field_is_in_roadmap: Consultar las peticiones en el roadmap
field_is_in_roadmap: Consultar las peticiones en la planificación
field_is_public: Público
field_is_required: Obligatorio
field_issue: Petición
field_issue_to_id: Petición Relacionada
field_issue_to_id: Petición relacionada
field_language: Idioma
field_last_login_on: Última conexión
field_lastname: Apellido
@@ -178,7 +178,7 @@ field_subproject: Proyecto secundario
field_summary: Resumen
field_time_zone: Zona horaria
field_title: Título
field_tracker: Tracker
field_tracker: Tipo
field_type: Tipo
field_updated_on: Actualizado
field_url: URL
@@ -215,7 +215,7 @@ label_ago: hace
label_all: todos
label_all_time: todo el tiempo
label_all_words: Todas las palabras
label_and_its_subprojects: %s y sus subproyectos
label_and_its_subprojects: %s y proyectos secundarios
label_applied_status: Aplicar estado
label_assigned_to_me_issues: Peticiones que me están asignadas
label_associated_revisions: Revisiones asociadas
@@ -234,7 +234,7 @@ label_blocks: bloquea a
label_board: Foro
label_board_new: Nuevo foro
label_board_plural: Foros
label_boolean: Boleano
label_boolean: Booleano
label_browse: Hojear
label_bulk_edit_selected_issues: Editar las peticiones seleccionadas
label_calendar: Calendario
@@ -293,7 +293,7 @@ label_enumerations: Listas de valores
label_environment: Entorno
label_equals: igual
label_example: Ejemplo
label_export_to: Exportar a
label_export_to: 'Exportar a:'
label_f_hour: %.2f hora
label_f_hour_plural: %.2f horas
label_feed_plural: Feeds
@@ -327,7 +327,7 @@ label_issue_category_new: Nueva categoría
label_issue_category_plural: Categorías de las peticiones
label_issue_new: Nueva petición
label_issue_plural: Peticiones
label_issue_status: Estado de petición
label_issue_status: Estado de la petición
label_issue_status_new: Nuevo estado
label_issue_status_plural: Estados de las peticiones
label_issue_tracking: Peticiones
@@ -337,7 +337,7 @@ label_issue_watchers: Seguidores
label_issues_by: Peticiones por %s
label_jump_to_a_project: Ir al proyecto...
label_language_based: Basado en el idioma
label_last_changes: %d cambios del último
label_last_changes: últimos %d cambios
label_last_login: Última conexión
label_last_month: último mes
label_last_n_days: últimos %d días
@@ -384,7 +384,7 @@ label_news_plural: Noticias
label_news_view_all: Ver todas las noticias
label_next: Siguiente
label_no_change_option: (Sin cambios)
label_no_data: Ningun dato a mostrar
label_no_data: Ningún dato a mostrar
label_nobody: nadie
label_none: ninguno
label_not_contains: no contiene
@@ -397,7 +397,7 @@ label_options: Opciones
label_overall_activity: Actividad global
label_overview: Vistazo
label_password_lost: ¿Olvidaste la contraseña?
label_per_page: Por la página
label_per_page: Por página
label_permissions: Permisos
label_permissions_report: Informe de permisos
label_personalize_page: Personalizar esta página
@@ -438,7 +438,7 @@ label_result_plural: Resultados
label_reverse_chronological_order: En orden cronológico inverso
label_revision: Revisión
label_revision_plural: Revisiones
label_roadmap: Roadmap
label_roadmap: Planificación
label_roadmap_due_in: Finaliza en %s
label_roadmap_no_issues: No hay peticiones para esta versión
label_roadmap_overdue: %s tarde
@@ -452,7 +452,7 @@ label_search_titles_only: Buscar sólo en títulos
label_send_information: Enviar información de la cuenta al usuario
label_send_test_email: Enviar un correo de prueba
label_settings: Configuración
label_show_completed_versions: Muestra las versiones completas
label_show_completed_versions: Muestra las versiones terminadas
label_sort_by: Ordenar por %s
label_sort_higher: Subir
label_sort_highest: Primero
@@ -474,16 +474,18 @@ label_time_tracking: Control de tiempo
label_today: hoy
label_topic_plural: Temas
label_total: Total
label_tracker: Tracker
label_tracker_new: Nuevo tracker
label_tracker_plural: Trackers
label_tracker: Tipo
label_tracker_new: Nuevo tipo
label_tracker_plural: Tipos de peticiones
label_updated_time: Actualizado hace %s
label_updated_time_by: Actualizado por %s hace %s
label_used_by: Utilizado por
label_user: Usuario
label_user_activity: "Actividad de %s"
label_user_mail_no_self_notified: "No quiero ser avisado de cambios hechos por mí"
label_user_mail_option_all: "Para cualquier evento en todos mis proyectos"
label_user_mail_option_none: "Sólo para elementos monitorizados o relacionados conmigo"
label_user_mail_option_selected: "Para cualquier evento del proyecto seleccionado..."
label_user_mail_option_selected: "Para cualquier evento de los proyectos seleccionados..."
label_user_new: Nuevo usuario
label_user_plural: Usuarios
label_version: Versión
@@ -501,22 +503,22 @@ label_wiki_page_plural: Wiki páginas
label_workflow: Flujo de trabajo
label_year: Año
label_yesterday: ayer
mail_body_account_activation_request: "Un nuevo usuario (%s) ha sido registrado. Esta cuenta está pendiende de aprobación"
mail_body_account_activation_request: 'Se ha inscrito un nuevo usuario (%s). La cuenta está pendiende de aprobación:'
mail_body_account_information: Información sobre su cuenta
mail_body_account_information_external: Puede usar su cuenta "%s" para conectarse.
mail_body_lost_password: 'Para cambiar su contraseña, haga click en el siguiente enlace:'
mail_body_register: 'Para activar su cuenta, haga click en el siguiente enlace:'
mail_body_lost_password: 'Para cambiar su contraseña, haga clic en el siguiente enlace:'
mail_body_register: 'Para activar su cuenta, haga clic en el siguiente enlace:'
mail_body_reminder: "%d peticion(es) asignadas a tí finalizan en los próximos %d días:"
mail_subject_account_activation_request: Petición de activación de cuenta %s
mail_subject_lost_password: Tu contraseña del %s
mail_subject_register: Activación de la cuenta del %s
mail_subject_reminder: "%d peticion(es) finalizan en los próximos días"
notice_account_activated: Su cuenta ha sido activada. Ahora se encuentra conectado.
notice_account_activated: Su cuenta ha sido activada. Ya puede conectarse.
notice_account_invalid_creditentials: Usuario o contraseña inválido.
notice_account_lost_email_sent: Se le ha enviado un correo con instrucciones para elegir una nueva contraseña.
notice_account_password_updated: Contraseña modificada correctamente.
notice_account_pending: "Su cuenta ha sido creada y está pendiende de la aprobación por parte de administrador"
notice_account_register_done: Cuenta creada correctamente.
notice_account_pending: "Su cuenta ha sido creada y está pendiende de la aprobación por parte del administrador."
notice_account_register_done: Cuenta creada correctamente. Para activarla, haga clic sobre el enlace que le ha sido enviado por correo.
notice_account_unknown_email: Usuario desconocido.
notice_account_updated: Cuenta actualizada correctamente.
notice_account_wrong_password: Contraseña incorrecta.
@@ -524,9 +526,9 @@ notice_can_t_change_password: Esta cuenta utiliza una fuente de autenticación e
notice_default_data_loaded: Configuración por defecto cargada correctamente.
notice_email_error: Ha ocurrido un error mientras enviando el correo (%s)
notice_email_sent: Se ha enviado un correo a %s
notice_failed_to_save_issues: "Imposible salvar %s peticion(es) en %d seleccionado: %s."
notice_feeds_access_key_reseted: Su clave de acceso para RSS ha sido reiniciada
notice_file_not_found: La página a la que intentas acceder no existe.
notice_failed_to_save_issues: "Imposible grabar %s peticion(es) en %d seleccionado: %s."
notice_feeds_access_key_reseted: Su clave de acceso para RSS ha sido reiniciada.
notice_file_not_found: La página a la que intenta acceder no existe.
notice_locking_conflict: Los datos han sido modificados por otro usuario.
notice_no_issue_selected: "Ninguna petición seleccionada. Por favor, compruebe la petición que quiere modificar"
notice_not_authorized: No tiene autorización para acceder a esta página.
@@ -544,9 +546,9 @@ permission_comment_news: Comentar noticias
permission_commit_access: Acceso de escritura
permission_delete_issues: Borrar peticiones
permission_delete_messages: Borrar mensajes
permission_delete_own_messages: Borrar mensajes propios
permission_delete_wiki_pages: Borrar páginas wiki
permission_delete_wiki_pages_attachments: Borrar ficheros
permission_delete_own_messages: Borrar mensajes propios
permission_edit_issue_notes: Modificar notas
permission_edit_issues: Modificar peticiones
permission_edit_messages: Modificar mensajes
@@ -602,15 +604,16 @@ setting_commit_fix_keywords: Palabras clave para la corrección
setting_commit_logs_encoding: Codificación de los mensajes de commit
setting_commit_ref_keywords: Palabras clave para la referencia
setting_cross_project_issue_relations: Permitir relacionar peticiones de distintos proyectos
setting_date_format: Formato de la fecha
setting_date_format: Formato de fecha
setting_default_language: Idioma por defecto
setting_default_projects_public: Los proyectos nuevos son públicos por defecto
setting_display_subprojects_issues: Mostrar peticiones de un subproyecto en el proyecto padre por defecto
setting_diff_max_lines_displayed: Número máximo de diferencias mostradas
setting_display_subprojects_issues: Mostrar por defecto peticiones de proy. secundarios en el principal
setting_emails_footer: Pie de mensajes
setting_enabled_scm: Activar SCM
setting_feeds_limit: Límite de contenido para sindicación
setting_gravatar_enabled: Usar iconos de usuario (Gravatar)
setting_host_name: Nombre de host
setting_host_name: Nombre y ruta del servidor
setting_issue_list_default_columns: Columnas por defecto para la lista de peticiones
setting_issues_export_limit: Límite de exportación de peticiones
setting_login_required: Se requiere identificación
@@ -632,7 +635,7 @@ setting_wiki_compression: Compresión del historial del Wiki
status_active: activo
status_locked: bloqueado
status_registered: registrado
text_are_you_sure: ¿ Estás seguro ?
text_are_you_sure: ¿Está seguro?
text_assign_time_entries_to_project: Asignar las horas al proyecto
text_caracters_maximum: %d caracteres como máximo.
text_caracters_minimum: %d caracteres como mínimo
@@ -640,11 +643,12 @@ text_comma_separated: Múltiples valores permitidos (separados por coma).
text_default_administrator_account_changed: Cuenta de administrador por defecto modificada
text_destroy_time_entries: Borrar las horas
text_destroy_time_entries_question: Existen %.02f horas asignadas a la petición que quiere borrar. ¿Qué quiere hacer ?
text_diff_truncated: '... Diferencia truncada por exceder el máximo tamaño visualizable.'
text_email_delivery_not_configured: "El envío de correos no está configurado, y las notificaciones se han desactivado. \n Configure el servidor de SMTP en config/email.yml y reinicie la aplicación para activar los cambios."
text_enumeration_category_reassign_to: 'Reasignar al siguiente valor:'
text_enumeration_destroy_question: '%d objetos con este valor asignado.'
text_file_repository_writable: Se puede escribir en el repositorio
text_issue_added: Petición añadida por %s.
text_issue_added: Petición %s añadida por %s.
text_issue_category_destroy_assignments: Dejar las peticiones sin categoría
text_issue_category_destroy_question: Algunas peticiones (%d) están asignadas a esta categoría. ¿Qué desea hacer?
text_issue_category_reassign_to: Reasignar las peticiones a la categoría
@@ -657,25 +661,26 @@ text_journal_set_to: fijado a %s
text_length_between: Longitud entre %d y %d caracteres.
text_load_default_configuration: Cargar la configuración por defecto
text_min_max_length_info: 0 para ninguna restricción
text_no_configuration_data: "Todavía no se han configurado roles, ni trackers, ni estados y flujo de trabajo asociado a peticiones. Se recomiendo encarecidamente cargar la configuración por defecto. Una vez cargada, podrá modificarla."
text_no_configuration_data: "Todavía no se han configurado perfiles, ni tipos, estados y flujo de trabajo asociado a peticiones. Se recomiendo encarecidamente cargar la configuración por defecto. Una vez cargada, podrá modificarla."
text_project_destroy_confirmation: ¿Estás seguro de querer eliminar el proyecto?
text_project_identifier_info: 'Letras minúsculas (a-z), números y signos de puntuación permitidos.<br />Una vez guardado, el identificador no puede modificarse.'
text_reassign_time_entries: 'Reasignar las horas a esta petición:'
text_regexp_info: ej. ^[A-Z0-9]+$
text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
text_repository_usernames_mapping: "Establezca la correspondencia entre los usuarios de Redmine y los presentes en el log del repositorio.\nLos usuarios con el mismo nombre o correo en Redmine y en el repositorio serán asociados automáticamente."
text_rmagick_available: RMagick disponible (opcional)
text_select_mail_notifications: Seleccionar los eventos a notificar
text_select_project_modules: 'Seleccione los módulos a activar para este proyecto:'
text_status_changed_by_changeset: Aplicado en los cambios %s
text_subprojects_destroy_warning: 'Los subproyectos: %s también se eliminarán'
text_subprojects_destroy_warning: 'Los proyectos secundarios: %s también se eliminarán'
text_tip_task_begin_day: tarea que comienza este día
text_tip_task_begin_end_day: tarea que comienza y termina este día
text_tip_task_end_day: tarea que termina este día
text_tracker_no_workflow: No hay ningún flujo de trabajo definido para este tracker
text_tracker_no_workflow: No hay ningún flujo de trabajo definido para este tipo de petición
text_unallowed_characters: Caracteres no permitidos
text_user_mail_option: "En los proyectos no seleccionados, sólo recibirá notificaciones sobre elementos monitorizados o elementos en los que esté involucrado (por ejemplo, peticiones de las que usted sea autor o asignadas a usted)."
text_user_mail_option: "De los proyectos no seleccionados, sólo recibirá notificaciones sobre elementos monitorizados o elementos en los que esté involucrado (por ejemplo, peticiones de las que usted sea autor o asignadas a usted)."
text_user_wrote: '%s escribió:'
text_wiki_destroy_confirmation: ¿Seguro que quiere borrar el wiki y todo su contenido?
text_workflow_edit: Seleccionar un flujo de trabajo para actualizar
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -694,3 +694,8 @@ permission_edit_own_messages: Muokkaa omia viestejä
permission_delete_own_messages: Poista omia viestejä
label_user_activity: "Käyttäjän %s historia"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -85,6 +85,8 @@ error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt
error_scm_annotate: "L'entrée n'existe pas ou ne peut pas être annotée."
error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas à ce projet"
warning_attachments_not_saved: "%d fichier(s) n'ont pas pu être sauvegardés."
mail_subject_lost_password: Votre mot de passe %s
mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant:'
mail_subject_register: Activation de votre compte %s
@@ -223,6 +225,7 @@ setting_mail_handler_api_enabled: "Activer le WS pour la réception d'emails"
setting_mail_handler_api_key: Clé de protection de l'API
setting_sequential_project_identifiers: Générer des identifiants de projet séquentiels
setting_gravatar_enabled: Afficher les Gravatar des utilisateurs
setting_diff_max_lines_displayed: Nombre maximum de lignes de diff affichées
permission_edit_project: Modifier le projet
permission_select_project_modules: Choisir les modules
@@ -579,7 +582,7 @@ label_reverse_chronological_order: Dans l'ordre chronologique inverse
label_planning: Planning
label_incoming_emails: Emails entrants
label_generate_key: Générer une clé
label_issue_watchers: Utilisateurs surveillant cette demande
label_issue_watchers: Observateurs
label_example: Exemple
button_login: Connexion
@@ -589,6 +592,7 @@ button_check_all: Tout cocher
button_uncheck_all: Tout décocher
button_delete: Supprimer
button_create: Créer
button_create_and_continue: Créer et continuer
button_test: Tester
button_edit: Modifier
button_add: Ajouter
@@ -660,6 +664,7 @@ text_issues_destroy_confirmation: 'Etes-vous sûr de vouloir supprimer le(s) dem
text_select_project_modules: 'Selectionner les modules à activer pour ce project:'
text_default_administrator_account_changed: Compte administrateur par défaut changé
text_file_repository_writable: Répertoire de stockage des fichiers accessible en écriture
text_plugin_assets_writable: Répertoire public des plugins accessible en écriture
text_rmagick_available: Bibliothèque RMagick présente (optionnelle)
text_destroy_time_entries_question: %.02f heures ont été enregistrées sur les demandes à supprimer. Que voulez-vous faire ?
text_destroy_time_entries: Supprimer les heures
@@ -670,6 +675,7 @@ text_enumeration_destroy_question: 'Cette valeur est affectée à %d objets.'
text_enumeration_category_reassign_to: 'Réaffecter les objets à cette valeur:'
text_email_delivery_not_configured: "L'envoi de mail n'est pas configuré, les notifications sont désactivées.\nConfigurez votre serveur SMTP dans config/email.yml et redémarrez l'application pour les activer."
text_repository_usernames_mapping: "Vous pouvez sélectionner ou modifier l'utilisateur Redmine associé à chaque nom d'utilisateur figurant dans l'historique du dépôt.\nLes utilisateurs avec le même identifiant ou la même adresse mail seront automatiquement associés."
text_diff_truncated: '... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.'
default_role_manager: Manager
default_role_developper: Développeur

View File

@@ -236,7 +236,7 @@ label_register: הרשמה
label_password_lost: אבדה הסיסמה?
label_home: דף הבית
label_my_page: הדף שלי
label_my_account: השבון שלי
label_my_account: החשבון שלי
label_my_projects: הפרויקטים שלי
label_administration: אדמיניסטרציה
label_login: התחבר
@@ -292,7 +292,7 @@ label_confirmation: אישור
label_export_to: יצא ל
label_read: קרא...
label_public_projects: פרויקטים פומביים
label_open_issues: פותח
label_open_issues: פתוח
label_open_issues_plural: פתוחים
label_closed_issues: סגור
label_closed_issues_plural: סגורים
@@ -308,7 +308,7 @@ label_used_by: בשימוש ע"י
label_details: פרטים
label_add_note: הוסף הערה
label_per_page: לכל דף
label_calendar: לו"ח שנה
label_calendar: לוח שנה
label_months_from: חודשים מ
label_gantt: גאנט
label_internal: פנימי
@@ -357,7 +357,7 @@ label_sort_higher: הזז למעלה
label_sort_lower: הזז למטה
label_sort_lowest: הזז לתחתית
label_roadmap: מפת הדרכים
label_roadmap_due_in: %s נגמר בעוד
label_roadmap_due_in: נגמר בעוד %s
label_roadmap_overdue: %s מאחר
label_roadmap_no_issues: אין נושאים לגירסא זו
label_search: חפש
@@ -421,8 +421,8 @@ label_send_information: שלח מידע על חשבון למשתמש
label_year: שנה
label_month: חודש
label_week: שבוע
label_date_from: מאת
label_date_to: אל
label_date_from: מתאריך
label_date_to: עד
label_language_based: מבוסס שפה
label_sort_by: מין לפי %s
label_send_test_email: שלח דו"ל בדיקה
@@ -487,7 +487,7 @@ text_journal_set_to: שונה ל %s
text_journal_deleted: נמחק
text_tip_task_begin_day: מטלה המתחילה היום
text_tip_task_end_day: מטלה המסתיימת היום
text_tip_task_begin_end_day: מתלה המתחילה ומסתיימת היום
text_tip_task_begin_end_day: מטלה המתחילה ומסתיימת היום
text_project_identifier_info: 'אותיות לטיניות (a-z), מספרים ומקפים.<br />ברגע שנשמר, לא ניתן לשנות את המזהה.'
text_caracters_maximum: מקסימום %d תווים.
text_length_between: אורך בין %d ל %d תווים.
@@ -618,79 +618,84 @@ label_overall_activity: פעילות כוללת
setting_default_projects_public: פרויקטים חדשים הינם פומביים כברירת מחדל
error_scm_annotate: "הכניסה לא קיימת או שלא ניתן לתאר אותה."
label_planning: תכנון
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
text_user_wrote: '%s wrote:'
label_duplicated_by: duplicated by
setting_enabled_scm: Enabled SCM
text_enumeration_category_reassign_to: 'Reassign them to this value:'
text_enumeration_destroy_question: '%d objects are assigned to this value.'
label_incoming_emails: Incoming emails
label_generate_key: Generate a key
text_subprojects_destroy_warning: 'תת הפרויקט\ים: %s ימחקו גם כן.'
label_and_its_subprojects: %s וכל תת הפרויקטים שלו
mail_body_reminder: "%d נושאים שמיועדים אליך מיועדים להגשה בתוך %d ימים:"
mail_subject_reminder: "%d נושאים מיעדים להגשה בימים הקרובים"
text_user_wrote: '%s כתב:'
label_duplicated_by: שוכפל ע"י
setting_enabled_scm: אפשר SCM
text_enumeration_category_reassign_to: 'הצב מחדש לערך הזה:'
text_enumeration_destroy_question: '%d אוביקטים מוצבים לערך זה.'
label_incoming_emails: דוא"ל נכנס
label_generate_key: יצר מפתח
setting_mail_handler_api_enabled: Enable WS for incoming emails
setting_mail_handler_api_key: API key
setting_mail_handler_api_key: מפתח API
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
field_parent_title: Parent page
label_issue_watchers: Watchers
field_parent_title: דף אב
label_issue_watchers: צופים
setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
button_quote: צטט
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
setting_plain_text_mail: plain text only (no HTML)
permission_view_files: View files
permission_edit_issues: Edit issues
permission_edit_own_time_entries: Edit own time logs
permission_manage_public_queries: Manage public queries
permission_add_issues: Add issues
permission_log_time: Log spent time
permission_view_changesets: View changesets
permission_view_time_entries: View spent time
permission_manage_versions: Manage versions
permission_manage_wiki: Manage wiki
permission_manage_categories: Manage issue categories
permission_protect_wiki_pages: Protect wiki pages
permission_comment_news: Comment news
permission_delete_messages: Delete messages
permission_select_project_modules: Select project modules
permission_manage_documents: Manage documents
permission_edit_wiki_pages: Edit wiki pages
permission_add_issue_watchers: Add watchers
permission_view_gantt: View gantt chart
permission_move_issues: Move issues
permission_manage_issue_relations: Manage issue relations
permission_delete_wiki_pages: Delete wiki pages
permission_manage_boards: Manage boards
permission_delete_wiki_pages_attachments: Delete attachments
permission_view_wiki_edits: View wiki history
permission_add_messages: Post messages
permission_view_messages: View messages
permission_manage_files: Manage files
permission_edit_issue_notes: Edit notes
permission_manage_news: Manage news
permission_view_calendar: View calendrier
permission_manage_members: Manage members
permission_edit_messages: Edit messages
permission_delete_issues: Delete issues
permission_view_issue_watchers: View watchers list
permission_manage_repository: Manage repository
notice_unable_delete_version: לא ניתן למחוק גירסא
label_renamed: השם שונה
label_copied: הועתק
setting_plain_text_mail: טקסט פשוט בלבד (ללא HTML)
permission_view_files: צפה בקבצים
permission_edit_issues: ערוך נושאים
permission_edit_own_time_entries: ערוך את לוג הזמן של עצמך
permission_manage_public_queries: נהל שאילתות פומביות
permission_add_issues: הוסף נושא
permission_log_time: תעד זמן שבוזבז
permission_view_changesets: צפה בקבוצות שינויים
permission_view_time_entries: צפה בזמן שבוזבז
permission_manage_versions: נהל גירסאות
permission_manage_wiki: נהל wiki
permission_manage_categories: נהל קטגוריות נושאים
permission_protect_wiki_pages: הגן כל דפי wiki
permission_comment_news: הגב על החדשות
permission_delete_messages: מחק הודעות
permission_select_project_modules: בחר מודולי פרויקט
permission_manage_documents: נהל מסמכים
permission_edit_wiki_pages: ערוך דפי wiki
permission_add_issue_watchers: הוסף צופים
permission_view_gantt: צפה בגאנט
permission_move_issues: הזז נושאים
permission_manage_issue_relations: נהל יחס בין נושאים
permission_delete_wiki_pages: מחק דפי wiki
permission_manage_boards: נהל לוחות
permission_delete_wiki_pages_attachments: מחק דבוקות
permission_view_wiki_edits: צפה בהיסטורית wiki
permission_add_messages: הצב הודעות
permission_view_messages: צפה בהודעות
permission_manage_files: נהל קבצים
permission_edit_issue_notes: ערוך רשימות
permission_manage_news: נהל חדשות
permission_view_calendar: צפה בלוח השנה
permission_manage_members: נהל חברים
permission_edit_messages: ערוך הודעות
permission_delete_issues: מחק נושאים
permission_view_issue_watchers: צפה ברשימה צופים
permission_manage_repository: נהל מאגר
permission_commit_access: Commit access
permission_browse_repository: Browse repository
permission_view_documents: View documents
permission_edit_project: Edit project
permission_browse_repository: סייר במאגר
permission_view_documents: צפה במסמכים
permission_edit_project: ערוך פרויקט
permission_add_issue_notes: Add notes
permission_save_queries: Save queries
permission_view_wiki_pages: View wiki
permission_rename_wiki_pages: Rename wiki pages
permission_edit_time_entries: Edit time logs
permission_save_queries: שמור שאילתות
permission_view_wiki_pages: צפה ב-wiki
permission_rename_wiki_pages: שנה שם של דפי wiki
permission_edit_time_entries: ערוך רישום זמנים
permission_edit_own_issue_notes: Edit own notes
setting_gravatar_enabled: Use Gravatar user icons
label_example: Example
label_example: דוגמא
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
permission_edit_own_messages: ערוך הודעות של עצמך
permission_delete_own_messages: מחק הודעות של עצמך
label_user_activity: "הפעילות של %s"
label_updated_time_by: עודכן ע"י %s לפני %s
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -694,4 +694,9 @@ text_repository_usernames_mapping: "Állítsd be a felhasználó összerendelés
permission_edit_own_messages: Saját üzenetek szerkesztése
permission_delete_own_messages: Saját üzenetek törlése
label_user_activity: "%s tevékenységei"
label_updated_time_by: Updated by %s %s ago
label_updated_time_by: "Módosította %s ennyivel ezelőtt: %s"
text_diff_truncated: '... A diff fájl vége nem jelenik meg, mert hosszab, mint a megjeleníthető sorok száma.'
setting_diff_max_lines_displayed: A megjelenítendő sorok száma (maximum) a diff fájloknál
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -694,3 +694,8 @@ permission_edit_own_messages: Modifica propri messaggi
permission_delete_own_messages: Elimina propri messaggi
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -695,3 +695,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -97,7 +97,7 @@ field_mail: 메일
field_filename: 파일
field_filesize: 크기
field_downloads: 다운로드
field_author: 보고
field_author:
field_created_on: 보고시간
field_updated_on: 변경시간
field_field_format: 포맷
@@ -120,18 +120,18 @@ field_subject: 제목
field_due_date: 완료 기한
field_assigned_to: 담당자
field_priority: 우선순위
field_fixed_version: 목표 버전
field_fixed_version: 목표버전
field_user: 사용자
field_role: 역할
field_homepage: 홈페이지
field_is_public: 공개
field_parent: 상위 프로젝트
field_is_in_chlog: 변경이력(changelog)에서 보여지는 일감들
field_is_in_roadmap: 로드맵에서 보여지는 일감들
field_is_in_chlog: 변경이력(changelog)에서 표시할 일감들
field_is_in_roadmap: 로드맵에서표시할 일감들
field_login: 로그인
field_mail_notification: 메일 알림
field_admin: 관리자
field_last_login_on: 최종 접속
field_last_login_on: 마지막 로그인
field_language: 언어
field_effective_date: 일자
field_password: 비밀번호
@@ -188,7 +188,7 @@ setting_commit_ref_keywords: 일감 참조에 사용할 키워드들
setting_commit_fix_keywords: 일감 해결에 사용할 키워드들
setting_autologin: 자동 로그인
setting_date_format: 날짜 형식
setting_cross_project_issue_relations: 프로젝트간 일감에 관을 맺는 것을 허용
setting_cross_project_issue_relations: 프로젝트간 일감에 관을 맺는 것을 허용
setting_issue_list_default_columns: 일감 목록에 보여줄 기본 컬럼들
setting_repositories_encodings: 저장소 인코딩
setting_emails_footer: 메일 꼬리
@@ -201,9 +201,9 @@ label_project_new: 새 프로젝트
label_project_plural: 프로젝트
label_project_all: 모든 프로젝트
label_project_latest: 최근 프로젝트
label_issue: 일감 보기
label_issue: 일감
label_issue_new: 새 일감만들기
label_issue_plural: 일감 보기
label_issue_plural: 일감
label_issue_view_all: 모든 일감 보기
label_document: 문서
label_document_new: 새 문서
@@ -243,15 +243,15 @@ label_administration: 관리자
label_login: 로그인
label_logout: 로그아웃
label_help: 도움말
label_reported_issues: 보고 일감
label_reported_issues: 보고 일감
label_assigned_to_me_issues: 나에게 할당된 일감
label_last_login: 최종 접속
label_last_updates: 최종 변경 내역
label_last_updates_plural: 최종변경 %d
label_registered_on: 등록시각
label_activity: 진행중인 작업
label_new: 신규
label_logged_as:
label_activity: 작업내역
label_new: 새로 만들기
label_logged_as: '로그인계정:'
label_environment: 환경
label_authentication: 인증설정
label_auth_source: 인증 모드
@@ -280,7 +280,7 @@ label_attachment_plural: 관련파일
label_report: 보고서
label_report_plural: 보고서
label_news: 뉴스
label_news_new: 뉴스추가
label_news_new: 뉴스
label_news_plural: 뉴스
label_news_latest: 최근 뉴스
label_news_view_all: 모든 뉴스
@@ -298,7 +298,7 @@ label_open_issues: 진행중
label_open_issues_plural: 진행중
label_closed_issues: 완료됨
label_closed_issues_plural: 완료됨
label_total: Total
label_total: 합계
label_permissions: 허가권한
label_current_status: 일감 상태
label_new_statuses_allowed: 허용되는 일감 상태
@@ -307,7 +307,7 @@ label_none: 없음
label_next: 다음
label_previous: 이전
label_used_by: 사용됨
label_details: 상세
label_details: 자세히
label_add_note: 일감덧글 추가
label_per_page: 페이지별
label_calendar: 달력
@@ -316,7 +316,7 @@ label_gantt: Gantt 챠트
label_internal: 내부
label_last_changes: 지난 변경사항 %d 건
label_change_view_all: 모든 변경 내역 보기
label_personalize_page: 입맛대로 구성하기(Drag & Drop)
label_personalize_page: 입맛대로 구성하기
label_comment: 댓글
label_comment_plural: 댓글
label_comment_add: 댓글 추가
@@ -353,7 +353,7 @@ label_latest_revision: 최근 개정판
label_latest_revision_plural: 최근 개정판
label_view_revisions: 개정판 보기
label_max_size: 최대 크기
label_on: 'on'
label_on: '전체: '
label_sort_highest: 최상단으로
label_sort_higher: 위로
label_sort_lower: 아래로
@@ -361,7 +361,7 @@ label_sort_lowest: 최하단으로
label_roadmap: 로드맵
label_roadmap_due_in: 기한 %s
label_roadmap_overdue: %s 지연
label_roadmap_no_issues: 버전에 해당하는 일감 없음
label_roadmap_no_issues: 이 버전에 해당하는 일감 없음
label_search: 검색
label_result_plural: 결과
label_all_words: 모든 단어
@@ -412,19 +412,19 @@ label_disabled: 비활성화
label_show_completed_versions: 완료된 버전 보기
label_me: 나
label_board: 게시판
label_board_new: 신규 게시판
label_board_new: 새 게시판
label_board_plural: 게시판
label_topic_plural: 주제
label_message_plural: 관련글
label_message_last: 최종 글
label_message_last: 마지막 글
label_message_new: 새글쓰기
label_reply_plural: 답글
label_send_information: 사용자에게 계정정보를 보냄
label_year: 년
label_month: 월
label_week: 주
label_date_from: 에서
label_date_to: (으)로
label_date_from: '기간:'
label_date_to: ' ~ '
label_language_based: 언어설정에 따름
label_sort_by: 정렬방법(%s)
label_send_test_email: 테스트 메일 보내기
@@ -533,7 +533,7 @@ default_activity_development: 개발
enumeration_issue_priorities: 일감 우선순위
enumeration_doc_categories: 문서 카테고리
enumeration_activities: 진행활동(시간 추적)
enumeration_activities: 작업분류(시간추적)
button_copy: 복사
mail_body_account_information_external: 레드마인에 로그인할 때 "%s" 계정을 사용하실 수 있습니다.
button_change_password: 비밀번호 변경
@@ -555,7 +555,7 @@ button_annotate: 주석달기(annotate)
label_issues_by: 일감분류 방식 %s
field_searchable: 검색가능
label_display_per_page: '페이지당: %s'
setting_per_page_options: 페이지당 표시할 객
setting_per_page_options: 페이지당 표시할 객
label_age: 마지막 수정일
notice_default_data_loaded: 기본 설정을 성공적으로 로드하였습니다.
text_load_default_configuration: 기본 설정을 로딩하기
@@ -585,20 +585,20 @@ project_module_files: 관련파일
project_module_documents: 문서
project_module_repository: 저장소
project_module_news: 뉴스
project_module_time_tracking: 진행중인 작업
project_module_time_tracking: 시간추적
text_file_repository_writable: 파일 저장소 쓰기 가능
text_default_administrator_account_changed: 기본 관리자 계정이 변경되었습니다.
text_rmagick_available: RMagick available (optional)
text_rmagick_available: RMagick 사용가능(옵션)
button_configure: 설정
label_plugins: 플러그인
label_ldap_authentication: LDAP 인증
label_downloads_abbr: D/L
label_add_another_file: 다른 파일 추가
label_this_month: 이번 달
text_destroy_time_entries_question: %.02f hours were reported on the issues you are about to delete. What do you want to do ?
text_destroy_time_entries_question: 삭제하려는 일감에 %.02f 시간이 보고되어 있습니다. 어떻게 하시겠습니까?
label_last_n_days: 지난 %d 일
label_all_time: 모든 시간
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
error_issue_not_found_in_project: '일감이 없거나 이 프로젝트의 것이 아닙니다.'
label_this_year: 올해
text_assign_time_entries_to_project: 보고된 시간을 프로젝트에 할당하기
label_date_range: 날짜 범위
@@ -608,15 +608,15 @@ label_optional_description: 부가적인 설명
label_last_month: 지난 달
text_destroy_time_entries: 보고된 시간을 삭제하기
text_reassign_time_entries: '이 알림에 보고된 시간을 재할당하기:'
setting_activity_days_default: 프로젝트 활동에 보여 날수
setting_activity_days_default: 프로젝트 작업내역에 보여 날수
label_chronological_order: 시간 순으로 정렬
field_comments_sorting: 히스토리 정렬 설정
label_reverse_chronological_order: 시간 역순으로 정렬
label_preferences: Preferences
label_preferences: 설정
setting_display_subprojects_issues: 하위 프로젝트의 일감을 최상위 프로젝트에서 표시
label_overall_activity: 전체 진행 상황
label_overall_activity: 전체 작업내역
setting_default_projects_public: 새 프로젝트를 공개로 설정
error_scm_annotate: "The entry does not exist or can not be annotated."
error_scm_annotate: "항목이 없거나 주석을 달 수 없습니다."
label_planning: 프로젝트계획(Planning)
text_subprojects_destroy_warning: '서브프로젝트(%s)가 자동으로 지워질 것입니다.'
label_and_its_subprojects: %s와 서브프로젝트들
@@ -692,5 +692,10 @@ label_example: 예
text_repository_usernames_mapping: "저장소 로그에서 발견된 각 사용자에 레드마인 사용자를 업데이트할때 선택합니다.\n레드마인과 저장소의 이름이나 이메일이 같은 사용자가 자동으로 연결됩니다."
permission_edit_own_messages: 자기 메시지 편집
permission_delete_own_messages: 자기 메시지 삭제
label_user_activity: "%s의 활동"
label_updated_time_by: Updated by %s %s ago
label_user_activity: "%s의 작업내역"
label_updated_time_by: %s %s 전에 변경
text_diff_truncated: '... 이 차이점은 표시할 수 있는 최대 줄수를 초과해서 이 차이점은 잘렸습니다.'
setting_diff_max_lines_displayed: 차이점보기에 표시할 최대 줄수
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

File diff suppressed because it is too large Load Diff

View File

@@ -696,3 +696,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -695,3 +695,8 @@ permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -632,7 +632,7 @@ setting_autofetch_changesets: Automatyczne pobieranie zmian
setting_autologin: Auto logowanie
setting_bcc_recipients: Odbiorcy kopii tajnej (kt/bcc)
setting_commit_fix_keywords: Słowa zmieniające status
setting_commit_logs_encoding: Zatwierdź kodowanie wiadomości
setting_commit_logs_encoding: Kodowanie komentarzy zatwierdzeń
setting_commit_ref_keywords: Słowa tworzące powiązania
setting_cross_project_issue_relations: Zezwól na powiązania zagadnień między projektami
setting_date_format: Format daty
@@ -712,4 +712,9 @@ text_wiki_destroy_confirmation: Jesteś pewien, że chcesz usunąć to wiki i ca
text_workflow_edit: Zaznacz rolę i typ zagadnienia do edycji przepływu
label_user_activity: "Aktywność: %s"
label_updated_time_by: Updated by %s %s ago
label_updated_time_by: Uaktualnione przez %s %s temu
text_diff_truncated: '... Ten plik różnic został przycięty ponieważ jest zbyt długi.'
setting_diff_max_lines_displayed: Maksymalna liczba linii różnicy do pokazania
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -47,8 +47,8 @@ general_text_Yes: 'Sim'
general_text_no: 'não'
general_text_yes: 'sim'
general_lang_name: 'Português(Brasil)'
general_csv_separator: ','
general_csv_decimal_separator: '.'
general_csv_separator: ';'
general_csv_decimal_separator: ','
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Segunda,Terça,Quarta,Quinta,Sexta,Sábado,Domingo
@@ -695,3 +695,8 @@ permission_edit_own_messages: Editar próprias mensagens
permission_delete_own_messages: Excluir próprias mensagens
label_user_activity: "Atividade de %s"
label_updated_time_by: Updated by %s %s ago
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

View File

@@ -104,8 +104,8 @@ field_name: Nome
field_description: Descrição
field_summary: Sumário
field_is_required: Obrigatório
field_firstname: Nome próprio
field_lastname: Último nome
field_firstname: Nome
field_lastname: Apelido
field_mail: E-mail
field_filename: Ficheiro
field_filesize: Tamanho
@@ -141,7 +141,7 @@ field_is_public: Público
field_parent: Sub-projecto de
field_is_in_chlog: Tarefas mostradas no changelog
field_is_in_roadmap: Tarefas mostradas no roadmap
field_login: Login
field_login: Nome de utilizador
field_mail_notification: Notificações por e-mail
field_admin: Administrador
field_last_login_on: Última visita
@@ -224,7 +224,7 @@ setting_mail_handler_api_key: Chave da API
setting_sequential_project_identifiers: Gerar identificadores de projecto sequênciais
project_module_issue_tracking: Tarefas
project_module_time_tracking: Contagem de tempo
project_module_time_tracking: Registo de tempo
project_module_news: Notícias
project_module_documents: Documentos
project_module_files: Ficheiros
@@ -440,7 +440,7 @@ label_issue_tracking: Tarefas
label_spent_time: Tempo gasto
label_f_hour: %.2f hora
label_f_hour_plural: %.2f horas
label_time_tracking: Contagem de tempo
label_time_tracking: Registo de tempo
label_change_plural: Mudanças
label_statistics: Estatísticas
label_commits_per_month: Commits por mês
@@ -551,7 +551,7 @@ button_move: Mover
button_back: Voltar
button_cancel: Cancelar
button_activate: Activar
button_sort: Ordernar
button_sort: Ordenar
button_log_time: Tempo de trabalho
button_rollback: Voltar para esta versão
button_watch: Observar
@@ -588,7 +588,7 @@ text_tip_task_begin_end_day: tarefa a começar e acabar neste dia
text_project_identifier_info: 'Apenas são permitidos letras minúsculas (a-z), números e hífens.<br />Uma vez guardado, o identificador não poderá ser alterado.'
text_caracters_maximum: máximo %d caracteres.
text_caracters_minimum: Deve ter pelo menos %d caracteres.
text_length_between: Deve ter entre %d and %d caracteres.
text_length_between: Deve ter entre %d e %d caracteres.
text_tracker_no_workflow: Sem workflow definido para este tipo de tarefa.
text_unallowed_characters: Caracteres não permitidos
text_comma_separated: Permitidos múltiplos valores (separados por vírgula).
@@ -641,58 +641,63 @@ default_activity_development: Desenvolvimento
enumeration_issue_priorities: Prioridade de tarefas
enumeration_doc_categories: Categorias de documentos
enumeration_activities: Actividades (Contagem de tempo)
setting_plain_text_mail: plain text only (no HTML)
permission_view_files: View files
permission_edit_issues: Edit issues
permission_edit_own_time_entries: Edit own time logs
permission_manage_public_queries: Manage public queries
permission_add_issues: Add issues
permission_log_time: Log spent time
permission_view_changesets: View changesets
permission_view_time_entries: View spent time
permission_manage_versions: Manage versions
permission_manage_wiki: Manage wiki
permission_manage_categories: Manage issue categories
permission_protect_wiki_pages: Protect wiki pages
permission_comment_news: Comment news
permission_delete_messages: Delete messages
permission_select_project_modules: Select project modules
permission_manage_documents: Manage documents
permission_edit_wiki_pages: Edit wiki pages
permission_add_issue_watchers: Add watchers
permission_view_gantt: View gantt chart
permission_move_issues: Move issues
permission_manage_issue_relations: Manage issue relations
permission_delete_wiki_pages: Delete wiki pages
permission_manage_boards: Manage boards
permission_delete_wiki_pages_attachments: Delete attachments
permission_view_wiki_edits: View wiki history
permission_add_messages: Post messages
permission_view_messages: View messages
permission_manage_files: Manage files
permission_edit_issue_notes: Edit notes
permission_manage_news: Manage news
permission_view_calendar: View calendrier
permission_manage_members: Manage members
permission_edit_messages: Edit messages
permission_delete_issues: Delete issues
permission_view_issue_watchers: View watchers list
permission_manage_repository: Manage repository
permission_commit_access: Commit access
permission_browse_repository: Browse repository
permission_view_documents: View documents
permission_edit_project: Edit project
permission_add_issue_notes: Add notes
permission_save_queries: Save queries
permission_view_wiki_pages: View wiki
permission_rename_wiki_pages: Rename wiki pages
permission_edit_time_entries: Edit time logs
permission_edit_own_issue_notes: Edit own notes
setting_gravatar_enabled: Use Gravatar user icons
label_example: Example
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
permission_edit_own_messages: Edit own messages
permission_delete_own_messages: Delete own messages
label_user_activity: "%s's activity"
label_updated_time_by: Updated by %s %s ago
enumeration_activities: Actividades (Registo de tempo)
setting_plain_text_mail: Apenas texto simples (sem HTML)
permission_view_files: Ver ficheiros
permission_edit_issues: Editar tarefas
permission_edit_own_time_entries: Editar horas pessoais
permission_manage_public_queries: Gerir queries públicas
permission_add_issues: Adicionar tarefas
permission_log_time: Registar tempo gasto
permission_view_changesets: Ver changesets
permission_view_time_entries: Ver tempo gasto
permission_manage_versions: Gerir versões
permission_manage_wiki: Gerir wiki
permission_manage_categories: Gerir categorias de tarefas
permission_protect_wiki_pages: Proteger páginas de wiki
permission_comment_news: Comentar notícias
permission_delete_messages: Apagar mensagens
permission_select_project_modules: Seleccionar módulos do projecto
permission_manage_documents: Gerir documentos
permission_edit_wiki_pages: Editar páginas de wiki
permission_add_issue_watchers: Adicionar observadores
permission_view_gantt: ver diagrama de Gantt
permission_move_issues: Mover tarefas
permission_manage_issue_relations: Gerir relações de tarefas
permission_delete_wiki_pages: Apagar páginas de wiki
permission_manage_boards: Gerir forums
permission_delete_wiki_pages_attachments: Apagar anexos
permission_view_wiki_edits: Ver histórico da wiki
permission_add_messages: Submeter mensagens
permission_view_messages: Ver mensagens
permission_manage_files: Gerir ficheiros
permission_edit_issue_notes: Editar notas de tarefas
permission_manage_news: Gerir notícias
permission_view_calendar: Ver calendário
permission_manage_members: Gerir membros
permission_edit_messages: Editar mensagens
permission_delete_issues: Apagar tarefas
permission_view_issue_watchers: Ver lista de observadores
permission_manage_repository: Gerir repositório
permission_commit_access: Acesso a submissão
permission_browse_repository: Navegar em repositório
permission_view_documents: Ver documentos
permission_edit_project: Editar projecto
permission_add_issue_notes: Adicionar notas a tarefas
permission_save_queries: Guardar queries
permission_view_wiki_pages: Ver wiki
permission_rename_wiki_pages: Renomear páginas de wiki
permission_edit_time_entries: Editar entradas de tempo
permission_edit_own_issue_notes: Editar as prórpias notas
setting_gravatar_enabled: Utilizar icons Gravatar
label_example: Exemplo
text_repository_usernames_mapping: "Seleccionar ou actualizar o utilizador de Redmine mapeado a cada nome de utilizador encontrado no repositório.\nUtilizadores com o mesmo nome de utilizador ou email no Redmine e no repositório são mapeados automaticamente."
permission_edit_own_messages: Editar as próprias mensagens
permission_delete_own_messages: Apagar as próprias mensagens
label_user_activity: "Actividade de %s"
label_updated_time_by: Actualizado por %s há %s
text_diff_truncated: '... Este diff foi truncado porque excede o tamanho máximo que pode ser mostrado.'
setting_diff_max_lines_displayed: Número máximo de linhas de diff mostradas
text_plugin_assets_writable: Plugin assets directory writable
warning_attachments_not_saved: "%d file(s) could not be saved."
button_create_and_continue: Create and continue

Some files were not shown because too many files have changed in this diff Show More