Merge branch 'ticket/master/30-upstream-code-review' into upstream-master
This commit is contained in:
commit
98f85b3332
|
@ -1,4 +1,5 @@
|
|||
/config/additional_environment.rb
|
||||
/config/configuration.yml
|
||||
/config/database.yml
|
||||
/config/email.yml
|
||||
/config/initializers/session_store.rb
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
syntax: glob
|
||||
|
||||
config/additional_environment.rb
|
||||
config/configuration.yml
|
||||
config/database.yml
|
||||
config/email.yml
|
||||
config/initializers/session_store.rb
|
||||
coverage
|
||||
db/*.db
|
||||
db/*.sqlite3
|
||||
db/schema.rb
|
||||
files/*
|
||||
log/*.log*
|
||||
log/mongrel_debug
|
||||
public/dispatch.*
|
||||
public/plugin_assets
|
||||
tmp/*
|
||||
tmp/cache/*
|
||||
tmp/sessions/*
|
||||
tmp/sockets/*
|
||||
tmp/test/*
|
||||
vendor/rails
|
||||
*.rbc
|
|
@ -203,12 +203,24 @@ class AccountController < ApplicationController
|
|||
self.logged_user = user
|
||||
# generate a key and set cookie if autologin
|
||||
if params[:autologin] && Setting.autologin?
|
||||
token = Token.create(:user => user, :action => 'autologin')
|
||||
cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
|
||||
set_autologin_cookie(user)
|
||||
end
|
||||
call_hook(:controller_account_success_authentication_after, {:user => user })
|
||||
redirect_back_or_default :controller => 'my', :action => 'page'
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.create(:user => user, :action => 'autologin')
|
||||
cookie_name = Redmine::Configuration['autologin_cookie_name'] || 'autologin'
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.year.from_now,
|
||||
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
|
||||
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
|
||||
:httponly => true
|
||||
}
|
||||
cookies[cookie_name] = cookie_options
|
||||
end
|
||||
|
||||
# Onthefly creation failed, display the registration form to fill/fix attributes
|
||||
def onthefly_creation_failed(user, auth_source_options = { })
|
||||
|
|
|
@ -23,7 +23,7 @@ class ActivitiesController < ApplicationController
|
|||
|
||||
events = @activity.events(@date_from, @date_to)
|
||||
|
||||
if events.empty? || stale?(:etag => [events.first, User.current])
|
||||
if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
@events_by_day = events.group_by(&:event_date)
|
||||
|
|
|
@ -22,7 +22,7 @@ class ApplicationController < ActionController::Base
|
|||
include Redmine::I18n
|
||||
|
||||
layout 'base'
|
||||
exempt_from_layout 'builder'
|
||||
exempt_from_layout 'builder', 'rsb'
|
||||
|
||||
# Remove broken cookie after upgrade from 0.8.x (#4292)
|
||||
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
|
||||
|
@ -71,10 +71,10 @@ class ApplicationController < ActionController::Base
|
|||
elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
|
||||
# RSS key authentication does not start a session
|
||||
User.find_by_rss_key(params[:key])
|
||||
elsif Setting.rest_api_enabled? && ['xml', 'json'].include?(params[:format])
|
||||
if params[:key].present? && accept_key_auth_actions.include?(params[:action])
|
||||
elsif Setting.rest_api_enabled? && api_request?
|
||||
if (key = api_key_from_request) && accept_key_auth_actions.include?(params[:action])
|
||||
# Use API key
|
||||
User.find_by_api_key(params[:key])
|
||||
User.find_by_api_key(key)
|
||||
else
|
||||
# HTTP Basic, either username/password or API key/random
|
||||
authenticate_with_http_basic do |username, password|
|
||||
|
@ -349,6 +349,30 @@ class ApplicationController < ActionController::Base
|
|||
per_page
|
||||
end
|
||||
|
||||
# Returns offset and limit used to retrieve objects
|
||||
# for an API response based on offset, limit and page parameters
|
||||
def api_offset_and_limit(options=params)
|
||||
if options[:offset].present?
|
||||
offset = options[:offset].to_i
|
||||
if offset < 0
|
||||
offset = 0
|
||||
end
|
||||
end
|
||||
limit = options[:limit].to_i
|
||||
if limit < 1
|
||||
limit = 25
|
||||
elsif limit > 100
|
||||
limit = 100
|
||||
end
|
||||
if offset.nil? && options[:page].present?
|
||||
offset = (options[:page].to_i - 1) * limit
|
||||
offset = 0 if offset < 0
|
||||
end
|
||||
offset ||= 0
|
||||
|
||||
[offset, limit]
|
||||
end
|
||||
|
||||
# qvalues http header parser
|
||||
# code taken from webrick
|
||||
def parse_qvalues(value)
|
||||
|
@ -378,6 +402,15 @@ class ApplicationController < ActionController::Base
|
|||
def api_request?
|
||||
%w(xml json).include? params[:format]
|
||||
end
|
||||
|
||||
# Returns the API key present in the request
|
||||
def api_key_from_request
|
||||
if params[:key].present?
|
||||
params[:key]
|
||||
elsif request.headers["X-Redmine-API-Key"].present?
|
||||
request.headers["X-Redmine-API-Key"]
|
||||
end
|
||||
end
|
||||
|
||||
# Renders a warning flash if obj has unsaved attachments
|
||||
def render_attachment_warning_if_needed(obj)
|
||||
|
@ -413,5 +446,37 @@ class ApplicationController < ActionController::Base
|
|||
{ attribute => error }
|
||||
end.to_json
|
||||
end
|
||||
|
||||
# Renders API response on validation failure
|
||||
def render_validation_errors(object)
|
||||
options = { :status => :unprocessable_entity, :layout => false }
|
||||
options.merge!(case params[:format]
|
||||
when 'xml'; { :xml => object.errors }
|
||||
when 'json'; { :json => {'errors' => object.errors} } # ActiveResource client compliance
|
||||
else
|
||||
raise "Unknown format #{params[:format]} in #render_validation_errors"
|
||||
end
|
||||
)
|
||||
render options
|
||||
end
|
||||
|
||||
# Overrides #default_template so that the api template
|
||||
# is used automatically if it exists
|
||||
def default_template(action_name = self.action_name)
|
||||
if api_request?
|
||||
begin
|
||||
return self.view_paths.find_template(default_template_name(action_name), 'api')
|
||||
rescue ::ActionView::MissingTemplate
|
||||
# the api template was not found
|
||||
# fallback to the default behaviour
|
||||
end
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
# Overrides #pick_layout so that #render with no arguments
|
||||
# doesn't use the layout for api requests
|
||||
def pick_layout(*args)
|
||||
api_request? ? nil : super
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,12 +4,14 @@ class AutoCompletesController < ApplicationController
|
|||
def issues
|
||||
@issues = []
|
||||
q = params[:q].to_s
|
||||
query = (params[:scope] == "all" && Setting.cross_project_issue_relations?) ? Issue : @project.issues
|
||||
if q.match(/^\d+$/)
|
||||
@issues << @project.issues.visible.find_by_id(q.to_i)
|
||||
@issues << query.visible.find_by_id(q.to_i)
|
||||
end
|
||||
unless q.blank?
|
||||
@issues += @project.issues.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
|
||||
@issues += query.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
|
||||
end
|
||||
@issues.compact!
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ class ContextMenusController < ApplicationController
|
|||
helper :watchers
|
||||
|
||||
def issues
|
||||
@issues = Issue.find_all_by_id(params[:ids], :include => :project)
|
||||
@issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project)
|
||||
|
||||
if (@issues.size == 1)
|
||||
@issue = @issues.first
|
||||
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
|
||||
|
|
|
@ -28,6 +28,7 @@ class IssueRelationsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
|
||||
format.js do
|
||||
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
|
||||
render :update do |page|
|
||||
page.replace_html "relations", :partial => 'issues/relations'
|
||||
if @relation.errors.empty?
|
||||
|
@ -47,7 +48,10 @@ class IssueRelationsController < ApplicationController
|
|||
end
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
|
||||
format.js { render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} }
|
||||
format.js {
|
||||
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
|
||||
render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ class IssuesController < ApplicationController
|
|||
include AttachmentsHelper
|
||||
helper :queries
|
||||
include QueriesHelper
|
||||
helper :repositories
|
||||
include RepositoriesHelper
|
||||
helper :sort
|
||||
include SortHelper
|
||||
include IssuesHelper
|
||||
|
@ -65,27 +67,29 @@ class IssuesController < ApplicationController
|
|||
sort_update(@query.sortable_columns)
|
||||
|
||||
if @query.valid?
|
||||
limit = case params[:format]
|
||||
case params[:format]
|
||||
when 'csv', 'pdf'
|
||||
Setting.issues_export_limit.to_i
|
||||
@limit = Setting.issues_export_limit.to_i
|
||||
when 'atom'
|
||||
Setting.feeds_limit.to_i
|
||||
@limit = Setting.feeds_limit.to_i
|
||||
when 'xml', 'json'
|
||||
@offset, @limit = api_offset_and_limit
|
||||
else
|
||||
per_page_option
|
||||
@limit = per_page_option
|
||||
end
|
||||
|
||||
@issue_count = @query.issue_count
|
||||
@issue_pages = Paginator.new self, @issue_count, limit, params['page']
|
||||
@issue_pages = Paginator.new self, @issue_count, @limit, params['page']
|
||||
@offset ||= @issue_pages.current.offset
|
||||
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
|
||||
:order => sort_clause,
|
||||
:offset => @issue_pages.current.offset,
|
||||
:limit => limit)
|
||||
:offset => @offset,
|
||||
:limit => @limit)
|
||||
@issue_count_by_group = @query.issue_count_by_group
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
|
||||
format.xml { render :layout => false }
|
||||
format.json { render :text => @issues.to_json, :layout => false }
|
||||
format.api
|
||||
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
|
||||
format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
|
||||
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
|
||||
|
@ -104,14 +108,14 @@ class IssuesController < ApplicationController
|
|||
@journals.reverse! if User.current.wants_comments_in_reverse_order?
|
||||
@changesets = @issue.changesets.visible.all
|
||||
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
|
||||
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
|
||||
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
|
||||
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
|
||||
@priorities = IssuePriority.all
|
||||
@time_entry = TimeEntry.new
|
||||
respond_to do |format|
|
||||
format.html { render :template => 'issues/show.rhtml' }
|
||||
format.xml { render :layout => false }
|
||||
format.json { render :text => @issue.to_json, :layout => false }
|
||||
format.api
|
||||
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
|
||||
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
|
||||
end
|
||||
|
@ -138,15 +142,13 @@ class IssuesController < ApplicationController
|
|||
redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
|
||||
{ :action => 'show', :id => @issue })
|
||||
}
|
||||
format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
|
||||
format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
|
||||
format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
|
||||
end
|
||||
return
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'new' }
|
||||
format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
|
||||
format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
|
||||
format.api { render_validation_errors(@issue) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -171,8 +173,7 @@ class IssuesController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
|
||||
format.xml { head :ok }
|
||||
format.json { head :ok }
|
||||
format.api { head :ok }
|
||||
end
|
||||
else
|
||||
render_attachment_warning_if_needed(@issue)
|
||||
|
@ -181,8 +182,7 @@ class IssuesController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'edit' }
|
||||
format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
|
||||
format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
|
||||
format.api { render_validation_errors(@issue) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -232,17 +232,14 @@ class IssuesController < ApplicationController
|
|||
TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
|
||||
end
|
||||
else
|
||||
unless params[:format] == 'xml' || params[:format] == 'json'
|
||||
# display the destroy form if it's a user request
|
||||
return
|
||||
end
|
||||
# display the destroy form if it's a user request
|
||||
return unless api_request?
|
||||
end
|
||||
end
|
||||
@issues.each(&:destroy)
|
||||
respond_to do |format|
|
||||
format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
|
||||
format.xml { head :ok }
|
||||
format.json { head :ok }
|
||||
format.api { head :ok }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ class JournalsController < ApplicationController
|
|||
before_filter :find_journal, :only => [:edit]
|
||||
before_filter :find_issue, :only => [:new]
|
||||
before_filter :find_optional_project, :only => [:index]
|
||||
before_filter :authorize, :only => [:new, :edit]
|
||||
accept_key_auth :index
|
||||
|
||||
helper :issues
|
||||
|
|
|
@ -19,6 +19,7 @@ class MyController < ApplicationController
|
|||
before_filter :require_login
|
||||
|
||||
helper :issues
|
||||
helper :users
|
||||
helper :custom_fields
|
||||
|
||||
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
|
||||
|
@ -53,21 +54,18 @@ class MyController < ApplicationController
|
|||
@user = User.current
|
||||
@pref = @user.pref
|
||||
if request.post?
|
||||
@user.attributes = params[:user]
|
||||
@user.mail_notification = params[:notification_option] || 'only_my_events'
|
||||
@user.safe_attributes = params[:user]
|
||||
@user.pref.attributes = params[:pref]
|
||||
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
|
||||
if @user.save
|
||||
@user.pref.save
|
||||
@user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
|
||||
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
|
||||
set_language_if_valid @user.language
|
||||
flash[:notice] = l(:notice_account_updated)
|
||||
redirect_to :action => 'account'
|
||||
return
|
||||
end
|
||||
end
|
||||
@notification_options = @user.valid_notification_options
|
||||
@notification_option = @user.mail_notification #? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected')
|
||||
end
|
||||
|
||||
# Manage user's password
|
||||
|
|
|
@ -26,15 +26,26 @@ class NewsController < ApplicationController
|
|||
accept_key_auth :index
|
||||
|
||||
def index
|
||||
@news_pages, @newss = paginate :news,
|
||||
:per_page => 10,
|
||||
:conditions => Project.allowed_to_condition(User.current, :view_news, :project => @project),
|
||||
:include => [:author, :project],
|
||||
:order => "#{News.table_name}.created_on DESC"
|
||||
case params[:format]
|
||||
when 'xml', 'json'
|
||||
@offset, @limit = api_offset_and_limit
|
||||
else
|
||||
@limit = 10
|
||||
end
|
||||
|
||||
scope = @project ? @project.news.visible : News.visible
|
||||
|
||||
@news_count = scope.count
|
||||
@news_pages = Paginator.new self, @news_count, @limit, params['page']
|
||||
@offset ||= @news_pages.current.offset
|
||||
@newss = scope.all(:include => [:author, :project],
|
||||
:order => "#{News.table_name}.created_on DESC",
|
||||
:offset => @offset,
|
||||
:limit => @limit)
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :layout => false if request.xhr? }
|
||||
format.xml { render :xml => @newss.to_xml }
|
||||
format.json { render :json => @newss.to_json }
|
||||
format.api
|
||||
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,9 +32,6 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: convert to PUT only
|
||||
verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :sort
|
||||
include SortHelper
|
||||
helper :custom_fields
|
||||
|
@ -52,8 +49,10 @@ class ProjectsController < ApplicationController
|
|||
format.html {
|
||||
@projects = Project.visible.find(:all, :order => 'lft')
|
||||
}
|
||||
format.xml {
|
||||
@projects = Project.visible.find(:all, :order => 'lft')
|
||||
format.api {
|
||||
@offset, @limit = api_offset_and_limit
|
||||
@project_count = Project.visible.count
|
||||
@projects = Project.visible.all(:offset => @offset, :limit => @limit, :order => 'lft')
|
||||
}
|
||||
format.atom {
|
||||
projects = Project.visible.find(:all, :order => 'created_on DESC',
|
||||
|
@ -67,19 +66,15 @@ class ProjectsController < ApplicationController
|
|||
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
|
||||
@trackers = Tracker.all
|
||||
@project = Project.new(params[:project])
|
||||
|
||||
@project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
|
||||
@project.trackers = Tracker.all
|
||||
@project.is_public = Setting.default_projects_public?
|
||||
@project.enabled_module_names = Setting.default_projects_modules
|
||||
end
|
||||
|
||||
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def create
|
||||
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
|
||||
@trackers = Tracker.all
|
||||
@project = Project.new(params[:project])
|
||||
@project = Project.new
|
||||
@project.safe_attributes = params[:project]
|
||||
|
||||
@project.enabled_module_names = params[:enabled_modules]
|
||||
if validate_parent_id && @project.save
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
# Add current user as a project member if he is not admin
|
||||
|
@ -93,12 +88,12 @@ class ProjectsController < ApplicationController
|
|||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :controller => 'projects', :action => 'settings', :id => @project
|
||||
}
|
||||
format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
|
||||
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'new' }
|
||||
format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
|
||||
format.api { render_validation_errors(@project) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -120,18 +115,19 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
else
|
||||
Mailer.with_deliveries(params[:notifications] == '1') do
|
||||
@project = Project.new(params[:project])
|
||||
@project = Project.new
|
||||
@project.safe_attributes = params[:project]
|
||||
@project.enabled_module_names = params[:enabled_modules]
|
||||
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :controller => 'projects', :action => 'settings'
|
||||
redirect_to :controller => 'projects', :action => 'settings', :id => @project
|
||||
elsif !@project.new_record?
|
||||
# Project was created
|
||||
# But some objects were not copied due to validation failures
|
||||
# (eg. issues from disabled trackers)
|
||||
# TODO: inform about that
|
||||
redirect_to :controller => 'projects', :action => 'settings'
|
||||
redirect_to :controller => 'projects', :action => 'settings', :id => @project
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -169,7 +165,7 @@ class ProjectsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -185,8 +181,10 @@ class ProjectsController < ApplicationController
|
|||
def edit
|
||||
end
|
||||
|
||||
# TODO: convert to PUT only
|
||||
verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def update
|
||||
@project.attributes = params[:project]
|
||||
@project.safe_attributes = params[:project]
|
||||
if validate_parent_id && @project.save
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
respond_to do |format|
|
||||
|
@ -194,7 +192,7 @@ class ProjectsController < ApplicationController
|
|||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'settings', :id => @project
|
||||
}
|
||||
format.xml { head :ok }
|
||||
format.api { head :ok }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
|
@ -202,13 +200,14 @@ class ProjectsController < ApplicationController
|
|||
settings
|
||||
render :action => 'settings'
|
||||
}
|
||||
format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
|
||||
format.api { render_validation_errors(@project) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
verify :method => :post, :only => :modules, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def modules
|
||||
@project.enabled_module_names = params[:enabled_modules]
|
||||
@project.enabled_module_names = params[:enabled_module_names]
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'settings', :id => @project, :tab => 'modules'
|
||||
end
|
||||
|
@ -233,11 +232,11 @@ class ProjectsController < ApplicationController
|
|||
if request.get?
|
||||
# display confirmation view
|
||||
else
|
||||
if params[:format] == 'xml' || params[:confirm]
|
||||
if api_request? || params[:confirm]
|
||||
@project_to_destroy.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :controller => 'admin', :action => 'projects' }
|
||||
format.xml { head :ok }
|
||||
format.api { head :ok }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -94,6 +94,7 @@ class RepositoriesController < ApplicationController
|
|||
(show_error_not_found; return) unless @entry
|
||||
@changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
|
||||
@properties = @repository.properties(@path, @rev)
|
||||
@changeset = @repository.find_changeset_by_name(@rev)
|
||||
end
|
||||
|
||||
def revisions
|
||||
|
@ -127,18 +128,21 @@ class RepositoriesController < ApplicationController
|
|||
else
|
||||
# Prevent empty lines when displaying a file with Windows style eol
|
||||
@content.gsub!("\r\n", "\n")
|
||||
@changeset = @repository.find_changeset_by_name(@rev)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def annotate
|
||||
@entry = @repository.entry(@path, @rev)
|
||||
(show_error_not_found; return) unless @entry
|
||||
|
||||
@annotate = @repository.scm.annotate(@path, @rev)
|
||||
(render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
|
||||
@changeset = @repository.find_changeset_by_name(@rev)
|
||||
end
|
||||
|
||||
|
||||
def revision
|
||||
raise ChangesetNotFound if @rev.blank?
|
||||
@changeset = @repository.find_changeset_by_name(@rev)
|
||||
raise ChangesetNotFound unless @changeset
|
||||
|
||||
|
@ -174,9 +178,13 @@ class RepositoriesController < ApplicationController
|
|||
@diff = @repository.diff(@path, @rev, @rev_to)
|
||||
show_error_not_found unless @diff
|
||||
end
|
||||
|
||||
@changeset = @repository.find_changeset_by_name(@rev)
|
||||
@changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
|
||||
@diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def stats
|
||||
end
|
||||
|
||||
|
@ -196,7 +204,10 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
|
||||
|
||||
def find_repository
|
||||
@project = Project.find(params[:id])
|
||||
@repository = @project.repository
|
||||
|
@ -205,6 +216,12 @@ private
|
|||
@path ||= ''
|
||||
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
|
||||
@rev_to = params[:rev_to]
|
||||
|
||||
unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE)
|
||||
if @repository.branches.blank?
|
||||
raise InvalidRevisionParam
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
rescue InvalidRevisionParam
|
||||
|
@ -212,7 +229,7 @@ private
|
|||
end
|
||||
|
||||
def show_error_not_found
|
||||
render_error l(:error_scm_not_found)
|
||||
render_error :message => l(:error_scm_not_found), :status => 404
|
||||
end
|
||||
|
||||
# Handler for Redmine::Scm::Adapters::CommandFailed exception
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2010 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
|
||||
|
@ -18,10 +18,11 @@
|
|||
class TimelogController < ApplicationController
|
||||
menu_item :issues
|
||||
before_filter :find_project, :only => [:new, :create]
|
||||
before_filter :find_time_entry, :only => [:edit, :update, :destroy]
|
||||
before_filter :find_time_entry, :only => [:show, :edit, :update, :destroy]
|
||||
before_filter :authorize, :except => [:index]
|
||||
before_filter :find_optional_project, :only => [:index]
|
||||
|
||||
accept_key_auth :index, :show, :create, :update, :destroy
|
||||
|
||||
helper :sort
|
||||
include SortHelper
|
||||
helper :issues
|
||||
|
@ -66,6 +67,16 @@ class TimelogController < ApplicationController
|
|||
|
||||
render :layout => !request.xhr?
|
||||
}
|
||||
format.api {
|
||||
@entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions)
|
||||
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
|
||||
@entries = TimeEntry.find(:all,
|
||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||
:conditions => cond.conditions,
|
||||
:order => sort_clause,
|
||||
:limit => @entry_pages.items_per_page,
|
||||
:offset => @entry_pages.current.offset)
|
||||
}
|
||||
format.atom {
|
||||
entries = TimeEntry.find(:all,
|
||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||
|
@ -85,6 +96,14 @@ class TimelogController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
# TODO: Implement html response
|
||||
format.html { render :nothing => true, :status => 406 }
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
|
||||
|
@ -102,10 +121,18 @@ class TimelogController < ApplicationController
|
|||
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
|
||||
|
||||
if @time_entry.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
||||
}
|
||||
format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
|
||||
end
|
||||
else
|
||||
render :action => 'edit'
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'edit' }
|
||||
format.api { render_validation_errors(@time_entry) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -122,21 +149,40 @@ class TimelogController < ApplicationController
|
|||
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
|
||||
|
||||
if @time_entry.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
||||
}
|
||||
format.api { head :ok }
|
||||
end
|
||||
else
|
||||
render :action => 'edit'
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'edit' }
|
||||
format.api { render_validation_errors(@time_entry) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def destroy
|
||||
if @time_entry.destroy && @time_entry.destroyed?
|
||||
flash[:notice] = l(:notice_successful_delete)
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_delete)
|
||||
redirect_to :back
|
||||
}
|
||||
format.api { head :ok }
|
||||
end
|
||||
else
|
||||
flash[:error] = l(:notice_unable_delete_time_entry)
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:error] = l(:notice_unable_delete_time_entry)
|
||||
redirect_to :back
|
||||
}
|
||||
format.api { render_validation_errors(@time_entry) }
|
||||
end
|
||||
end
|
||||
redirect_to :back
|
||||
rescue ::ActionController::RedirectBackError
|
||||
redirect_to :action => 'index', :project_id => @time_entry.project
|
||||
end
|
||||
|
@ -154,11 +200,11 @@ private
|
|||
end
|
||||
|
||||
def find_project
|
||||
if params[:issue_id]
|
||||
@issue = Issue.find(params[:issue_id])
|
||||
if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
|
||||
@issue = Issue.find(issue_id)
|
||||
@project = @issue.project
|
||||
elsif params[:project_id]
|
||||
@project = Project.find(params[:project_id])
|
||||
elsif (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
|
||||
@project = Project.find(project_id)
|
||||
else
|
||||
render_404
|
||||
return false
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2009 Jean-Philippe Lang
|
||||
# Copyright (C) 2006-2010 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
|
||||
|
@ -19,6 +19,8 @@ class UsersController < ApplicationController
|
|||
layout 'admin'
|
||||
|
||||
before_filter :require_admin, :except => :show
|
||||
before_filter :find_user, :only => [:show, :edit, :update, :edit_membership, :destroy_membership]
|
||||
accept_key_auth :index, :show, :create, :update
|
||||
|
||||
helper :sort
|
||||
include SortHelper
|
||||
|
@ -29,6 +31,13 @@ class UsersController < ApplicationController
|
|||
sort_init 'login', 'asc'
|
||||
sort_update %w(login firstname lastname mail admin created_on last_login_on)
|
||||
|
||||
case params[:format]
|
||||
when 'xml', 'json'
|
||||
@offset, @limit = api_offset_and_limit
|
||||
else
|
||||
@limit = per_page_option
|
||||
end
|
||||
|
||||
@status = params[:status] ? params[:status].to_i : 1
|
||||
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
|
||||
|
||||
|
@ -38,20 +47,21 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
@user_count = User.count(:conditions => c.conditions)
|
||||
@user_pages = Paginator.new self, @user_count,
|
||||
per_page_option,
|
||||
params['page']
|
||||
@users = User.find :all,:order => sort_clause,
|
||||
@user_pages = Paginator.new self, @user_count, @limit, params['page']
|
||||
@offset ||= @user_pages.current.offset
|
||||
@users = User.find :all,
|
||||
:order => sort_clause,
|
||||
:conditions => c.conditions,
|
||||
:limit => @user_pages.items_per_page,
|
||||
:offset => @user_pages.current.offset
|
||||
:limit => @limit,
|
||||
:offset => @offset
|
||||
|
||||
render :layout => !request.xhr?
|
||||
respond_to do |format|
|
||||
format.html { render :layout => !request.xhr? }
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@user = User.find(params[:id])
|
||||
|
||||
# show projects based on current user visibility
|
||||
@memberships = @user.memberships.all(:conditions => Project.visible_by(User.current))
|
||||
|
||||
|
@ -64,104 +74,110 @@ class UsersController < ApplicationController
|
|||
return
|
||||
end
|
||||
end
|
||||
render :layout => 'base'
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :layout => 'base' }
|
||||
format.api
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@notification_options = User::MAIL_NOTIFICATION_OPTIONS
|
||||
@notification_option = Setting.default_notification_option
|
||||
|
||||
@user = User.new(:language => Setting.default_language)
|
||||
@user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
|
||||
@auth_sources = AuthSource.find(:all)
|
||||
end
|
||||
|
||||
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def create
|
||||
@notification_options = User::MAIL_NOTIFICATION_OPTIONS
|
||||
@notification_option = Setting.default_notification_option
|
||||
|
||||
@user = User.new(params[:user])
|
||||
@user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
|
||||
@user.safe_attributes = params[:user]
|
||||
@user.admin = params[:user][:admin] || false
|
||||
@user.login = params[:user][:login]
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
|
||||
@user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
|
||||
|
||||
# TODO: Similar to My#account
|
||||
@user.mail_notification = params[:notification_option] || 'only_my_events'
|
||||
@user.pref.attributes = params[:pref]
|
||||
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
|
||||
|
||||
if @user.save
|
||||
@user.pref.save
|
||||
@user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
|
||||
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
|
||||
|
||||
Mailer.deliver_account_information(@user, params[:password]) if params[:send_information]
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to(params[:continue] ? {:controller => 'users', :action => 'new'} :
|
||||
{:controller => 'users', :action => 'edit', :id => @user})
|
||||
return
|
||||
Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information]
|
||||
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to(params[:continue] ?
|
||||
{:controller => 'users', :action => 'new'} :
|
||||
{:controller => 'users', :action => 'edit', :id => @user}
|
||||
)
|
||||
}
|
||||
format.api { render :action => 'show', :status => :created, :location => user_url(@user) }
|
||||
end
|
||||
else
|
||||
@auth_sources = AuthSource.find(:all)
|
||||
@notification_option = @user.mail_notification
|
||||
# Clear password input
|
||||
@user.password = @user.password_confirmation = nil
|
||||
|
||||
render :action => 'new'
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'new' }
|
||||
format.api { render_validation_errors(@user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@user = User.find(params[:id])
|
||||
@notification_options = @user.valid_notification_options
|
||||
@notification_option = @user.mail_notification
|
||||
|
||||
@auth_sources = AuthSource.find(:all)
|
||||
@membership ||= Member.new
|
||||
end
|
||||
|
||||
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
|
||||
def update
|
||||
@user = User.find(params[:id])
|
||||
@notification_options = @user.valid_notification_options
|
||||
@notification_option = @user.mail_notification
|
||||
|
||||
@user.admin = params[:user][:admin] if params[:user][:admin]
|
||||
@user.login = params[:user][:login] if params[:user][:login]
|
||||
if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
|
||||
if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
|
||||
@user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
|
||||
end
|
||||
@user.group_ids = params[:user][:group_ids] if params[:user][:group_ids]
|
||||
@user.attributes = params[:user]
|
||||
@user.safe_attributes = params[:user]
|
||||
# Was the account actived ? (do it before User#save clears the change)
|
||||
was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
|
||||
# TODO: Similar to My#account
|
||||
@user.mail_notification = params[:notification_option] || 'only_my_events'
|
||||
@user.pref.attributes = params[:pref]
|
||||
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
|
||||
|
||||
if @user.save
|
||||
@user.pref.save
|
||||
@user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
|
||||
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
|
||||
|
||||
if was_activated
|
||||
Mailer.deliver_account_activated(@user)
|
||||
elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil?
|
||||
Mailer.deliver_account_information(@user, params[:password])
|
||||
elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
|
||||
Mailer.deliver_account_information(@user, params[:user][:password])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :back
|
||||
}
|
||||
format.api { head :ok }
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :back
|
||||
else
|
||||
@auth_sources = AuthSource.find(:all)
|
||||
@membership ||= Member.new
|
||||
# Clear password input
|
||||
@user.password = @user.password_confirmation = nil
|
||||
|
||||
render :action => :edit
|
||||
respond_to do |format|
|
||||
format.html { render :action => :edit }
|
||||
format.api { render_validation_errors(@user) }
|
||||
end
|
||||
end
|
||||
rescue ::ActionController::RedirectBackError
|
||||
redirect_to :controller => 'users', :action => 'edit', :id => @user
|
||||
end
|
||||
|
||||
def edit_membership
|
||||
@user = User.find(params[:id])
|
||||
@membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
|
||||
@membership.save if request.post?
|
||||
respond_to do |format|
|
||||
|
@ -184,7 +200,6 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy_membership
|
||||
@user = User.find(params[:id])
|
||||
@membership = Member.find(params[:membership_id])
|
||||
if request.post? && @membership.deletable?
|
||||
@membership.destroy
|
||||
|
@ -194,4 +209,17 @@ class UsersController < ApplicationController
|
|||
format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_user
|
||||
if params[:id] == 'current'
|
||||
require_login || return
|
||||
@user = User.current
|
||||
else
|
||||
@user = User.find(params[:id])
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,8 +104,24 @@ module ApplicationHelper
|
|||
# * :text - Link text (default to the formatted revision)
|
||||
def link_to_revision(revision, project, options={})
|
||||
text = options.delete(:text) || format_revision(revision)
|
||||
rev = revision.respond_to?(:identifier) ? revision.identifier : revision
|
||||
|
||||
link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision))
|
||||
link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev},
|
||||
:title => l(:label_revision_id, format_revision(revision)))
|
||||
end
|
||||
|
||||
# Generates a link to a message
|
||||
def link_to_message(message, options={}, html_options = nil)
|
||||
link_to(
|
||||
h(truncate(message.subject, :length => 60)),
|
||||
{ :controller => 'messages', :action => 'show',
|
||||
:board_id => message.board_id,
|
||||
:id => message.root,
|
||||
:r => (message.parent_id && message.id),
|
||||
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
|
||||
}.merge(options),
|
||||
html_options
|
||||
)
|
||||
end
|
||||
|
||||
# Generates a link to a project if active
|
||||
|
@ -449,12 +465,19 @@ module ApplicationHelper
|
|||
only_path = options.delete(:only_path) == false ? false : true
|
||||
|
||||
text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
|
||||
|
||||
parse_non_pre_blocks(text) do |text|
|
||||
|
||||
@parsed_headings = []
|
||||
text = parse_non_pre_blocks(text) do |text|
|
||||
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
|
||||
send method_name, text, project, obj, attr, only_path, options
|
||||
end
|
||||
end
|
||||
|
||||
if @parsed_headings.any?
|
||||
replace_toc(text, @parsed_headings)
|
||||
end
|
||||
|
||||
text
|
||||
end
|
||||
|
||||
def parse_non_pre_blocks(text)
|
||||
|
@ -579,16 +602,26 @@ module ApplicationHelper
|
|||
# source:some/file#L120 -> Link to line 120 of the file
|
||||
# source:some/file@52#L120 -> Link to line 120 of the file's revision 52
|
||||
# export:some/file -> Force the download of the file
|
||||
# Forum messages:
|
||||
# Forum messages:
|
||||
# message#1218 -> Link to message with id 1218
|
||||
#
|
||||
# Links can refer other objects from other projects, using project identifier:
|
||||
# identifier:r52
|
||||
# identifier:document:"Some document"
|
||||
# identifier:version:1.0.0
|
||||
# identifier:source:some/file
|
||||
def parse_redmine_links(text, project, obj, attr, only_path, options)
|
||||
text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
|
||||
leading, esc, prefix, sep, identifier = $1, $2, $3, $5 || $7, $6 || $8
|
||||
text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-]+):)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
|
||||
leading, esc, project_prefix, project_identifier, prefix, sep, identifier = $1, $2, $3, $4, $5, $7 || $9, $8 || $10
|
||||
link = nil
|
||||
if project_identifier
|
||||
project = Project.visible.find_by_identifier(project_identifier)
|
||||
end
|
||||
if esc.nil?
|
||||
if prefix.nil? && sep == 'r'
|
||||
if project && (changeset = project.changesets.find_by_revision(identifier))
|
||||
link = link_to("r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
|
||||
# project.changesets.visible raises an SQL error because of a double join on repositories
|
||||
if project && project.repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(project.repository.id, identifier))
|
||||
link = link_to("#{project_prefix}r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100))
|
||||
end
|
||||
|
@ -602,24 +635,18 @@ module ApplicationHelper
|
|||
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
|
||||
end
|
||||
when 'document'
|
||||
if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
|
||||
if document = Document.visible.find_by_id(oid)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
when 'version'
|
||||
if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
|
||||
if version = Version.visible.find_by_id(oid)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'message'
|
||||
if message = Message.find_by_id(oid, :include => [:parent, {:board => :project}], :conditions => Project.visible_by(User.current))
|
||||
link = link_to h(truncate(message.subject, :length => 60)), {:only_path => only_path,
|
||||
:controller => 'messages',
|
||||
:action => 'show',
|
||||
:board_id => message.board,
|
||||
:id => message.root,
|
||||
:anchor => (message.parent ? "message-#{message.id}" : nil)},
|
||||
:class => 'message'
|
||||
if message = Message.visible.find_by_id(oid, :include => :parent)
|
||||
link = link_to_message(message, {:only_path => only_path}, :class => 'message')
|
||||
end
|
||||
when 'project'
|
||||
if p = Project.visible.find_by_id(oid)
|
||||
|
@ -631,26 +658,26 @@ module ApplicationHelper
|
|||
name = identifier.gsub(%r{^"(.*)"$}, "\\1")
|
||||
case prefix
|
||||
when 'document'
|
||||
if project && document = project.documents.find_by_title(name)
|
||||
if project && document = project.documents.visible.find_by_title(name)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
when 'version'
|
||||
if project && version = project.versions.find_by_name(name)
|
||||
if project && version = project.versions.visible.find_by_name(name)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'commit'
|
||||
if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
|
||||
link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
|
||||
if project && project.repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", project.repository.id, "#{name}%"]))
|
||||
link = link_to h("#{project_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.identifier},
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100)
|
||||
end
|
||||
when 'source', 'export'
|
||||
if project && project.repository
|
||||
if project && project.repository && User.current.allowed_to?(:browse_repository, project)
|
||||
name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
|
||||
path, rev, anchor = $1, $3, $5
|
||||
link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
|
||||
link = link_to h("#{project_prefix}#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
|
||||
:path => to_path_param(path),
|
||||
:rev => rev,
|
||||
:anchor => anchor,
|
||||
|
@ -670,25 +697,30 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
end
|
||||
leading + (link || "#{prefix}#{sep}#{identifier}")
|
||||
leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}")
|
||||
end
|
||||
end
|
||||
|
||||
TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
|
||||
HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE)
|
||||
|
||||
# Headings and TOC
|
||||
# Adds ids and links to headings and renders the TOC if needed unless options[:headings] is set to false
|
||||
# Adds ids and links to headings unless options[:headings] is set to false
|
||||
def parse_headings(text, project, obj, attr, only_path, options)
|
||||
headings = []
|
||||
return if options[:headings] == false
|
||||
|
||||
text.gsub!(HEADING_RE) do
|
||||
level, attrs, content = $1.to_i, $2, $3
|
||||
item = strip_tags(content).strip
|
||||
anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
|
||||
headings << [level, anchor, item]
|
||||
@parsed_headings << [level, anchor, item]
|
||||
"<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>"
|
||||
end unless options[:headings] == false
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
|
||||
|
||||
# Renders the TOC with given headings
|
||||
def replace_toc(text, headings)
|
||||
text.gsub!(TOC_RE) do
|
||||
if headings.empty?
|
||||
''
|
||||
|
@ -866,7 +898,29 @@ module ApplicationHelper
|
|||
def favicon
|
||||
"<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
|
||||
end
|
||||
|
||||
# Returns true if arg is expected in the API response
|
||||
def include_in_api_response?(arg)
|
||||
unless @included_in_api_response
|
||||
param = params[:include]
|
||||
@included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
|
||||
@included_in_api_response.collect!(&:strip)
|
||||
end
|
||||
@included_in_api_response.include?(arg.to_s)
|
||||
end
|
||||
|
||||
# Returns options or nil if nometa param or X-Redmine-Nometa header
|
||||
# was set in the request
|
||||
def api_meta(options)
|
||||
if params[:nometa].present? || request.headers['X-Redmine-Nometa']
|
||||
# compatibility mode for activeresource clients that raise
|
||||
# an error when unserializing an array with attributes
|
||||
nil
|
||||
else
|
||||
options
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def wiki_helper
|
||||
|
|
|
@ -29,6 +29,18 @@ module AttachmentsHelper
|
|||
end
|
||||
|
||||
def to_utf8(str)
|
||||
str
|
||||
if str.respond_to?(:force_encoding)
|
||||
str.force_encoding('UTF-8')
|
||||
return str if str.valid_encoding?
|
||||
else
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
end
|
||||
|
||||
begin
|
||||
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
|
||||
rescue Iconv::InvalidEncoding
|
||||
# "UTF-8//IGNORE" is not supported on some OS
|
||||
str
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,4 +104,15 @@ module CustomFieldsHelper
|
|||
def custom_field_formats_for_select
|
||||
Redmine::CustomFieldFormat.as_select
|
||||
end
|
||||
|
||||
# Renders the custom_values in api views
|
||||
def render_api_custom_values(custom_values, api)
|
||||
api.array :custom_fields do
|
||||
custom_values.each do |custom_value|
|
||||
api.custom_field :id => custom_value.custom_field_id, :name => custom_value.custom_field.name do
|
||||
api.value custom_value.value
|
||||
end
|
||||
end
|
||||
end unless custom_values.empty?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -189,6 +189,20 @@ module IssuesHelper
|
|||
end
|
||||
end
|
||||
|
||||
# Renders issue children recursively
|
||||
def render_api_issue_children(issue, api)
|
||||
return if issue.leaf?
|
||||
api.array :children do
|
||||
issue.children.each do |child|
|
||||
api.issue(:id => child.id) do
|
||||
api.tracker(:id => child.tracker_id, :name => child.tracker.name) unless child.tracker.nil?
|
||||
api.subject child.subject
|
||||
render_api_issue_children(child, api)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def issues_to_csv(issues, project = nil)
|
||||
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
||||
decimal_separator = l(:general_csv_decimal_separator)
|
||||
|
|
|
@ -16,14 +16,4 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module MessagesHelper
|
||||
|
||||
def link_to_message(message)
|
||||
return '' unless message
|
||||
link_to h(truncate(message.subject, :length => 60)), :controller => 'messages',
|
||||
:action => 'show',
|
||||
:board_id => message.board_id,
|
||||
:id => message.root,
|
||||
:r => (message.parent_id && message.id),
|
||||
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,8 +18,12 @@
|
|||
require 'iconv'
|
||||
|
||||
module RepositoriesHelper
|
||||
def format_revision(txt)
|
||||
txt.to_s[0,8]
|
||||
def format_revision(revision)
|
||||
if revision.respond_to? :format_identifier
|
||||
revision.format_identifier
|
||||
else
|
||||
revision.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def truncate_at_line_break(text, length = 255)
|
||||
|
@ -87,7 +91,7 @@ module RepositoriesHelper
|
|||
:action => 'show',
|
||||
:id => @project,
|
||||
:path => path_param,
|
||||
:rev => @changeset.revision)
|
||||
:rev => @changeset.identifier)
|
||||
output << "<li class='#{style}'>#{text}</li>"
|
||||
output << render_changes_tree(s)
|
||||
elsif c = tree[file][:c]
|
||||
|
@ -97,13 +101,13 @@ module RepositoriesHelper
|
|||
:action => 'entry',
|
||||
:id => @project,
|
||||
:path => path_param,
|
||||
:rev => @changeset.revision) unless c.action == 'D'
|
||||
:rev => @changeset.identifier) unless c.action == 'D'
|
||||
text << " - #{c.revision}" unless c.revision.blank?
|
||||
text << ' (' + link_to('diff', :controller => 'repositories',
|
||||
:action => 'diff',
|
||||
:id => @project,
|
||||
:path => path_param,
|
||||
:rev => @changeset.revision) + ') ' if c.action == 'M'
|
||||
:rev => @changeset.identifier) + ') ' if c.action == 'M'
|
||||
text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
|
||||
output << "<li class='#{style}'>#{text}</li>"
|
||||
end
|
||||
|
@ -113,7 +117,13 @@ module RepositoriesHelper
|
|||
end
|
||||
|
||||
def to_utf8(str)
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
if str.respond_to?(:force_encoding)
|
||||
str.force_encoding('UTF-8')
|
||||
return str if str.valid_encoding?
|
||||
else
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
end
|
||||
|
||||
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
|
||||
@encodings.each do |encoding|
|
||||
begin
|
||||
|
|
|
@ -33,6 +33,10 @@ module UsersHelper
|
|||
options
|
||||
end
|
||||
|
||||
def user_mail_notification_options(user)
|
||||
user.valid_notification_options.collect {|o| [l(o.last), o.first]}
|
||||
end
|
||||
|
||||
def change_status_link(user)
|
||||
url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class Attachment < ActiveRecord::Base
|
|||
"LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"}
|
||||
|
||||
cattr_accessor :storage_path
|
||||
@@storage_path = "#{RAILS_ROOT}/files"
|
||||
@@storage_path = Redmine::Configuration['attachments_storage_path'] || "#{RAILS_ROOT}/files"
|
||||
|
||||
def validate
|
||||
if self.filesize > Setting.attachment_max_size.to_i.kilobytes
|
||||
|
|
|
@ -23,10 +23,10 @@ class Changeset < ActiveRecord::Base
|
|||
has_many :changes, :dependent => :delete_all
|
||||
has_and_belongs_to_many :issues
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
|
||||
:description => :long_comments,
|
||||
:datetime => :committed_on,
|
||||
:url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :rev => o.revision}}
|
||||
:url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :rev => o.identifier}}
|
||||
|
||||
acts_as_searchable :columns => 'comments',
|
||||
:include => {:repository => :project},
|
||||
|
@ -47,6 +47,15 @@ class Changeset < ActiveRecord::Base
|
|||
def revision=(r)
|
||||
write_attribute :revision, (r.nil? ? nil : r.to_s)
|
||||
end
|
||||
|
||||
# Returns the identifier of this changeset; depending on repository backends
|
||||
def identifier
|
||||
if repository.class.respond_to? :changeset_identifier
|
||||
repository.class.changeset_identifier self
|
||||
else
|
||||
revision.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def comments=(comment)
|
||||
write_attribute(:comments, Changeset.normalize_comments(comment))
|
||||
|
@ -56,6 +65,15 @@ class Changeset < ActiveRecord::Base
|
|||
self.commit_date = date
|
||||
super
|
||||
end
|
||||
|
||||
# Returns the readable identifier
|
||||
def format_identifier
|
||||
if repository.class.respond_to? :format_changeset_identifier
|
||||
repository.class.format_changeset_identifier self
|
||||
else
|
||||
identifier
|
||||
end
|
||||
end
|
||||
|
||||
def committer=(arg)
|
||||
write_attribute(:committer, self.class.to_utf8(arg.to_s))
|
||||
|
@ -77,52 +95,40 @@ class Changeset < ActiveRecord::Base
|
|||
scan_comment_for_issue_ids
|
||||
end
|
||||
|
||||
TIMELOG_RE = /
|
||||
(
|
||||
(\d+([.,]\d+)?)h?
|
||||
|
|
||||
(\d+):(\d+)
|
||||
|
|
||||
((\d+)(h|hours?))?((\d+)(m|min)?)?
|
||||
)
|
||||
/x
|
||||
|
||||
def scan_comment_for_issue_ids
|
||||
return if comments.blank?
|
||||
# keywords used to reference issues
|
||||
ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
|
||||
ref_keywords_any = ref_keywords.delete('*')
|
||||
# keywords used to fix issues
|
||||
fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
|
||||
|
||||
kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
|
||||
return if kw_regexp.blank?
|
||||
|
||||
referenced_issues = []
|
||||
|
||||
if ref_keywords.delete('*')
|
||||
# find any issue ID in the comments
|
||||
target_issue_ids = []
|
||||
comments.scan(%r{([\s\(\[,-]|^)#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
|
||||
referenced_issues += find_referenced_issues_by_id(target_issue_ids)
|
||||
end
|
||||
|
||||
comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
|
||||
action = match[0]
|
||||
target_issue_ids = match[1].scan(/\d+/)
|
||||
target_issues = find_referenced_issues_by_id(target_issue_ids)
|
||||
if fix_keywords.include?(action.downcase) && fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
|
||||
# update status of issues
|
||||
logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
|
||||
target_issues.each do |issue|
|
||||
# the issue may have been updated by the closure of another one (eg. duplicate)
|
||||
issue.reload
|
||||
# don't change the status is the issue is closed
|
||||
next if issue.status.is_closed?
|
||||
csettext = "r#{self.revision}"
|
||||
if self.scmid && (! (csettext =~ /^r[0-9]+$/))
|
||||
csettext = "commit:\"#{self.scmid}\""
|
||||
end
|
||||
journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, csettext))
|
||||
issue.status = fix_status
|
||||
unless Setting.commit_fix_done_ratio.blank?
|
||||
issue.done_ratio = Setting.commit_fix_done_ratio.to_i
|
||||
end
|
||||
Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
|
||||
{ :changeset => self, :issue => issue })
|
||||
issue.save
|
||||
comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
|
||||
action, refs = match[2], match[3]
|
||||
next unless action.present? || ref_keywords_any
|
||||
|
||||
refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
|
||||
issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
|
||||
if issue
|
||||
referenced_issues << issue
|
||||
fix_issue(issue) if fix_keywords.include?(action.to_s.downcase)
|
||||
log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
|
||||
end
|
||||
end
|
||||
referenced_issues += target_issues
|
||||
end
|
||||
|
||||
referenced_issues.uniq!
|
||||
|
@ -136,6 +142,14 @@ class Changeset < ActiveRecord::Base
|
|||
def long_comments
|
||||
@long_comments || split_comments.last
|
||||
end
|
||||
|
||||
def text_tag
|
||||
if scmid?
|
||||
"commit:#{scmid}"
|
||||
else
|
||||
"r#{revision}"
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the previous changeset
|
||||
def previous
|
||||
|
@ -163,13 +177,64 @@ class Changeset < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
# Finds issues that can be referenced by the commit message
|
||||
# i.e. issues that belong to the repository project, a subproject or a parent project
|
||||
def find_referenced_issues_by_id(ids)
|
||||
return [] if ids.compact.empty?
|
||||
Issue.find_all_by_id(ids, :include => :project).select {|issue|
|
||||
project == issue.project || project.is_ancestor_of?(issue.project) || project.is_descendant_of?(issue.project)
|
||||
}
|
||||
# Finds an issue that can be referenced by the commit message
|
||||
# i.e. an issue that belong to the repository project, a subproject or a parent project
|
||||
def find_referenced_issue_by_id(id)
|
||||
return nil if id.blank?
|
||||
issue = Issue.find_by_id(id.to_i, :include => :project)
|
||||
if issue
|
||||
unless project == issue.project || project.is_ancestor_of?(issue.project) || project.is_descendant_of?(issue.project)
|
||||
issue = nil
|
||||
end
|
||||
end
|
||||
issue
|
||||
end
|
||||
|
||||
def fix_issue(issue)
|
||||
status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
|
||||
if status.nil?
|
||||
logger.warn("No status macthes commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
|
||||
return issue
|
||||
end
|
||||
|
||||
# the issue may have been updated by the closure of another one (eg. duplicate)
|
||||
issue.reload
|
||||
# don't change the status is the issue is closed
|
||||
return if issue.status && issue.status.is_closed?
|
||||
|
||||
journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag))
|
||||
issue.status = status
|
||||
unless Setting.commit_fix_done_ratio.blank?
|
||||
issue.done_ratio = Setting.commit_fix_done_ratio.to_i
|
||||
end
|
||||
Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
|
||||
{ :changeset => self, :issue => issue })
|
||||
unless issue.save
|
||||
logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger
|
||||
end
|
||||
issue
|
||||
end
|
||||
|
||||
def log_time(issue, hours)
|
||||
time_entry = TimeEntry.new(
|
||||
:user => user,
|
||||
:hours => hours,
|
||||
:issue => issue,
|
||||
:spent_on => commit_date,
|
||||
:comments => l(:text_time_logged_by_changeset, :value => text_tag, :locale => Setting.default_language)
|
||||
)
|
||||
time_entry.activity = log_time_activity unless log_time_activity.nil?
|
||||
|
||||
unless time_entry.save
|
||||
logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
|
||||
end
|
||||
time_entry
|
||||
end
|
||||
|
||||
def log_time_activity
|
||||
if Setting.commit_logtime_activity_id.to_i > 0
|
||||
TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
def split_comments
|
||||
|
@ -180,7 +245,13 @@ class Changeset < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.to_utf8(str)
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
if str.respond_to?(:force_encoding)
|
||||
str.force_encoding('UTF-8')
|
||||
return str if str.valid_encoding?
|
||||
else
|
||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||
end
|
||||
|
||||
encoding = Setting.commit_logs_encoding.to_s.strip
|
||||
unless encoding.blank? || encoding == 'UTF-8'
|
||||
begin
|
||||
|
|
|
@ -23,7 +23,6 @@ class CustomField < ActiveRecord::Base
|
|||
validates_presence_of :name, :field_format
|
||||
validates_uniqueness_of :name, :scope => :type
|
||||
validates_length_of :name, :maximum => 30
|
||||
validates_format_of :name, :with => /^[\w\s\.\'\-]*$/i
|
||||
validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
|
||||
|
||||
def initialize(attributes = nil)
|
||||
|
|
|
@ -29,6 +29,9 @@ class Document < ActiveRecord::Base
|
|||
validates_presence_of :project, :title, :category
|
||||
validates_length_of :title, :maximum => 60
|
||||
|
||||
named_scope :visible, lambda {|*args| { :include => :project,
|
||||
:conditions => Project.allowed_to_condition(args.first || User.current, :view_documents) } }
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_documents, project)
|
||||
end
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Issue < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :tracker
|
||||
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
|
||||
|
@ -32,7 +34,7 @@ class Issue < ActiveRecord::Base
|
|||
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_nested_set :scope => 'root_id'
|
||||
acts_as_nested_set :scope => 'root_id', :dependent => :destroy
|
||||
acts_as_attachable :after_remove => :attachment_removed
|
||||
acts_as_customizable
|
||||
acts_as_watchable
|
||||
|
@ -87,7 +89,6 @@ class Issue < ActiveRecord::Base
|
|||
before_create :default_assign
|
||||
before_save :close_duplicates, :update_done_ratio_from_issue_status
|
||||
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal
|
||||
after_destroy :destroy_children
|
||||
after_destroy :update_parent_attributes
|
||||
|
||||
# Returns true if usr or current user is allowed to view the issue
|
||||
|
@ -214,30 +215,29 @@ class Issue < ActiveRecord::Base
|
|||
write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
|
||||
end
|
||||
|
||||
SAFE_ATTRIBUTES = %w(
|
||||
tracker_id
|
||||
status_id
|
||||
parent_issue_id
|
||||
category_id
|
||||
assigned_to_id
|
||||
priority_id
|
||||
fixed_version_id
|
||||
subject
|
||||
description
|
||||
start_date
|
||||
due_date
|
||||
done_ratio
|
||||
estimated_hours
|
||||
custom_field_values
|
||||
lock_version
|
||||
) unless const_defined?(:SAFE_ATTRIBUTES)
|
||||
safe_attributes 'tracker_id',
|
||||
'status_id',
|
||||
'parent_issue_id',
|
||||
'category_id',
|
||||
'assigned_to_id',
|
||||
'priority_id',
|
||||
'fixed_version_id',
|
||||
'subject',
|
||||
'description',
|
||||
'start_date',
|
||||
'due_date',
|
||||
'done_ratio',
|
||||
'estimated_hours',
|
||||
'custom_field_values',
|
||||
'custom_fields',
|
||||
'lock_version',
|
||||
:if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
|
||||
|
||||
SAFE_ATTRIBUTES_ON_TRANSITION = %w(
|
||||
status_id
|
||||
assigned_to_id
|
||||
fixed_version_id
|
||||
done_ratio
|
||||
) unless const_defined?(:SAFE_ATTRIBUTES_ON_TRANSITION)
|
||||
safe_attributes 'status_id',
|
||||
'assigned_to_id',
|
||||
'fixed_version_id',
|
||||
'done_ratio',
|
||||
:if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? }
|
||||
|
||||
# Safely sets attributes
|
||||
# Should be called from controllers instead of #attributes=
|
||||
|
@ -248,13 +248,8 @@ class Issue < ActiveRecord::Base
|
|||
return unless attrs.is_a?(Hash)
|
||||
|
||||
# User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
|
||||
if new_record? || user.allowed_to?(:edit_issues, project)
|
||||
attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)}
|
||||
elsif new_statuses_allowed_to(user).any?
|
||||
attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES_ON_TRANSITION.include?(k)}
|
||||
else
|
||||
return
|
||||
end
|
||||
attrs = delete_unsafe_attributes(attrs, user)
|
||||
return if attrs.empty?
|
||||
|
||||
# Tracker must be set before since new_statuses_allowed_to depends on it.
|
||||
if t = attrs.delete('tracker_id')
|
||||
|
@ -460,11 +455,14 @@ class Issue < ActiveRecord::Base
|
|||
(relations_from + relations_to).sort
|
||||
end
|
||||
|
||||
def all_dependent_issues
|
||||
def all_dependent_issues(except=nil)
|
||||
except ||= self
|
||||
dependencies = []
|
||||
relations_from.each do |relation|
|
||||
dependencies << relation.issue_to
|
||||
dependencies += relation.issue_to.all_dependent_issues
|
||||
if relation.issue_to && relation.issue_to != except
|
||||
dependencies << relation.issue_to
|
||||
dependencies += relation.issue_to.all_dependent_issues(except)
|
||||
end
|
||||
end
|
||||
dependencies
|
||||
end
|
||||
|
@ -759,14 +757,6 @@ class Issue < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def destroy_children
|
||||
unless leaf?
|
||||
children.each do |child|
|
||||
child.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Update issues so their versions are not pointing to a
|
||||
# fixed_version that is not shared with the issue's project
|
||||
def self.update_versions(conditions=nil)
|
||||
|
|
|
@ -84,14 +84,15 @@ class IssueRelation < ActiveRecord::Base
|
|||
|
||||
def set_issue_to_dates
|
||||
soonest_start = self.successor_soonest_start
|
||||
if soonest_start
|
||||
if soonest_start && issue_to
|
||||
issue_to.reschedule_after(soonest_start)
|
||||
end
|
||||
end
|
||||
|
||||
def successor_soonest_start
|
||||
return nil unless (TYPE_PRECEDES == self.relation_type) && (issue_from.start_date || issue_from.due_date)
|
||||
(issue_from.due_date || issue_from.start_date) + 1 + delay
|
||||
if (TYPE_PRECEDES == self.relation_type) && delay && issue_from && (issue_from.start_date || issue_from.due_date)
|
||||
(issue_from.due_date || issue_from.start_date) + 1 + delay
|
||||
end
|
||||
end
|
||||
|
||||
def <=>(relation)
|
||||
|
|
|
@ -25,7 +25,6 @@ class IssueStatus < ActiveRecord::Base
|
|||
validates_presence_of :name
|
||||
validates_uniqueness_of :name
|
||||
validates_length_of :name, :maximum => 30
|
||||
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
||||
validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true
|
||||
|
||||
def after_save
|
||||
|
|
|
@ -148,6 +148,9 @@ class MailHandler < ActionMailer::Base
|
|||
raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project)
|
||||
end
|
||||
|
||||
# ignore CLI-supplied defaults for new issues
|
||||
@@handler_options[:issue].clear
|
||||
|
||||
journal = issue.init_journal(user, cleaned_up_text_body)
|
||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||
|
@ -232,8 +235,8 @@ class MailHandler < ActionMailer::Base
|
|||
def extract_keyword!(text, attr, format=nil)
|
||||
keys = [attr.to_s.humanize]
|
||||
if attr.is_a?(Symbol)
|
||||
keys << l("field_#{attr}", :default => '', :locale => user.language) if user
|
||||
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
|
||||
keys << l("field_#{attr}", :default => '', :locale => user.language) if user && user.language.present?
|
||||
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) if Setting.default_language.present?
|
||||
end
|
||||
keys.reject! {|k| k.blank?}
|
||||
keys.collect! {|k| Regexp.escape(k)}
|
||||
|
@ -256,8 +259,8 @@ class MailHandler < ActionMailer::Base
|
|||
assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_user_from_keyword(k)
|
||||
assigned_to = nil if assigned_to && !issue.assignable_users.include?(assigned_to)
|
||||
|
||||
{
|
||||
'tracker_id' => ((k = get_keyword(:tracker)) && issue.project.trackers.find_by_name(k).try(:id)) || issue.project.trackers.find(:first).try(:id),
|
||||
attrs = {
|
||||
'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.find_by_name(k).try(:id),
|
||||
'status_id' => (k = get_keyword(:status)) && IssueStatus.find_by_name(k).try(:id),
|
||||
'priority_id' => (k = get_keyword(:priority)) && IssuePriority.find_by_name(k).try(:id),
|
||||
'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.find_by_name(k).try(:id),
|
||||
|
@ -268,6 +271,12 @@ class MailHandler < ActionMailer::Base
|
|||
'estimated_hours' => get_keyword(:estimated_hours, :override => true),
|
||||
'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
|
||||
}.delete_if {|k, v| v.blank? }
|
||||
|
||||
if issue.new_record? && attrs['tracker_id'].nil?
|
||||
attrs['tracker_id'] = issue.project.trackers.find(:first).try(:id)
|
||||
end
|
||||
|
||||
attrs
|
||||
end
|
||||
|
||||
# Returns a Hash of issue custom field values extracted from keywords in the email body
|
||||
|
|
|
@ -296,7 +296,7 @@ class Mailer < ActionMailer::Base
|
|||
if raise_errors
|
||||
raise e
|
||||
elsif mylogger
|
||||
mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/email.yml."
|
||||
mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
|
||||
end
|
||||
ensure
|
||||
self.class.raise_delivery_errors = raise_errors
|
||||
|
|
|
@ -42,6 +42,9 @@ class Message < ActiveRecord::Base
|
|||
|
||||
after_create :add_author_as_watcher
|
||||
|
||||
named_scope :visible, lambda {|*args| { :include => {:board => :project},
|
||||
:conditions => Project.allowed_to_condition(args.first || User.current, :view_messages) } }
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_messages, project)
|
||||
end
|
||||
|
|
|
@ -29,6 +29,11 @@ class News < ActiveRecord::Base
|
|||
acts_as_activity_provider :find_options => {:include => [:project, :author]},
|
||||
:author_key => :author_id
|
||||
|
||||
named_scope :visible, lambda {|*args| {
|
||||
:include => :project,
|
||||
:conditions => Project.allowed_to_condition(args.first || User.current, :view_news)
|
||||
}}
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_news, project)
|
||||
end
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
# Project statuses
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_ARCHIVED = 9
|
||||
|
@ -64,7 +66,7 @@ class Project < ActiveRecord::Base
|
|||
:url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}},
|
||||
:author => nil
|
||||
|
||||
attr_protected :status, :enabled_module_names
|
||||
attr_protected :status
|
||||
|
||||
validates_presence_of :name, :identifier
|
||||
validates_uniqueness_of :identifier
|
||||
|
@ -84,6 +86,24 @@ class Project < ActiveRecord::Base
|
|||
named_scope :all_public, { :conditions => { :is_public => true } }
|
||||
named_scope :visible, lambda { { :conditions => Project.visible_by(User.current) } }
|
||||
|
||||
def initialize(attributes = nil)
|
||||
super
|
||||
|
||||
initialized = (attributes || {}).stringify_keys
|
||||
if !initialized.key?('identifier') && Setting.sequential_project_identifiers?
|
||||
self.identifier = Project.next_identifier
|
||||
end
|
||||
if !initialized.key?('is_public')
|
||||
self.is_public = Setting.default_projects_public?
|
||||
end
|
||||
if !initialized.key?('enabled_module_names')
|
||||
self.enabled_module_names = Setting.default_projects_modules
|
||||
end
|
||||
if !initialized.key?('trackers') && !initialized.key?('tracker_ids')
|
||||
self.trackers = Tracker.all
|
||||
end
|
||||
end
|
||||
|
||||
def identifier=(identifier)
|
||||
super unless identifier_frozen?
|
||||
end
|
||||
|
@ -431,24 +451,20 @@ class Project < ActiveRecord::Base
|
|||
|
||||
# The earliest start date of a project, based on it's issues and versions
|
||||
def start_date
|
||||
if module_enabled?(:issue_tracking)
|
||||
[
|
||||
issues.minimum('start_date'),
|
||||
shared_versions.collect(&:effective_date),
|
||||
shared_versions.collect {|v| v.fixed_issues.minimum('start_date')}
|
||||
].flatten.compact.min
|
||||
end
|
||||
[
|
||||
issues.minimum('start_date'),
|
||||
shared_versions.collect(&:effective_date),
|
||||
shared_versions.collect(&:start_date)
|
||||
].flatten.compact.min
|
||||
end
|
||||
|
||||
# The latest due date of an issue or version
|
||||
def due_date
|
||||
if module_enabled?(:issue_tracking)
|
||||
[
|
||||
issues.maximum('due_date'),
|
||||
shared_versions.collect(&:effective_date),
|
||||
shared_versions.collect {|v| v.fixed_issues.maximum('due_date')}
|
||||
].flatten.compact.max
|
||||
end
|
||||
[
|
||||
issues.maximum('due_date'),
|
||||
shared_versions.collect(&:effective_date),
|
||||
shared_versions.collect {|v| v.fixed_issues.maximum('due_date')}
|
||||
].flatten.compact.max
|
||||
end
|
||||
|
||||
def overdue?
|
||||
|
@ -492,7 +508,7 @@ class Project < ActiveRecord::Base
|
|||
|
||||
def enabled_module_names=(module_names)
|
||||
if module_names && module_names.is_a?(Array)
|
||||
module_names = module_names.collect(&:to_s)
|
||||
module_names = module_names.collect(&:to_s).reject(&:blank?)
|
||||
# remove disabled modules
|
||||
enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)}
|
||||
# add new modules
|
||||
|
@ -501,7 +517,25 @@ class Project < ActiveRecord::Base
|
|||
enabled_modules.clear
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an array of the enabled modules names
|
||||
def enabled_module_names
|
||||
enabled_modules.collect(&:name)
|
||||
end
|
||||
|
||||
safe_attributes 'name',
|
||||
'description',
|
||||
'homepage',
|
||||
'is_public',
|
||||
'identifier',
|
||||
'custom_field_values',
|
||||
'custom_fields',
|
||||
'tracker_ids',
|
||||
'issue_custom_field_ids'
|
||||
|
||||
safe_attributes 'enabled_module_names',
|
||||
:if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) }
|
||||
|
||||
# Returns an array of projects that are in this project's hierarchy
|
||||
#
|
||||
# Example: parents, children, siblings
|
||||
|
@ -669,12 +703,20 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
self.issues << new_issue
|
||||
issues_map[issue.id] = new_issue
|
||||
if new_issue.new_record?
|
||||
logger.info "Project#copy_issues: issue ##{issue.id} could not be copied: #{new_issue.errors.full_messages}" if logger && logger.info
|
||||
else
|
||||
issues_map[issue.id] = new_issue unless new_issue.new_record?
|
||||
end
|
||||
end
|
||||
|
||||
# Relations after in case issues related each other
|
||||
project.issues.each do |issue|
|
||||
new_issue = issues_map[issue.id]
|
||||
unless new_issue
|
||||
# Issue was not copied
|
||||
next
|
||||
end
|
||||
|
||||
# Relations
|
||||
issue.relations_from.each do |source_relation|
|
||||
|
@ -701,7 +743,12 @@ class Project < ActiveRecord::Base
|
|||
|
||||
# Copies members from +project+
|
||||
def copy_members(project)
|
||||
project.memberships.each do |member|
|
||||
# Copy users first, then groups to handle members with inherited and given roles
|
||||
members_to_copy = []
|
||||
members_to_copy += project.memberships.select {|m| m.principal.is_a?(User)}
|
||||
members_to_copy += project.memberships.select {|m| !m.principal.is_a?(User)}
|
||||
|
||||
members_to_copy.each do |member|
|
||||
new_member = Member.new
|
||||
new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on")
|
||||
# only copy non inherited roles
|
||||
|
|
|
@ -187,10 +187,18 @@ class Query < ActiveRecord::Base
|
|||
if project
|
||||
user_values += project.users.sort.collect{|s| [s.name, s.id.to_s] }
|
||||
else
|
||||
project_ids = Project.all(:conditions => Project.visible_by(User.current)).collect(&:id)
|
||||
if project_ids.any?
|
||||
# members of the user's projects
|
||||
user_values += User.active.find(:all, :conditions => ["#{User.table_name}.id IN (SELECT DISTINCT user_id FROM members WHERE project_id IN (?))", project_ids]).sort.collect{|s| [s.name, s.id.to_s] }
|
||||
all_projects = Project.visible.all
|
||||
if all_projects.any?
|
||||
# members of visible projects
|
||||
user_values += User.active.find(:all, :conditions => ["#{User.table_name}.id IN (SELECT DISTINCT user_id FROM members WHERE project_id IN (?))", all_projects.collect(&:id)]).sort.collect{|s| [s.name, s.id.to_s] }
|
||||
|
||||
# project filter
|
||||
project_values = []
|
||||
Project.project_tree(all_projects) do |p, level|
|
||||
prefix = (level > 0 ? ('--' * level + ' ') : '')
|
||||
project_values << ["#{prefix}#{p.name}", p.id.to_s]
|
||||
end
|
||||
@available_filters["project_id"] = { :type => :list, :order => 1, :values => project_values} unless project_values.empty?
|
||||
end
|
||||
end
|
||||
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
|
||||
|
@ -225,12 +233,6 @@ class Query < ActiveRecord::Base
|
|||
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => system_shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
|
||||
end
|
||||
add_custom_fields_filters(IssueCustomField.find(:all, :conditions => {:is_filter => true, :is_for_all => true}))
|
||||
# project filter
|
||||
project_values = Project.all(:conditions => Project.visible_by(User.current), :order => 'lft').map do |p|
|
||||
pre = (p.level > 0 ? ('--' * p.level + ' ') : '')
|
||||
["#{pre}#{p.name}",p.id.to_s]
|
||||
end
|
||||
@available_filters["project_id"] = { :type => :list, :order => 1, :values => project_values}
|
||||
end
|
||||
@available_filters
|
||||
end
|
||||
|
@ -376,15 +378,15 @@ class Query < ActiveRecord::Base
|
|||
|
||||
# Returns true if the query is a grouped query
|
||||
def grouped?
|
||||
!group_by.blank?
|
||||
!group_by_column.nil?
|
||||
end
|
||||
|
||||
def group_by_column
|
||||
groupable_columns.detect {|c| c.name.to_s == group_by}
|
||||
groupable_columns.detect {|c| c.groupable && c.name.to_s == group_by}
|
||||
end
|
||||
|
||||
def group_by_statement
|
||||
group_by_column.groupable
|
||||
group_by_column.try(:groupable)
|
||||
end
|
||||
|
||||
def project_statement
|
||||
|
|
|
@ -86,17 +86,25 @@ class Repository < ActiveRecord::Base
|
|||
def diff(path, rev, rev_to)
|
||||
scm.diff(path, rev, rev_to)
|
||||
end
|
||||
|
||||
|
||||
def diff_format_revisions(cs, cs_to, sep=':')
|
||||
text = ""
|
||||
text << cs_to.format_identifier + sep if cs_to
|
||||
text << cs.format_identifier if cs
|
||||
text
|
||||
end
|
||||
|
||||
# Returns a path relative to the url of the repository
|
||||
def relative_path(path)
|
||||
path
|
||||
end
|
||||
|
||||
|
||||
# Finds and returns a revision with a number or the beginning of a hash
|
||||
def find_changeset_by_name(name)
|
||||
return nil if name.blank?
|
||||
changesets.find(:first, :conditions => (name.match(/^\d*$/) ? ["revision = ?", name.to_s] : ["revision LIKE ?", name + '%']))
|
||||
end
|
||||
|
||||
|
||||
def latest_changeset
|
||||
@latest_changeset ||= changesets.find(:first)
|
||||
end
|
||||
|
|
|
@ -104,10 +104,11 @@ class Repository::Cvs < Repository
|
|||
scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
|
||||
# only add the change to the database, if it doen't exists. the cvs log
|
||||
# is not exclusive at all.
|
||||
unless changes.find_by_path_and_revision(scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
|
||||
revision
|
||||
tmp_time = revision.time.clone
|
||||
unless changes.find_by_path_and_revision(
|
||||
scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
|
||||
cs = changesets.find(:first, :conditions=>{
|
||||
:committed_on=>revision.time-time_delta..revision.time+time_delta,
|
||||
:committed_on=>tmp_time - time_delta .. tmp_time + time_delta,
|
||||
:committer=>revision.author,
|
||||
:comments=>Changeset.normalize_comments(revision.message)
|
||||
})
|
||||
|
@ -116,11 +117,14 @@ class Repository::Cvs < Repository
|
|||
unless cs
|
||||
# we use a temporaray revision number here (just for inserting)
|
||||
# later on, we calculate a continous positive number
|
||||
latest = changesets.find(:first, :order => 'id DESC')
|
||||
tmp_time2 = tmp_time.clone.gmtime
|
||||
branch = revision.paths[0][:branch]
|
||||
scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
|
||||
cs = Changeset.create(:repository => self,
|
||||
:revision => "_#{tmp_rev_num}",
|
||||
:revision => "tmp#{tmp_rev_num}",
|
||||
:scmid => scmid,
|
||||
:committer => revision.author,
|
||||
:committed_on => revision.time,
|
||||
:committed_on => tmp_time,
|
||||
:comments => revision.message)
|
||||
tmp_rev_num += 1
|
||||
end
|
||||
|
@ -144,10 +148,13 @@ class Repository::Cvs < Repository
|
|||
end
|
||||
|
||||
# Renumber new changesets in chronological order
|
||||
changesets.find(:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE '_%'").each do |changeset|
|
||||
changesets.find(
|
||||
:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE 'tmp%'"
|
||||
).each do |changeset|
|
||||
changeset.update_attribute :revision, next_revision_number
|
||||
end
|
||||
end # transaction
|
||||
@current_revision_number = nil
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -155,7 +162,9 @@ class Repository::Cvs < Repository
|
|||
# Returns the next revision number to assign to a CVS changeset
|
||||
def next_revision_number
|
||||
# Need to retrieve existing revision numbers to sort them as integers
|
||||
@current_revision_number ||= (connection.select_values("SELECT revision FROM #{Changeset.table_name} WHERE repository_id = #{id} AND revision NOT LIKE '_%'").collect(&:to_i).max || 0)
|
||||
sql = "SELECT revision FROM #{Changeset.table_name} "
|
||||
sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'"
|
||||
@current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0)
|
||||
@current_revision_number += 1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,6 +29,16 @@ class Repository::Git < Repository
|
|||
'Git'
|
||||
end
|
||||
|
||||
# Returns the identifier for the given git changeset
|
||||
def self.changeset_identifier(changeset)
|
||||
changeset.scmid
|
||||
end
|
||||
|
||||
# Returns the readable identifier for the given git changeset
|
||||
def self.format_changeset_identifier(changeset)
|
||||
changeset.revision[0, 8]
|
||||
end
|
||||
|
||||
def branches
|
||||
scm.branches
|
||||
end
|
||||
|
|
|
@ -18,17 +18,34 @@
|
|||
require 'redmine/scm/adapters/mercurial_adapter'
|
||||
|
||||
class Repository::Mercurial < Repository
|
||||
# sort changesets by revision number
|
||||
has_many :changesets, :order => "#{Changeset.table_name}.id DESC", :foreign_key => 'repository_id'
|
||||
|
||||
attr_protected :root_url
|
||||
validates_presence_of :url
|
||||
|
||||
def scm_adapter
|
||||
Redmine::Scm::Adapters::MercurialAdapter
|
||||
end
|
||||
|
||||
|
||||
def self.scm_name
|
||||
'Mercurial'
|
||||
end
|
||||
|
||||
|
||||
# Returns the readable identifier for the given mercurial changeset
|
||||
def self.format_changeset_identifier(changeset)
|
||||
"#{changeset.revision}:#{changeset.scmid}"
|
||||
end
|
||||
|
||||
# Returns the identifier for the given Mercurial changeset
|
||||
def self.changeset_identifier(changeset)
|
||||
changeset.scmid
|
||||
end
|
||||
|
||||
def diff_format_revisions(cs, cs_to, sep=':')
|
||||
super(cs, cs_to, ' ')
|
||||
end
|
||||
|
||||
def entries(path=nil, identifier=nil)
|
||||
entries=scm.entries(path, identifier)
|
||||
if entries
|
||||
|
@ -52,6 +69,30 @@ class Repository::Mercurial < Repository
|
|||
entries
|
||||
end
|
||||
|
||||
# Finds and returns a revision with a number or the beginning of a hash
|
||||
def find_changeset_by_name(name)
|
||||
return nil if name.nil? || name.empty?
|
||||
if /[^\d]/ =~ name or name.to_s.size > 8
|
||||
e = changesets.find(:first, :conditions => ['scmid = ?', name.to_s])
|
||||
else
|
||||
e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
|
||||
end
|
||||
return e if e
|
||||
changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"]) # last ditch
|
||||
end
|
||||
|
||||
# Returns the latest changesets for +path+; sorted by revision number
|
||||
def latest_changesets(path, rev, limit=10)
|
||||
if path.blank?
|
||||
changesets.find(:all, :include => :user, :limit => limit)
|
||||
else
|
||||
changes.find(:all, :include => {:changeset => :user},
|
||||
:conditions => ["path = ?", path.with_leading_slash],
|
||||
:order => "#{Changeset.table_name}.id DESC",
|
||||
:limit => limit).collect(&:changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_changesets
|
||||
scm_info = scm.info
|
||||
if scm_info
|
||||
|
|
|
@ -43,7 +43,6 @@ class Role < ActiveRecord::Base
|
|||
validates_presence_of :name
|
||||
validates_uniqueness_of :name
|
||||
validates_length_of :name, :maximum => 30
|
||||
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
||||
|
||||
def permissions
|
||||
read_attribute(:permissions) || []
|
||||
|
|
|
@ -66,6 +66,9 @@ class TimeEntry < ActiveRecord::Base
|
|||
# these attributes make time aggregations easier
|
||||
def spent_on=(date)
|
||||
super
|
||||
if spent_on.is_a?(Time)
|
||||
self.spent_on = spent_on.to_date
|
||||
end
|
||||
self.tyear = spent_on ? spent_on.year : nil
|
||||
self.tmonth = spent_on ? spent_on.month : nil
|
||||
self.tweek = spent_on ? Date.civil(spent_on.year, spent_on.month, spent_on.day).cweek : nil
|
||||
|
|
|
@ -31,7 +31,6 @@ class Tracker < ActiveRecord::Base
|
|||
validates_presence_of :name
|
||||
validates_uniqueness_of :name
|
||||
validates_length_of :name, :maximum => 30
|
||||
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
||||
|
||||
def to_s; name end
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
require "digest/sha1"
|
||||
|
||||
class User < Principal
|
||||
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
# Account statuses
|
||||
STATUS_ANONYMOUS = 0
|
||||
STATUS_ACTIVE = 1
|
||||
|
@ -34,13 +35,13 @@ class User < Principal
|
|||
}
|
||||
|
||||
MAIL_NOTIFICATION_OPTIONS = [
|
||||
[:all, :label_user_mail_option_all],
|
||||
[:selected, :label_user_mail_option_selected],
|
||||
[:none, :label_user_mail_option_none],
|
||||
[:only_my_events, :label_user_mail_option_only_my_events],
|
||||
[:only_assigned, :label_user_mail_option_only_assigned],
|
||||
[:only_owner, :label_user_mail_option_only_owner]
|
||||
]
|
||||
['all', :label_user_mail_option_all],
|
||||
['selected', :label_user_mail_option_selected],
|
||||
['only_my_events', :label_user_mail_option_only_my_events],
|
||||
['only_assigned', :label_user_mail_option_only_assigned],
|
||||
['only_owner', :label_user_mail_option_only_owner],
|
||||
['none', :label_user_mail_option_none]
|
||||
]
|
||||
|
||||
has_and_belongs_to_many :groups, :after_add => Proc.new {|user, group| group.user_added(user)},
|
||||
:after_remove => Proc.new {|user, group| group.user_removed(user)}
|
||||
|
@ -59,7 +60,7 @@ class User < Principal
|
|||
attr_accessor :password, :password_confirmation
|
||||
attr_accessor :last_before_login_on
|
||||
# Prevents unauthorized assignments
|
||||
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password, :group_ids
|
||||
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
|
||||
|
||||
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
|
||||
validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false
|
||||
|
@ -67,11 +68,11 @@ class User < Principal
|
|||
# Login must contain lettres, numbers, underscores only
|
||||
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
|
||||
validates_length_of :login, :maximum => 30
|
||||
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-\.]*$/i
|
||||
validates_length_of :firstname, :lastname, :maximum => 30
|
||||
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
|
||||
validates_length_of :mail, :maximum => 60, :allow_nil => true
|
||||
validates_confirmation_of :password, :allow_nil => true
|
||||
validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
|
||||
|
||||
def before_create
|
||||
self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
|
||||
|
@ -259,12 +260,16 @@ class User < Principal
|
|||
notified_projects_ids
|
||||
end
|
||||
|
||||
# Only users that belong to more than 1 project can select projects for which they are notified
|
||||
def valid_notification_options
|
||||
self.class.valid_notification_options(self)
|
||||
end
|
||||
|
||||
# Only users that belong to more than 1 project can select projects for which they are notified
|
||||
def self.valid_notification_options(user=nil)
|
||||
# Note that @user.membership.size would fail since AR ignores
|
||||
# :include association option when doing a count
|
||||
if memberships.length < 1
|
||||
MAIL_NOTIFICATION_OPTIONS.delete_if {|option| option.first == :selected}
|
||||
if user.nil? || user.memberships.length < 1
|
||||
MAIL_NOTIFICATION_OPTIONS.reject {|option| option.first == 'selected'}
|
||||
else
|
||||
MAIL_NOTIFICATION_OPTIONS
|
||||
end
|
||||
|
@ -390,32 +395,54 @@ class User < Principal
|
|||
def allowed_to_globally?(action, options)
|
||||
allowed_to?(action, nil, options.reverse_merge(:global => true))
|
||||
end
|
||||
|
||||
safe_attributes 'login',
|
||||
'firstname',
|
||||
'lastname',
|
||||
'mail',
|
||||
'mail_notification',
|
||||
'language',
|
||||
'custom_field_values',
|
||||
'custom_fields',
|
||||
'identity_url'
|
||||
|
||||
safe_attributes 'status',
|
||||
'auth_source_id',
|
||||
:if => lambda {|user, current_user| current_user.admin?}
|
||||
|
||||
safe_attributes 'group_ids',
|
||||
:if => lambda {|user, current_user| current_user.admin? && !user.new_record?}
|
||||
|
||||
# Utility method to help check if a user should be notified about an
|
||||
# event.
|
||||
#
|
||||
# TODO: only supports Issue events currently
|
||||
def notify_about?(object)
|
||||
case mail_notification.to_sym
|
||||
when :all
|
||||
case mail_notification
|
||||
when 'all'
|
||||
true
|
||||
when :selected
|
||||
# Handled by the Project
|
||||
when :none
|
||||
false
|
||||
when :only_my_events
|
||||
when 'selected'
|
||||
# user receives notifications for created/assigned issues on unselected projects
|
||||
if object.is_a?(Issue) && (object.author == self || object.assigned_to == self)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
when :only_assigned
|
||||
when 'none'
|
||||
false
|
||||
when 'only_my_events'
|
||||
if object.is_a?(Issue) && (object.author == self || object.assigned_to == self)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
when 'only_assigned'
|
||||
if object.is_a?(Issue) && object.assigned_to == self
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
when :only_owner
|
||||
when 'only_owner'
|
||||
if object.is_a?(Issue) && object.author == self
|
||||
true
|
||||
else
|
||||
|
|
|
@ -43,7 +43,7 @@ class Version < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def start_date
|
||||
effective_date
|
||||
@start_date ||= fixed_issues.minimum('start_date')
|
||||
end
|
||||
|
||||
def due_date
|
||||
|
@ -77,8 +77,7 @@ class Version < ActiveRecord::Base
|
|||
def behind_schedule?
|
||||
if completed_pourcent == 100
|
||||
return false
|
||||
elsif due_date && fixed_issues.present? && fixed_issues.minimum('start_date') # TODO: should use #start_date but that method is wrong...
|
||||
start_date = fixed_issues.minimum('start_date')
|
||||
elsif due_date && start_date
|
||||
done_date = start_date + ((due_date - start_date+1)* completed_pourcent/100).floor
|
||||
return done_date <= Date.today
|
||||
else
|
||||
|
|
|
@ -45,11 +45,11 @@ class Wiki < ActiveRecord::Base
|
|||
# find the page with the given title
|
||||
def find_page(title, options = {})
|
||||
title = start_page if title.blank?
|
||||
title = Wiki.titleize(title).downcase
|
||||
page = pages.first(:conditions => ["LOWER(title) LIKE ?", title])
|
||||
title = Wiki.titleize(title)
|
||||
page = pages.first(:conditions => ["LOWER(title) LIKE LOWER(?)", title])
|
||||
if !page && !(options[:with_redirect] == false)
|
||||
# search for a redirect
|
||||
redirect = redirects.first(:conditions => ["LOWER(title) LIKE ?", title])
|
||||
redirect = redirects.first(:conditions => ["LOWER(title) LIKE LOWER(?)", title])
|
||||
page = find_page(redirect.redirects_to, :with_redirect => false) if redirect
|
||||
end
|
||||
page
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<% if diff_type == 'sbs' -%>
|
||||
<table class="filecontent">
|
||||
<thead>
|
||||
<tr><th colspan="4" class="filename"><%= table_file.file_name %></th></tr>
|
||||
<tr><th colspan="4" class="filename"><%=to_utf8 table_file.file_name %></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% prev_line_left, prev_line_right = nil, nil -%>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<% else -%>
|
||||
<table class="filecontent syntaxhl">
|
||||
<thead>
|
||||
<tr><th colspan="3" class="filename"><%= table_file.file_name %></th></tr>
|
||||
<tr><th colspan="3" class="filename"><%=to_utf8 table_file.file_name %></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% prev_line_left, prev_line_right = nil, nil -%>
|
||||
|
|
|
@ -59,10 +59,19 @@ end
|
|||
|
||||
# Width of the entire chart
|
||||
g_width = (@gantt.date_to - @gantt.date_from + 1)*zoom
|
||||
# Collect the number of issues on Versions
|
||||
|
||||
@gantt.render(:top => headers_height + 8, :zoom => zoom, :g_width => g_width)
|
||||
|
||||
g_height = [(20 * (@gantt.number_of_rows + 6))+150, 206].max
|
||||
t_height = g_height + headers_height
|
||||
|
||||
|
||||
%>
|
||||
|
||||
<% if @gantt.truncated %>
|
||||
<p class="warning"><%= l(:notice_gantt_chart_truncated, :max => @gantt.max_rows) %></p>
|
||||
<% end %>
|
||||
|
||||
<table width="100%" style="border:0; border-collapse: collapse;">
|
||||
<tr>
|
||||
<td style="width:<%= subject_width %>px; padding:0px;">
|
||||
|
@ -70,9 +79,10 @@ t_height = g_height + headers_height
|
|||
<div style="position:relative;height:<%= t_height + 24 %>px;width:<%= subject_width + 1 %>px;">
|
||||
<div style="right:-2px;width:<%= subject_width %>px;height:<%= headers_height %>px;background: #eee;" class="gantt_hdr"></div>
|
||||
<div style="right:-2px;width:<%= subject_width %>px;height:<%= t_height %>px;border-left: 1px solid #c0c0c0;overflow:hidden;" class="gantt_hdr"></div>
|
||||
<% top = headers_height + 8 %>
|
||||
|
||||
<%= @gantt.subjects(:headers_height => headers_height, :top => top, :g_width => g_width) %>
|
||||
<div class="gantt_subjects">
|
||||
<%= @gantt.subjects %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
@ -151,9 +161,7 @@ if show_days
|
|||
end
|
||||
end %>
|
||||
|
||||
<% top = headers_height + 10 %>
|
||||
|
||||
<%= @gantt.lines(:top => top, :zoom => zoom, :g_width => g_width ) %>
|
||||
<%= @gantt.lines %>
|
||||
|
||||
<%
|
||||
#
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
<%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join %>
|
||||
|
||||
<div class="box tabular">
|
||||
<fieldset class="attributes">
|
||||
<legend><%= l(:label_change_properties) %></legend>
|
||||
|
||||
<div class="splitcontentleft">
|
||||
<p><label for="new_project_id"><%=l(:field_project)%>:</label>
|
||||
<%= select_tag "new_project_id",
|
||||
project_tree_options_for_select(@allowed_projects, :selected => @target_project),
|
||||
|
@ -21,13 +25,6 @@
|
|||
<p><label for="new_tracker_id"><%=l(:field_tracker)%>:</label>
|
||||
<%= select_tag "new_tracker_id", "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@trackers, "id", "name") %></p>
|
||||
|
||||
<p>
|
||||
<label><%= l(:field_assigned_to) %></label>
|
||||
<%= select_tag('assigned_to_id', content_tag('option', l(:label_no_change_option), :value => '') +
|
||||
content_tag('option', l(:label_nobody), :value => 'none') +
|
||||
options_from_collection_for_select(@target_project.assignable_users, :id, :name)) %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label><%= l(:field_status) %></label>
|
||||
<%= select_tag('status_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %>
|
||||
|
@ -38,6 +35,15 @@
|
|||
<%= select_tag('priority_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(IssuePriority.all, :id, :name)) %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label><%= l(:field_assigned_to) %></label>
|
||||
<%= select_tag('assigned_to_id', content_tag('option', l(:label_no_change_option), :value => '') +
|
||||
content_tag('option', l(:label_nobody), :value => 'none') +
|
||||
options_from_collection_for_select(@target_project.assignable_users, :id, :name)) %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="splitcontentright">
|
||||
<p>
|
||||
<label><%= l(:field_start_date) %></label>
|
||||
<%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %>
|
||||
|
@ -47,6 +53,9 @@
|
|||
<label><%= l(:field_due_date) %></label>
|
||||
<%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset><legend><%= l(:field_notes) %></legend>
|
||||
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<%= error_messages_for 'relation' %>
|
||||
|
||||
<p><%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %>
|
||||
<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 6 %>
|
||||
<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 10 %>
|
||||
<div id="related_issue_candidates" class="autocomplete"></div>
|
||||
<%= javascript_tag "observeRelatedIssueField('#{auto_complete_issues_path(:id => @issue, :project_id => @project) }')" %>
|
||||
<span id="predecessor_fields" style="display:none;">
|
||||
<%= l(:field_delay) %>: <%= f.text_field :delay, :size => 3 %> <%= l(:label_day_plural) %>
|
||||
</span>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<% changesets.each do |changeset| %>
|
||||
<div class="changeset <%= cycle('odd', 'even') %>">
|
||||
<p><%= link_to("#{l(:label_revision)} #{changeset.revision}",
|
||||
:controller => 'repositories', :action => 'revision', :id => changeset.project, :rev => changeset.revision) %><br />
|
||||
<p><%= link_to_revision(changeset, changeset.project,
|
||||
:text => "#{l(:label_revision)} #{changeset.format_identifier}") %><br />
|
||||
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
|
||||
<div class="changeset-changes">
|
||||
<%= textilizable(changeset, :comments) %>
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
<p><strong><%=l(:label_related_issues)%></strong></p>
|
||||
|
||||
<% if @issue.relations.any? %>
|
||||
<% if @relations.present? %>
|
||||
<table style="width:100%">
|
||||
<% @issue.relations.select {|r| r.other_issue(@issue).visible? }.each do |relation| %>
|
||||
<% @relations.each do |relation| %>
|
||||
<tr>
|
||||
<td><%= l(relation.label_for(@issue)) %> <%= "(#{l('datetime.distance_in_words.x_days', :count => relation.delay)})" if relation.delay && relation.delay != 0 %>
|
||||
<%= h(relation.other_issue(@issue).project) + ' - ' if Setting.cross_project_issue_relations? %>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<label><%= l(:field_fixed_version) %></label>
|
||||
<%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
|
||||
content_tag('option', l(:label_none), :value => 'none') +
|
||||
version_options_for_select(@project.shared_versions.open)) %>
|
||||
version_options_for_select(@project.shared_versions.open.sort)) %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :limit => @limit) do
|
||||
@issues.each do |issue|
|
||||
api.issue do
|
||||
api.id issue.id
|
||||
api.project(:id => issue.project_id, :name => issue.project.name) unless issue.project.nil?
|
||||
api.tracker(:id => issue.tracker_id, :name => issue.tracker.name) unless issue.tracker.nil?
|
||||
api.status(:id => issue.status_id, :name => issue.status.name) unless issue.status.nil?
|
||||
api.priority(:id => issue.priority_id, :name => issue.priority.name) unless issue.priority.nil?
|
||||
api.author(:id => issue.author_id, :name => issue.author.name) unless issue.author.nil?
|
||||
api.assigned_to(:id => issue.assigned_to_id, :name => issue.assigned_to.name) unless issue.assigned_to.nil?
|
||||
api.category(:id => issue.category_id, :name => issue.category.name) unless issue.category.nil?
|
||||
api.fixed_version(:id => issue.fixed_version_id, :name => issue.fixed_version.name) unless issue.fixed_version.nil?
|
||||
api.parent(:id => issue.parent_id) unless issue.parent.nil?
|
||||
|
||||
api.subject issue.subject
|
||||
api.description issue.description
|
||||
api.start_date issue.start_date
|
||||
api.due_date issue.due_date
|
||||
api.done_ratio issue.done_ratio
|
||||
api.estimated_hours issue.estimated_hours
|
||||
|
||||
render_api_custom_values issue.custom_field_values, api
|
||||
|
||||
api.created_on issue.created_on
|
||||
api.updated_on issue.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,33 +0,0 @@
|
|||
xml.instruct!
|
||||
xml.issues :type => 'array' do
|
||||
@issues.each do |issue|
|
||||
xml.issue do
|
||||
xml.id issue.id
|
||||
xml.project(:id => issue.project_id, :name => issue.project.name) unless issue.project.nil?
|
||||
xml.tracker(:id => issue.tracker_id, :name => issue.tracker.name) unless issue.tracker.nil?
|
||||
xml.status(:id => issue.status_id, :name => issue.status.name) unless issue.status.nil?
|
||||
xml.priority(:id => issue.priority_id, :name => issue.priority.name) unless issue.priority.nil?
|
||||
xml.author(:id => issue.author_id, :name => issue.author.name) unless issue.author.nil?
|
||||
xml.assigned_to(:id => issue.assigned_to_id, :name => issue.assigned_to.name) unless issue.assigned_to.nil?
|
||||
xml.category(:id => issue.category_id, :name => issue.category.name) unless issue.category.nil?
|
||||
xml.fixed_version(:id => issue.fixed_version_id, :name => issue.fixed_version.name) unless issue.fixed_version.nil?
|
||||
xml.parent(:id => issue.parent_id) unless issue.parent.nil?
|
||||
|
||||
xml.subject issue.subject
|
||||
xml.description issue.description
|
||||
xml.start_date issue.start_date
|
||||
xml.due_date issue.due_date
|
||||
xml.done_ratio issue.done_ratio
|
||||
xml.estimated_hours issue.estimated_hours
|
||||
|
||||
xml.custom_fields do
|
||||
issue.custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end
|
||||
|
||||
xml.created_on issue.created_on
|
||||
xml.updated_on issue.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
api.issue do
|
||||
api.id @issue.id
|
||||
api.project(:id => @issue.project_id, :name => @issue.project.name) unless @issue.project.nil?
|
||||
api.tracker(:id => @issue.tracker_id, :name => @issue.tracker.name) unless @issue.tracker.nil?
|
||||
api.status(:id => @issue.status_id, :name => @issue.status.name) unless @issue.status.nil?
|
||||
api.priority(:id => @issue.priority_id, :name => @issue.priority.name) unless @issue.priority.nil?
|
||||
api.author(:id => @issue.author_id, :name => @issue.author.name) unless @issue.author.nil?
|
||||
api.assigned_to(:id => @issue.assigned_to_id, :name => @issue.assigned_to.name) unless @issue.assigned_to.nil?
|
||||
api.category(:id => @issue.category_id, :name => @issue.category.name) unless @issue.category.nil?
|
||||
api.fixed_version(:id => @issue.fixed_version_id, :name => @issue.fixed_version.name) unless @issue.fixed_version.nil?
|
||||
api.parent(:id => @issue.parent_id) unless @issue.parent.nil?
|
||||
|
||||
api.subject @issue.subject
|
||||
api.description @issue.description
|
||||
api.start_date @issue.start_date
|
||||
api.due_date @issue.due_date
|
||||
api.done_ratio @issue.done_ratio
|
||||
api.estimated_hours @issue.estimated_hours
|
||||
api.spent_hours(@issue.spent_hours) if User.current.allowed_to?(:view_time_entries, @project)
|
||||
|
||||
render_api_custom_values @issue.custom_field_values, api
|
||||
|
||||
api.created_on @issue.created_on
|
||||
api.updated_on @issue.updated_on
|
||||
|
||||
render_api_issue_children(@issue, api) if include_in_api_response?('children')
|
||||
|
||||
api.array :relations do
|
||||
@relations.each do |relation|
|
||||
api.relation(:id => relation.id, :issue_id => relation.other_issue(@issue).id, :relation_type => relation.relation_type_for(@issue), :delay => relation.delay)
|
||||
end
|
||||
end if include_in_api_response?('relations') && @relations.present?
|
||||
|
||||
api.array :changesets do
|
||||
@issue.changesets.each do |changeset|
|
||||
api.changeset :revision => changeset.revision do
|
||||
api.user(:id => changeset.user_id, :name => changeset.user.name) unless changeset.user.nil?
|
||||
api.comments changeset.comments
|
||||
api.committed_on changeset.committed_on
|
||||
end
|
||||
end
|
||||
end if include_in_api_response?('changesets') && User.current.allowed_to?(:view_changesets, @project)
|
||||
|
||||
api.array :journals do
|
||||
@issue.journals.each do |journal|
|
||||
api.journal :id => journal.id do
|
||||
api.user(:id => journal.user_id, :name => journal.user.name) unless journal.user.nil?
|
||||
api.notes journal.notes
|
||||
api.created_on journal.created_on
|
||||
api.array :details do
|
||||
journal.details.each do |detail|
|
||||
api.detail :property => detail.property, :name => detail.prop_key do
|
||||
api.old_value detail.old_value
|
||||
api.new_value detail.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end if include_in_api_response?('journals')
|
||||
end
|
|
@ -47,14 +47,16 @@
|
|||
|
||||
<% if @issue.description? || @issue.attachments.any? -%>
|
||||
<hr />
|
||||
<div class="contextual">
|
||||
<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') if @issue.description? %>
|
||||
</div>
|
||||
|
||||
<div class="wiki">
|
||||
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
|
||||
</div>
|
||||
|
||||
<% if @issue.description? %>
|
||||
<div class="contextual">
|
||||
<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:controller => 'journals', :action => 'new', :id => @issue} }, :class => 'icon icon-comment') %>
|
||||
</div>
|
||||
|
||||
<p><strong><%=l(:field_description)%></strong></p>
|
||||
<div class="wiki">
|
||||
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= link_to_attachments @issue %>
|
||||
<% end -%>
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
xml.instruct!
|
||||
xml.issue do
|
||||
xml.id @issue.id
|
||||
xml.project(:id => @issue.project_id, :name => @issue.project.name) unless @issue.project.nil?
|
||||
xml.tracker(:id => @issue.tracker_id, :name => @issue.tracker.name) unless @issue.tracker.nil?
|
||||
xml.status(:id => @issue.status_id, :name => @issue.status.name) unless @issue.status.nil?
|
||||
xml.priority(:id => @issue.priority_id, :name => @issue.priority.name) unless @issue.priority.nil?
|
||||
xml.author(:id => @issue.author_id, :name => @issue.author.name) unless @issue.author.nil?
|
||||
xml.assigned_to(:id => @issue.assigned_to_id, :name => @issue.assigned_to.name) unless @issue.assigned_to.nil?
|
||||
xml.category(:id => @issue.category_id, :name => @issue.category.name) unless @issue.category.nil?
|
||||
xml.fixed_version(:id => @issue.fixed_version_id, :name => @issue.fixed_version.name) unless @issue.fixed_version.nil?
|
||||
xml.parent(:id => @issue.parent_id) unless @issue.parent.nil?
|
||||
|
||||
xml.subject @issue.subject
|
||||
xml.description @issue.description
|
||||
xml.start_date @issue.start_date
|
||||
xml.due_date @issue.due_date
|
||||
xml.done_ratio @issue.done_ratio
|
||||
xml.estimated_hours @issue.estimated_hours
|
||||
if User.current.allowed_to?(:view_time_entries, @project)
|
||||
xml.spent_hours @issue.spent_hours
|
||||
end
|
||||
|
||||
xml.custom_fields do
|
||||
@issue.custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end unless @issue.custom_field_values.empty?
|
||||
|
||||
xml.created_on @issue.created_on
|
||||
xml.updated_on @issue.updated_on
|
||||
|
||||
xml.relations do
|
||||
@issue.relations.select {|r| r.other_issue(@issue).visible? }.each do |relation|
|
||||
xml.relation(:id => relation.id, :issue_id => relation.other_issue(@issue).id, :relation_type => relation.relation_type_for(@issue), :delay => relation.delay)
|
||||
end
|
||||
end
|
||||
|
||||
xml.changesets do
|
||||
@issue.changesets.each do |changeset|
|
||||
xml.changeset :revision => changeset.revision do
|
||||
xml.user(:id => changeset.user_id, :name => changeset.user.name) unless changeset.user.nil?
|
||||
xml.comments changeset.comments
|
||||
xml.committed_on changeset.committed_on
|
||||
end
|
||||
end
|
||||
end if User.current.allowed_to?(:view_changesets, @project) && @issue.changesets.any?
|
||||
|
||||
xml.journals do
|
||||
@issue.journals.each do |journal|
|
||||
xml.journal :id => journal.id do
|
||||
xml.user(:id => journal.user_id, :name => journal.user.name) unless journal.user.nil?
|
||||
xml.notes journal.notes
|
||||
xml.details do
|
||||
journal.details.each do |detail|
|
||||
xml.detail :property => detail.property, :name => detail.prop_key, :old => detail.old_value, :new => detail.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end unless @issue.journals.empty?
|
||||
end
|
|
@ -9,8 +9,9 @@
|
|||
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
||||
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
||||
<%= javascript_include_tag :defaults %>
|
||||
<%= heads_for_theme %>
|
||||
<%= heads_for_wiki_formatter %>
|
||||
<!--[if IE]>
|
||||
<!--[if IE 6]>
|
||||
<style type="text/css">
|
||||
* html body{ width: expression( document.documentElement.clientWidth < 900 ? '900px' : '100%' ); }
|
||||
body {behavior: url(<%= stylesheet_path "csshover.htc" %>);}
|
||||
|
@ -68,7 +69,7 @@
|
|||
|
||||
<div id="footer">
|
||||
<div class="bgl"><div class="bgr">
|
||||
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> © 2006-2010 Jean-Philippe Lang
|
||||
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> © 2006-2011 Jean-Philippe Lang
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,7 @@ function removeBlock(block) {
|
|||
|
||||
<div class="contextual">
|
||||
<% form_tag({:action => "add_block"}, :id => "block-form") do %>
|
||||
<%= label_tag('block-select', l(:label_my_page_block)) %>
|
||||
<%= label_tag('block-select', l(:label_my_page_block)) %>:
|
||||
<%= select_tag 'block', "<option></option>" + options_for_select(@block_options), :id => "block-select" %>
|
||||
<%= link_to_remote l(:button_add),
|
||||
{:url => { :action => "add_block" },
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
api.array :news, api_meta(:total_count => @news_count, :offset => @offset, :limit => @limit) do
|
||||
@newss.each do |news|
|
||||
api.news do
|
||||
api.id news.id
|
||||
api.project(:id => news.project_id, :name => news.project.name) unless news.project.nil?
|
||||
api.author(:id => news.author_id, :name => news.author.name) unless news.author.nil?
|
||||
|
||||
api.title news.title
|
||||
api.summary news.summary
|
||||
api.description news.description
|
||||
api.created_on news.created_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -23,8 +23,22 @@
|
|||
<%= call_hook(:view_projects_form, :project => @project, :form => f) %>
|
||||
</div>
|
||||
|
||||
<% if @project.new_record? %>
|
||||
<fieldset class="box"><legend><%= l(:label_module_plural) %></legend>
|
||||
<% Redmine::AccessControl.available_project_modules.each do |m| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'project[enabled_module_names][]', m, @project.module_enabled?(m), :id => "project_enabled_module_names_#{m}" %>
|
||||
<%= l_or_humanize(m, :prefix => "project_module_") %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= hidden_field_tag 'project[enabled_module_names][]', '' %>
|
||||
<%= javascript_tag 'observeProjectModules()' %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if @project.new_record? || @project.module_enabled?('issue_tracking') %>
|
||||
<% unless @trackers.empty? %>
|
||||
<fieldset class="box"><legend><%=l(:label_tracker_plural)%></legend>
|
||||
<fieldset class="box" id="project_trackers"><legend><%=l(:label_tracker_plural)%></legend>
|
||||
<% @trackers.each do |tracker| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'project[tracker_ids][]', tracker.id, @project.trackers.include?(tracker) %>
|
||||
|
@ -36,7 +50,7 @@
|
|||
<% end %>
|
||||
|
||||
<% unless @issue_custom_fields.empty? %>
|
||||
<fieldset class="box"><legend><%=l(:label_custom_field_plural)%></legend>
|
||||
<fieldset class="box" id="project_issue_custom_fields"><legend><%=l(:label_custom_field_plural)%></legend>
|
||||
<% @issue_custom_fields.each do |custom_field| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'project[issue_custom_field_ids][]', custom_field.id, (@project.all_issue_custom_fields.include? custom_field), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %>
|
||||
|
@ -46,4 +60,5 @@
|
|||
<%= hidden_field_tag 'project[issue_custom_field_ids][]', '' %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<!--[eoform:project]-->
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
api.array :projects, api_meta(:total_count => @project_count, :offset => @offset, :limit => @limit) do
|
||||
@projects.each do |project|
|
||||
api.project do
|
||||
api.id project.id
|
||||
api.name project.name
|
||||
api.identifier project.identifier
|
||||
api.description project.description
|
||||
api.parent(:id => project.parent_id, :name => project.parent.name) unless project.parent.nil?
|
||||
|
||||
render_api_custom_values project.visible_custom_field_values, api
|
||||
|
||||
api.created_on project.created_on
|
||||
api.updated_on project.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,19 +0,0 @@
|
|||
xml.instruct!
|
||||
xml.projects :type => 'array' do
|
||||
@projects.each do |project|
|
||||
xml.project do
|
||||
xml.id project.id
|
||||
xml.name project.name
|
||||
xml.identifier project.identifier
|
||||
xml.description project.description
|
||||
xml.parent(:id => project.parent_id, :name => project.parent.name) unless project.parent.nil?
|
||||
xml.custom_fields do
|
||||
project.visible_custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end unless project.custom_field_values.empty?
|
||||
xml.created_on project.created_on
|
||||
xml.updated_on project.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,16 +2,6 @@
|
|||
|
||||
<% labelled_tabular_form_for :project, @project, :url => { :action => "create" } do |f| %>
|
||||
<%= render :partial => 'form', :locals => { :f => f } %>
|
||||
|
||||
<fieldset class="box"><legend><%= l(:label_module_plural) %></legend>
|
||||
<% Redmine::AccessControl.available_project_modules.each do |m| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %>
|
||||
<%= l_or_humanize(m, :prefix => "project_module_") %>
|
||||
</label>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<%= javascript_tag "Form.Element.focus('project_name');" %>
|
||||
<% end %>
|
||||
|
|
|
@ -56,8 +56,8 @@
|
|||
<div class="splitcontentright">
|
||||
<% if roles.any? && principals.any? %>
|
||||
<% remote_form_for(:member, @member, :url => {:controller => 'members', :action => 'new', :id => @project}, :method => :post,
|
||||
:loading => "$('member-add-submit').disable()",
|
||||
:complete => "$('member-add-submit').enable()") do |f| %>
|
||||
:loading => '$(\'member-add-submit\').disable();',
|
||||
:complete => 'if($(\'member-add-submit\')) $(\'member-add-submit\').enable();') do |f| %>
|
||||
<fieldset><legend><%=l(:label_member_new)%></legend>
|
||||
|
||||
<p><%= label_tag "principal_search", l(:label_principal_search) %><%= text_field_tag 'principal_search', nil %></p>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<legend><%= l(:text_select_project_modules) %></legend>
|
||||
|
||||
<% Redmine::AccessControl.available_project_modules.each do |m| %>
|
||||
<p><label><%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) -%>
|
||||
<p><label><%= check_box_tag 'enabled_module_names[]', m, @project.module_enabled?(m) -%>
|
||||
<%= l_or_humanize(m, :prefix => "project_module_") %></label></p>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
api.project do
|
||||
api.id @project.id
|
||||
api.name @project.name
|
||||
api.identifier @project.identifier
|
||||
api.description @project.description
|
||||
api.homepage @project.homepage
|
||||
|
||||
render_api_custom_values @project.visible_custom_field_values, api
|
||||
|
||||
api.created_on @project.created_on
|
||||
api.updated_on @project.updated_on
|
||||
|
||||
api.array :trackers do
|
||||
@project.trackers.each do |tracker|
|
||||
api.tracker(:id => tracker.id, :name => tracker.name)
|
||||
end
|
||||
end if include_in_api_response?('trackers')
|
||||
end
|
|
@ -1,23 +0,0 @@
|
|||
xml.instruct!
|
||||
xml.project do
|
||||
xml.id @project.id
|
||||
xml.name @project.name
|
||||
xml.identifier @project.identifier
|
||||
xml.description @project.description
|
||||
xml.homepage @project.homepage
|
||||
|
||||
xml.custom_fields do
|
||||
@project.visible_custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end unless @project.custom_field_values.empty?
|
||||
|
||||
xml.created_on @project.created_on
|
||||
xml.updated_on @project.updated_on
|
||||
|
||||
xml.trackers do
|
||||
@project.trackers.each do |tracker|
|
||||
xml.tracker(:id => tracker.id, :name => tracker.name)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,6 +16,6 @@ dirs.each do |dir|
|
|||
/ <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
|
||||
<% end %>
|
||||
|
||||
<%= "@ #{h revision}" if revision %>
|
||||
<%= "@ #{h format_revision(@changeset)}" if @changeset %>
|
||||
|
||||
<% html_title(with_leading_slash(path)) -%>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</td>
|
||||
<td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
|
||||
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %>
|
||||
<td class="revision"><%= link_to_revision(changeset.revision, @project) if changeset %></td>
|
||||
<td class="revision"><%= link_to_revision(changeset, @project) if changeset %></td>
|
||||
<td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
|
||||
<td class="author"><%= changeset.nil? ? h(entry.lastrev.author.to_s.split('<').first) : changeset.author if entry.lastrev %></td>
|
||||
<td class="comments"><%=h truncate(changeset.comments, :length => 50) unless changeset.nil? %></td>
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<% line_num = 1 %>
|
||||
<% revisions.each do |changeset| %>
|
||||
<tr class="changeset <%= cycle 'odd', 'even' %>">
|
||||
<td class="id"><%= link_to_revision(changeset.revision, project) %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('rev', changeset.revision, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.revision, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td>
|
||||
<td class="id"><%= link_to_revision(changeset, project) %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('rev', changeset.identifier, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td>
|
||||
<td class="committed_on"><%= format_time(changeset.committed_on) %></td>
|
||||
<td class="author"><%=h changeset.author %></td>
|
||||
<td class="comments"><%= textilizable(truncate_at_line_break(changeset.comments)) %></td>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
|
||||
<th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
|
||||
<td class="revision">
|
||||
<%= (revision.identifier ? link_to(format_revision(revision.identifier), :action => 'revision', :id => @project, :rev => revision.identifier) : format_revision(revision.revision)) if revision %></td>
|
||||
<%= (revision.identifier ? link_to_revision(revision, @project) : format_revision(revision)) if revision %></td>
|
||||
<td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
|
||||
<td class="line-code"><pre><%= line %></pre></td>
|
||||
</tr>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<h2><%= l(:label_revision) %> <%= format_revision(@rev_to) + ':' if @rev_to %><%= format_revision(@rev) %> <%=h @path %></h2>
|
||||
<h2><%= l(:label_revision) %> <%= @diff_format_revisions %> <%=h @path %></h2>
|
||||
|
||||
<!-- Choose view type -->
|
||||
<% form_tag({:path => to_path_param(@path)}, :method => 'get') do %>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<div class="contextual">
|
||||
«
|
||||
<% unless @changeset.previous.nil? -%>
|
||||
<%= link_to_revision(@changeset.previous.revision, @project, :text => l(:label_previous)) %>
|
||||
<%= link_to_revision(@changeset.previous, @project, :text => l(:label_previous)) %>
|
||||
<% else -%>
|
||||
<%= l(:label_previous) %>
|
||||
<% end -%>
|
||||
|
|
||||
<% unless @changeset.next.nil? -%>
|
||||
<%= link_to_revision(@changeset.next.revision, @project, :text => l(:label_next)) %>
|
||||
<%= link_to_revision(@changeset.next, @project, :text => l(:label_next)) %>
|
||||
<% else -%>
|
||||
<%= l(:label_next) %>
|
||||
<% end -%>
|
||||
»
|
||||
|
||||
<% form_tag({:controller => 'repositories', :action => 'revision', :id => @project, :rev => nil}, :method => :get) do %>
|
||||
<%= text_field_tag 'rev', @rev[0,8], :size => 8 %>
|
||||
<%= text_field_tag 'rev', @rev, :size => 8 %>
|
||||
<%= submit_tag 'OK', :name => nil %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<h2><%= l(:label_revision) %> <%= format_revision(@changeset.revision) %></h2>
|
||||
<h2><%= l(:label_revision) %> <%= format_revision(@changeset) %></h2>
|
||||
|
||||
<p><% if @changeset.scmid %>ID: <%= @changeset.scmid %><br /><% end %>
|
||||
<span class="author"><%= authoring(@changeset.committed_on, @changeset.author) %></span></p>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<li class="change change-D"><%= l(:label_deleted) %></li>
|
||||
</ul>
|
||||
|
||||
<p><%= link_to(l(:label_view_diff), :action => 'diff', :id => @project, :path => "", :rev => @changeset.revision) if @changeset.changes.any? %></p>
|
||||
<p><%= link_to(l(:label_view_diff), :action => 'diff', :id => @project, :path => "", :rev => @changeset.identifier) if @changeset.changes.any? %></p>
|
||||
|
||||
<div class="changeset-changes">
|
||||
<%= render_changeset_changes %>
|
||||
|
@ -56,4 +56,4 @@
|
|||
<%= stylesheet_link_tag "scm" %>
|
||||
<% end %>
|
||||
|
||||
<% html_title("#{l(:label_revision)} #{@changeset.revision}") -%>
|
||||
<% html_title("#{l(:label_revision)} #{format_revision(@changeset)}") -%>
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
<p><%= setting_select :issue_done_ratio, Issue::DONE_RATIO_OPTIONS.collect {|i| [l("setting_issue_done_ratio_#{i}"), i]} %></p>
|
||||
|
||||
<p><%= setting_text_field :issues_export_limit, :size => 6 %></p>
|
||||
|
||||
<p><%= setting_text_field :gantt_items_limit, :size => 6 %></p>
|
||||
</div>
|
||||
|
||||
<fieldset class="box settings"><legend><%= l(:setting_issue_list_default_columns) %></legend>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<p><%= setting_check_box :plain_text_mail %></p>
|
||||
|
||||
<p><%= setting_select(:default_notification_option, User::MAIL_NOTIFICATION_OPTIONS.collect {|o| [l(o.last), o.first.to_s]}) %></p>
|
||||
<p><%= setting_select(:default_notification_option, User.valid_notification_options.collect {|o| [l(o.last), o.first.to_s]}) %></p>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -31,6 +31,13 @@
|
|||
<%= l(:label_applied_status) %>: <%= setting_select :commit_fix_status_id, [["", 0]] + IssueStatus.find(:all).collect{|status| [status.name, status.id.to_s]}, :label => false %>
|
||||
<%= l(:field_done_ratio) %>: <%= setting_select :commit_fix_done_ratio, (0..10).to_a.collect {|r| ["#{r*10} %", "#{r*10}"] }, :blank => :label_no_change_option, :label => false %>
|
||||
<br /><em><%= l(:text_comma_separated) %></em></p>
|
||||
|
||||
<p><%= setting_check_box :commit_logtime_enabled,
|
||||
:onclick => "if (this.checked) { Form.Element.enable('settings_commit_logtime_activity_id'); } else { Form.Element.disable('settings_commit_logtime_activity_id'); }"%></p>
|
||||
|
||||
<p><%= setting_select :commit_logtime_activity_id,
|
||||
[[l(:label_default), 0]] + TimeEntryActivity.shared.all.collect{|activity| [activity.name, activity.id.to_s]},
|
||||
:disabled => !Setting.commit_logtime_enabled?%></p>
|
||||
</fieldset>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
api.array :time_entries do
|
||||
@entries.each do |time_entry|
|
||||
api.time_entry do
|
||||
api.id time_entry.id
|
||||
api.project(:id => time_entry.project_id, :name => time_entry.project.name) unless time_entry.project.nil?
|
||||
api.issue(:id => time_entry.issue_id) unless time_entry.issue.nil?
|
||||
api.user(:id => time_entry.user_id, :name => time_entry.user.name) unless time_entry.user.nil?
|
||||
api.activity(:id => time_entry.activity_id, :name => time_entry.activity.name) unless time_entry.activity.nil?
|
||||
api.hours time_entry.hours
|
||||
api.comments time_entry.comments
|
||||
api.spent_on time_entry.spent_on
|
||||
api.created_on time_entry.created_on
|
||||
api.updated_on time_entry.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
api.time_entry do
|
||||
api.id @time_entry.id
|
||||
api.project(:id => @time_entry.project_id, :name => @time_entry.project.name) unless @time_entry.project.nil?
|
||||
api.issue(:id => @time_entry.issue_id) unless @time_entry.issue.nil?
|
||||
api.user(:id => @time_entry.user_id, :name => @time_entry.user.name) unless @time_entry.user.nil?
|
||||
api.activity(:id => @time_entry.activity_id, :name => @time_entry.activity.name) unless @time_entry.activity.nil?
|
||||
api.hours @time_entry.hours
|
||||
api.comments @time_entry.comments
|
||||
api.spent_on @time_entry.spent_on
|
||||
api.created_on @time_entry.created_on
|
||||
api.updated_on @time_entry.updated_on
|
||||
end
|
|
@ -25,11 +25,9 @@
|
|||
<p><%= f.select :auth_source_id, ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }), {}, :onchange => "if (this.value=='') {Element.show('password_fields');} else {Element.hide('password_fields');}" %></p>
|
||||
<% end %>
|
||||
<div id="password_fields" style="<%= 'display:none;' if @user.auth_source %>">
|
||||
<p><label for="password"><%=l(:field_password)%><span class="required"> *</span></label>
|
||||
<%= password_field_tag 'password', nil, :size => 25 %><br />
|
||||
<p><%= f.password_field :password, :required => true, :size => 25 %><br />
|
||||
<em><%= l(:text_caracters_minimum, :count => Setting.password_min_length) %></em></p>
|
||||
<p><label for="password_confirmation"><%=l(:field_password_confirmation)%><span class="required"> *</span></label>
|
||||
<%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
|
||||
<p><%= f.password_field :password_confirmation, :required => true, :size => 25 %></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<p>
|
||||
<%= select_tag 'notification_option', options_for_select(@notification_options.collect {|o| [l(o.last), o.first]}, @notification_option.to_sym),
|
||||
:onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
|
||||
<%= select_tag 'user[mail_notification]', options_for_select(user_mail_notification_options(@user), @user.mail_notification),
|
||||
:onchange => 'if (this.value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
|
||||
</p>
|
||||
<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %>
|
||||
<% content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %>
|
||||
<p><% @user.projects.each do |project| %>
|
||||
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
|
||||
<% end %></p>
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
</td>
|
||||
<%= call_hook(:view_users_memberships_table_row, :user => @user, :membership => membership, :roles => roles, :projects => projects )%>
|
||||
</tr>
|
||||
<% end; reset_cycle %>
|
||||
</tbody>
|
||||
<% end; reset_cycle %>
|
||||
</table>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
api.array :users, api_meta(:total_count => @user_count, :offset => @offset, :limit => @limit) do
|
||||
@users.each do |user|
|
||||
api.user do
|
||||
api.id user.id
|
||||
api.login user.login
|
||||
api.firstname user.firstname
|
||||
api.lastname user.lastname
|
||||
api.mail user.mail
|
||||
api.created_on user.created_on
|
||||
api.last_login_on user.last_login_on
|
||||
|
||||
render_api_custom_values user.visible_custom_field_values, api
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
api.user do
|
||||
api.id @user.id
|
||||
api.login @user.login if User.current.admin?
|
||||
api.firstname @user.firstname
|
||||
api.lastname @user.lastname
|
||||
api.mail @user.mail if User.current.admin? || !@user.pref.hide_mail
|
||||
api.created_on @user.created_on
|
||||
api.last_login_on @user.last_login_on
|
||||
|
||||
render_api_custom_values @user.visible_custom_field_values, api
|
||||
|
||||
api.array :memberships do
|
||||
@memberships.each do |membership|
|
||||
api.membership do
|
||||
api.project :id => membership.project.id, :name => membership.project.name
|
||||
api.array :roles do
|
||||
membership.roles.each do |role|
|
||||
api.role :id => role.id, :name => role.name
|
||||
end
|
||||
end
|
||||
end if membership.project
|
||||
end
|
||||
end if include_in_api_response?('memberships') && @memberships
|
||||
end
|
|
@ -5,10 +5,10 @@
|
|||
<h2><%= @page.pretty_title %></h2>
|
||||
|
||||
<p>
|
||||
<%= l(:label_version) %> <%= link_to @diff.content_from.version, :action => 'show', :id => @page.title, :version => @diff.content_from.version %>
|
||||
<%= l(:label_version) %> <%= link_to @diff.content_from.version, :action => 'show', :id => @page.title, :project_id => @page.project, :version => @diff.content_from.version %>
|
||||
<em>(<%= @diff.content_from.author ? @diff.content_from.author.name : "anonyme" %>, <%= format_time(@diff.content_from.updated_on) %>)</em>
|
||||
→
|
||||
<%= l(:label_version) %> <%= link_to @diff.content_to.version, :action => 'show', :id => @page.title, :version => @diff.content_to.version %>/<%= @page.content.version %>
|
||||
<%= l(:label_version) %> <%= link_to @diff.content_to.version, :action => 'show', :id => @page.title, :project_id => @page.project, :version => @diff.content_to.version %>/<%= @page.content.version %>
|
||||
<em>(<%= @diff.content_to.author ? @diff.content_to.author.name : "anonyme" %>, <%= format_time(@diff.content_to.updated_on) %>)</em>
|
||||
</p>
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
<h3><%= l(:label_history) %></h3>
|
||||
|
||||
<% form_tag({:action => "diff"}, :method => :get) do %>
|
||||
<%= hidden_field_tag('project_id', h(@project.to_param)) %>
|
||||
<table class="list">
|
||||
<table class="list wiki-page-versions">
|
||||
<thead><tr>
|
||||
<th>#</th>
|
||||
<th></th>
|
||||
|
@ -18,14 +17,14 @@
|
|||
<% show_diff = @versions.size > 1 %>
|
||||
<% line_num = 1 %>
|
||||
<% @versions.each do |ver| %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<tr class="wiki-page-version <%= cycle("odd", "even") %>">
|
||||
<td class="id"><%= link_to ver.version, :action => 'show', :id => @page.title, :project_id => @page.project, :version => ver.version %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < @versions.size) %></td>
|
||||
<td class="checkbox"><%= radio_button_tag('version_from', ver.version, (line_num==2), :id => "cbto-#{line_num}") if show_diff && (line_num > 1) %></td>
|
||||
<td align="center"><%= format_time(ver.updated_on) %></td>
|
||||
<td><%= link_to_user ver.author %></td>
|
||||
<td><%=h ver.comments %></td>
|
||||
<td align="center"><%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %></td>
|
||||
<td class="updated_on"><%= format_time(ver.updated_on) %></td>
|
||||
<td class="author"><%= link_to_user ver.author %></td>
|
||||
<td class="comments"><%=h ver.comments %></td>
|
||||
<td class="buttons"><%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %></td>
|
||||
</tr>
|
||||
<% line_num += 1 %>
|
||||
<% end %>
|
||||
|
|
|
@ -106,5 +106,17 @@ module Rails
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Workaround for #7013 to be removed for 1.2.0
|
||||
# Loads i18n 0.4.2 before Rails loads any more recent gem
|
||||
# 0.5.0 is not compatible with the old interpolation syntax
|
||||
# Plugins will have to migrate to the new syntax for 1.2.0
|
||||
require 'rubygems'
|
||||
begin
|
||||
gem 'i18n', '0.4.2'
|
||||
rescue Gem::LoadError => load_error
|
||||
$stderr.puts %(Missing the i18n 0.4.2 gem. Please `gem install -v=0.4.2 i18n`)
|
||||
exit 1
|
||||
end
|
||||
|
||||
# All that for this:
|
||||
Rails.boot!
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# = Redmine configuration file
|
||||
#
|
||||
# Each environment has it's own configuration options. If you are only
|
||||
# running in production, only the production block needs to be configured.
|
||||
# Environment specific configuration options override the default ones.
|
||||
#
|
||||
# Note that this file needs to be a valid YAML file.
|
||||
#
|
||||
# == Outgoing email settings (email_delivery setting)
|
||||
#
|
||||
# === Common configurations
|
||||
#
|
||||
# ==== Sendmail command
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :sendmail
|
||||
#
|
||||
# ==== Simple SMTP server at localhost
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "localhost"
|
||||
# port: 25
|
||||
#
|
||||
# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "example.com"
|
||||
# port: 25
|
||||
# authentication: :login
|
||||
# domain: 'foo.com'
|
||||
# user_name: 'myaccount'
|
||||
# password: 'password'
|
||||
#
|
||||
# ==== SMTP server at example.com using PLAIN authentication
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "example.com"
|
||||
# port: 25
|
||||
# authentication: :plain
|
||||
# domain: 'example.com'
|
||||
# user_name: 'myaccount'
|
||||
# password: 'password'
|
||||
#
|
||||
# ==== SMTP server at using TLS (GMail)
|
||||
#
|
||||
# This requires some additional configuration. See the article at:
|
||||
# http://redmineblog.com/articles/setup-redmine-to-send-email-using-gmail/
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# tls: true
|
||||
# address: "smtp.gmail.com"
|
||||
# port: 587
|
||||
# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
|
||||
# authentication: :plain
|
||||
# user_name: "your_email@gmail.com"
|
||||
# password: "your_password"
|
||||
#
|
||||
#
|
||||
# === More configuration options
|
||||
#
|
||||
# See the "Configuration options" at the following website for a list of the
|
||||
# full options allowed:
|
||||
#
|
||||
# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
|
||||
|
||||
|
||||
# default configuration options for all environments
|
||||
default:
|
||||
# Outgoing emails configuration (see examples above)
|
||||
email_delivery:
|
||||
delivery_method: :smtp
|
||||
smtp_settings:
|
||||
address: smtp.example.net
|
||||
port: 25
|
||||
domain: example.net
|
||||
authentication: :login
|
||||
user_name: "redmine@example.net"
|
||||
password: "redmine"
|
||||
|
||||
# Absolute path to the directory where attachments are stored.
|
||||
# The default is the 'files' directory in your Redmine instance.
|
||||
# Your Redmine instance needs to have write permission on this
|
||||
# directory.
|
||||
# Examples:
|
||||
# attachments_storage_path: /var/redmine/files
|
||||
# attachments_storage_path: D:/redmine/files
|
||||
attachments_storage_path:
|
||||
|
||||
# Configuration of the autologin cookie.
|
||||
# autologin_cookie_name: the name of the cookie (default: autologin)
|
||||
# autologin_cookie_path: the cookie path (default: /)
|
||||
# autologin_cookie_secure: true sets the cookie secure flag (default: false)
|
||||
autologin_cookie_name:
|
||||
autologin_cookie_path:
|
||||
autologin_cookie_secure:
|
||||
|
||||
# Configuration of SCM executable command.
|
||||
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
|
||||
# On Windows, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
|
||||
scm_subversion_command: svn # (default: svn)
|
||||
scm_mercurial_command: "\"C:\Program Files\TortoiseHg\hg.exe\"" # (default: hg)
|
||||
scm_git_command: /usr/local/bin/git # (default: git)
|
||||
scm_cvs_command: cvs # (default: cvs)
|
||||
scm_bazaar_command: bzr.exe # (default: bzr)
|
||||
scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
|
||||
|
||||
# specific configuration options for production environment
|
||||
# that overrides the default ones
|
||||
production:
|
||||
|
||||
# specific configuration options for development environment
|
||||
# that overrides the default ones
|
||||
development:
|
|
@ -36,4 +36,4 @@ test_pgsql:
|
|||
|
||||
test_sqlite3:
|
||||
adapter: sqlite3
|
||||
database: db/test.db
|
||||
database: db/test.sqlite3
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
# = Outgoing email settings
|
||||
#
|
||||
# Each environment has it's own configuration options. If you are only
|
||||
# running in production, only the production block needs to be configured.
|
||||
#
|
||||
# == Common configurations
|
||||
#
|
||||
# === Sendmail command
|
||||
#
|
||||
# production:
|
||||
# delivery_method: :sendmail
|
||||
#
|
||||
# === Simple SMTP server at localhost
|
||||
#
|
||||
# production:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "localhost"
|
||||
# port: 25
|
||||
#
|
||||
# === SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
|
||||
#
|
||||
# production:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "example.com"
|
||||
# port: 25
|
||||
# authentication: :login
|
||||
# domain: 'foo.com'
|
||||
# user_name: 'myaccount'
|
||||
# password: 'password'
|
||||
#
|
||||
# === SMTP server at example.com using PLAIN authentication
|
||||
#
|
||||
# production:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: "example.com"
|
||||
# port: 25
|
||||
# authentication: :plain
|
||||
# domain: 'example.com'
|
||||
# user_name: 'myaccount'
|
||||
# password: 'password'
|
||||
#
|
||||
# === SMTP server at using TLS (GMail)
|
||||
#
|
||||
# This requires some additional configuration. See the article at:
|
||||
# http://redmineblog.com/articles/setup-redmine-to-send-email-using-gmail/
|
||||
#
|
||||
# production:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# tls: true
|
||||
# address: "smtp.gmail.com"
|
||||
# port: 587
|
||||
# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
|
||||
# authentication: :plain
|
||||
# user_name: "your_email@gmail.com"
|
||||
# password: "your_password"
|
||||
#
|
||||
#
|
||||
# == More configuration options
|
||||
#
|
||||
# See the "Configuration options" at the following website for a list of the
|
||||
# full options allowed:
|
||||
#
|
||||
# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
|
||||
|
||||
production:
|
||||
delivery_method: :smtp
|
||||
smtp_settings:
|
||||
address: smtp.example.net
|
||||
port: 25
|
||||
domain: example.net
|
||||
authentication: :login
|
||||
user_name: "redmine@example.net"
|
||||
password: "redmine"
|
||||
|
||||
development:
|
||||
delivery_method: :smtp
|
||||
smtp_settings:
|
||||
address: 127.0.0.1
|
||||
port: 25
|
||||
domain: example.net
|
||||
authentication: :login
|
||||
user_name: "redmine@example.net"
|
||||
password: "redmine"
|
|
@ -46,11 +46,12 @@ Rails::Initializer.run do |config|
|
|||
# config.active_record.schema_format = :ruby
|
||||
|
||||
# Deliveries are disabled by default. Do NOT modify this section.
|
||||
# Define your email configuration in email.yml instead.
|
||||
# Define your email configuration in configuration.yml instead.
|
||||
# It will automatically turn deliveries on
|
||||
config.action_mailer.perform_deliveries = false
|
||||
|
||||
config.gem 'rubytree', :lib => 'tree'
|
||||
config.gem 'coderay', :version => '~>0.9.7'
|
||||
|
||||
# Load any local configuration that is kept out of source control
|
||||
# (e.g. gems, patches).
|
||||
|
|
|
@ -86,9 +86,19 @@ module I18n
|
|||
module Base
|
||||
def warn_syntax_deprecation!(*args)
|
||||
return if @skip_syntax_deprecation
|
||||
warn "The {{key}} interpolation syntax in I18n messages is deprecated. Please use %{key} instead.\nDowngrade your i18n gem to 0.3.7 (everything above must be deinstalled) to remove this warning, see http://www.redmine.org/issues/5608 for more information."
|
||||
warn "The {{key}} interpolation syntax in I18n messages is deprecated and will be removed in Redmine 1.2. Please use %{key} instead, see http://www.redmine.org/issues/7013 for more information."
|
||||
@skip_syntax_deprecation = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ActionController
|
||||
module MimeResponds
|
||||
class Responder
|
||||
def api(&block)
|
||||
any(:xml, :json, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
I18n.default_locale = 'en'
|
||||
# Adds fallback to default locale for untranslated strings
|
||||
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
||||
|
||||
require 'redmine'
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Loads action_mailer settings from email.yml
|
||||
# and turns deliveries on if configuration file is found
|
||||
|
||||
filename = File.join(File.dirname(__FILE__), '..', 'email.yml')
|
||||
if File.file?(filename)
|
||||
mailconfig = YAML::load_file(filename)
|
||||
|
||||
if mailconfig.is_a?(Hash) && mailconfig.has_key?(Rails.env)
|
||||
# Enable deliveries
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
|
||||
mailconfig[Rails.env].each do |k, v|
|
||||
v.symbolize_keys! if v.respond_to?(:symbolize_keys!)
|
||||
ActionMailer::Base.send("#{k}=", v)
|
||||
end
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -32,37 +32,37 @@ bs:
|
|||
half_a_minute: "pola minute"
|
||||
less_than_x_seconds:
|
||||
one: "manje od 1 sekunde"
|
||||
other: "manje od {{count}} sekudni"
|
||||
other: "manje od %{count} sekudni"
|
||||
x_seconds:
|
||||
one: "1 sekunda"
|
||||
other: "{{count}} sekundi"
|
||||
other: "%{count} sekundi"
|
||||
less_than_x_minutes:
|
||||
one: "manje od 1 minute"
|
||||
other: "manje od {{count}} minuta"
|
||||
other: "manje od %{count} minuta"
|
||||
x_minutes:
|
||||
one: "1 minuta"
|
||||
other: "{{count}} minuta"
|
||||
other: "%{count} minuta"
|
||||
about_x_hours:
|
||||
one: "oko 1 sahat"
|
||||
other: "oko {{count}} sahata"
|
||||
other: "oko %{count} sahata"
|
||||
x_days:
|
||||
one: "1 dan"
|
||||
other: "{{count}} dana"
|
||||
other: "%{count} dana"
|
||||
about_x_months:
|
||||
one: "oko 1 mjesec"
|
||||
other: "oko {{count}} mjeseci"
|
||||
other: "oko %{count} mjeseci"
|
||||
x_months:
|
||||
one: "1 mjesec"
|
||||
other: "{{count}} mjeseci"
|
||||
other: "%{count} mjeseci"
|
||||
about_x_years:
|
||||
one: "oko 1 godine"
|
||||
other: "oko {{count}} godina"
|
||||
other: "oko %{count} godina"
|
||||
over_x_years:
|
||||
one: "preko 1 godine"
|
||||
other: "preko {{count}} godina"
|
||||
other: "preko %{count} godina"
|
||||
almost_x_years:
|
||||
one: "almost 1 year"
|
||||
other: "almost {{count}} years"
|
||||
other: "almost %{count} years"
|
||||
|
||||
|
||||
number:
|
||||
|
@ -106,6 +106,10 @@ bs:
|
|||
|
||||
activerecord:
|
||||
errors:
|
||||
template:
|
||||
header:
|
||||
one: "1 error prohibited this %{model} from being saved"
|
||||
other: "%{count} errors prohibited this %{model} from being saved"
|
||||
messages:
|
||||
inclusion: "nije uključeno u listu"
|
||||
exclusion: "je rezervisano"
|
||||
|
@ -120,11 +124,11 @@ bs:
|
|||
taken: "već je zauzeto"
|
||||
not_a_number: "nije broj"
|
||||
not_a_date: "nije ispravan datum"
|
||||
greater_than: "mora bit veći od {{count}}"
|
||||
greater_than_or_equal_to: "mora bit veći ili jednak {{count}}"
|
||||
equal_to: "mora biti jednak {{count}}"
|
||||
less_than: "mora biti manji od {{count}}"
|
||||
less_than_or_equal_to: "mora bit manji ili jednak {{count}}"
|
||||
greater_than: "mora bit veći od %{count}"
|
||||
greater_than_or_equal_to: "mora bit veći ili jednak %{count}"
|
||||
equal_to: "mora biti jednak %{count}"
|
||||
less_than: "mora biti manji od %{count}"
|
||||
less_than_or_equal_to: "mora bit manji ili jednak %{count}"
|
||||
odd: "mora biti neparan"
|
||||
even: "mora biti paran"
|
||||
greater_than_start_date: "mora biti veći nego početni datum"
|
||||
|
@ -156,9 +160,9 @@ bs:
|
|||
notice_account_wrong_password: Pogrešna lozinka
|
||||
notice_can_t_change_password: Ovaj nalog koristi eksterni izvor prijavljivanja. Ne mogu da promjenim šifru.
|
||||
notice_default_data_loaded: Podrazumjevana konfiguracija uspječno učitana.
|
||||
notice_email_error: Došlo je do greške pri slanju emaila ({{value}})
|
||||
notice_email_sent: "Email je poslan {{value}}"
|
||||
notice_failed_to_save_issues: "Neuspješno snimanje {{count}} aktivnosti na {{total}} izabrano: {{ids}}."
|
||||
notice_email_error: Došlo je do greške pri slanju emaila (%{value})
|
||||
notice_email_sent: "Email je poslan %{value}"
|
||||
notice_failed_to_save_issues: "Neuspješno snimanje %{count} aktivnosti na %{total} izabrano: %{ids}."
|
||||
notice_feeds_access_key_reseted: Vaš RSS pristup je resetovan.
|
||||
notice_file_not_found: Stranica kojoj pokušavate da pristupite ne postoji ili je uklonjena.
|
||||
notice_locking_conflict: "Konflikt: podaci su izmjenjeni od strane drugog korisnika."
|
||||
|
@ -169,28 +173,28 @@ bs:
|
|||
notice_successful_delete: Brisanje izvršeno.
|
||||
notice_successful_update: Promjene uspješno izvršene.
|
||||
|
||||
error_can_t_load_default_data: "Podrazumjevane postavke se ne mogu učitati {{value}}"
|
||||
error_scm_command_failed: "Desila se greška pri pristupu repozitoriju: {{value}}"
|
||||
error_can_t_load_default_data: "Podrazumjevane postavke se ne mogu učitati %{value}"
|
||||
error_scm_command_failed: "Desila se greška pri pristupu repozitoriju: %{value}"
|
||||
error_scm_not_found: "Unos i/ili revizija ne postoji u repozitoriju."
|
||||
|
||||
error_scm_annotate: "Ova stavka ne postoji ili nije označena."
|
||||
error_issue_not_found_in_project: 'Aktivnost nije nađena ili ne pripada ovom projektu'
|
||||
|
||||
warning_attachments_not_saved: "{{count}} fajl(ovi) ne mogu biti snimljen(i)."
|
||||
warning_attachments_not_saved: "%{count} fajl(ovi) ne mogu biti snimljen(i)."
|
||||
|
||||
mail_subject_lost_password: "Vaša {{value}} lozinka"
|
||||
mail_subject_lost_password: "Vaša %{value} lozinka"
|
||||
mail_body_lost_password: 'Za promjenu lozinke, kliknite na sljedeći link:'
|
||||
mail_subject_register: "Aktivirajte {{value}} vaš korisnički račun"
|
||||
mail_subject_register: "Aktivirajte %{value} vaš korisnički račun"
|
||||
mail_body_register: 'Za aktivaciju vašeg korisničkog računa, kliknite na sljedeći link:'
|
||||
mail_body_account_information_external: "Možete koristiti vaš {{value}} korisnički račun za prijavu na sistem."
|
||||
mail_body_account_information_external: "Možete koristiti vaš %{value} korisnički račun za prijavu na sistem."
|
||||
mail_body_account_information: Informacija o vašem korisničkom računu
|
||||
mail_subject_account_activation_request: "{{value}} zahtjev za aktivaciju korisničkog računa"
|
||||
mail_body_account_activation_request: "Novi korisnik ({{value}}) se registrovao. Korisnički račun čeka vaše odobrenje za aktivaciju:"
|
||||
mail_subject_reminder: "{{count}} aktivnost(i) u kašnjenju u narednim {{days}} danima"
|
||||
mail_body_reminder: "{{count}} aktivnost(i) koje su dodjeljenje vama u narednim {{days}} danima:"
|
||||
mail_subject_account_activation_request: "%{value} zahtjev za aktivaciju korisničkog računa"
|
||||
mail_body_account_activation_request: "Novi korisnik (%{value}) se registrovao. Korisnički račun čeka vaše odobrenje za aktivaciju:"
|
||||
mail_subject_reminder: "%{count} aktivnost(i) u kašnjenju u narednim %{days} danima"
|
||||
mail_body_reminder: "%{count} aktivnost(i) koje su dodjeljenje vama u narednim %{days} danima:"
|
||||
|
||||
gui_validation_error: 1 greška
|
||||
gui_validation_error_plural: "{{count}} grešaka"
|
||||
gui_validation_error_plural: "%{count} grešaka"
|
||||
|
||||
field_name: Ime
|
||||
field_description: Opis
|
||||
|
@ -252,6 +256,7 @@ bs:
|
|||
field_attr_lastname: Atribut za prezime
|
||||
field_attr_mail: Atribut za email
|
||||
field_onthefly: 'Kreiranje korisnika "On-the-fly"'
|
||||
field_start_date: Početak
|
||||
field_done_ratio: % Realizovano
|
||||
field_auth_source: Mod za authentifikaciju
|
||||
field_hide_mail: Sakrij moju email adresu
|
||||
|
@ -391,14 +396,14 @@ bs:
|
|||
label_x_projects:
|
||||
zero: 0 projekata
|
||||
one: 1 projekat
|
||||
other: "{{count}} projekata"
|
||||
other: "%{count} projekata"
|
||||
label_project_all: Svi projekti
|
||||
label_project_latest: Posljednji projekti
|
||||
label_issue: Aktivnost
|
||||
label_issue_new: Nova aktivnost
|
||||
label_issue_plural: Aktivnosti
|
||||
label_issue_view_all: Vidi sve aktivnosti
|
||||
label_issues_by: "Aktivnosti po {{value}}"
|
||||
label_issues_by: "Aktivnosti po %{value}"
|
||||
label_issue_added: Aktivnost je dodana
|
||||
label_issue_updated: Aktivnost je izmjenjena
|
||||
label_document: Dokument
|
||||
|
@ -448,7 +453,7 @@ bs:
|
|||
label_activity_plural: Promjene
|
||||
label_activity: Operacija
|
||||
label_overall_activity: Pregled svih promjena
|
||||
label_user_activity: "Promjene izvršene od: {{value}}"
|
||||
label_user_activity: "Promjene izvršene od: %{value}"
|
||||
label_new: Novi
|
||||
label_logged_as: Prijavljen kao
|
||||
label_environment: Sistemsko okruženje
|
||||
|
@ -457,7 +462,7 @@ bs:
|
|||
label_auth_source_new: Novi mod authentifikacije
|
||||
label_auth_source_plural: Modovi authentifikacije
|
||||
label_subproject_plural: Podprojekti
|
||||
label_and_its_subprojects: "{{value}} i njegovi podprojekti"
|
||||
label_and_its_subprojects: "%{value} i njegovi podprojekti"
|
||||
label_min_max_length: Min - Maks dužina
|
||||
label_list: Lista
|
||||
label_date: Datum
|
||||
|
@ -468,8 +473,8 @@ bs:
|
|||
label_text: Dugi tekst
|
||||
label_attribute: Atribut
|
||||
label_attribute_plural: Atributi
|
||||
label_download: "{{count}} download"
|
||||
label_download_plural: "{{count}} download-i"
|
||||
label_download: "%{count} download"
|
||||
label_download_plural: "%{count} download-i"
|
||||
label_no_data: Nema podataka za prikaz
|
||||
label_change_status: Promjeni status
|
||||
label_history: Istorija
|
||||
|
@ -500,17 +505,17 @@ bs:
|
|||
label_closed_issues: zatvoren
|
||||
label_closed_issues_plural: zatvoreni
|
||||
label_x_open_issues_abbr_on_total:
|
||||
zero: 0 otvoreno / {{total}}
|
||||
one: 1 otvorena / {{total}}
|
||||
other: "{{count}} otvorene / {{total}}"
|
||||
zero: 0 otvoreno / %{total}
|
||||
one: 1 otvorena / %{total}
|
||||
other: "%{count} otvorene / %{total}"
|
||||
label_x_open_issues_abbr:
|
||||
zero: 0 otvoreno
|
||||
one: 1 otvorena
|
||||
other: "{{count}} otvorene"
|
||||
other: "%{count} otvorene"
|
||||
label_x_closed_issues_abbr:
|
||||
zero: 0 zatvoreno
|
||||
one: 1 zatvorena
|
||||
other: "{{count}} zatvorene"
|
||||
other: "%{count} zatvorene"
|
||||
label_total: Ukupno
|
||||
label_permissions: Dozvole
|
||||
label_current_status: Tekući status
|
||||
|
@ -528,7 +533,7 @@ bs:
|
|||
label_months_from: mjeseci od
|
||||
label_gantt: Gantt
|
||||
label_internal: Interno
|
||||
label_last_changes: "posljednjih {{count}} promjena"
|
||||
label_last_changes: "posljednjih %{count} promjena"
|
||||
label_change_view_all: Vidi sve promjene
|
||||
label_personalize_page: Personaliziraj ovu stranicu
|
||||
label_comment: Komentar
|
||||
|
@ -536,7 +541,7 @@ bs:
|
|||
label_x_comments:
|
||||
zero: bez komentara
|
||||
one: 1 komentar
|
||||
other: "{{count}} komentari"
|
||||
other: "%{count} komentari"
|
||||
label_comment_add: Dodaj komentar
|
||||
label_comment_added: Komentar je dodan
|
||||
label_comment_delete: Izbriši komentar
|
||||
|
@ -555,7 +560,7 @@ bs:
|
|||
label_yesterday: juče
|
||||
label_this_week: ova hefta
|
||||
label_last_week: zadnja hefta
|
||||
label_last_n_days: "posljednjih {{count}} dana"
|
||||
label_last_n_days: "posljednjih %{count} dana"
|
||||
label_this_month: ovaj mjesec
|
||||
label_last_month: posljednji mjesec
|
||||
label_this_year: ova godina
|
||||
|
@ -569,8 +574,8 @@ bs:
|
|||
label_repository: Repozitorij
|
||||
label_repository_plural: Repozitoriji
|
||||
label_browse: Listaj
|
||||
label_modification: "{{count}} promjena"
|
||||
label_modification_plural: "{{count}} promjene"
|
||||
label_modification: "%{count} promjena"
|
||||
label_modification_plural: "%{count} promjene"
|
||||
label_revision: Revizija
|
||||
label_revision_plural: Revizije
|
||||
label_associated_revisions: Doddjeljene revizije
|
||||
|
@ -588,8 +593,8 @@ bs:
|
|||
label_sort_lower: Pomjeri dole
|
||||
label_sort_lowest: Pomjeri na dno
|
||||
label_roadmap: Plan realizacije
|
||||
label_roadmap_due_in: "Obavezan do {{value}}"
|
||||
label_roadmap_overdue: "{{value}} kasni"
|
||||
label_roadmap_due_in: "Obavezan do %{value}"
|
||||
label_roadmap_overdue: "%{value} kasni"
|
||||
label_roadmap_no_issues: Nema aktivnosti za ovu verziju
|
||||
label_search: Traži
|
||||
label_result_plural: Rezultati
|
||||
|
@ -607,8 +612,8 @@ bs:
|
|||
label_changes_details: Detalji svih promjena
|
||||
label_issue_tracking: Evidencija aktivnosti
|
||||
label_spent_time: Utrošak vremena
|
||||
label_f_hour: "{{value}} sahat"
|
||||
label_f_hour_plural: "{{value}} sahata"
|
||||
label_f_hour: "%{value} sahat"
|
||||
label_f_hour_plural: "%{value} sahata"
|
||||
label_time_tracking: Evidencija vremena
|
||||
label_change_plural: Promjene
|
||||
label_statistics: Statistika
|
||||
|
@ -657,13 +662,13 @@ bs:
|
|||
label_date_from: Od
|
||||
label_date_to: Do
|
||||
label_language_based: Bazirano na korisnikovom jeziku
|
||||
label_sort_by: "Sortiraj po {{value}}"
|
||||
label_sort_by: "Sortiraj po %{value}"
|
||||
label_send_test_email: Pošalji testni email
|
||||
label_feeds_access_key_created_on: "RSS pristupni ključ kreiran prije {{value}} dana"
|
||||
label_feeds_access_key_created_on: "RSS pristupni ključ kreiran prije %{value} dana"
|
||||
label_module_plural: Moduli
|
||||
label_added_time_by: "Dodano od {{author}} prije {{age}}"
|
||||
label_updated_time_by: "Izmjenjeno od {{author}} prije {{age}}"
|
||||
label_updated_time: "Izmjenjeno prije {{value}}"
|
||||
label_added_time_by: "Dodano od %{author} prije %{age}"
|
||||
label_updated_time_by: "Izmjenjeno od %{author} prije %{age}"
|
||||
label_updated_time: "Izmjenjeno prije %{value}"
|
||||
label_jump_to_a_project: Skoči na projekat...
|
||||
label_file_plural: Fajlovi
|
||||
label_changeset_plural: Setovi promjena
|
||||
|
@ -679,7 +684,7 @@ bs:
|
|||
label_registration_activation_by_email: aktivacija korisničkog računa email-om
|
||||
label_registration_manual_activation: ručna aktivacija korisničkog računa
|
||||
label_registration_automatic_activation: automatska kreacija korisničkog računa
|
||||
label_display_per_page: "Po stranici: {{value}}"
|
||||
label_display_per_page: "Po stranici: %{value}"
|
||||
label_age: Starost
|
||||
label_change_properties: Promjena osobina
|
||||
label_general: Generalno
|
||||
|
@ -745,44 +750,44 @@ bs:
|
|||
text_regexp_info: npr. ^[A-Z0-9]+$
|
||||
text_min_max_length_info: 0 znači bez restrikcije
|
||||
text_project_destroy_confirmation: Sigurno želite izbrisati ovaj projekat i njegove podatke ?
|
||||
text_subprojects_destroy_warning: "Podprojekt(i): {{value}} će takođe biti izbrisani."
|
||||
text_subprojects_destroy_warning: "Podprojekt(i): %{value} će takođe biti izbrisani."
|
||||
text_workflow_edit: Odaberite ulogu i područje aktivnosti za ispravku toka promjena na aktivnosti
|
||||
text_are_you_sure: Da li ste sigurni ?
|
||||
text_tip_issue_begin_day: zadatak počinje danas
|
||||
text_tip_issue_end_day: zadatak završava danas
|
||||
text_tip_issue_begin_end_day: zadatak započinje i završava danas
|
||||
text_project_identifier_info: 'Samo mala slova (a-z), brojevi i crtice su dozvoljeni.<br />Nakon snimanja, identifikator se ne može mijenjati.'
|
||||
text_caracters_maximum: "maksimum {{count}} karaktera."
|
||||
text_caracters_minimum: "Dužina mora biti najmanje {{count}} znakova."
|
||||
text_length_between: "Broj znakova između {{min}} i {{max}}."
|
||||
text_caracters_maximum: "maksimum %{count} karaktera."
|
||||
text_caracters_minimum: "Dužina mora biti najmanje %{count} znakova."
|
||||
text_length_between: "Broj znakova između %{min} i %{max}."
|
||||
text_tracker_no_workflow: Tok statusa nije definisan za ovo područje aktivnosti
|
||||
text_unallowed_characters: Nedozvoljeni znakovi
|
||||
text_comma_separated: Višestruke vrijednosti dozvoljene (odvojiti zarezom).
|
||||
text_issues_ref_in_commit_messages: 'Referenciranje i zatvaranje aktivnosti putem "commit" poruka'
|
||||
text_issue_added: "Aktivnost {{id}} je prijavljena od {{author}}."
|
||||
text_issue_updated: "Aktivnost {{id}} je izmjenjena od {{author}}."
|
||||
text_issue_added: "Aktivnost %{id} je prijavljena od %{author}."
|
||||
text_issue_updated: "Aktivnost %{id} je izmjenjena od %{author}."
|
||||
text_wiki_destroy_confirmation: Sigurno želite izbrisati ovaj wiki i čitav njegov sadržaj ?
|
||||
text_issue_category_destroy_question: "Neke aktivnosti ({{count}}) pripadaju ovoj kategoriji. Sigurno to želite uraditi ?"
|
||||
text_issue_category_destroy_question: "Neke aktivnosti (%{count}) pripadaju ovoj kategoriji. Sigurno to želite uraditi ?"
|
||||
text_issue_category_destroy_assignments: Ukloni kategoriju
|
||||
text_issue_category_reassign_to: Ponovo dodijeli ovu kategoriju
|
||||
text_user_mail_option: "Za projekte koje niste odabrali, primićete samo notifikacije o stavkama koje pratite ili ste u njih uključeni (npr. vi ste autor ili su vama dodjeljenje)."
|
||||
text_no_configuration_data: "Uloge, područja aktivnosti, statusi aktivnosti i tok promjena statusa nisu konfigurisane.\nKrajnje je preporučeno da učitate tekuđe postavke. Kasnije ćete ih moći mjenjati po svojim potrebama."
|
||||
text_load_default_configuration: Učitaj tekuću konfiguraciju
|
||||
text_status_changed_by_changeset: "Primjenjeno u setu promjena {{value}}."
|
||||
text_status_changed_by_changeset: "Primjenjeno u setu promjena %{value}."
|
||||
text_issues_destroy_confirmation: 'Sigurno želite izbrisati odabranu/e aktivnost/i ?'
|
||||
text_select_project_modules: 'Odaberi module koje želite u ovom projektu:'
|
||||
text_default_administrator_account_changed: Tekući administratorski račun je promjenjen
|
||||
text_file_repository_writable: U direktorij sa fajlovima koji su prilozi se može pisati
|
||||
text_plugin_assets_writable: U direktorij plugin-ova se može pisati
|
||||
text_rmagick_available: RMagick je dostupan (opciono)
|
||||
text_destroy_time_entries_question: "{{hours}} sahata je prijavljeno na aktivnostima koje želite brisati. Želite li to učiniti ?"
|
||||
text_destroy_time_entries_question: "%{hours} sahata je prijavljeno na aktivnostima koje želite brisati. Želite li to učiniti ?"
|
||||
text_destroy_time_entries: Izbriši prijavljeno vrijeme
|
||||
text_assign_time_entries_to_project: Dodaj prijavljenoo vrijeme projektu
|
||||
text_reassign_time_entries: 'Preraspodjeli prijavljeno vrijeme na ovu aktivnost:'
|
||||
text_user_wrote: "{{value}} je napisao/la:"
|
||||
text_enumeration_destroy_question: "Za {{count}} objekata je dodjeljenja ova vrijednost."
|
||||
text_user_wrote: "%{value} je napisao/la:"
|
||||
text_enumeration_destroy_question: "Za %{count} objekata je dodjeljenja ova vrijednost."
|
||||
text_enumeration_category_reassign_to: 'Ponovo im dodjeli ovu vrijednost:'
|
||||
text_email_delivery_not_configured: "Email dostava nije konfiguraisana, notifikacija je onemogućena.\nKonfiguriši SMTP server u config/email.yml i restartuj aplikaciju nakon toga."
|
||||
text_email_delivery_not_configured: "Email dostava nije konfiguraisana, notifikacija je onemogućena.\nKonfiguriši SMTP server u config/configuration.yml i restartuj aplikaciju nakon toga."
|
||||
text_repository_usernames_mapping: "Odaberi ili ispravi redmine korisnika mapiranog za svako korisničko ima nađeno u logu repozitorija.\nKorisnici sa istim imenom u redmineu i u repozitoruju se automatski mapiraju."
|
||||
text_diff_truncated: '... Ovaj prikaz razlike je odsječen pošto premašuje maksimalnu veličinu za prikaz'
|
||||
text_custom_field_possible_values_info: 'Jedna linija za svaku vrijednost'
|
||||
|
@ -817,23 +822,23 @@ bs:
|
|||
button_annotate: Zabilježi
|
||||
button_activate: Aktiviraj
|
||||
label_sort: Sortiranje
|
||||
label_date_from_to: Od {{start}} do {{end}}
|
||||
label_date_from_to: Od %{start} do %{end}
|
||||
label_ascending: Rastuće
|
||||
label_descending: Opadajuće
|
||||
label_greater_or_equal: ">="
|
||||
label_less_or_equal: <=
|
||||
text_wiki_page_destroy_question: This page has {{descendants}} child page(s) and descendant(s). What do you want to do?
|
||||
text_wiki_page_destroy_question: This page has %{descendants} child page(s) and descendant(s). What do you want to do?
|
||||
text_wiki_page_reassign_children: Reassign child pages to this parent page
|
||||
text_wiki_page_nullify_children: Keep child pages as root pages
|
||||
text_wiki_page_destroy_children: Delete child pages and all their descendants
|
||||
setting_password_min_length: Minimum password length
|
||||
field_group_by: Group results by
|
||||
mail_subject_wiki_content_updated: "'{{id}}' wiki page has been updated"
|
||||
mail_subject_wiki_content_updated: "'%{id}' wiki page has been updated"
|
||||
label_wiki_content_added: Wiki page added
|
||||
mail_subject_wiki_content_added: "'{{id}}' wiki page has been added"
|
||||
mail_body_wiki_content_added: The '{{id}}' wiki page has been added by {{author}}.
|
||||
mail_subject_wiki_content_added: "'%{id}' wiki page has been added"
|
||||
mail_body_wiki_content_added: The '%{id}' wiki page has been added by %{author}.
|
||||
label_wiki_content_updated: Wiki page updated
|
||||
mail_body_wiki_content_updated: The '{{id}}' wiki page has been updated by {{author}}.
|
||||
mail_body_wiki_content_updated: The '%{id}' wiki page has been updated by %{author}.
|
||||
permission_add_project: Create project
|
||||
setting_new_project_user_role_id: Role given to a non-admin user who creates a project
|
||||
label_view_all_revisions: View all revisions
|
||||
|
@ -841,14 +846,14 @@ bs:
|
|||
label_branch: Branch
|
||||
error_no_tracker_in_project: No tracker is associated to this project. Please check the Project settings.
|
||||
error_no_default_issue_status: No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").
|
||||
text_journal_changed: "{{label}} changed from {{old}} to {{new}}"
|
||||
text_journal_set_to: "{{label}} set to {{value}}"
|
||||
text_journal_deleted: "{{label}} deleted ({{old}})"
|
||||
text_journal_changed: "%{label} changed from %{old} to %{new}"
|
||||
text_journal_set_to: "%{label} set to %{value}"
|
||||
text_journal_deleted: "%{label} deleted (%{old})"
|
||||
label_group_plural: Groups
|
||||
label_group: Group
|
||||
label_group_new: New group
|
||||
label_time_entry_plural: Spent time
|
||||
text_journal_added: "{{label}} {{value}} added"
|
||||
text_journal_added: "%{label} %{value} added"
|
||||
field_active: Active
|
||||
enumeration_system_activity: System Activity
|
||||
permission_delete_issue_watchers: Delete watchers
|
||||
|
@ -883,9 +888,9 @@ bs:
|
|||
setting_start_of_week: Start calendars on
|
||||
permission_view_issues: View Issues
|
||||
label_display_used_statuses_only: Only display statuses that are used by this tracker
|
||||
label_revision_id: Revision {{value}}
|
||||
label_revision_id: Revision %{value}
|
||||
label_api_access_key: API access key
|
||||
label_api_access_key_created_on: API access key created {{value}} ago
|
||||
label_api_access_key_created_on: API access key created %{value} ago
|
||||
label_feeds_access_key: RSS access key
|
||||
notice_api_access_key_reseted: Your API access key was reset.
|
||||
setting_rest_api_enabled: Enable REST web service
|
||||
|
@ -912,12 +917,12 @@ bs:
|
|||
label_subtask_plural: Subtasks
|
||||
label_project_copy_notifications: Send email notifications during the project copy
|
||||
error_can_not_delete_custom_field: Unable to delete custom field
|
||||
error_unable_to_connect: Unable to connect ({{value}})
|
||||
error_unable_to_connect: Unable to connect (%{value})
|
||||
error_can_not_remove_role: This role is in use and can not be deleted.
|
||||
error_can_not_delete_tracker: This tracker contains issues and can't be deleted.
|
||||
field_principal: Principal
|
||||
label_my_page_block: My page block
|
||||
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
|
||||
notice_failed_to_save_members: "Failed to save member(s): %{errors}."
|
||||
text_zoom_out: Zoom out
|
||||
text_zoom_in: Zoom in
|
||||
notice_unable_delete_time_entry: Unable to delete time log entry.
|
||||
|
@ -925,7 +930,7 @@ bs:
|
|||
field_time_entries: Log time
|
||||
project_module_gantt: Gantt
|
||||
project_module_calendar: Calendar
|
||||
button_edit_associated_wikipage: "Edit associated Wiki page: {{page_title}}"
|
||||
button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}"
|
||||
text_are_you_sure_with_children: Delete issue and all child issues?
|
||||
field_text: Text field
|
||||
label_user_mail_option_only_owner: Only for things I am the owner of
|
||||
|
@ -936,8 +941,12 @@ bs:
|
|||
field_member_of_group: Assignee's group
|
||||
field_assigned_to_role: Assignee's role
|
||||
notice_not_authorized_archived_project: The project you're trying to access has been archived.
|
||||
field_start_date: Start date
|
||||
label_principal_search: "Search for user or group:"
|
||||
label_user_search: "Search for user:"
|
||||
field_visible: Visible
|
||||
setting_emails_header: Emails header
|
||||
setting_commit_logtime_activity_id: Activity for logged time
|
||||
text_time_logged_by_changeset: Applied in changeset %{value}.
|
||||
setting_commit_logtime_enabled: Enable time logging
|
||||
notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})
|
||||
setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
|
||||
|
|
|
@ -36,37 +36,37 @@ ca:
|
|||
half_a_minute: "mig minut"
|
||||
less_than_x_seconds:
|
||||
one: "menys d'un segon"
|
||||
other: "menys de {{count}} segons"
|
||||
other: "menys de %{count} segons"
|
||||
x_seconds:
|
||||
one: "1 segons"
|
||||
other: "{{count}} segons"
|
||||
other: "%{count} segons"
|
||||
less_than_x_minutes:
|
||||
one: "menys d'un minut"
|
||||
other: "menys de {{count}} minuts"
|
||||
other: "menys de %{count} minuts"
|
||||
x_minutes:
|
||||
one: "1 minut"
|
||||
other: "{{count}} minuts"
|
||||
other: "%{count} minuts"
|
||||
about_x_hours:
|
||||
one: "aproximadament 1 hora"
|
||||
other: "aproximadament {{count}} hores"
|
||||
other: "aproximadament %{count} hores"
|
||||
x_days:
|
||||
one: "1 dia"
|
||||
other: "{{count}} dies"
|
||||
other: "%{count} dies"
|
||||
about_x_months:
|
||||
one: "aproximadament 1 mes"
|
||||
other: "aproximadament {{count}} mesos"
|
||||
other: "aproximadament %{count} mesos"
|
||||
x_months:
|
||||
one: "1 mes"
|
||||
other: "{{count}} mesos"
|
||||
other: "%{count} mesos"
|
||||
about_x_years:
|
||||
one: "aproximadament 1 any"
|
||||
other: "aproximadament {{count}} anys"
|
||||
other: "aproximadament %{count} anys"
|
||||
over_x_years:
|
||||
one: "més d'un any"
|
||||
other: "més de {{count}} anys"
|
||||
other: "més de %{count} anys"
|
||||
almost_x_years:
|
||||
one: "almost 1 year"
|
||||
other: "almost {{count}} years"
|
||||
other: "almost %{count} years"
|
||||
|
||||
number:
|
||||
# Default format for numbers
|
||||
|
@ -98,6 +98,10 @@ ca:
|
|||
|
||||
activerecord:
|
||||
errors:
|
||||
template:
|
||||
header:
|
||||
one: "1 error prohibited this %{model} from being saved"
|
||||
other: "%{count} errors prohibited this %{model} from being saved"
|
||||
messages:
|
||||
inclusion: "no està inclòs a la llista"
|
||||
exclusion: "està reservat"
|
||||
|
@ -112,11 +116,11 @@ ca:
|
|||
taken: "ja s'està utilitzant"
|
||||
not_a_number: "no és un número"
|
||||
not_a_date: "no és una data vàlida"
|
||||
greater_than: "ha de ser més gran que {{count}}"
|
||||
greater_than_or_equal_to: "ha de ser més gran o igual a {{count}}"
|
||||
equal_to: "ha de ser igual a {{count}}"
|
||||
less_than: "ha de ser menys que {{count}}"
|
||||
less_than_or_equal_to: "ha de ser menys o igual a {{count}}"
|
||||
greater_than: "ha de ser més gran que %{count}"
|
||||
greater_than_or_equal_to: "ha de ser més gran o igual a %{count}"
|
||||
equal_to: "ha de ser igual a %{count}"
|
||||
less_than: "ha de ser menys que %{count}"
|
||||
less_than_or_equal_to: "ha de ser menys o igual a %{count}"
|
||||
odd: "ha de ser senar"
|
||||
even: "ha de ser parell"
|
||||
greater_than_start_date: "ha de ser superior que la data inicial"
|
||||
|
@ -153,12 +157,12 @@ ca:
|
|||
notice_file_not_found: "La pàgina a la que intenteu accedir no existeix o s'ha suprimit."
|
||||
notice_locking_conflict: Un altre usuari ha actualitzat les dades.
|
||||
notice_not_authorized: No teniu permís per a accedir a aquesta pàgina.
|
||||
notice_email_sent: "S'ha enviat un correu electrònic a {{value}}"
|
||||
notice_email_error: "S'ha produït un error en enviar el correu ({{value}})"
|
||||
notice_email_sent: "S'ha enviat un correu electrònic a %{value}"
|
||||
notice_email_error: "S'ha produït un error en enviar el correu (%{value})"
|
||||
notice_feeds_access_key_reseted: "S'ha reiniciat la clau d'accés del RSS."
|
||||
notice_api_access_key_reseted: "S'ha reiniciat la clau d'accés a l'API."
|
||||
notice_failed_to_save_issues: "No s'han pogut desar %s assumptes de {{count}} seleccionats: {{ids}}."
|
||||
notice_failed_to_save_members: "No s'han pogut desar els membres: {{errors}}."
|
||||
notice_failed_to_save_issues: "No s'han pogut desar %s assumptes de %{count} seleccionats: %{ids}."
|
||||
notice_failed_to_save_members: "No s'han pogut desar els membres: %{errors}."
|
||||
notice_no_issue_selected: "No s'ha seleccionat cap assumpte. Activeu els assumptes que voleu editar."
|
||||
notice_account_pending: "S'ha creat el compte i ara està pendent de l'aprovació de l'administrador."
|
||||
notice_default_data_loaded: "S'ha carregat correctament la configuració predeterminada."
|
||||
|
@ -166,9 +170,9 @@ ca:
|
|||
notice_unable_delete_time_entry: "No s'ha pogut suprimir l'entrada del registre de temps."
|
||||
notice_issue_done_ratios_updated: "S'ha actualitzat el tant per cent dels assumptes."
|
||||
|
||||
error_can_t_load_default_data: "No s'ha pogut carregar la configuració predeterminada: {{value}} "
|
||||
error_can_t_load_default_data: "No s'ha pogut carregar la configuració predeterminada: %{value} "
|
||||
error_scm_not_found: "No s'ha trobat l'entrada o la revisió en el dipòsit."
|
||||
error_scm_command_failed: "S'ha produït un error en intentar accedir al dipòsit: {{value}}"
|
||||
error_scm_command_failed: "S'ha produït un error en intentar accedir al dipòsit: %{value}"
|
||||
error_scm_annotate: "L'entrada no existeix o no s'ha pogut anotar."
|
||||
error_issue_not_found_in_project: "No s'ha trobat l'assumpte o no pertany a aquest projecte"
|
||||
error_no_tracker_in_project: "Aquest projecte no té seguidor associat. Comproveu els paràmetres del projecte."
|
||||
|
@ -182,26 +186,26 @@ ca:
|
|||
error_workflow_copy_source: "Seleccioneu un seguidor o rol font"
|
||||
error_workflow_copy_target: "Seleccioneu seguidors i rols objectiu"
|
||||
error_unable_delete_issue_status: "No s'ha pogut suprimir l'estat de l'assumpte"
|
||||
error_unable_to_connect: "No s'ha pogut connectar ({{value}})"
|
||||
warning_attachments_not_saved: "No s'han pogut desar {{count}} fitxers."
|
||||
error_unable_to_connect: "No s'ha pogut connectar (%{value})"
|
||||
warning_attachments_not_saved: "No s'han pogut desar %{count} fitxers."
|
||||
|
||||
mail_subject_lost_password: "Contrasenya de {{value}}"
|
||||
mail_subject_lost_password: "Contrasenya de %{value}"
|
||||
mail_body_lost_password: "Per a canviar la contrasenya, feu clic en l'enllaç següent:"
|
||||
mail_subject_register: "Activació del compte de {{value}}"
|
||||
mail_subject_register: "Activació del compte de %{value}"
|
||||
mail_body_register: "Per a activar el compte, feu clic en l'enllaç següent:"
|
||||
mail_body_account_information_external: "Podeu utilitzar el compte «{{value}}» per a entrar."
|
||||
mail_body_account_information_external: "Podeu utilitzar el compte «%{value}» per a entrar."
|
||||
mail_body_account_information: Informació del compte
|
||||
mail_subject_account_activation_request: "Sol·licitud d'activació del compte de {{value}}"
|
||||
mail_body_account_activation_request: "S'ha registrat un usuari nou ({{value}}). El seu compte està pendent d'aprovació:"
|
||||
mail_subject_reminder: "{{count}} assumptes venceran els següents {{days}} dies"
|
||||
mail_body_reminder: "{{count}} assumptes que teniu assignades venceran els següents {{days}} dies:"
|
||||
mail_subject_wiki_content_added: "S'ha afegit la pàgina wiki «{{id}}»"
|
||||
mail_body_wiki_content_added: "En {{author}} ha afegit la pàgina wiki «{{id}}»."
|
||||
mail_subject_wiki_content_updated: "S'ha actualitzat la pàgina wiki «{{id}}»"
|
||||
mail_body_wiki_content_updated: "En {{author}} ha actualitzat la pàgina wiki «{{id}}»."
|
||||
mail_subject_account_activation_request: "Sol·licitud d'activació del compte de %{value}"
|
||||
mail_body_account_activation_request: "S'ha registrat un usuari nou (%{value}). El seu compte està pendent d'aprovació:"
|
||||
mail_subject_reminder: "%{count} assumptes venceran els següents %{days} dies"
|
||||
mail_body_reminder: "%{count} assumptes que teniu assignades venceran els següents %{days} dies:"
|
||||
mail_subject_wiki_content_added: "S'ha afegit la pàgina wiki «%{id}»"
|
||||
mail_body_wiki_content_added: "En %{author} ha afegit la pàgina wiki «%{id}»."
|
||||
mail_subject_wiki_content_updated: "S'ha actualitzat la pàgina wiki «%{id}»"
|
||||
mail_body_wiki_content_updated: "En %{author} ha actualitzat la pàgina wiki «%{id}»."
|
||||
|
||||
gui_validation_error: 1 error
|
||||
gui_validation_error_plural: "{{count}} errors"
|
||||
gui_validation_error_plural: "%{count} errors"
|
||||
|
||||
field_name: Nom
|
||||
field_description: Descripció
|
||||
|
@ -264,6 +268,7 @@ ca:
|
|||
field_attr_lastname: Atribut del cognom
|
||||
field_attr_mail: Atribut del correu electrònic
|
||||
field_onthefly: "Creació de l'usuari «al vol»"
|
||||
field_start_date: Inici
|
||||
field_done_ratio: % realitzat
|
||||
field_auth_source: "Mode d'autenticació"
|
||||
field_hide_mail: "Oculta l'adreça de correu electrònic"
|
||||
|
@ -427,14 +432,14 @@ ca:
|
|||
label_x_projects:
|
||||
zero: cap projecte
|
||||
one: 1 projecte
|
||||
other: "{{count}} projectes"
|
||||
other: "%{count} projectes"
|
||||
label_project_all: Tots els projectes
|
||||
label_project_latest: Els últims projectes
|
||||
label_issue: Assumpte
|
||||
label_issue_new: Assumpte nou
|
||||
label_issue_plural: Assumptes
|
||||
label_issue_view_all: Visualitza tots els assumptes
|
||||
label_issues_by: "Assumptes per {{value}}"
|
||||
label_issues_by: "Assumptes per %{value}"
|
||||
label_issue_added: Assumpte afegit
|
||||
label_issue_updated: Assumpte actualitzat
|
||||
label_document: Document
|
||||
|
@ -484,7 +489,7 @@ ca:
|
|||
label_registered_on: Informat el
|
||||
label_activity: Activitat
|
||||
label_overall_activity: Activitat global
|
||||
label_user_activity: "Activitat de {{value}}"
|
||||
label_user_activity: "Activitat de %{value}"
|
||||
label_new: Nou
|
||||
label_logged_as: Heu entrat com a
|
||||
label_environment: Entorn
|
||||
|
@ -494,7 +499,7 @@ ca:
|
|||
label_auth_source_plural: "Modes d'autenticació"
|
||||
label_subproject_plural: Subprojectes
|
||||
label_subproject_new: "Subprojecte nou"
|
||||
label_and_its_subprojects: "{{value}} i els seus subprojectes"
|
||||
label_and_its_subprojects: "%{value} i els seus subprojectes"
|
||||
label_min_max_length: Longitud mín - max
|
||||
label_list: Llist
|
||||
label_date: Data
|
||||
|
@ -505,8 +510,8 @@ ca:
|
|||
label_text: Text llarg
|
||||
label_attribute: Atribut
|
||||
label_attribute_plural: Atributs
|
||||
label_download: "{{count}} baixada"
|
||||
label_download_plural: "{{count}} baixades"
|
||||
label_download: "%{count} baixada"
|
||||
label_download_plural: "%{count} baixades"
|
||||
label_no_data: Sense dades a mostrar
|
||||
label_change_status: "Canvia l'estat"
|
||||
label_history: Historial
|
||||
|
@ -538,17 +543,17 @@ ca:
|
|||
label_closed_issues: tancat
|
||||
label_closed_issues_plural: tancats
|
||||
label_x_open_issues_abbr_on_total:
|
||||
zero: 0 oberts / {{total}}
|
||||
one: 1 obert / {{total}}
|
||||
other: "{{count}} oberts / {{total}}"
|
||||
zero: 0 oberts / %{total}
|
||||
one: 1 obert / %{total}
|
||||
other: "%{count} oberts / %{total}"
|
||||
label_x_open_issues_abbr:
|
||||
zero: 0 oberts
|
||||
one: 1 obert
|
||||
other: "{{count}} oberts"
|
||||
other: "%{count} oberts"
|
||||
label_x_closed_issues_abbr:
|
||||
zero: 0 tancats
|
||||
one: 1 tancat
|
||||
other: "{{count}} tancats"
|
||||
other: "%{count} tancats"
|
||||
label_total: Total
|
||||
label_permissions: Permisos
|
||||
label_current_status: Estat actual
|
||||
|
@ -566,7 +571,7 @@ ca:
|
|||
label_months_from: mesos des de
|
||||
label_gantt: Gantt
|
||||
label_internal: Intern
|
||||
label_last_changes: "últims {{count}} canvis"
|
||||
label_last_changes: "últims %{count} canvis"
|
||||
label_change_view_all: Visualitza tots els canvis
|
||||
label_personalize_page: Personalitza aquesta pàgina
|
||||
label_comment: Comentari
|
||||
|
@ -574,7 +579,7 @@ ca:
|
|||
label_x_comments:
|
||||
zero: sense comentaris
|
||||
one: 1 comentari
|
||||
other: "{{count}} comentaris"
|
||||
other: "%{count} comentaris"
|
||||
label_comment_add: Afegeix un comentari
|
||||
label_comment_added: Comentari afegit
|
||||
label_comment_delete: Suprimeix comentaris
|
||||
|
@ -595,7 +600,7 @@ ca:
|
|||
label_yesterday: ahir
|
||||
label_this_week: aquesta setmana
|
||||
label_last_week: "l'última setmana"
|
||||
label_last_n_days: "els últims {{count}} dies"
|
||||
label_last_n_days: "els últims %{count} dies"
|
||||
label_this_month: aquest més
|
||||
label_last_month: "l'últim més"
|
||||
label_this_year: aquest any
|
||||
|
@ -609,13 +614,13 @@ ca:
|
|||
label_repository: Dipòsit
|
||||
label_repository_plural: Dipòsits
|
||||
label_browse: Navega
|
||||
label_modification: "{{count}} canvi"
|
||||
label_modification_plural: "{{count}} canvis"
|
||||
label_modification: "%{count} canvi"
|
||||
label_modification_plural: "%{count} canvis"
|
||||
label_branch: Branca
|
||||
label_tag: Etiqueta
|
||||
label_revision: Revisió
|
||||
label_revision_plural: Revisions
|
||||
label_revision_id: "Revisió {{value}}"
|
||||
label_revision_id: "Revisió %{value}"
|
||||
label_associated_revisions: Revisions associades
|
||||
label_added: afegit
|
||||
label_modified: modificat
|
||||
|
@ -632,8 +637,8 @@ ca:
|
|||
label_sort_lower: Mou cap avall
|
||||
label_sort_lowest: Mou a la part inferior
|
||||
label_roadmap: Planificació
|
||||
label_roadmap_due_in: "Venç en {{value}}"
|
||||
label_roadmap_overdue: "{{value}} tard"
|
||||
label_roadmap_due_in: "Venç en %{value}"
|
||||
label_roadmap_overdue: "%{value} tard"
|
||||
label_roadmap_no_issues: No hi ha assumptes per a aquesta versió
|
||||
label_search: Cerca
|
||||
label_result_plural: Resultats
|
||||
|
@ -652,8 +657,8 @@ ca:
|
|||
label_issue_tracking: "Seguiment d'assumptes"
|
||||
label_spent_time: Temps invertit
|
||||
label_overall_spent_time: "Temps total invertit"
|
||||
label_f_hour: "{{value}} hora"
|
||||
label_f_hour_plural: "{{value}} hores"
|
||||
label_f_hour: "%{value} hora"
|
||||
label_f_hour_plural: "%{value} hores"
|
||||
label_time_tracking: Temps de seguiment
|
||||
label_change_plural: Canvis
|
||||
label_statistics: Estadístiques
|
||||
|
@ -704,15 +709,15 @@ ca:
|
|||
label_date_from: Des de
|
||||
label_date_to: A
|
||||
label_language_based: "Basat en l'idioma de l'usuari"
|
||||
label_sort_by: "Ordena per {{value}}"
|
||||
label_sort_by: "Ordena per %{value}"
|
||||
label_send_test_email: Envia un correu electrònic de prova
|
||||
label_feeds_access_key: "Clau d'accés del RSS"
|
||||
label_missing_feeds_access_key: "Falta una clau d'accés del RSS"
|
||||
label_feeds_access_key_created_on: "Clau d'accés del RSS creada fa {{value}}"
|
||||
label_feeds_access_key_created_on: "Clau d'accés del RSS creada fa %{value}"
|
||||
label_module_plural: Mòduls
|
||||
label_added_time_by: "Afegit per {{author}} fa {{age}}"
|
||||
label_updated_time_by: "Actualitzat per {{author}} fa {{age}}"
|
||||
label_updated_time: "Actualitzat fa {{value}}"
|
||||
label_added_time_by: "Afegit per %{author} fa %{age}"
|
||||
label_updated_time_by: "Actualitzat per %{author} fa %{age}"
|
||||
label_updated_time: "Actualitzat fa %{value}"
|
||||
label_jump_to_a_project: Salta al projecte...
|
||||
label_file_plural: Fitxers
|
||||
label_changeset_plural: Conjunt de canvis
|
||||
|
@ -728,7 +733,7 @@ ca:
|
|||
label_registration_activation_by_email: activació del compte per correu electrònic
|
||||
label_registration_manual_activation: activació del compte manual
|
||||
label_registration_automatic_activation: activació del compte automàtica
|
||||
label_display_per_page: "Per pàgina: {{value}}"
|
||||
label_display_per_page: "Per pàgina: %{value}"
|
||||
label_age: Edat
|
||||
label_change_properties: Canvia les propietats
|
||||
label_general: General
|
||||
|
@ -751,7 +756,7 @@ ca:
|
|||
label_sort: Ordena
|
||||
label_ascending: Ascendent
|
||||
label_descending: Descendent
|
||||
label_date_from_to: Des de {{start}} a {{end}}
|
||||
label_date_from_to: Des de %{start} a %{end}
|
||||
label_wiki_content_added: "S'ha afegit la pàgina wiki"
|
||||
label_wiki_content_updated: "S'ha actualitzat la pàgina wiki"
|
||||
label_group: Grup
|
||||
|
@ -770,7 +775,7 @@ ca:
|
|||
label_display_used_statuses_only: "Mostra només els estats que utilitza aquest seguidor"
|
||||
label_api_access_key: "Clau d'accés a l'API"
|
||||
label_missing_api_access_key: "Falta una clau d'accés de l'API"
|
||||
label_api_access_key_created_on: "Clau d'accés de l'API creada fa {{value}}"
|
||||
label_api_access_key_created_on: "Clau d'accés de l'API creada fa %{value}"
|
||||
label_profile: Perfil
|
||||
label_subtask_plural: Subtasques
|
||||
label_project_copy_notifications: "Envia notificacions de correu electrònic durant la còpia del projecte"
|
||||
|
@ -833,53 +838,53 @@ ca:
|
|||
text_regexp_info: ex. ^[A-Z0-9]+$
|
||||
text_min_max_length_info: 0 significa sense restricció
|
||||
text_project_destroy_confirmation: Segur que voleu suprimir aquest projecte i les dades relacionades?
|
||||
text_subprojects_destroy_warning: "També seran suprimits els seus subprojectes: {{value}}."
|
||||
text_subprojects_destroy_warning: "També seran suprimits els seus subprojectes: %{value}."
|
||||
text_workflow_edit: Seleccioneu un rol i un seguidor per a editar el flux de treball
|
||||
text_are_you_sure: Segur?
|
||||
text_journal_changed: "{{label}} ha canviat de {{old}} a {{new}}"
|
||||
text_journal_set_to: "{{label}} s'ha establert a {{value}}"
|
||||
text_journal_deleted: "{{label}} s'ha suprimit ({{old}})"
|
||||
text_journal_added: "S'ha afegit {{label}} {{value}}"
|
||||
text_journal_changed: "%{label} ha canviat de %{old} a %{new}"
|
||||
text_journal_set_to: "%{label} s'ha establert a %{value}"
|
||||
text_journal_deleted: "%{label} s'ha suprimit (%{old})"
|
||||
text_journal_added: "S'ha afegit %{label} %{value}"
|
||||
text_tip_issue_begin_day: "tasca que s'inicia aquest dia"
|
||||
text_tip_issue_end_day: tasca que finalitza aquest dia
|
||||
text_tip_issue_begin_end_day: "tasca que s'inicia i finalitza aquest dia"
|
||||
text_project_identifier_info: "Es permeten lletres en minúscules (a-z), números i guions.<br />Un cop desat, l'identificador no es pot modificar."
|
||||
text_caracters_maximum: "{{count}} caràcters com a màxim."
|
||||
text_caracters_minimum: "Com a mínim ha de tenir {{count}} caràcters."
|
||||
text_length_between: "Longitud entre {{min}} i {{max}} caràcters."
|
||||
text_caracters_maximum: "%{count} caràcters com a màxim."
|
||||
text_caracters_minimum: "Com a mínim ha de tenir %{count} caràcters."
|
||||
text_length_between: "Longitud entre %{min} i %{max} caràcters."
|
||||
text_tracker_no_workflow: "No s'ha definit cap flux de treball per a aquest seguidor"
|
||||
text_unallowed_characters: Caràcters no permesos
|
||||
text_comma_separated: Es permeten valors múltiples (separats per una coma).
|
||||
text_line_separated: "Es permeten diversos valors (una línia per cada valor)."
|
||||
text_issues_ref_in_commit_messages: Referència i soluciona els assumptes en els missatges publicats
|
||||
text_issue_added: "L'assumpte {{id}} ha sigut informat per {{author}}."
|
||||
text_issue_updated: "L'assumpte {{id}} ha sigut actualitzat per {{author}}."
|
||||
text_issue_added: "L'assumpte %{id} ha sigut informat per %{author}."
|
||||
text_issue_updated: "L'assumpte %{id} ha sigut actualitzat per %{author}."
|
||||
text_wiki_destroy_confirmation: Segur que voleu suprimir aquest wiki i tots els seus continguts?
|
||||
text_issue_category_destroy_question: "Alguns assumptes ({{count}}) estan assignats a aquesta categoria. Què voleu fer?"
|
||||
text_issue_category_destroy_question: "Alguns assumptes (%{count}) estan assignats a aquesta categoria. Què voleu fer?"
|
||||
text_issue_category_destroy_assignments: Suprimeix les assignacions de la categoria
|
||||
text_issue_category_reassign_to: Torna a assignar els assumptes a aquesta categoria
|
||||
text_user_mail_option: "Per als projectes no seleccionats, només rebreu notificacions sobre les coses que vigileu o que hi esteu implicat (ex. assumptes que en sou l'autor o hi esteu assignat)."
|
||||
text_no_configuration_data: "Encara no s'han configurat els rols, seguidors, estats de l'assumpte i flux de treball.\nÉs altament recomanable que carregueu la configuració predeterminada. Podreu modificar-la un cop carregada."
|
||||
text_load_default_configuration: Carrega la configuració predeterminada
|
||||
text_status_changed_by_changeset: "Aplicat en el conjunt de canvis {{value}}."
|
||||
text_status_changed_by_changeset: "Aplicat en el conjunt de canvis %{value}."
|
||||
text_issues_destroy_confirmation: "Segur que voleu suprimir els assumptes seleccionats?"
|
||||
text_select_project_modules: "Seleccioneu els mòduls a habilitar per a aquest projecte:"
|
||||
text_default_administrator_account_changed: "S'ha canviat el compte d'administrador predeterminat"
|
||||
text_file_repository_writable: Es pot escriure en el dipòsit de fitxers
|
||||
text_plugin_assets_writable: Es pot escriure als connectors actius
|
||||
text_rmagick_available: RMagick disponible (opcional)
|
||||
text_destroy_time_entries_question: "S'han informat {{hours}} hores en els assumptes que aneu a suprimir. Què voleu fer?"
|
||||
text_destroy_time_entries_question: "S'han informat %{hours} hores en els assumptes que aneu a suprimir. Què voleu fer?"
|
||||
text_destroy_time_entries: Suprimeix les hores informades
|
||||
text_assign_time_entries_to_project: Assigna les hores informades al projecte
|
||||
text_reassign_time_entries: "Torna a assignar les hores informades a aquest assumpte:"
|
||||
text_user_wrote: "{{value}} va escriure:"
|
||||
text_enumeration_destroy_question: "{{count}} objectes estan assignats a aquest valor."
|
||||
text_user_wrote: "%{value} va escriure:"
|
||||
text_enumeration_destroy_question: "%{count} objectes estan assignats a aquest valor."
|
||||
text_enumeration_category_reassign_to: "Torna a assignar-los a aquest valor:"
|
||||
text_email_delivery_not_configured: "El lliurament per correu electrònic no està configurat i les notificacions estan inhabilitades.\nConfigureu el servidor SMTP a config/email.yml i reinicieu l'aplicació per habilitar-lo."
|
||||
text_email_delivery_not_configured: "El lliurament per correu electrònic no està configurat i les notificacions estan inhabilitades.\nConfigureu el servidor SMTP a config/configuration.yml i reinicieu l'aplicació per habilitar-lo."
|
||||
text_repository_usernames_mapping: "Seleccioneu l'assignació entre els usuaris del Redmine i cada nom d'usuari trobat al dipòsit.\nEls usuaris amb el mateix nom d'usuari o correu del Redmine i del dipòsit s'assignaran automàticament."
|
||||
text_diff_truncated: "... Aquestes diferències s'han trucat perquè excedeixen la mida màxima que es pot mostrar."
|
||||
text_custom_field_possible_values_info: "Una línia per a cada valor"
|
||||
text_wiki_page_destroy_question: "Aquesta pàgina té {{descendants}} pàgines fill i descendents. Què voleu fer?"
|
||||
text_wiki_page_destroy_question: "Aquesta pàgina té %{descendants} pàgines fill i descendents. Què voleu fer?"
|
||||
text_wiki_page_nullify_children: "Deixa les pàgines fill com a pàgines arrel"
|
||||
text_wiki_page_destroy_children: "Suprimeix les pàgines fill i tots els seus descendents"
|
||||
text_wiki_page_reassign_children: "Reasigna les pàgines fill a aquesta pàgina pare"
|
||||
|
@ -914,7 +919,7 @@ ca:
|
|||
enumeration_activities: Activitats (seguidor de temps)
|
||||
enumeration_system_activity: Activitat del sistema
|
||||
|
||||
button_edit_associated_wikipage: "Edit associated Wiki page: {{page_title}}"
|
||||
button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}"
|
||||
text_are_you_sure_with_children: Delete issue and all child issues?
|
||||
field_text: Text field
|
||||
label_user_mail_option_only_owner: Only for things I am the owner of
|
||||
|
@ -925,8 +930,12 @@ ca:
|
|||
field_member_of_group: Assignee's group
|
||||
field_assigned_to_role: Assignee's role
|
||||
notice_not_authorized_archived_project: The project you're trying to access has been archived.
|
||||
field_start_date: Start date
|
||||
label_principal_search: "Search for user or group:"
|
||||
label_user_search: "Search for user:"
|
||||
field_visible: Visible
|
||||
setting_emails_header: Emails header
|
||||
setting_commit_logtime_activity_id: Activity for logged time
|
||||
text_time_logged_by_changeset: Applied in changeset %{value}.
|
||||
setting_commit_logtime_enabled: Enable time logging
|
||||
notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})
|
||||
setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
|
||||
|
|
|
@ -32,37 +32,37 @@ cs:
|
|||
half_a_minute: "půl minuty"
|
||||
less_than_x_seconds:
|
||||
one: "méně než sekunda"
|
||||
other: "méně než {{count}} sekund"
|
||||
other: "méně než %{count} sekund"
|
||||
x_seconds:
|
||||
one: "1 sekunda"
|
||||
other: "{{count}} sekund"
|
||||
other: "%{count} sekund"
|
||||
less_than_x_minutes:
|
||||
one: "méně než minuta"
|
||||
other: "méně než {{count}} minut"
|
||||
other: "méně než %{count} minut"
|
||||
x_minutes:
|
||||
one: "1 minuta"
|
||||
other: "{{count}} minut"
|
||||
other: "%{count} minut"
|
||||
about_x_hours:
|
||||
one: "asi 1 hodina"
|
||||
other: "asi {{count}} hodin"
|
||||
other: "asi %{count} hodin"
|
||||
x_days:
|
||||
one: "1 den"
|
||||
other: "{{count}} dnů"
|
||||
other: "%{count} dnů"
|
||||
about_x_months:
|
||||
one: "asi 1 měsíc"
|
||||
other: "asi {{count}} měsíců"
|
||||
other: "asi %{count} měsíců"
|
||||
x_months:
|
||||
one: "1 měsíc"
|
||||
other: "{{count}} měsíců"
|
||||
other: "%{count} měsíců"
|
||||
about_x_years:
|
||||
one: "asi 1 rok"
|
||||
other: "asi {{count}} let"
|
||||
other: "asi %{count} let"
|
||||
over_x_years:
|
||||
one: "více než 1 rok"
|
||||
other: "více než {{count}} roky"
|
||||
other: "více než %{count} roky"
|
||||
almost_x_years:
|
||||
one: "témeř 1 rok"
|
||||
other: "téměř {{count}} roky"
|
||||
other: "téměř %{count} roky"
|
||||
|
||||
number:
|
||||
format:
|
||||
|
@ -92,6 +92,10 @@ cs:
|
|||
|
||||
activerecord:
|
||||
errors:
|
||||
template:
|
||||
header:
|
||||
one: "1 error prohibited this %{model} from being saved"
|
||||
other: "%{count} errors prohibited this %{model} from being saved"
|
||||
messages:
|
||||
inclusion: "není zahrnuto v seznamu"
|
||||
exclusion: "je rezervováno"
|
||||
|
@ -106,11 +110,11 @@ cs:
|
|||
taken: "je již použito"
|
||||
not_a_number: "není číslo"
|
||||
not_a_date: "není platné datum"
|
||||
greater_than: "musí být větší než {{count}}"
|
||||
greater_than_or_equal_to: "musí být větší nebo rovno {{count}}"
|
||||
equal_to: "musí být přesně {{count}}"
|
||||
less_than: "musí být méně než {{count}}"
|
||||
less_than_or_equal_to: "musí být méně nebo rovno {{count}}"
|
||||
greater_than: "musí být větší než %{count}"
|
||||
greater_than_or_equal_to: "musí být větší nebo rovno %{count}"
|
||||
equal_to: "musí být přesně %{count}"
|
||||
less_than: "musí být méně než %{count}"
|
||||
less_than_or_equal_to: "musí být méně nebo rovno %{count}"
|
||||
odd: "musí být liché"
|
||||
even: "musí být sudé"
|
||||
greater_than_start_date: "musí být větší než počáteční datum"
|
||||
|
@ -152,30 +156,30 @@ cs:
|
|||
notice_locking_conflict: Údaje byly změněny jiným uživatelem.
|
||||
notice_scm_error: Záznam a/nebo revize neexistuje v repozitáři.
|
||||
notice_not_authorized: Nemáte dostatečná práva pro zobrazení této stránky.
|
||||
notice_email_sent: "Na adresu {{value}} byl odeslán email"
|
||||
notice_email_error: "Při odesílání emailu nastala chyba ({{value}})"
|
||||
notice_email_sent: "Na adresu %{value} byl odeslán email"
|
||||
notice_email_error: "Při odesílání emailu nastala chyba (%{value})"
|
||||
notice_feeds_access_key_reseted: Váš klíč pro přístup k RSS byl resetován.
|
||||
notice_failed_to_save_issues: "Chyba při uložení {{count}} úkolu(ů) z {{total}} vybraných: {{ids}}."
|
||||
notice_failed_to_save_issues: "Chyba při uložení %{count} úkolu(ů) z %{total} vybraných: %{ids}."
|
||||
notice_no_issue_selected: "Nebyl zvolen žádný úkol. Prosím, zvolte úkoly, které chcete editovat"
|
||||
notice_account_pending: "Váš účet byl vytvořen, nyní čeká na schválení administrátorem."
|
||||
notice_default_data_loaded: Výchozí konfigurace úspěšně nahrána.
|
||||
|
||||
error_can_t_load_default_data: "Výchozí konfigurace nebyla nahrána: {{value}}"
|
||||
error_can_t_load_default_data: "Výchozí konfigurace nebyla nahrána: %{value}"
|
||||
error_scm_not_found: "Položka a/nebo revize neexistují v repozitáři."
|
||||
error_scm_command_failed: "Při pokusu o přístup k repozitáři došlo k chybě: {{value}}"
|
||||
error_scm_command_failed: "Při pokusu o přístup k repozitáři došlo k chybě: %{value}"
|
||||
error_issue_not_found_in_project: 'Úkol nebyl nalezen nebo nepatří k tomuto projektu'
|
||||
|
||||
mail_subject_lost_password: "Vaše heslo ({{value}})"
|
||||
mail_subject_lost_password: "Vaše heslo (%{value})"
|
||||
mail_body_lost_password: 'Pro změnu vašeho hesla klikněte na následující odkaz:'
|
||||
mail_subject_register: "Aktivace účtu ({{value}})"
|
||||
mail_subject_register: "Aktivace účtu (%{value})"
|
||||
mail_body_register: 'Pro aktivaci vašeho účtu klikněte na následující odkaz:'
|
||||
mail_body_account_information_external: "Pomocí vašeho účtu {{value}} se můžete přihlásit."
|
||||
mail_body_account_information_external: "Pomocí vašeho účtu %{value} se můžete přihlásit."
|
||||
mail_body_account_information: Informace o vašem účtu
|
||||
mail_subject_account_activation_request: "Aktivace {{value}} účtu"
|
||||
mail_body_account_activation_request: "Byl zaregistrován nový uživatel {{value}}. Aktivace jeho účtu závisí na vašem potvrzení."
|
||||
mail_subject_account_activation_request: "Aktivace %{value} účtu"
|
||||
mail_body_account_activation_request: "Byl zaregistrován nový uživatel %{value}. Aktivace jeho účtu závisí na vašem potvrzení."
|
||||
|
||||
gui_validation_error: 1 chyba
|
||||
gui_validation_error_plural: "{{count}} chyb(y)"
|
||||
gui_validation_error_plural: "%{count} chyb(y)"
|
||||
|
||||
field_name: Název
|
||||
field_description: Popis
|
||||
|
@ -237,6 +241,7 @@ cs:
|
|||
field_attr_lastname: Příjemní (atribut)
|
||||
field_attr_mail: Email (atribut)
|
||||
field_onthefly: Automatické vytváření uživatelů
|
||||
field_start_date: Začátek
|
||||
field_done_ratio: % Hotovo
|
||||
field_auth_source: Autentifikační mód
|
||||
field_hide_mail: Nezobrazovat můj email
|
||||
|
@ -310,14 +315,14 @@ cs:
|
|||
label_x_projects:
|
||||
zero: žádné projekty
|
||||
one: 1 projekt
|
||||
other: "{{count}} projekty(ů)"
|
||||
other: "%{count} projekty(ů)"
|
||||
label_project_all: Všechny projekty
|
||||
label_project_latest: Poslední projekty
|
||||
label_issue: Úkol
|
||||
label_issue_new: Nový úkol
|
||||
label_issue_plural: Úkoly
|
||||
label_issue_view_all: Všechny úkoly
|
||||
label_issues_by: "Úkoly podle {{value}}"
|
||||
label_issues_by: "Úkoly podle %{value}"
|
||||
label_issue_added: Úkol přidán
|
||||
label_issue_updated: Úkol aktualizován
|
||||
label_document: Dokument
|
||||
|
@ -383,8 +388,8 @@ cs:
|
|||
label_text: Dlouhý text
|
||||
label_attribute: Atribut
|
||||
label_attribute_plural: Atributy
|
||||
label_download: "{{count}} stažení"
|
||||
label_download_plural: "{{count}} stažení"
|
||||
label_download: "%{count} stažení"
|
||||
label_download_plural: "%{count} stažení"
|
||||
label_no_data: Žádné položky
|
||||
label_change_status: Změnit stav
|
||||
label_history: Historie
|
||||
|
@ -415,17 +420,17 @@ cs:
|
|||
label_closed_issues: uzavřený
|
||||
label_closed_issues_plural: uzavřené
|
||||
label_x_open_issues_abbr_on_total:
|
||||
zero: 0 otevřených / {{total}}
|
||||
one: 1 otevřený / {{total}}
|
||||
other: "{{count}} otevřených / {{total}}"
|
||||
zero: 0 otevřených / %{total}
|
||||
one: 1 otevřený / %{total}
|
||||
other: "%{count} otevřených / %{total}"
|
||||
label_x_open_issues_abbr:
|
||||
zero: 0 otevřených
|
||||
one: 1 otevřený
|
||||
other: "{{count}} otevřených"
|
||||
other: "%{count} otevřených"
|
||||
label_x_closed_issues_abbr:
|
||||
zero: 0 uzavřených
|
||||
one: 1 uzavřený
|
||||
other: "{{count}} uzavřených"
|
||||
other: "%{count} uzavřených"
|
||||
label_total: Celkem
|
||||
label_permissions: Práva
|
||||
label_current_status: Aktuální stav
|
||||
|
@ -443,7 +448,7 @@ cs:
|
|||
label_months_from: měsíců od
|
||||
label_gantt: Ganttův graf
|
||||
label_internal: Interní
|
||||
label_last_changes: "posledních {{count}} změn"
|
||||
label_last_changes: "posledních %{count} změn"
|
||||
label_change_view_all: Zobrazit všechny změny
|
||||
label_personalize_page: Přizpůsobit tuto stránku
|
||||
label_comment: Komentář
|
||||
|
@ -451,7 +456,7 @@ cs:
|
|||
label_x_comments:
|
||||
zero: žádné komentáře
|
||||
one: 1 komentář
|
||||
other: "{{count}} komentářů"
|
||||
other: "%{count} komentářů"
|
||||
label_comment_add: Přidat komentáře
|
||||
label_comment_added: Komentář přidán
|
||||
label_comment_delete: Odstranit komentář
|
||||
|
@ -470,7 +475,7 @@ cs:
|
|||
label_yesterday: včera
|
||||
label_this_week: tento týden
|
||||
label_last_week: minulý týden
|
||||
label_last_n_days: "posledních {{count}} dnů"
|
||||
label_last_n_days: "posledních %{count} dnů"
|
||||
label_this_month: tento měsíc
|
||||
label_last_month: minulý měsíc
|
||||
label_this_year: tento rok
|
||||
|
@ -484,8 +489,8 @@ cs:
|
|||
label_repository: Repozitář
|
||||
label_repository_plural: Repozitáře
|
||||
label_browse: Procházet
|
||||
label_modification: "{{count}} změna"
|
||||
label_modification_plural: "{{count}} změn"
|
||||
label_modification: "%{count} změna"
|
||||
label_modification_plural: "%{count} změn"
|
||||
label_revision: Revize
|
||||
label_revision_plural: Revizí
|
||||
label_associated_revisions: Související verze
|
||||
|
@ -501,8 +506,8 @@ cs:
|
|||
label_sort_lower: Přesunout dolů
|
||||
label_sort_lowest: Přesunout na konec
|
||||
label_roadmap: Plán
|
||||
label_roadmap_due_in: "Zbývá {{value}}"
|
||||
label_roadmap_overdue: "{{value}} pozdě"
|
||||
label_roadmap_due_in: "Zbývá %{value}"
|
||||
label_roadmap_overdue: "%{value} pozdě"
|
||||
label_roadmap_no_issues: Pro tuto verzi nejsou žádné úkoly
|
||||
label_search: Hledat
|
||||
label_result_plural: Výsledky
|
||||
|
@ -520,8 +525,8 @@ cs:
|
|||
label_changes_details: Detail všech změn
|
||||
label_issue_tracking: Sledování úkolů
|
||||
label_spent_time: Strávený čas
|
||||
label_f_hour: "{{value}} hodina"
|
||||
label_f_hour_plural: "{{value}} hodin"
|
||||
label_f_hour: "%{value} hodina"
|
||||
label_f_hour_plural: "%{value} hodin"
|
||||
label_time_tracking: Sledování času
|
||||
label_change_plural: Změny
|
||||
label_statistics: Statistiky
|
||||
|
@ -541,7 +546,7 @@ cs:
|
|||
label_relation_delete: Odstranit souvislost
|
||||
label_relates_to: související s
|
||||
label_duplicates: duplicity
|
||||
label_blocks: bloků
|
||||
label_blocks: blokuje
|
||||
label_blocked_by: zablokován
|
||||
label_precedes: předchází
|
||||
label_follows: následuje
|
||||
|
@ -569,12 +574,12 @@ cs:
|
|||
label_date_from: Od
|
||||
label_date_to: Do
|
||||
label_language_based: Podle výchozího jazyku
|
||||
label_sort_by: "Seřadit podle {{value}}"
|
||||
label_sort_by: "Seřadit podle %{value}"
|
||||
label_send_test_email: Poslat testovací email
|
||||
label_feeds_access_key_created_on: "Přístupový klíč pro RSS byl vytvořen před {{value}}"
|
||||
label_feeds_access_key_created_on: "Přístupový klíč pro RSS byl vytvořen před %{value}"
|
||||
label_module_plural: Moduly
|
||||
label_added_time_by: "Přidáno uživatelem {{author}} před {{age}}"
|
||||
label_updated_time: "Aktualizováno před {{value}}"
|
||||
label_added_time_by: "Přidáno uživatelem %{author} před %{age}"
|
||||
label_updated_time: "Aktualizováno před %{value}"
|
||||
label_jump_to_a_project: Vyberte projekt...
|
||||
label_file_plural: Soubory
|
||||
label_changeset_plural: Changesety
|
||||
|
@ -590,7 +595,7 @@ cs:
|
|||
label_registration_activation_by_email: aktivace účtu emailem
|
||||
label_registration_manual_activation: manuální aktivace účtu
|
||||
label_registration_automatic_activation: automatická aktivace účtu
|
||||
label_display_per_page: "{{value}} na stránku"
|
||||
label_display_per_page: "%{value} na stránku"
|
||||
label_age: Věk
|
||||
label_change_properties: Změnit vlastnosti
|
||||
label_general: Obecné
|
||||
|
@ -657,29 +662,29 @@ cs:
|
|||
text_tip_issue_end_day: úkol končí v tento den
|
||||
text_tip_issue_begin_end_day: úkol začíná a končí v tento den
|
||||
text_project_identifier_info: 'Jsou povolena malá písmena (a-z), čísla a pomlčky.<br />Po uložení již není možné identifikátor změnit.'
|
||||
text_caracters_maximum: "{{count}} znaků maximálně."
|
||||
text_caracters_minimum: "Musí být alespoň {{count}} znaků dlouhé."
|
||||
text_length_between: "Délka mezi {{min}} a {{max}} znaky."
|
||||
text_caracters_maximum: "%{count} znaků maximálně."
|
||||
text_caracters_minimum: "Musí být alespoň %{count} znaků dlouhé."
|
||||
text_length_between: "Délka mezi %{min} a %{max} znaky."
|
||||
text_tracker_no_workflow: Pro tuto frontu není definován žádný průběh práce
|
||||
text_unallowed_characters: Nepovolené znaky
|
||||
text_comma_separated: Povoleno více hodnot (oddělěné čárkou).
|
||||
text_issues_ref_in_commit_messages: Odkazování a opravování úkolů ve zprávách commitů
|
||||
text_issue_added: "Úkol {{id}} byl vytvořen uživatelem {{author}}."
|
||||
text_issue_updated: "Úkol {{id}} byl aktualizován uživatelem {{author}}."
|
||||
text_issue_added: "Úkol %{id} byl vytvořen uživatelem %{author}."
|
||||
text_issue_updated: "Úkol %{id} byl aktualizován uživatelem %{author}."
|
||||
text_wiki_destroy_confirmation: Opravdu si přejete odstranit tuto Wiki a celý její obsah?
|
||||
text_issue_category_destroy_question: "Některé úkoly ({{count}}) jsou přiřazeny k této kategorii. Co s nimi chtete udělat?"
|
||||
text_issue_category_destroy_question: "Některé úkoly (%{count}) jsou přiřazeny k této kategorii. Co s nimi chtete udělat?"
|
||||
text_issue_category_destroy_assignments: Zrušit přiřazení ke kategorii
|
||||
text_issue_category_reassign_to: Přiřadit úkoly do této kategorie
|
||||
text_user_mail_option: "U projektů, které nebyly vybrány, budete dostávat oznámení pouze o vašich či o sledovaných položkách (např. o položkách jejichž jste autor nebo ke kterým jste přiřazen(a))."
|
||||
text_no_configuration_data: "Role, fronty, stavy úkolů ani průběh práce nebyly zatím nakonfigurovány.\nVelice doporučujeme nahrát výchozí konfiguraci. Po té si můžete vše upravit"
|
||||
text_load_default_configuration: Nahrát výchozí konfiguraci
|
||||
text_status_changed_by_changeset: "Použito v changesetu {{value}}."
|
||||
text_status_changed_by_changeset: "Použito v changesetu %{value}."
|
||||
text_issues_destroy_confirmation: 'Opravdu si přejete odstranit všechny zvolené úkoly?'
|
||||
text_select_project_modules: 'Aktivní moduly v tomto projektu:'
|
||||
text_default_administrator_account_changed: Výchozí nastavení administrátorského účtu změněno
|
||||
text_file_repository_writable: Povolen zápis do adresáře ukládání souborů
|
||||
text_rmagick_available: RMagick k dispozici (volitelné)
|
||||
text_destroy_time_entries_question: "U úkolů, které chcete odstranit je evidováno {{hours}} práce. Co chete udělat?"
|
||||
text_destroy_time_entries_question: "U úkolů, které chcete odstranit je evidováno %{hours} práce. Co chete udělat?"
|
||||
text_destroy_time_entries: Odstranit evidované hodiny.
|
||||
text_assign_time_entries_to_project: Přiřadit evidované hodiny projektu
|
||||
text_reassign_time_entries: 'Přeřadit evidované hodiny k tomuto úkolu:'
|
||||
|
@ -711,20 +716,20 @@ cs:
|
|||
enumeration_activities: Aktivity (sledování času)
|
||||
error_scm_annotate: "Položka neexistuje nebo nemůže být komentována."
|
||||
label_planning: Plánování
|
||||
text_subprojects_destroy_warning: "Jeho podprojek(y): {{value}} budou také smazány."
|
||||
label_and_its_subprojects: "{{value}} a jeho podprojekty"
|
||||
mail_body_reminder: "{{count}} úkol(ů), které máte přiřazeny má termín během několik dní ({{days}}):"
|
||||
mail_subject_reminder: "{{count}} úkol(ů) má termín během několik dní ({{days}})"
|
||||
text_user_wrote: "{{value}} napsal:"
|
||||
text_subprojects_destroy_warning: "Jeho podprojek(y): %{value} budou také smazány."
|
||||
label_and_its_subprojects: "%{value} a jeho podprojekty"
|
||||
mail_body_reminder: "%{count} úkol(ů), které máte přiřazeny má termín během několik dní (%{days}):"
|
||||
mail_subject_reminder: "%{count} úkol(ů) má termín během několik dní (%{days})"
|
||||
text_user_wrote: "%{value} napsal:"
|
||||
label_duplicated_by: duplikováno od
|
||||
setting_enabled_scm: Povolené SCM
|
||||
text_enumeration_category_reassign_to: 'Přeřadit je do této:'
|
||||
text_enumeration_destroy_question: "Několik ({{count}}) objektů je přiřazeno k této hodnotě."
|
||||
text_enumeration_destroy_question: "Několik (%{count}) objektů je přiřazeno k této hodnotě."
|
||||
label_incoming_emails: Příchozí e-maily
|
||||
label_generate_key: Generovat klíč
|
||||
setting_mail_handler_api_enabled: Povolit WS pro příchozí e-maily
|
||||
setting_mail_handler_api_key: API klíč
|
||||
text_email_delivery_not_configured: "Doručování e-mailů není nastaveno a odesílání notifikací je zakázáno.\nNastavte Váš SMTP server v souboru config/email.yml a restartujte aplikaci."
|
||||
text_email_delivery_not_configured: "Doručování e-mailů není nastaveno a odesílání notifikací je zakázáno.\nNastavte Váš SMTP server v souboru config/configuration.yml a restartujte aplikaci."
|
||||
field_parent_title: Rodičovská stránka
|
||||
label_issue_watchers: Sledování
|
||||
setting_commit_logs_encoding: Kódování zpráv při commitu
|
||||
|
@ -785,12 +790,12 @@ cs:
|
|||
text_repository_usernames_mapping: "Vybrat nebo upravit mapování mezi Redmine uživateli a uživatelskými jmény nalezenými v logu repozitáře.\nUživatelé se shodným Redmine uživatelským jménem a uživatelským jménem v repozitáři jsou mapovaní automaticky."
|
||||
permission_edit_own_messages: Upravit vlastní zprávy
|
||||
permission_delete_own_messages: Smazat vlastní zprávy
|
||||
label_user_activity: "Aktivita uživatele: {{value}}"
|
||||
label_updated_time_by: "Akutualizováno: {{author}} před: {{age}}"
|
||||
label_user_activity: "Aktivita uživatele: %{value}"
|
||||
label_updated_time_by: "Akutualizováno: %{author} před: %{age}"
|
||||
text_diff_truncated: '... Rozdílový soubor je zkrácen, protože jeho délka přesahuje max. limit.'
|
||||
setting_diff_max_lines_displayed: Maximální počet zobrazenách řádků rozdílů
|
||||
text_plugin_assets_writable: Možnost zápisu do adresáře plugin assets
|
||||
warning_attachments_not_saved: "{{count}} soubor(ů) nebylo možné uložit."
|
||||
warning_attachments_not_saved: "%{count} soubor(ů) nebylo možné uložit."
|
||||
button_create_and_continue: Vytvořit a pokračovat
|
||||
text_custom_field_possible_values_info: 'Každá hodnota na novém řádku'
|
||||
label_display: Zobrazit
|
||||
|
@ -805,21 +810,21 @@ cs:
|
|||
label_descending: Sestupně
|
||||
label_sort: Řazení
|
||||
label_ascending: Vzestupně
|
||||
label_date_from_to: Od {{start}} do {{end}}
|
||||
label_date_from_to: Od %{start} do %{end}
|
||||
label_greater_or_equal: ">="
|
||||
label_less_or_equal: <=
|
||||
text_wiki_page_destroy_question: Tato stránka má {{descendants}} podstránek a potomků. Co chcete udělat?
|
||||
text_wiki_page_destroy_question: Tato stránka má %{descendants} podstránek a potomků. Co chcete udělat?
|
||||
text_wiki_page_reassign_children: Přiřadit podstránky k tomuto rodiči
|
||||
text_wiki_page_nullify_children: Ponechat podstránky jako kořenové stránky
|
||||
text_wiki_page_destroy_children: Smazat podstránky a všechny jejich potomky
|
||||
setting_password_min_length: Minimální délka hesla
|
||||
field_group_by: Seskupovat výsledky podle
|
||||
mail_subject_wiki_content_updated: "'{{id}}' Wiki stránka byla aktualizována"
|
||||
mail_subject_wiki_content_updated: "'%{id}' Wiki stránka byla aktualizována"
|
||||
label_wiki_content_added: Wiki stránka přidána
|
||||
mail_subject_wiki_content_added: "'{{id}}' Wiki stránka byla přidána"
|
||||
mail_body_wiki_content_added: "'{{id}}' Wiki stránka byla přidána od {{author}}."
|
||||
mail_subject_wiki_content_added: "'%{id}' Wiki stránka byla přidána"
|
||||
mail_body_wiki_content_added: "'%{id}' Wiki stránka byla přidána od %{author}."
|
||||
label_wiki_content_updated: Wiki stránka aktualizována
|
||||
mail_body_wiki_content_updated: "'{{id}}' Wiki stránka byla aktualizována od {{author}}."
|
||||
mail_body_wiki_content_updated: "'%{id}' Wiki stránka byla aktualizována od %{author}."
|
||||
permission_add_project: Vytvořit projekt
|
||||
setting_new_project_user_role_id: Role přiřazená uživateli bez práv administrátora, který projekt vytvořil
|
||||
label_view_all_revisions: Zobrazit všechny revize
|
||||
|
@ -827,14 +832,14 @@ cs:
|
|||
label_branch: Branch
|
||||
error_no_tracker_in_project: Žádná fronta nebyla přiřazena tomuto projektu. Prosím zkontroluje nastavení projektu.
|
||||
error_no_default_issue_status: Není nastaven výchozí stav úkolu. Prosím zkontrolujte nastavení ("Administrace -> Stavy úkolů").
|
||||
text_journal_changed: "{{label}} změněn z {{old}} na {{new}}"
|
||||
text_journal_set_to: "{{label}} nastaven na {{value}}"
|
||||
text_journal_deleted: "{{label}} smazán ({{old}})"
|
||||
text_journal_changed: "%{label} změněn z %{old} na %{new}"
|
||||
text_journal_set_to: "%{label} nastaven na %{value}"
|
||||
text_journal_deleted: "%{label} smazán (%{old})"
|
||||
label_group_plural: Skupiny
|
||||
label_group: Skupina
|
||||
label_group_new: Nová skupina
|
||||
label_time_entry_plural: Strávený čas
|
||||
text_journal_added: "{{label}} {{value}} přidán"
|
||||
text_journal_added: "%{label} %{value} přidán"
|
||||
field_active: Aktivní
|
||||
enumeration_system_activity: Systémová aktivita
|
||||
permission_delete_issue_watchers: Smazat přihlížející
|
||||
|
@ -869,9 +874,9 @@ cs:
|
|||
setting_start_of_week: Začínat kalendáře
|
||||
permission_view_issues: Zobrazit úkoly
|
||||
label_display_used_statuses_only: Zobrazit pouze stavy které jsou použité touto frontou
|
||||
label_revision_id: Revize {{value}}
|
||||
label_revision_id: Revize %{value}
|
||||
label_api_access_key: API přístupový klíč
|
||||
label_api_access_key_created_on: API přístupový klíč vytvořen {{value}}
|
||||
label_api_access_key_created_on: API přístupový klíč vytvořen %{value}
|
||||
label_feeds_access_key: RSS přístupový klíč
|
||||
notice_api_access_key_reseted: Váš API přístupový klíč byl resetován.
|
||||
setting_rest_api_enabled: Zapnout službu REST
|
||||
|
@ -898,12 +903,12 @@ cs:
|
|||
label_subtask_plural: Podúkol
|
||||
label_project_copy_notifications: Odeslat email oznámení v průběhu kopie projektu
|
||||
error_can_not_delete_custom_field: Nelze smazat volitelné pole
|
||||
error_unable_to_connect: Nelze se připojit ({{value}})
|
||||
error_unable_to_connect: Nelze se připojit (%{value})
|
||||
error_can_not_remove_role: Tato role je právě používaná a nelze ji smazat.
|
||||
error_can_not_delete_tracker: Tato fronta obsahuje úkoly a nemůže být smazán.
|
||||
field_principal: Hlavní
|
||||
label_my_page_block: Bloky na mé stránce
|
||||
notice_failed_to_save_members: "Nepodařilo se uložit člena(y): {{errors}}."
|
||||
notice_failed_to_save_members: "Nepodařilo se uložit člena(y): %{errors}."
|
||||
text_zoom_out: Oddálit
|
||||
text_zoom_in: Přiblížit
|
||||
notice_unable_delete_time_entry: Nelze smazat čas ze záznamu.
|
||||
|
@ -911,7 +916,7 @@ cs:
|
|||
field_time_entries: Zaznamenaný čas
|
||||
project_module_gantt: Gantt
|
||||
project_module_calendar: Kalendář
|
||||
button_edit_associated_wikipage: "Upravit přiřazenou Wiki stránku: {{page_title}}"
|
||||
button_edit_associated_wikipage: "Upravit přiřazenou Wiki stránku: %{page_title}"
|
||||
text_are_you_sure_with_children: Smazat úkol včetně všech podúkolů?
|
||||
field_text: Textové pole
|
||||
label_user_mail_option_only_owner: Only for things I am the owner of
|
||||
|
@ -922,8 +927,12 @@ cs:
|
|||
field_member_of_group: Assignee's group
|
||||
field_assigned_to_role: Assignee's role
|
||||
notice_not_authorized_archived_project: The project you're trying to access has been archived.
|
||||
field_start_date: Start date
|
||||
label_principal_search: "Search for user or group:"
|
||||
label_user_search: "Search for user:"
|
||||
field_visible: Visible
|
||||
setting_emails_header: Emails header
|
||||
setting_commit_logtime_activity_id: Activity for logged time
|
||||
text_time_logged_by_changeset: Applied in changeset %{value}.
|
||||
setting_commit_logtime_enabled: Enable time logging
|
||||
notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})
|
||||
setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
|
||||
|
|
|
@ -35,37 +35,37 @@ da:
|
|||
half_a_minute: "et halvt minut"
|
||||
less_than_x_seconds:
|
||||
one: "mindre end et sekund"
|
||||
other: "mindre end {{count}} sekunder"
|
||||
other: "mindre end %{count} sekunder"
|
||||
x_seconds:
|
||||
one: "et sekund"
|
||||
other: "{{count}} sekunder"
|
||||
other: "%{count} sekunder"
|
||||
less_than_x_minutes:
|
||||
one: "mindre end et minut"
|
||||
other: "mindre end {{count}} minutter"
|
||||
other: "mindre end %{count} minutter"
|
||||
x_minutes:
|
||||
one: "et minut"
|
||||
other: "{{count}} minutter"
|
||||
other: "%{count} minutter"
|
||||
about_x_hours:
|
||||
one: "cirka en time"
|
||||
other: "cirka {{count}} timer"
|
||||
other: "cirka %{count} timer"
|
||||
x_days:
|
||||
one: "en dag"
|
||||
other: "{{count}} dage"
|
||||
other: "%{count} dage"
|
||||
about_x_months:
|
||||
one: "cirka en måned"
|
||||
other: "cirka {{count}} måneder"
|
||||
other: "cirka %{count} måneder"
|
||||
x_months:
|
||||
one: "en måned"
|
||||
other: "{{count}} måneder"
|
||||
other: "%{count} måneder"
|
||||
about_x_years:
|
||||
one: "cirka et år"
|
||||
other: "cirka {{count}} år"
|
||||
other: "cirka %{count} år"
|
||||
over_x_years:
|
||||
one: "mere end et år"
|
||||
other: "mere end {{count}} år"
|
||||
other: "mere end %{count} år"
|
||||
almost_x_years:
|
||||
one: "næsten 1 år"
|
||||
other: "næsten {{count}} år"
|
||||
other: "næsten %{count} år"
|
||||
|
||||
number:
|
||||
format:
|
||||
|
@ -107,6 +107,10 @@ da:
|
|||
|
||||
activerecord:
|
||||
errors:
|
||||
template:
|
||||
header:
|
||||
one: "1 error prohibited this %{model} from being saved"
|
||||
other: "%{count} errors prohibited this %{model} from being saved"
|
||||
messages:
|
||||
inclusion: "er ikke i listen"
|
||||
exclusion: "er reserveret"
|
||||
|
@ -115,16 +119,16 @@ da:
|
|||
accepted: "skal accepteres"
|
||||
empty: "må ikke udelades"
|
||||
blank: "skal udfyldes"
|
||||
too_long: "er for lang (højst {{count}} tegn)"
|
||||
too_short: "er for kort (mindst {{count}} tegn)"
|
||||
wrong_length: "har forkert længde (skulle være {{count}} tegn)"
|
||||
too_long: "er for lang (højst %{count} tegn)"
|
||||
too_short: "er for kort (mindst %{count} tegn)"
|
||||
wrong_length: "har forkert længde (skulle være %{count} tegn)"
|
||||
taken: "er allerede anvendt"
|
||||
not_a_number: "er ikke et tal"
|
||||
greater_than: "skal være større end {{count}}"
|
||||
greater_than_or_equal_to: "skal være større end eller lig med {{count}}"
|
||||
equal_to: "skal være lig med {{count}}"
|
||||
less_than: "skal være mindre end {{count}}"
|
||||
less_than_or_equal_to: "skal være mindre end eller lig med {{count}}"
|
||||
greater_than: "skal være større end %{count}"
|
||||
greater_than_or_equal_to: "skal være større end eller lig med %{count}"
|
||||
equal_to: "skal være lig med %{count}"
|
||||
less_than: "skal være mindre end %{count}"
|
||||
less_than_or_equal_to: "skal være mindre end eller lig med %{count}"
|
||||
odd: "skal være ulige"
|
||||
even: "skal være lige"
|
||||
greater_than_start_date: "skal være senere end startdatoen"
|
||||
|
@ -134,8 +138,8 @@ da:
|
|||
|
||||
template:
|
||||
header:
|
||||
one: "En fejl forhindrede {{model}} i at blive gemt"
|
||||
other: "{{count}} fejl forhindrede denne {{model}} i at blive gemt"
|
||||
one: "En fejl forhindrede %{model} i at blive gemt"
|
||||
other: "%{count} fejl forhindrede denne %{model} i at blive gemt"
|
||||
body: "Der var problemer med følgende felter:"
|
||||
|
||||
actionview_instancetag_blank_option: Vælg venligst
|
||||
|
@ -166,29 +170,29 @@ da:
|
|||
notice_file_not_found: Siden du forsøger at tilgå eksisterer ikke eller er blevet fjernet.
|
||||
notice_locking_conflict: Data er opdateret af en anden bruger.
|
||||
notice_not_authorized: Du har ikke adgang til denne side.
|
||||
notice_email_sent: "En email er sendt til {{value}}"
|
||||
notice_email_error: "En fejl opstod under afsendelse af email ({{value}})"
|
||||
notice_email_sent: "En email er sendt til %{value}"
|
||||
notice_email_error: "En fejl opstod under afsendelse af email (%{value})"
|
||||
notice_feeds_access_key_reseted: Din adgangsnøgle til RSS er nulstillet.
|
||||
notice_failed_to_save_issues: "Det mislykkedes at gemme {{count}} sage(r) på {{total}} valgt: {{ids}}."
|
||||
notice_failed_to_save_issues: "Det mislykkedes at gemme %{count} sage(r) på %{total} valgt: %{ids}."
|
||||
notice_no_issue_selected: "Ingen sag er valgt! Vælg venligst hvilke emner du vil rette."
|
||||
notice_account_pending: "Din konto er oprettet, og afventer administrators godkendelse."
|
||||
notice_default_data_loaded: Standardopsætningen er indlæst.
|
||||
|
||||
error_can_t_load_default_data: "Standardopsætning kunne ikke indlæses: {{value}}"
|
||||
error_can_t_load_default_data: "Standardopsætning kunne ikke indlæses: %{value}"
|
||||
error_scm_not_found: "Adgang nægtet og/eller revision blev ikke fundet i det valgte repository."
|
||||
error_scm_command_failed: "En fejl opstod under forbindelsen til det valgte repository: {{value}}"
|
||||
error_scm_command_failed: "En fejl opstod under forbindelsen til det valgte repository: %{value}"
|
||||
|
||||
mail_subject_lost_password: "Dit {{value}} kodeord"
|
||||
mail_subject_lost_password: "Dit %{value} kodeord"
|
||||
mail_body_lost_password: 'For at ændre dit kodeord, klik på dette link:'
|
||||
mail_subject_register: "{{value}} kontoaktivering"
|
||||
mail_subject_register: "%{value} kontoaktivering"
|
||||
mail_body_register: 'Klik på dette link for at aktivere din konto:'
|
||||
mail_body_account_information_external: "Du kan bruge din {{value}} konto til at logge ind."
|
||||
mail_body_account_information_external: "Du kan bruge din %{value} konto til at logge ind."
|
||||
mail_body_account_information: Din kontoinformation
|
||||
mail_subject_account_activation_request: "{{value}} kontoaktivering"
|
||||
mail_body_account_activation_request: "En ny bruger ({{value}}) er registreret. Godkend venligst kontoen:"
|
||||
mail_subject_account_activation_request: "%{value} kontoaktivering"
|
||||
mail_body_account_activation_request: "En ny bruger (%{value}) er registreret. Godkend venligst kontoen:"
|
||||
|
||||
gui_validation_error: 1 fejl
|
||||
gui_validation_error_plural: "{{count}} fejl"
|
||||
gui_validation_error_plural: "%{count} fejl"
|
||||
|
||||
field_name: Navn
|
||||
field_description: Beskrivelse
|
||||
|
@ -250,6 +254,7 @@ da:
|
|||
field_attr_lastname: Efternavn attribut
|
||||
field_attr_mail: Email attribut
|
||||
field_onthefly: løbende brugeroprettelse
|
||||
field_start_date: Start date
|
||||
field_done_ratio: % Færdig
|
||||
field_auth_source: Sikkerhedsmetode
|
||||
field_hide_mail: Skjul min email
|
||||
|
@ -318,14 +323,14 @@ da:
|
|||
label_x_projects:
|
||||
zero: Ingen projekter
|
||||
one: 1 projekt
|
||||
other: "{{count}} projekter"
|
||||
other: "%{count} projekter"
|
||||
label_project_all: Alle projekter
|
||||
label_project_latest: Seneste projekter
|
||||
label_issue: Sag
|
||||
label_issue_new: Opret sag
|
||||
label_issue_plural: Sager
|
||||
label_issue_view_all: Vis alle sager
|
||||
label_issues_by: "Sager fra {{value}}"
|
||||
label_issues_by: "Sager fra %{value}"
|
||||
label_issue_added: Sagen er oprettet
|
||||
label_issue_updated: Sagen er opdateret
|
||||
label_document: Dokument
|
||||
|
@ -390,8 +395,8 @@ da:
|
|||
label_text: Lang tekst
|
||||
label_attribute: Attribut
|
||||
label_attribute_plural: Attributter
|
||||
label_download: "{{count}} Download"
|
||||
label_download_plural: "{{count}} Downloads"
|
||||
label_download: "%{count} Download"
|
||||
label_download_plural: "%{count} Downloads"
|
||||
label_no_data: Ingen data at vise
|
||||
label_change_status: Ændringsstatus
|
||||
label_history: Historik
|
||||
|
@ -422,17 +427,17 @@ da:
|
|||
label_closed_issues: lukket
|
||||
label_closed_issues_plural: lukkede
|
||||
label_x_open_issues_abbr_on_total:
|
||||
zero: 0 åbne / {{total}}
|
||||
one: 1 åben / {{total}}
|
||||
other: "{{count}} åbne / {{total}}"
|
||||
zero: 0 åbne / %{total}
|
||||
one: 1 åben / %{total}
|
||||
other: "%{count} åbne / %{total}"
|
||||
label_x_open_issues_abbr:
|
||||
zero: 0 åbne
|
||||
one: 1 åben
|
||||
other: "{{count}} åbne"
|
||||
other: "%{count} åbne"
|
||||
label_x_closed_issues_abbr:
|
||||
zero: 0 lukkede
|
||||
one: 1 lukket
|
||||
other: "{{count}} lukkede"
|
||||
other: "%{count} lukkede"
|
||||
label_total: Total
|
||||
label_permissions: Rettigheder
|
||||
label_current_status: Nuværende status
|
||||
|
@ -450,7 +455,7 @@ da:
|
|||
label_months_from: måneder frem
|
||||
label_gantt: Gantt
|
||||
label_internal: Intern
|
||||
label_last_changes: "sidste {{count}} ændringer"
|
||||
label_last_changes: "sidste %{count} ændringer"
|
||||
label_change_view_all: Vis alle ændringer
|
||||
label_personalize_page: Tilret denne side
|
||||
label_comment: Kommentar
|
||||
|
@ -458,7 +463,7 @@ da:
|
|||
label_x_comments:
|
||||
zero: ingen kommentarer
|
||||
one: 1 kommentar
|
||||
other: "{{count}} kommentarer"
|
||||
other: "%{count} kommentarer"
|
||||
label_comment_add: Tilføj en kommentar
|
||||
label_comment_added: Kommentaren er tilføjet
|
||||
label_comment_delete: Slet kommentar
|
||||
|
@ -477,7 +482,7 @@ da:
|
|||
label_yesterday: i går
|
||||
label_this_week: denne uge
|
||||
label_last_week: sidste uge
|
||||
label_last_n_days: "sidste {{count}} dage"
|
||||
label_last_n_days: "sidste %{count} dage"
|
||||
label_this_month: denne måned
|
||||
label_last_month: sidste måned
|
||||
label_this_year: dette år
|
||||
|
@ -491,8 +496,8 @@ da:
|
|||
label_repository: Repository
|
||||
label_repository_plural: Repositories
|
||||
label_browse: Gennemse
|
||||
label_modification: "{{count}} ændring"
|
||||
label_modification_plural: "{{count}} ændringer"
|
||||
label_modification: "%{count} ændring"
|
||||
label_modification_plural: "%{count} ændringer"
|
||||
label_revision: Revision
|
||||
label_revision_plural: Revisioner
|
||||
label_associated_revisions: Tilnyttede revisioner
|
||||
|
@ -509,7 +514,7 @@ da:
|
|||
label_sort_lowest: Flyt til bunden
|
||||
label_roadmap: Roadmap
|
||||
label_roadmap_due_in: Deadline
|
||||
label_roadmap_overdue: "{{value}} forsinket"
|
||||
label_roadmap_overdue: "%{value} forsinket"
|
||||
label_roadmap_no_issues: Ingen sager i denne version
|
||||
label_search: Søg
|
||||
label_result_plural: Resultater
|
||||
|
@ -527,8 +532,8 @@ da:
|
|||
label_changes_details: Detaljer for alle ændringer
|
||||
label_issue_tracking: Sags søgning
|
||||
label_spent_time: Anvendt tid
|
||||
label_f_hour: "{{value}} time"
|
||||
label_f_hour_plural: "{{value}} timer"
|
||||
label_f_hour: "%{value} time"
|
||||
label_f_hour_plural: "%{value} timer"
|
||||
label_time_tracking: Tidsstyring
|
||||
label_change_plural: Ændringer
|
||||
label_statistics: Statistik
|
||||
|
@ -576,12 +581,12 @@ da:
|
|||
label_date_from: Fra
|
||||
label_date_to: Til
|
||||
label_language_based: Baseret på brugerens sprog
|
||||
label_sort_by: "Sortér efter {{value}}"
|
||||
label_sort_by: "Sortér efter %{value}"
|
||||
label_send_test_email: Send en test email
|
||||
label_feeds_access_key_created_on: "RSS adgangsnøgle dannet for {{value}} siden"
|
||||
label_feeds_access_key_created_on: "RSS adgangsnøgle dannet for %{value} siden"
|
||||
label_module_plural: Moduler
|
||||
label_added_time_by: "Tilføjet af {{author}} for {{age}} siden"
|
||||
label_updated_time: "Opdateret for {{value}} siden"
|
||||
label_added_time_by: "Tilføjet af %{author} for %{age} siden"
|
||||
label_updated_time: "Opdateret for %{value} siden"
|
||||
label_jump_to_a_project: Skift til projekt...
|
||||
label_file_plural: Filer
|
||||
label_changeset_plural: Ændringer
|
||||
|
@ -597,7 +602,7 @@ da:
|
|||
label_registration_activation_by_email: kontoaktivering på email
|
||||
label_registration_manual_activation: manuel kontoaktivering
|
||||
label_registration_automatic_activation: automatisk kontoaktivering
|
||||
label_display_per_page: "Per side: {{value}}"
|
||||
label_display_per_page: "Per side: %{value}"
|
||||
label_age: Alder
|
||||
label_change_properties: Ændre indstillinger
|
||||
label_general: Generelt
|
||||
|
@ -659,23 +664,23 @@ da:
|
|||
text_tip_issue_end_day: opaven slutter denne dag
|
||||
text_tip_issue_begin_end_day: opgaven begynder og slutter denne dag
|
||||
text_project_identifier_info: 'Små bogstaver (a-z), numre og bindestreg er tilladt.<br />Denne er en unik identifikation for projektet, og kan defor ikke rettes senere.'
|
||||
text_caracters_maximum: "max {{count}} karakterer."
|
||||
text_caracters_minimum: "Skal være mindst {{count}} karakterer lang."
|
||||
text_length_between: "Længde skal være mellem {{min}} og {{max}} karakterer."
|
||||
text_caracters_maximum: "max %{count} karakterer."
|
||||
text_caracters_minimum: "Skal være mindst %{count} karakterer lang."
|
||||
text_length_between: "Længde skal være mellem %{min} og %{max} karakterer."
|
||||
text_tracker_no_workflow: Ingen arbejdsgang defineret for denne type
|
||||
text_unallowed_characters: Ikke-tilladte karakterer
|
||||
text_comma_separated: Adskillige værdier tilladt (adskilt med komma).
|
||||
text_issues_ref_in_commit_messages: Referer og løser sager i commit-beskeder
|
||||
text_issue_added: "Sag {{id}} er rapporteret af {{author}}."
|
||||
text_issue_updated: "Sag {{id}} er blevet opdateret af {{author}}."
|
||||
text_issue_added: "Sag %{id} er rapporteret af %{author}."
|
||||
text_issue_updated: "Sag %{id} er blevet opdateret af %{author}."
|
||||
text_wiki_destroy_confirmation: Er du sikker på at du vil slette denne wiki og dens indhold?
|
||||
text_issue_category_destroy_question: "Nogle sager ({{count}}) er tildelt denne kategori. Hvad ønsker du at gøre?"
|
||||
text_issue_category_destroy_question: "Nogle sager (%{count}) er tildelt denne kategori. Hvad ønsker du at gøre?"
|
||||
text_issue_category_destroy_assignments: Slet tildelinger af kategori
|
||||
text_issue_category_reassign_to: Tildel sager til denne kategori
|
||||
text_user_mail_option: "For ikke-valgte projekter vil du kun modtage beskeder omhandlende ting du er involveret i eller overvåger (f.eks. sager du har indberettet eller ejer)."
|
||||
text_no_configuration_data: "Roller, typer, sagsstatuser og arbejdsgange er endnu ikke konfigureret.\nDet er anbefalet at indlæse standardopsætningen. Du vil kunne ændre denne når den er indlæst."
|
||||
text_load_default_configuration: Indlæs standardopsætningen
|
||||
text_status_changed_by_changeset: "Anvendt i ændring {{value}}."
|
||||
text_status_changed_by_changeset: "Anvendt i ændring %{value}."
|
||||
text_issues_destroy_confirmation: 'Er du sikker på du ønsker at slette den/de valgte sag(er)?'
|
||||
text_select_project_modules: 'Vælg moduler er skal være aktiveret for dette projekt:'
|
||||
text_default_administrator_account_changed: Standard administratorkonto ændret
|
||||
|
@ -711,7 +716,7 @@ da:
|
|||
label_add_another_file: Tilføj endnu en fil
|
||||
label_chronological_order: I kronologisk rækkefølge
|
||||
setting_activity_days_default: Antal dage der vises under projektaktivitet
|
||||
text_destroy_time_entries_question: "{{hours}} timer er registreret på denne sag som du er ved at slette. Hvad vil du gøre?"
|
||||
text_destroy_time_entries_question: "%{hours} timer er registreret på denne sag som du er ved at slette. Hvad vil du gøre?"
|
||||
error_issue_not_found_in_project: 'Sagen blev ikke fundet eller tilhører ikke dette projekt'
|
||||
text_assign_time_entries_to_project: Tildel raporterede timer til projektet
|
||||
setting_display_subprojects_issues: Vis sager for underprojekter på hovedprojektet som standard
|
||||
|
@ -725,7 +730,7 @@ da:
|
|||
setting_default_projects_public: Nye projekter er offentlige som standard
|
||||
error_scm_annotate: "Filen findes ikke, eller kunne ikke annoteres."
|
||||
label_planning: Planlægning
|
||||
text_subprojects_destroy_warning: "Dets underprojekter(er): {{value}} vil også blive slettet."
|
||||
text_subprojects_destroy_warning: "Dets underprojekter(er): %{value} vil også blive slettet."
|
||||
permission_edit_issues: Redigér sager
|
||||
setting_diff_max_lines_displayed: Højeste antal forskelle der vises
|
||||
permission_edit_own_issue_notes: Redigér egne noter
|
||||
|
@ -748,11 +753,11 @@ da:
|
|||
setting_sequential_project_identifiers: Generér sekventielle projekt-identifikatorer
|
||||
setting_plain_text_mail: Emails som almindelig tekst (ingen HTML)
|
||||
field_parent_title: Siden over
|
||||
text_email_delivery_not_configured: "Email-afsendelse er ikke indstillet og notifikationer er defor slået fra.\nKonfigurér din SMTP server i config/email.yml og genstart applikationen for at aktivere email-afsendelse."
|
||||
text_email_delivery_not_configured: "Email-afsendelse er ikke indstillet og notifikationer er defor slået fra.\nKonfigurér din SMTP server i config/configuration.yml og genstart applikationen for at aktivere email-afsendelse."
|
||||
permission_protect_wiki_pages: Beskyt wiki sider
|
||||
permission_manage_documents: Administrér dokumenter
|
||||
permission_add_issue_watchers: Tilføj overvågere
|
||||
warning_attachments_not_saved: "der var {{count}} fil(er), som ikke kunne gemmes."
|
||||
warning_attachments_not_saved: "der var %{count} fil(er), som ikke kunne gemmes."
|
||||
permission_comment_news: Kommentér nyheder
|
||||
text_enumeration_category_reassign_to: 'FLyt dem til denne værdi:'
|
||||
permission_select_project_modules: Vælg projektmoduler
|
||||
|
@ -760,7 +765,7 @@ da:
|
|||
permission_delete_messages: Slet beskeder
|
||||
permission_move_issues: Flyt sager
|
||||
permission_edit_wiki_pages: Redigér wiki sider
|
||||
label_user_activity: "{{value}}'s aktivitet"
|
||||
label_user_activity: "%{value}'s aktivitet"
|
||||
permission_manage_issue_relations: Administrér sags-relationer
|
||||
label_issue_watchers: Overvågere
|
||||
permission_delete_wiki_pages: Slet wiki sider
|
||||
|
@ -771,27 +776,27 @@ da:
|
|||
permission_manage_boards: Administrér fora
|
||||
permission_delete_wiki_pages_attachments: Slet filer vedhæftet wiki sider
|
||||
permission_view_messages: Se beskeder
|
||||
text_enumeration_destroy_question: "{{count}} objekter er tildelt denne værdi."
|
||||
text_enumeration_destroy_question: "%{count} objekter er tildelt denne værdi."
|
||||
permission_manage_files: Administrér filer
|
||||
permission_add_messages: Opret beskeder
|
||||
permission_edit_issue_notes: Redigér noter
|
||||
permission_manage_news: Administrér nyheder
|
||||
text_plugin_assets_writable: Der er skriverettigheder til plugin assets folderen
|
||||
label_display: Vis
|
||||
label_and_its_subprojects: "{{value}} og dets underprojekter"
|
||||
label_and_its_subprojects: "%{value} og dets underprojekter"
|
||||
permission_view_calendar: Se kalender
|
||||
button_create_and_continue: Opret og fortsæt
|
||||
setting_gravatar_enabled: Anvend Gravatar bruger ikoner
|
||||
label_updated_time_by: "Opdateret af {{author}} for {{age}} siden"
|
||||
label_updated_time_by: "Opdateret af %{author} for %{age} siden"
|
||||
text_diff_truncated: '... Listen over forskelle er bleve afkortet da den overstiger den maksimale størrelse der kan vises.'
|
||||
text_user_wrote: "{{value}} skrev:"
|
||||
text_user_wrote: "%{value} skrev:"
|
||||
setting_mail_handler_api_enabled: Aktiver webservice for indkomne emails
|
||||
permission_delete_issues: Slet sager
|
||||
permission_view_documents: Se dokumenter
|
||||
permission_browse_repository: Gennemse repository
|
||||
permission_manage_repository: Administrér repository
|
||||
permission_manage_members: Administrér medlemmer
|
||||
mail_subject_reminder: "{{count}} sag(er) har deadline i de kommende dage ({{days}})"
|
||||
mail_subject_reminder: "%{count} sag(er) har deadline i de kommende dage (%{days})"
|
||||
permission_add_issue_notes: Tilføj noter
|
||||
permission_edit_messages: Redigér beskeder
|
||||
permission_view_issue_watchers: Se liste over overvågere
|
||||
|
@ -816,26 +821,26 @@ da:
|
|||
field_identity_url: OpenID URL
|
||||
label_login_with_open_id_option: eller login med OpenID
|
||||
setting_per_page_options: Enheder per side muligheder
|
||||
mail_body_reminder: "{{count}} sage(er) som er tildelt dig har deadline indenfor de næste {{days}} dage:"
|
||||
mail_body_reminder: "%{count} sage(er) som er tildelt dig har deadline indenfor de næste %{days} dage:"
|
||||
field_content: Indhold
|
||||
label_descending: Aftagende
|
||||
label_sort: Sortér
|
||||
label_ascending: Tiltagende
|
||||
label_date_from_to: Fra {{start}} til {{end}}
|
||||
label_date_from_to: Fra %{start} til %{end}
|
||||
label_greater_or_equal: ">="
|
||||
label_less_or_equal: <=
|
||||
text_wiki_page_destroy_question: Denne side har {{descendants}} underside(r) og afledte. Hvad vil du gøre?
|
||||
text_wiki_page_destroy_question: Denne side har %{descendants} underside(r) og afledte. Hvad vil du gøre?
|
||||
text_wiki_page_reassign_children: Flyt undersider til denne side
|
||||
text_wiki_page_nullify_children: Behold undersider som rod-sider
|
||||
text_wiki_page_destroy_children: Slet undersider ogalle deres afledte sider.
|
||||
setting_password_min_length: Mindste længde på kodeord
|
||||
field_group_by: Gruppér resultater efter
|
||||
mail_subject_wiki_content_updated: "'{{id}}' wikisiden er blevet opdateret"
|
||||
mail_subject_wiki_content_updated: "'%{id}' wikisiden er blevet opdateret"
|
||||
label_wiki_content_added: Wiki side tilføjet
|
||||
mail_subject_wiki_content_added: "'{{id}}' wikisiden er blevet tilføjet"
|
||||
mail_body_wiki_content_added: The '{{id}}' wikiside er blevet tilføjet af {{author}}.
|
||||
mail_subject_wiki_content_added: "'%{id}' wikisiden er blevet tilføjet"
|
||||
mail_body_wiki_content_added: The '%{id}' wikiside er blevet tilføjet af %{author}.
|
||||
label_wiki_content_updated: Wikiside opdateret
|
||||
mail_body_wiki_content_updated: Wikisiden '{{id}}' er blevet opdateret af {{author}}.
|
||||
mail_body_wiki_content_updated: Wikisiden '%{id}' er blevet opdateret af %{author}.
|
||||
permission_add_project: Opret projekt
|
||||
setting_new_project_user_role_id: Denne rolle gives til en bruger, som ikke er administrator, og som opretter et projekt
|
||||
label_view_all_revisions: Se alle revisioner
|
||||
|
@ -843,14 +848,14 @@ da:
|
|||
label_branch: Branch
|
||||
error_no_tracker_in_project: Der er ingen sagshåndtering for dette projekt. Kontrollér venligst projektindstillingerne.
|
||||
error_no_default_issue_status: Der er ikek defineret en standardstatus. Kontrollér venligst indstillingernen (Gå til "Administration -> Sagsstatuser").
|
||||
text_journal_changed: "{{label}} ændret fra {{old}} til {{new}}"
|
||||
text_journal_set_to: "{{label}} sat til {{value}}"
|
||||
text_journal_deleted: "{{label}} slettet ({{old}})"
|
||||
text_journal_changed: "%{label} ændret fra %{old} til %{new}"
|
||||
text_journal_set_to: "%{label} sat til %{value}"
|
||||
text_journal_deleted: "%{label} slettet (%{old})"
|
||||
label_group_plural: Grupper
|
||||
label_group: Grupper
|
||||
label_group_new: Ny gruppe
|
||||
label_time_entry_plural: Anvendt tid
|
||||
text_journal_added: "{{label}} {{value}} tilføjet"
|
||||
text_journal_added: "%{label} %{value} tilføjet"
|
||||
field_active: Aktiv
|
||||
enumeration_system_activity: System Aktivitet
|
||||
permission_delete_issue_watchers: Slet overvågere
|
||||
|
@ -885,9 +890,9 @@ da:
|
|||
setting_start_of_week: Start kalendre på
|
||||
permission_view_issues: Vis sager
|
||||
label_display_used_statuses_only: Vis kun statuser der er benyttet af denne tracker
|
||||
label_revision_id: Revision {{value}}
|
||||
label_revision_id: Revision %{value}
|
||||
label_api_access_key: API nøgle
|
||||
label_api_access_key_created_on: API nøgle genereret {{value}} siden
|
||||
label_api_access_key_created_on: API nøgle genereret %{value} siden
|
||||
label_feeds_access_key: RSS nøgle
|
||||
notice_api_access_key_reseted: Din API nøgle er nulstillet.
|
||||
setting_rest_api_enabled: Aktiver REST web service
|
||||
|
@ -914,12 +919,12 @@ da:
|
|||
label_subtask_plural: Under opgaver
|
||||
label_project_copy_notifications: Send email notifikationer, mens projektet kopieres
|
||||
error_can_not_delete_custom_field: Kan ikke slette brugerdefineret felt
|
||||
error_unable_to_connect: Kan ikke forbinde ({{value}})
|
||||
error_unable_to_connect: Kan ikke forbinde (%{value})
|
||||
error_can_not_remove_role: Denne rolle er i brug og kan ikke slettes.
|
||||
error_can_not_delete_tracker: Denne type indeholder sager og kan ikke slettes.
|
||||
field_principal: Principal
|
||||
label_my_page_block: blok
|
||||
notice_failed_to_save_members: "Fejl under lagring af medlem(mer): {{errors}}."
|
||||
notice_failed_to_save_members: "Fejl under lagring af medlem(mer): %{errors}."
|
||||
text_zoom_out: Zoom ud
|
||||
text_zoom_in: Zoom in
|
||||
notice_unable_delete_time_entry: Kan ikke slette tidsregistrering.
|
||||
|
@ -927,7 +932,7 @@ da:
|
|||
field_time_entries: Log tid
|
||||
project_module_gantt: Gantt
|
||||
project_module_calendar: Kalender
|
||||
button_edit_associated_wikipage: "Redigér tilknyttet Wiki side: {{page_title}}"
|
||||
button_edit_associated_wikipage: "Redigér tilknyttet Wiki side: %{page_title}"
|
||||
text_are_you_sure_with_children: Slet sag og alle undersager?
|
||||
field_text: Tekstfelt
|
||||
label_user_mail_option_only_owner: Only for things I am the owner of
|
||||
|
@ -938,8 +943,12 @@ da:
|
|||
field_member_of_group: Medlem af Gruppe
|
||||
field_assigned_to_role: Medlem af Rolle
|
||||
notice_not_authorized_archived_project: The project you're trying to access has been archived.
|
||||
field_start_date: Start date
|
||||
label_principal_search: "Search for user or group:"
|
||||
label_user_search: "Search for user:"
|
||||
field_visible: Visible
|
||||
setting_emails_header: Emails header
|
||||
setting_commit_logtime_activity_id: Activity for logged time
|
||||
text_time_logged_by_changeset: Applied in changeset %{value}.
|
||||
setting_commit_logtime_enabled: Enable time logging
|
||||
notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})
|
||||
setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue