Actualiza a Redmine 3.4.13
This commit is contained in:
parent
807ff3308d
commit
ecddcaf1d3
224 changed files with 2222 additions and 1000 deletions
20
Gemfile
20
Gemfile
|
@ -1,10 +1,8 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
if Gem::Version.new(Bundler::VERSION) < Gem::Version.new('1.5.0')
|
gem "bundler", ">= 1.5.0", "< 2.0.0"
|
||||||
abort "Redmine requires Bundler 1.5.0 or higher (you're using #{Bundler::VERSION}).\nPlease update with 'gem update bundler'."
|
|
||||||
end
|
|
||||||
|
|
||||||
gem "rails", "4.2.8"
|
gem "rails", "4.2.11.1"
|
||||||
gem "addressable", "2.4.0" if RUBY_VERSION < "2.0"
|
gem "addressable", "2.4.0" if RUBY_VERSION < "2.0"
|
||||||
if RUBY_VERSION < "2.1"
|
if RUBY_VERSION < "2.1"
|
||||||
gem "public_suffix", (RUBY_VERSION < "2.0" ? "~> 1.4" : "~> 2.0.5")
|
gem "public_suffix", (RUBY_VERSION < "2.0" ? "~> 1.4" : "~> 2.0.5")
|
||||||
|
@ -23,13 +21,17 @@ gem "mail", "~> 2.6.4"
|
||||||
gem "nokogiri", (RUBY_VERSION >= "2.1" ? "~> 1.8.1" : "~> 1.6.8")
|
gem "nokogiri", (RUBY_VERSION >= "2.1" ? "~> 1.8.1" : "~> 1.6.8")
|
||||||
gem "i18n", "~> 0.7.0"
|
gem "i18n", "~> 0.7.0"
|
||||||
gem "ffi", "1.9.14", :platforms => :mingw if RUBY_VERSION < "2.0"
|
gem "ffi", "1.9.14", :platforms => :mingw if RUBY_VERSION < "2.0"
|
||||||
|
gem "xpath", "< 3.2.0" if RUBY_VERSION < "2.3"
|
||||||
|
|
||||||
# Request at least rails-html-sanitizer 1.0.3 because of security advisories
|
# Request at least rails-html-sanitizer 1.0.3 because of security advisories
|
||||||
gem "rails-html-sanitizer", ">= 1.0.3"
|
gem "rails-html-sanitizer", ">= 1.0.3"
|
||||||
|
|
||||||
|
# TODO: Remove the following line when #32223 is fixed
|
||||||
|
gem "sprockets", "~> 3.7.2"
|
||||||
|
|
||||||
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||||
gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin]
|
gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin]
|
||||||
gem "rbpdf", "~> 1.19.3"
|
gem "rbpdf", "~> 1.19.6"
|
||||||
|
|
||||||
# Optional gem for LDAP authentication
|
# Optional gem for LDAP authentication
|
||||||
group :ldap do
|
group :ldap do
|
||||||
|
@ -38,14 +40,14 @@ end
|
||||||
|
|
||||||
# Optional gem for OpenID authentication
|
# Optional gem for OpenID authentication
|
||||||
group :openid do
|
group :openid do
|
||||||
gem "ruby-openid", "~> 2.3.0", :require => "openid"
|
gem "ruby-openid", "~> 2.9.2", :require => "openid"
|
||||||
gem "rack-openid"
|
gem "rack-openid"
|
||||||
end
|
end
|
||||||
|
|
||||||
platforms :mri, :mingw, :x64_mingw do
|
platforms :mri, :mingw, :x64_mingw do
|
||||||
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
|
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
|
||||||
group :rmagick do
|
group :rmagick do
|
||||||
gem "rmagick", ">= 2.14.0"
|
gem "rmagick", "~> 2.16.0"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Optional Markdown support, not for JRuby
|
# Optional Markdown support, not for JRuby
|
||||||
|
@ -94,12 +96,12 @@ end
|
||||||
group :test do
|
group :test do
|
||||||
gem "minitest"
|
gem "minitest"
|
||||||
gem "rails-dom-testing"
|
gem "rails-dom-testing"
|
||||||
gem "mocha"
|
gem 'mocha', '>= 1.4.0'
|
||||||
gem "simplecov", "~> 0.9.1", :require => false
|
gem "simplecov", "~> 0.9.1", :require => false
|
||||||
# TODO: remove this after upgrading to Rails 5
|
# TODO: remove this after upgrading to Rails 5
|
||||||
gem "test_after_commit", "~> 0.4.2"
|
gem "test_after_commit", "~> 0.4.2"
|
||||||
# For running UI tests
|
# For running UI tests
|
||||||
gem "capybara"
|
gem "capybara", '~> 2.13'
|
||||||
gem "selenium-webdriver", "~> 2.53.4"
|
gem "selenium-webdriver", "~> 2.53.4"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ class AccountController < ApplicationController
|
||||||
@user.must_change_passwd = false
|
@user.must_change_passwd = false
|
||||||
if @user.save
|
if @user.save
|
||||||
@token.destroy
|
@token.destroy
|
||||||
Mailer.password_updated(@user)
|
Mailer.password_updated(@user, { remote_ip: request.remote_ip })
|
||||||
flash[:notice] = l(:notice_account_password_updated)
|
flash[:notice] = l(:notice_account_password_updated)
|
||||||
redirect_to signin_path
|
redirect_to signin_path
|
||||||
return
|
return
|
||||||
|
|
|
@ -60,7 +60,7 @@ class AttachmentsController < ApplicationController
|
||||||
@attachment.increment_download
|
@attachment.increment_download
|
||||||
end
|
end
|
||||||
|
|
||||||
if stale?(:etag => @attachment.digest)
|
if stale?(:etag => @attachment.digest, :template => false)
|
||||||
# images are sent inline
|
# images are sent inline
|
||||||
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
|
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
|
||||||
:type => detect_content_type(@attachment),
|
:type => detect_content_type(@attachment),
|
||||||
|
@ -70,7 +70,7 @@ class AttachmentsController < ApplicationController
|
||||||
|
|
||||||
def thumbnail
|
def thumbnail
|
||||||
if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size])
|
if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size])
|
||||||
if stale?(:etag => tbnail)
|
if stale?(:etag => tbnail, :template => false)
|
||||||
send_file tbnail,
|
send_file tbnail,
|
||||||
:filename => filename_for_content_disposition(@attachment.filename),
|
:filename => filename_for_content_disposition(@attachment.filename),
|
||||||
:type => detect_content_type(@attachment),
|
:type => detect_content_type(@attachment),
|
||||||
|
|
|
@ -19,7 +19,7 @@ class AutoCompletesController < ApplicationController
|
||||||
before_action :find_project
|
before_action :find_project
|
||||||
|
|
||||||
def issues
|
def issues
|
||||||
@issues = []
|
issues = []
|
||||||
q = (params[:q] || params[:term]).to_s.strip
|
q = (params[:q] || params[:term]).to_s.strip
|
||||||
status = params[:status].to_s
|
status = params[:status].to_s
|
||||||
issue_id = params[:issue_id].to_s
|
issue_id = params[:issue_id].to_s
|
||||||
|
@ -32,13 +32,14 @@ class AutoCompletesController < ApplicationController
|
||||||
scope = scope.where.not(:id => issue_id.to_i)
|
scope = scope.where.not(:id => issue_id.to_i)
|
||||||
end
|
end
|
||||||
if q.match(/\A#?(\d+)\z/)
|
if q.match(/\A#?(\d+)\z/)
|
||||||
@issues << scope.find_by_id($1.to_i)
|
issues << scope.find_by_id($1.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
@issues += scope.like(q).order(:id => :desc).limit(10).to_a
|
issues += scope.like(q).order(:id => :desc).limit(10).to_a
|
||||||
@issues.compact!
|
issues.compact!
|
||||||
end
|
end
|
||||||
render :layout => false
|
|
||||||
|
render :json => format_issues_json(issues)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -50,4 +51,13 @@ class AutoCompletesController < ApplicationController
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_issues_json(issues)
|
||||||
|
issues.map {|issue| {
|
||||||
|
'id' => issue.id,
|
||||||
|
'label' => "#{issue.tracker} ##{issue.id}: #{issue.subject.to_s.truncate(60)}",
|
||||||
|
'value' => issue.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,8 +91,10 @@ class EnumerationsController < ApplicationController
|
||||||
|
|
||||||
def build_new_enumeration
|
def build_new_enumeration
|
||||||
class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
|
class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
|
||||||
@enumeration = Enumeration.new_subclass_instance(class_name, enumeration_params)
|
@enumeration = Enumeration.new_subclass_instance(class_name)
|
||||||
if @enumeration.nil?
|
if @enumeration
|
||||||
|
@enumeration.attributes = enumeration_params || {}
|
||||||
|
else
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -105,6 +107,7 @@ class EnumerationsController < ApplicationController
|
||||||
|
|
||||||
def enumeration_params
|
def enumeration_params
|
||||||
# can't require enumeration on #new action
|
# can't require enumeration on #new action
|
||||||
params.permit(:enumeration => [:name, :active, :is_default, :position])[:enumeration]
|
cf_ids = @enumeration.available_custom_fields.map{|c| c.id.to_s}
|
||||||
|
params.permit(:enumeration => [:name, :active, :is_default, :position, :custom_field_values => cf_ids])[:enumeration]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,7 +40,8 @@ class IssuesController < ApplicationController
|
||||||
helper :timelog
|
helper :timelog
|
||||||
|
|
||||||
def index
|
def index
|
||||||
retrieve_query
|
use_session = !request.format.csv?
|
||||||
|
retrieve_query(IssueQuery, use_session)
|
||||||
|
|
||||||
if @query.valid?
|
if @query.valid?
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
@ -367,7 +368,12 @@ class IssuesController < ApplicationController
|
||||||
when 'destroy'
|
when 'destroy'
|
||||||
# nothing to do
|
# nothing to do
|
||||||
when 'nullify'
|
when 'nullify'
|
||||||
|
if Setting.timelog_required_fields.include?('issue_id')
|
||||||
|
flash.now[:error] = l(:field_issue) + " " + ::I18n.t('activerecord.errors.messages.blank')
|
||||||
|
return
|
||||||
|
else
|
||||||
time_entries.update_all(:issue_id => nil)
|
time_entries.update_all(:issue_id => nil)
|
||||||
|
end
|
||||||
when 'reassign'
|
when 'reassign'
|
||||||
reassign_to = @project && @project.issues.find_by_id(params[:reassign_to_id])
|
reassign_to = @project && @project.issues.find_by_id(params[:reassign_to_id])
|
||||||
if reassign_to.nil?
|
if reassign_to.nil?
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SearchController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
# quick jump to an issue
|
# quick jump to an issue
|
||||||
if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
|
if !api_request? && (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
|
||||||
redirect_to issue_path(issue)
|
redirect_to issue_path(issue)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,7 @@ class SearchController < ApplicationController
|
||||||
when 'my_projects'
|
when 'my_projects'
|
||||||
User.current.projects
|
User.current.projects
|
||||||
when 'subprojects'
|
when 'subprojects'
|
||||||
@project ? (@project.self_and_descendants.active.to_a) : nil
|
@project ? (@project.self_and_descendants.to_a) : nil
|
||||||
else
|
else
|
||||||
@project
|
@project
|
||||||
end
|
end
|
||||||
|
|
|
@ -114,6 +114,7 @@ class TimelogController < ApplicationController
|
||||||
:time_entry => {
|
:time_entry => {
|
||||||
:project_id => params[:time_entry][:project_id],
|
:project_id => params[:time_entry][:project_id],
|
||||||
:issue_id => @time_entry.issue_id,
|
:issue_id => @time_entry.issue_id,
|
||||||
|
:spent_on => @time_entry.spent_on,
|
||||||
:activity_id => @time_entry.activity_id
|
:activity_id => @time_entry.activity_id
|
||||||
},
|
},
|
||||||
:back_url => params[:back_url]
|
:back_url => params[:back_url]
|
||||||
|
|
|
@ -106,6 +106,6 @@ class TrackersController < ApplicationController
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@trackers = Tracker.sorted.to_a
|
@trackers = Tracker.sorted.to_a
|
||||||
@custom_fields = IssueCustomField.all.sort
|
@custom_fields = IssueCustomField.sorted
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
class WikiController < ApplicationController
|
class WikiController < ApplicationController
|
||||||
default_search_scope :wiki_pages
|
default_search_scope :wiki_pages
|
||||||
before_action :find_wiki, :authorize
|
before_action :find_wiki, :authorize
|
||||||
before_action :find_existing_or_new_page, :only => [:show, :edit, :update]
|
before_action :find_existing_or_new_page, :only => [:show, :edit]
|
||||||
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
|
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
|
||||||
before_action :find_attachments, :only => [:preview]
|
before_action :find_attachments, :only => [:preview]
|
||||||
accept_api_auth :index, :show, :update, :destroy
|
accept_api_auth :index, :show, :update, :destroy
|
||||||
|
@ -42,8 +42,6 @@ class WikiController < ApplicationController
|
||||||
helper :watchers
|
helper :watchers
|
||||||
include Redmine::Export::PDF
|
include Redmine::Export::PDF
|
||||||
|
|
||||||
include ActionView::Helpers::SanitizeHelper
|
|
||||||
|
|
||||||
# List of pages, sorted alphabetically and by parent (hierarchy)
|
# List of pages, sorted alphabetically and by parent (hierarchy)
|
||||||
def index
|
def index
|
||||||
load_pages_for_index
|
load_pages_for_index
|
||||||
|
@ -109,7 +107,7 @@ class WikiController < ApplicationController
|
||||||
send_data(export, :type => 'text/html', :filename => filename_for_content_disposition("#{@page.title}.html"))
|
send_data(export, :type => 'text/html', :filename => filename_for_content_disposition("#{@page.title}.html"))
|
||||||
return
|
return
|
||||||
elsif params[:format] == 'txt'
|
elsif params[:format] == 'txt'
|
||||||
send_data(strip_tags(@content.text), :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt"))
|
send_data(@content.text, :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt"))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -152,6 +150,8 @@ class WikiController < ApplicationController
|
||||||
|
|
||||||
# Creates a new page or updates an existing one
|
# Creates a new page or updates an existing one
|
||||||
def update
|
def update
|
||||||
|
@page = @wiki.find_or_new_page(params[:id])
|
||||||
|
|
||||||
return render_403 unless editable?
|
return render_403 unless editable?
|
||||||
was_new_page = @page.new_record?
|
was_new_page = @page.new_record?
|
||||||
@page.safe_attributes = params[:wiki_page]
|
@page.safe_attributes = params[:wiki_page]
|
||||||
|
|
|
@ -1272,7 +1272,7 @@ module ApplicationHelper
|
||||||
link_to_function '',
|
link_to_function '',
|
||||||
"toggleCheckboxesBySelector('#{selector}')",
|
"toggleCheckboxesBySelector('#{selector}')",
|
||||||
:title => "#{l(:button_check_all)} / #{l(:button_uncheck_all)}",
|
:title => "#{l(:button_check_all)} / #{l(:button_uncheck_all)}",
|
||||||
:class => 'toggle-checkboxes'
|
:class => 'icon icon-checked'
|
||||||
end
|
end
|
||||||
|
|
||||||
def progress_bar(pcts, options={})
|
def progress_bar(pcts, options={})
|
||||||
|
@ -1423,10 +1423,13 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
if email.present?
|
if email.present?
|
||||||
gravatar(email.to_s.downcase, options) rescue nil
|
gravatar(email.to_s.downcase, options) rescue nil
|
||||||
else
|
elsif user.is_a?(AnonymousUser)
|
||||||
|
options[:size] &&= options[:size].to_s
|
||||||
image_tag 'anonymous.png',
|
image_tag 'anonymous.png',
|
||||||
GravatarHelper::DEFAULT_OPTIONS
|
GravatarHelper::DEFAULT_OPTIONS
|
||||||
.except(:default, :rating, :ssl).merge(options)
|
.except(:default, :rating, :ssl).merge(options)
|
||||||
|
else
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
''
|
''
|
||||||
|
|
|
@ -127,8 +127,8 @@ module IssuesHelper
|
||||||
content_tag('td', check_box_tag("ids[]", other_issue.id, false, :id => nil), :class => 'checkbox') +
|
content_tag('td', check_box_tag("ids[]", other_issue.id, false, :id => nil), :class => 'checkbox') +
|
||||||
content_tag('td', relation.to_s(@issue) {|other| link_to_issue(other, :project => Setting.cross_project_issue_relations?)}.html_safe, :class => 'subject', :style => 'width: 50%') +
|
content_tag('td', relation.to_s(@issue) {|other| link_to_issue(other, :project => Setting.cross_project_issue_relations?)}.html_safe, :class => 'subject', :style => 'width: 50%') +
|
||||||
content_tag('td', other_issue.status, :class => 'status') +
|
content_tag('td', other_issue.status, :class => 'status') +
|
||||||
content_tag('td', other_issue.start_date, :class => 'start_date') +
|
content_tag('td', format_date(other_issue.start_date), :class => 'start_date') +
|
||||||
content_tag('td', other_issue.due_date, :class => 'due_date') +
|
content_tag('td', format_date(other_issue.due_date), :class => 'due_date') +
|
||||||
content_tag('td', other_issue.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(other_issue.done_ratio), :class=> 'done_ratio') +
|
content_tag('td', other_issue.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(other_issue.done_ratio), :class=> 'done_ratio') +
|
||||||
content_tag('td', link, :class => 'buttons'),
|
content_tag('td', link, :class => 'buttons'),
|
||||||
:id => "relation-#{relation.id}",
|
:id => "relation-#{relation.id}",
|
||||||
|
@ -246,8 +246,12 @@ module IssuesHelper
|
||||||
issue_fields_rows do |rows|
|
issue_fields_rows do |rows|
|
||||||
values.each_with_index do |value, i|
|
values.each_with_index do |value, i|
|
||||||
css = "cf_#{value.custom_field.id}"
|
css = "cf_#{value.custom_field.id}"
|
||||||
|
attr_value = show_value(value)
|
||||||
|
if value.custom_field.text_formatting == 'full'
|
||||||
|
attr_value = content_tag('div', attr_value, class: 'wiki')
|
||||||
|
end
|
||||||
m = (i < half ? :left : :right)
|
m = (i < half ? :left : :right)
|
||||||
rows.send m, custom_field_name_tag(value.custom_field), show_value(value), :class => css
|
rows.send m, custom_field_name_tag(value.custom_field), attr_value, :class => css
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -310,7 +314,7 @@ module IssuesHelper
|
||||||
# Returns an array of users that are proposed as watchers
|
# Returns an array of users that are proposed as watchers
|
||||||
# on the new issue form
|
# on the new issue form
|
||||||
def users_for_new_issue_watchers(issue)
|
def users_for_new_issue_watchers(issue)
|
||||||
users = issue.watcher_users
|
users = issue.watcher_users.select{|u| u.status == User::STATUS_ACTIVE}
|
||||||
if issue.project.users.count <= 20
|
if issue.project.users.count <= 20
|
||||||
users = (users + issue.project.users.sort).uniq
|
users = (users + issue.project.users.sort).uniq
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,14 +18,11 @@
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
module SearchHelper
|
module SearchHelper
|
||||||
include ActionView::Helpers::SanitizeHelper
|
|
||||||
|
|
||||||
def highlight_tokens(text, tokens)
|
def highlight_tokens(text, tokens)
|
||||||
return text unless text && tokens && !tokens.empty?
|
return text unless text && tokens && !tokens.empty?
|
||||||
re_tokens = tokens.collect {|t| Regexp.escape(t)}
|
re_tokens = tokens.collect {|t| Regexp.escape(t)}
|
||||||
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
|
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
|
||||||
result = ''
|
result = ''
|
||||||
text = strip_tags(text)
|
|
||||||
text.split(regexp).each_with_index do |words, i|
|
text.split(regexp).each_with_index do |words, i|
|
||||||
if result.length > 1200
|
if result.length > 1200
|
||||||
# maximum length of the preview reached
|
# maximum length of the preview reached
|
||||||
|
|
|
@ -156,7 +156,7 @@ class Attachment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
title = filename.to_s
|
title = filename.dup
|
||||||
if description.present?
|
if description.present?
|
||||||
title << " (#{description})"
|
title << " (#{description})"
|
||||||
end
|
end
|
||||||
|
|
|
@ -217,6 +217,7 @@ class Import < ActiveRecord::Base
|
||||||
|
|
||||||
csv_options = {:headers => false}
|
csv_options = {:headers => false}
|
||||||
csv_options[:encoding] = settings['encoding'].to_s.presence || 'UTF-8'
|
csv_options[:encoding] = settings['encoding'].to_s.presence || 'UTF-8'
|
||||||
|
csv_options[:encoding] = 'bom|UTF-8' if csv_options[:encoding] == 'UTF-8'
|
||||||
separator = settings['separator'].to_s
|
separator = settings['separator'].to_s
|
||||||
csv_options[:col_sep] = separator if separator.size == 1
|
csv_options[:col_sep] = separator if separator.size == 1
|
||||||
wrapper = settings['wrapper'].to_s
|
wrapper = settings['wrapper'].to_s
|
||||||
|
|
|
@ -275,7 +275,8 @@ class Issue < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
unless options[:watchers] == false
|
unless options[:watchers] == false
|
||||||
self.watcher_user_ids = issue.watcher_user_ids.dup
|
self.watcher_user_ids =
|
||||||
|
issue.watcher_users.select{|u| u.status == User::STATUS_ACTIVE}.map(&:id)
|
||||||
end
|
end
|
||||||
@copied_from = issue
|
@copied_from = issue
|
||||||
@copy_options = options
|
@copy_options = options
|
||||||
|
@ -1086,7 +1087,7 @@ class Issue < ActiveRecord::Base
|
||||||
if leaf?
|
if leaf?
|
||||||
estimated_hours
|
estimated_hours
|
||||||
else
|
else
|
||||||
@total_estimated_hours ||= self_and_descendants.sum(:estimated_hours)
|
@total_estimated_hours ||= self_and_descendants.visible.sum(:estimated_hours)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1300,7 +1301,7 @@ class Issue < ActiveRecord::Base
|
||||||
|
|
||||||
# Reschedules the issue on the given date or the next working day and saves the record.
|
# Reschedules the issue on the given date or the next working day and saves the record.
|
||||||
# If the issue is a parent task, this is done by rescheduling its subtasks.
|
# If the issue is a parent task, this is done by rescheduling its subtasks.
|
||||||
def reschedule_on!(date)
|
def reschedule_on!(date, journal=nil)
|
||||||
return if date.nil?
|
return if date.nil?
|
||||||
if leaf? || !dates_derived?
|
if leaf? || !dates_derived?
|
||||||
if start_date.nil? || start_date != date
|
if start_date.nil? || start_date != date
|
||||||
|
@ -1308,6 +1309,9 @@ class Issue < ActiveRecord::Base
|
||||||
# Issue can not be moved earlier than its soonest start date
|
# Issue can not be moved earlier than its soonest start date
|
||||||
date = [soonest_start(true), date].compact.max
|
date = [soonest_start(true), date].compact.max
|
||||||
end
|
end
|
||||||
|
if journal
|
||||||
|
init_journal(journal.user)
|
||||||
|
end
|
||||||
reschedule_on(date)
|
reschedule_on(date)
|
||||||
begin
|
begin
|
||||||
save
|
save
|
||||||
|
@ -1631,6 +1635,8 @@ class Issue < ActiveRecord::Base
|
||||||
copy.author = author
|
copy.author = author
|
||||||
copy.project = project
|
copy.project = project
|
||||||
copy.parent_issue_id = copied_issue_ids[child.parent_id]
|
copy.parent_issue_id = copied_issue_ids[child.parent_id]
|
||||||
|
copy.fixed_version_id = nil unless child.fixed_version.present? && child.fixed_version.status == 'open'
|
||||||
|
copy.assigned_to = nil unless child.assigned_to_id.present? && child.assigned_to.status == User::STATUS_ACTIVE
|
||||||
unless copy.save
|
unless copy.save
|
||||||
logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
|
logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
|
||||||
next
|
next
|
||||||
|
@ -1789,7 +1795,7 @@ class Issue < ActiveRecord::Base
|
||||||
def reschedule_following_issues
|
def reschedule_following_issues
|
||||||
if start_date_changed? || due_date_changed?
|
if start_date_changed? || due_date_changed?
|
||||||
relations_from.each do |relation|
|
relations_from.each do |relation|
|
||||||
relation.set_issue_to_dates
|
relation.set_issue_to_dates(@current_journal)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -122,7 +122,10 @@ class IssueImport < Import
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if issue.project && version_name = row_value(row, 'fixed_version')
|
if issue.project && version_name = row_value(row, 'fixed_version')
|
||||||
if version = issue.project.versions.named(version_name).first
|
version =
|
||||||
|
issue.project.versions.named(version_name).first ||
|
||||||
|
issue.project.shared_versions.named(version_name).first
|
||||||
|
if version
|
||||||
attributes['fixed_version_id'] = version.id
|
attributes['fixed_version_id'] = version.id
|
||||||
elsif create_versions?
|
elsif create_versions?
|
||||||
version = issue.project.versions.build
|
version = issue.project.versions.build
|
||||||
|
|
|
@ -37,8 +37,8 @@ class IssueQuery < Query
|
||||||
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
|
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
|
||||||
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours", :totalable => true),
|
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours", :totalable => true),
|
||||||
QueryColumn.new(:total_estimated_hours,
|
QueryColumn.new(:total_estimated_hours,
|
||||||
:sortable => "COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" +
|
:sortable => -> { "COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" +
|
||||||
" WHERE subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)",
|
" WHERE #{Issue.visible_condition(User.current).gsub(/\bissues\b/, 'subtasks')} AND subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)" },
|
||||||
:default_order => 'desc'),
|
:default_order => 'desc'),
|
||||||
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
|
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
|
||||||
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
|
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
|
||||||
|
@ -221,6 +221,7 @@ class IssueQuery < Query
|
||||||
end
|
end
|
||||||
|
|
||||||
disabled_fields = Tracker.disabled_core_fields(trackers).map {|field| field.sub(/_id$/, '')}
|
disabled_fields = Tracker.disabled_core_fields(trackers).map {|field| field.sub(/_id$/, '')}
|
||||||
|
disabled_fields << "total_estimated_hours" if disabled_fields.include?("estimated_hours")
|
||||||
@available_columns.reject! {|column|
|
@available_columns.reject! {|column|
|
||||||
disabled_fields.include?(column.name.to_s)
|
disabled_fields.include?(column.name.to_s)
|
||||||
}
|
}
|
||||||
|
@ -373,7 +374,7 @@ class IssueQuery < Query
|
||||||
neg = (operator == '!' ? 'NOT' : '')
|
neg = (operator == '!' ? 'NOT' : '')
|
||||||
subquery = "SELECT 1 FROM #{Journal.table_name} sj" +
|
subquery = "SELECT 1 FROM #{Journal.table_name} sj" +
|
||||||
" WHERE sj.journalized_type='Issue' AND sj.journalized_id=#{Issue.table_name}.id AND (#{sql_for_field field, '=', value, 'sj', 'user_id'})" +
|
" WHERE sj.journalized_type='Issue' AND sj.journalized_id=#{Issue.table_name}.id AND (#{sql_for_field field, '=', value, 'sj', 'user_id'})" +
|
||||||
" AND sj.id = (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
|
" AND sj.id IN (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
|
||||||
" WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" +
|
" WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" +
|
||||||
" AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)}))"
|
" AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)}))"
|
||||||
|
|
||||||
|
@ -382,8 +383,26 @@ class IssueQuery < Query
|
||||||
|
|
||||||
def sql_for_watcher_id_field(field, operator, value)
|
def sql_for_watcher_id_field(field, operator, value)
|
||||||
db_table = Watcher.table_name
|
db_table = Watcher.table_name
|
||||||
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND " +
|
|
||||||
sql_for_field(field, '=', value, db_table, 'user_id') + ')'
|
me, others = value.partition { |id| ['0', User.current.id.to_s].include?(id) }
|
||||||
|
sql = if others.any?
|
||||||
|
"SELECT #{Issue.table_name}.id FROM #{Issue.table_name} " +
|
||||||
|
"INNER JOIN #{db_table} ON #{Issue.table_name}.id = #{db_table}.watchable_id AND #{db_table}.watchable_type = 'Issue' " +
|
||||||
|
"LEFT OUTER JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Issue.table_name}.project_id " +
|
||||||
|
"WHERE (" +
|
||||||
|
sql_for_field(field, '=', me, db_table, 'user_id') +
|
||||||
|
') OR (' +
|
||||||
|
Project.allowed_to_condition(User.current, :view_issue_watchers) +
|
||||||
|
' AND ' +
|
||||||
|
sql_for_field(field, '=', others, db_table, 'user_id') +
|
||||||
|
')'
|
||||||
|
else
|
||||||
|
"SELECT #{db_table}.watchable_id FROM #{db_table} " +
|
||||||
|
"WHERE #{db_table}.watchable_type='Issue' AND " +
|
||||||
|
sql_for_field(field, '=', me, db_table, 'user_id')
|
||||||
|
end
|
||||||
|
|
||||||
|
"#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (#{sql})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def sql_for_member_of_group_field(field, operator, value)
|
def sql_for_member_of_group_field(field, operator, value)
|
||||||
|
|
|
@ -176,10 +176,10 @@ class IssueRelation < ActiveRecord::Base
|
||||||
set_issue_to_dates
|
set_issue_to_dates
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_issue_to_dates
|
def set_issue_to_dates(journal=nil)
|
||||||
soonest_start = self.successor_soonest_start
|
soonest_start = self.successor_soonest_start
|
||||||
if soonest_start && issue_to
|
if soonest_start && issue_to
|
||||||
issue_to.reschedule_on!(soonest_start)
|
issue_to.reschedule_on!(soonest_start, journal)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ class MailHandler < ActionMailer::Base
|
||||||
def self.safe_receive(*args)
|
def self.safe_receive(*args)
|
||||||
receive(*args)
|
receive(*args)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
logger.error "MailHandler: an unexpected error occurred when receiving email: #{e.message}" if logger
|
Rails.logger.error "MailHandler: an unexpected error occurred when receiving email: #{e.message}"
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class MailHandler < ActionMailer::Base
|
||||||
%w(project status tracker category priority assigned_to fixed_version).each do |option|
|
%w(project status tracker category priority assigned_to fixed_version).each do |option|
|
||||||
options[:issue][option.to_sym] = env[option] if env[option]
|
options[:issue][option.to_sym] = env[option] if env[option]
|
||||||
end
|
end
|
||||||
%w(allow_override unknown_user no_permission_check no_account_notice default_group project_from_subaddress).each do |option|
|
%w(allow_override unknown_user no_permission_check no_account_notice no_notification default_group project_from_subaddress).each do |option|
|
||||||
options[option.to_sym] = env[option] if env[option]
|
options[option.to_sym] = env[option] if env[option]
|
||||||
end
|
end
|
||||||
if env['private']
|
if env['private']
|
||||||
|
@ -250,8 +250,8 @@ class MailHandler < ActionMailer::Base
|
||||||
|
|
||||||
# add To and Cc as watchers before saving so the watchers can reply to Redmine
|
# add To and Cc as watchers before saving so the watchers can reply to Redmine
|
||||||
add_watchers(issue)
|
add_watchers(issue)
|
||||||
add_attachments(issue)
|
|
||||||
issue.save!
|
issue.save!
|
||||||
|
add_attachments(issue)
|
||||||
if logger
|
if logger
|
||||||
logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
|
logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
|
||||||
end
|
end
|
||||||
|
@ -286,7 +286,7 @@ class MailHandler < ActionMailer::Base
|
||||||
reply
|
reply
|
||||||
else
|
else
|
||||||
if logger
|
if logger
|
||||||
logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
|
logger.info "MailHandler: ignoring reply from [#{email.from.first}] to a locked topic"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -311,7 +311,7 @@ class Mailer < ActionMailer::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
# Notifies user that his password was updated
|
# Notifies user that his password was updated
|
||||||
def self.password_updated(user)
|
def self.password_updated(user, options={})
|
||||||
# Don't send a notification to the dummy email address when changing the password
|
# Don't send a notification to the dummy email address when changing the password
|
||||||
# of the default admin account which is required after the first login
|
# of the default admin account which is required after the first login
|
||||||
# TODO: maybe not the best way to handle this
|
# TODO: maybe not the best way to handle this
|
||||||
|
@ -320,6 +320,8 @@ class Mailer < ActionMailer::Base
|
||||||
security_notification(user,
|
security_notification(user,
|
||||||
message: :mail_body_password_updated,
|
message: :mail_body_password_updated,
|
||||||
title: :button_change_password,
|
title: :button_change_password,
|
||||||
|
remote_ip: options[:remote_ip],
|
||||||
|
originator: user,
|
||||||
url: {controller: 'my', action: 'password'}
|
url: {controller: 'my', action: 'password'}
|
||||||
).deliver
|
).deliver
|
||||||
end
|
end
|
||||||
|
@ -333,7 +335,6 @@ class Mailer < ActionMailer::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def security_notification(recipients, options={})
|
def security_notification(recipients, options={})
|
||||||
redmine_headers 'Sender' => User.current.login
|
|
||||||
@user = Array(recipients).detect{|r| r.is_a? User }
|
@user = Array(recipients).detect{|r| r.is_a? User }
|
||||||
set_language_if_valid(@user.try :language)
|
set_language_if_valid(@user.try :language)
|
||||||
@message = l(options[:message],
|
@message = l(options[:message],
|
||||||
|
@ -341,7 +342,11 @@ class Mailer < ActionMailer::Base
|
||||||
value: options[:value]
|
value: options[:value]
|
||||||
)
|
)
|
||||||
@title = options[:title] && l(options[:title])
|
@title = options[:title] && l(options[:title])
|
||||||
|
@originator = options[:originator] || User.current
|
||||||
|
@remote_ip = options[:remote_ip] || @originator.remote_ip
|
||||||
@url = options[:url] && (options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url])
|
@url = options[:url] && (options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url])
|
||||||
|
redmine_headers 'Sender' => @originator.login
|
||||||
|
redmine_headers 'Url' => @url
|
||||||
mail :to => recipients,
|
mail :to => recipients,
|
||||||
:subject => "[#{Setting.app_title}] #{l(:mail_subject_security_notification)}"
|
:subject => "[#{Setting.app_title}] #{l(:mail_subject_security_notification)}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -319,9 +319,10 @@ class Query < ActiveRecord::Base
|
||||||
" INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" +
|
" INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" +
|
||||||
" INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" +
|
" INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" +
|
||||||
" INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" +
|
" INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" +
|
||||||
|
" INNER JOIN #{Project.table_name} p ON p.id = m.project_id AND p.status <> ?" +
|
||||||
" WHERE q.project_id IS NULL OR q.project_id = m.project_id))" +
|
" WHERE q.project_id IS NULL OR q.project_id = m.project_id))" +
|
||||||
" OR #{table_name}.user_id = ?",
|
" OR #{table_name}.user_id = ?",
|
||||||
VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, user.id)
|
VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, Project::STATUS_ARCHIVED, user.id)
|
||||||
elsif user.logged?
|
elsif user.logged?
|
||||||
scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id)
|
scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id)
|
||||||
else
|
else
|
||||||
|
@ -340,7 +341,7 @@ class Query < ActiveRecord::Base
|
||||||
if project
|
if project
|
||||||
(user.roles_for_project(project) & roles).any?
|
(user.roles_for_project(project) & roles).any?
|
||||||
else
|
else
|
||||||
Member.where(:user_id => user.id).joins(:roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
|
user.memberships.joins(:member_roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
user == self.user
|
user == self.user
|
||||||
|
@ -398,6 +399,8 @@ class Query < ActiveRecord::Base
|
||||||
params[:v][field] = options[:values]
|
params[:v][field] = options[:values]
|
||||||
end
|
end
|
||||||
params[:c] = column_names
|
params[:c] = column_names
|
||||||
|
params[:group_by] = group_by.to_s if group_by.present?
|
||||||
|
params[:t] = totalable_names.map(&:to_s) if totalable_names.any?
|
||||||
params[:sort] = sort_criteria.to_param
|
params[:sort] = sort_criteria.to_param
|
||||||
params[:set_filter] = 1
|
params[:set_filter] = 1
|
||||||
params
|
params
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Version < ActiveRecord::Base
|
||||||
scope :like, lambda {|arg|
|
scope :like, lambda {|arg|
|
||||||
if arg.present?
|
if arg.present?
|
||||||
pattern = "%#{arg.to_s.strip}%"
|
pattern = "%#{arg.to_s.strip}%"
|
||||||
where("LOWER(#{Version.table_name}.name) LIKE :p", :p => pattern)
|
where([Redmine::Database.like("#{Version.table_name}.name", '?'), pattern])
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
scope :open, lambda { where(:status => 'open') }
|
scope :open, lambda { where(:status => 'open') }
|
||||||
|
@ -268,7 +268,7 @@ class Version < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def deletable?
|
def deletable?
|
||||||
fixed_issues.empty? && !referenced_by_a_custom_field?
|
fixed_issues.empty? && !referenced_by_a_custom_field? && attachments.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_project_version
|
def default_project_version
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<%= call_hook :view_account_login_top %>
|
<%= call_hook :view_account_login_top %>
|
||||||
|
|
||||||
<div id="login-form">
|
<div id="login-form">
|
||||||
<h2><%= l(:label_login) %></h2>
|
|
||||||
<%= form_tag(signin_path, onsubmit: 'return keepAnchorOnSignIn(this);') do %>
|
<%= form_tag(signin_path, onsubmit: 'return keepAnchorOnSignIn(this);') do %>
|
||||||
<%= back_url_hidden_field_tag %>
|
<%= back_url_hidden_field_tag %>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
<br />
|
<br />
|
||||||
<div class="box">
|
<div class="box autoscroll">
|
||||||
<pre><%= Redmine::Info.environment %></pre>
|
<pre><%= Redmine::Info.environment %></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
<%= title l(:label_plugins) %>
|
<%= title l(:label_plugins) %>
|
||||||
|
|
||||||
<% if @plugins.any? %>
|
<% if @plugins.any? %>
|
||||||
<table class="list plugins">
|
<div class="autoscroll">
|
||||||
<% @plugins.each do |plugin| %>
|
<table class="list plugins">
|
||||||
<tr id="plugin-<%= plugin.id %>">
|
<% @plugins.each do |plugin| %>
|
||||||
<td class="name"><span class="name"><%= plugin.name %></span>
|
<tr id="plugin-<%= plugin.id %>">
|
||||||
<%= content_tag('span', plugin.description, :class => 'description') unless plugin.description.blank? %>
|
<td class="name"><span class="name"><%= plugin.name %></span>
|
||||||
<%= content_tag('span', link_to(plugin.url, plugin.url), :class => 'url') unless plugin.url.blank? %>
|
<%= content_tag('span', plugin.description, :class => 'description') unless plugin.description.blank? %>
|
||||||
</td>
|
<%= content_tag('span', link_to(plugin.url, plugin.url), :class => 'url') unless plugin.url.blank? %>
|
||||||
<td class="author"><%= plugin.author_url.blank? ? plugin.author : link_to(plugin.author, plugin.author_url) %></td>
|
</td>
|
||||||
<td class="version"><span class="icon"><%= plugin.version %></span></td>
|
<td class="author"><%= plugin.author_url.blank? ? plugin.author : link_to(plugin.author, plugin.author_url) %></td>
|
||||||
<td class="configure"><%= link_to(l(:button_configure), plugin_settings_path(plugin)) if plugin.configurable? %></td>
|
<td class="version"><span class="icon"><%= plugin.version %></span></td>
|
||||||
</tr>
|
<td class="configure"><%= link_to(l(:button_configure), plugin_settings_path(plugin)) if plugin.configurable? %></td>
|
||||||
<% end %>
|
</tr>
|
||||||
</table>
|
<% end %>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<p><a href="#" id="check-for-updates"><%= l(:label_check_for_updates) %></a></p>
|
<p><a href="#" id="check-for-updates"><%= l(:label_check_for_updates) %></a></p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||||
|
@ -27,7 +29,7 @@ $(document).ready(function(){
|
||||||
dataType: "jsonp",
|
dataType: "jsonp",
|
||||||
url: "https://www.redmine.org/plugins/check_updates",
|
url: "https://www.redmine.org/plugins/check_updates",
|
||||||
data: <%= raw_json plugin_data_for_updates(@plugins) %>,
|
data: <%= raw_json plugin_data_for_updates(@plugins) %>,
|
||||||
timeout: 3000,
|
timeout: 10000,
|
||||||
beforeSend: function(){
|
beforeSend: function(){
|
||||||
$('#ajax-indicator').show();
|
$('#ajax-indicator').show();
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<% @priorities.each do |p| -%>
|
<% @priorities.each do |p| -%>
|
||||||
<li><%= context_menu_link p.name, bulk_update_issues_path(:ids => @issue_ids, :issue => {'priority_id' => p}, :back_url => @back), :method => :post,
|
<li><%= context_menu_link p.name, bulk_update_issues_path(:ids => @issue_ids, :issue => {'priority_id' => p}, :back_url => @back), :method => :post,
|
||||||
:selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit]) %></li>
|
:selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit] || @issues.any?(&:priority_derived?)) %></li>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<% (0..10).map{|x|x*10}.each do |p| -%>
|
<% (0..10).map{|x|x*10}.each do |p| -%>
|
||||||
<li><%= context_menu_link "#{p}%", bulk_update_issues_path(:ids => @issue_ids, :issue => {'done_ratio' => p}, :back_url => @back), :method => :post,
|
<li><%= context_menu_link "#{p}%", bulk_update_issues_path(:ids => @issue_ids, :issue => {'done_ratio' => p}, :back_url => @back), :method => :post,
|
||||||
:selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %></li>
|
:selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.any?(&:done_ratio_derived?)) %></li>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -6,41 +6,43 @@
|
||||||
|
|
||||||
<% delete_allowed = User.current.allowed_to?(:manage_files, @project) %>
|
<% delete_allowed = User.current.allowed_to?(:manage_files, @project) %>
|
||||||
|
|
||||||
<table class="list files">
|
<div class="autoscroll">
|
||||||
<thead><tr>
|
<table class="list files">
|
||||||
<%= sort_header_tag('filename', :caption => l(:field_filename)) %>
|
<thead><tr>
|
||||||
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
|
<%= sort_header_tag('filename', :caption => l(:field_filename)) %>
|
||||||
<%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %>
|
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
|
||||||
<%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
|
<%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %>
|
||||||
<th><%= l(:field_digest) %></th>
|
<%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
|
||||||
<th></th>
|
<th><%= l(:field_digest) %></th>
|
||||||
</tr></thead>
|
<th></th>
|
||||||
<tbody>
|
</tr></thead>
|
||||||
<% @containers.each do |container| %>
|
<tbody>
|
||||||
<% next if container.attachments.empty? -%>
|
<% @containers.each do |container| %>
|
||||||
<% if container.is_a?(Version) -%>
|
<% next if container.attachments.empty? -%>
|
||||||
<tr>
|
<% if container.is_a?(Version) -%>
|
||||||
<th colspan="6">
|
<tr>
|
||||||
<%= link_to(container, {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
|
<th colspan="6">
|
||||||
</th>
|
<%= link_to(container, {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
|
||||||
</tr>
|
</th>
|
||||||
<% end -%>
|
</tr>
|
||||||
<% container.attachments.each do |file| %>
|
<% end -%>
|
||||||
<tr class="file">
|
<% container.attachments.each do |file| %>
|
||||||
<td class="filename"><%= link_to_attachment file, :title => file.description -%></td>
|
<tr class="file">
|
||||||
<td class="created_on"><%= format_time(file.created_on) %></td>
|
<td class="filename"><%= link_to_attachment file, :title => file.description -%></td>
|
||||||
<td class="filesize"><%= number_to_human_size(file.filesize) %></td>
|
<td class="created_on"><%= format_time(file.created_on) %></td>
|
||||||
<td class="downloads"><%= file.downloads %></td>
|
<td class="filesize"><%= number_to_human_size(file.filesize) %></td>
|
||||||
<td class="digest"><%= file.digest_type %>: <%= file.digest %></td>
|
<td class="downloads"><%= file.downloads %></td>
|
||||||
<td class="buttons">
|
<td class="digest"><%= file.digest_type %>: <%= file.digest %></td>
|
||||||
<%= link_to_attachment file, class: 'icon-only icon-download', title: l(:button_download), download: true %>
|
<td class="buttons">
|
||||||
<%= link_to(l(:button_delete), attachment_path(file), :class => 'icon-only icon-del',
|
<%= link_to_attachment file, class: 'icon-only icon-download', title: l(:button_download), download: true %>
|
||||||
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete) if delete_allowed %>
|
<%= link_to(l(:button_delete), attachment_path(file), :class => 'icon-only icon-del',
|
||||||
</td>
|
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete) if delete_allowed %>
|
||||||
</tr>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
|
|
||||||
<% html_title(l(:label_attachment_plural)) -%>
|
<% html_title(l(:label_attachment_plural)) -%>
|
||||||
|
|
|
@ -2,6 +2,6 @@ $('#relations').html('<%= escape_javascript(render :partial => 'issues/relations
|
||||||
<% if @relation.errors.empty? %>
|
<% if @relation.errors.empty? %>
|
||||||
$('#relation_delay').val('');
|
$('#relation_delay').val('');
|
||||||
$('#relation_issue_to_id').val('');
|
$('#relation_issue_to_id').val('');
|
||||||
$('#relation_issue_to_id').focus();
|
|
||||||
<% end %>
|
<% end %>
|
||||||
$('#new-relation-form').show();
|
$('#new-relation-form').show();
|
||||||
|
$('#relation_issue_to_id').focus();
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<br />
|
<br />
|
||||||
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
|
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
|
||||||
<div class="wiki changeset-comments"><%= format_changeset_comments changeset %></div>
|
<div class="wiki changeset-comments">
|
||||||
|
<%= format_changeset_comments changeset %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
<p><strong><%= l(:text_destroy_time_entries_question, :hours => number_with_precision(@hours, :precision => 2)) %></strong></p>
|
<p><strong><%= l(:text_destroy_time_entries_question, :hours => number_with_precision(@hours, :precision => 2)) %></strong></p>
|
||||||
<p>
|
<p>
|
||||||
<label><%= radio_button_tag 'todo', 'destroy', true %> <%= l(:text_destroy_time_entries) %></label><br />
|
<label><%= radio_button_tag 'todo', 'destroy', true %> <%= l(:text_destroy_time_entries) %></label><br />
|
||||||
|
<% unless Setting.timelog_required_fields.include?('issue_id') %>
|
||||||
<label><%= radio_button_tag 'todo', 'nullify', false %> <%= l(:text_assign_time_entries_to_project) %></label><br />
|
<label><%= radio_button_tag 'todo', 'nullify', false %> <%= l(:text_assign_time_entries_to_project) %></label><br />
|
||||||
|
<% end %>
|
||||||
<% if @project %>
|
<% if @project %>
|
||||||
<label><%= radio_button_tag 'todo', 'reassign', false, :onchange => 'if (this.checked) { $("#reassign_to_id").focus(); }' %> <%= l(:text_reassign_time_entries) %></label>
|
<label><%= radio_button_tag 'todo', 'reassign', false, :onchange => 'if (this.checked) { $("#reassign_to_id").focus(); }' %> <%= l(:text_reassign_time_entries) %></label>
|
||||||
<%= text_field_tag 'reassign_to_id', params[:reassign_to_id], :size => 6, :onfocus => '$("#todo_reassign").attr("checked", true);' %>
|
<%= text_field_tag 'reassign_to_id', params[:reassign_to_id], :size => 6, :onfocus => '$("#todo_reassign").attr("checked", true);' %>
|
||||||
|
|
|
@ -2,31 +2,28 @@
|
||||||
<html lang="<%= current_language %>">
|
<html lang="<%= current_language %>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||||
<title><%= html_title %></title>
|
<title><%= html_title %></title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="description" content="<%= Redmine::Info.app_name %>" />
|
<meta name="description" content="<%= Redmine::Info.app_name %>" />
|
||||||
<meta name="keywords" content="issue,bug,tracker" />
|
<meta name="keywords" content="issue,bug,tracker" />
|
||||||
<%= csrf_meta_tag %>
|
<%= csrf_meta_tag %>
|
||||||
<%= favicon %>
|
<%= favicon %>
|
||||||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.11.0', 'cookieconsent.min', 'application', 'responsive', :media => 'all' %>
|
<%= stylesheet_link_tag 'jquery/jquery-ui-1.11.0', 'application', 'responsive', :media => 'all' %>
|
||||||
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
||||||
<% is_welcome = !User.current.logged? && current_page?(:controller => 'welcome', :action => 'index') %>
|
|
||||||
<%= stylesheet_link_tag 'frontpage', :media => 'all' if is_welcome %>
|
|
||||||
|
|
||||||
<%= javascript_heads %>
|
<%= javascript_heads %>
|
||||||
<script src="/themes/circlepro/javascripts/cookieconsent.min.js"></script>
|
|
||||||
<%= heads_for_theme %>
|
<%= heads_for_theme %>
|
||||||
<%= call_hook :view_layouts_base_html_head %>
|
<%= call_hook :view_layouts_base_html_head %>
|
||||||
<!-- page specific tags -->
|
<!-- page specific tags -->
|
||||||
<%= yield :header_tags -%>
|
<%= yield :header_tags -%>
|
||||||
</head>
|
</head>
|
||||||
<body class="<%= body_css_classes %><%= ' is-preload' if is_welcome %>">
|
<body class="<%= body_css_classes %>">
|
||||||
<%= call_hook :view_layouts_base_body_top %>
|
<%= call_hook :view_layouts_base_body_top %>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
|
||||||
<div class="flyout-menu js-flyout-menu">
|
<div class="flyout-menu js-flyout-menu">
|
||||||
|
|
||||||
|
|
||||||
<% if User.current.logged? || !Setting.login_required? %>
|
<% if User.current.logged? || !Setting.login_required? %>
|
||||||
<div class="flyout-menu__search">
|
<div class="flyout-menu__search">
|
||||||
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
||||||
|
@ -64,58 +61,45 @@
|
||||||
<div id="wrapper2">
|
<div id="wrapper2">
|
||||||
<div id="wrapper3">
|
<div id="wrapper3">
|
||||||
<div id="top-menu">
|
<div id="top-menu">
|
||||||
<div id="wrapper-top-menu">
|
|
||||||
<ul class="social-menu">
|
|
||||||
<li class="social-link-blog"><a href="https://manuel.cillero.es" title="<%= l(:link_my_blog) %>" class="icon-blog"><span><%= l(:link_my_blog) %></span></a></li>
|
|
||||||
<li class="social-link-twitter"><a href="https://twitter.com/manuelcillero" title="Twitter" target="_blank" class="icon-twitter"><span>Twitter</span></a></li>
|
|
||||||
<li class="social-link-facebook"><a href="https://facebook.com/manuelcillero" title="Facebook" target="_blank" class="icon-facebook"><span>Facebook</span></a></li>
|
|
||||||
<li class="social-link-linkedin"><a href="https://es.linkedin.com/in/manuelcillero" title="Linkedin" target="_blank" class="icon-linkedin"><span>Linkedin</span></a></li>
|
|
||||||
<li class="social-link-gitlab"><a href="https://gitlab.com/manuelcillero" title="Gitlab" target="_blank" class="icon-gitlab"><span>Gitlab</span></a></li>
|
|
||||||
<li class="social-link-mail"><a href="https://manuel.cillero.es/contacto/#suitepro" title="Mail" class="icon-mail"><span>Mail</span></a></li>
|
|
||||||
</ul>
|
|
||||||
<div id="account">
|
<div id="account">
|
||||||
<%= render_menu :account_menu -%>
|
<%= render_menu :account_menu -%>
|
||||||
</div>
|
</div>
|
||||||
<%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
|
<%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
|
||||||
<%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
|
<%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="header">
|
<div id="header">
|
||||||
|
|
||||||
<a href="#" class="mobile-toggle-button js-flyout-menu-toggle-button"></a>
|
<a href="#" class="mobile-toggle-button js-flyout-menu-toggle-button"></a>
|
||||||
|
|
||||||
<div id="wrapper-header">
|
|
||||||
<% if User.current.logged? || !Setting.login_required? %>
|
<% if User.current.logged? || !Setting.login_required? %>
|
||||||
<div id="quick-search" class="hide-when-print">
|
<div id="quick-search">
|
||||||
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
||||||
<%= hidden_field_tag 'scope', default_search_project_scope, :id => nil %>
|
<%= hidden_field_tag 'scope', default_search_project_scope, :id => nil %>
|
||||||
<%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %>
|
<%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %>
|
||||||
<label for='q'>
|
<label for='q'>
|
||||||
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>:
|
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project, :scope => default_search_project_scope}, :accesskey => accesskey(:search) %>:
|
||||||
</label>
|
</label>
|
||||||
<%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %>
|
<%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render_project_jump_box %>
|
<%= render_project_jump_box %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<h1><%= page_header_title %></h1>
|
<h1><%= page_header_title %></h1>
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if display_main_menu?(@project) %>
|
<% if display_main_menu?(@project) %>
|
||||||
<div id="main-menu" class="tabs">
|
<div id="main-menu" class="tabs">
|
||||||
<div id="wrapper-main-menu">
|
|
||||||
<%= render_main_menu(@project) %>
|
<%= render_main_menu(@project) %>
|
||||||
<div class="tabs-buttons" style="display:none;">
|
<div class="tabs-buttons" style="display:none;">
|
||||||
<button class="tab-left" onclick="moveTabLeft(this); return false;"></button>
|
<button class="tab-left" onclick="moveTabLeft(this); return false;"></button>
|
||||||
<button class="tab-right" onclick="moveTabRight(this); return false;"></button>
|
<button class="tab-right" onclick="moveTabRight(this); return false;"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>">
|
<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>">
|
||||||
<div id="wrapper-main">
|
|
||||||
<div id="sidebar">
|
<div id="sidebar">
|
||||||
<%= yield :sidebar %>
|
<%= yield :sidebar %>
|
||||||
<%= view_layouts_base_sidebar_hook_response %>
|
<%= view_layouts_base_sidebar_hook_response %>
|
||||||
|
@ -127,51 +111,19 @@
|
||||||
<%= call_hook :view_layouts_base_content %>
|
<%= call_hook :view_layouts_base_content %>
|
||||||
<div style="clear:both;"></div>
|
<div style="clear:both;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="#" id="scrollup" class="hide-when-print"><%=l(:label_sort_higher)%></a><%= javascript_tag "$('#scrollup').click(function(){$('html,body').animate({scrollTop:0},600);return false;});" %>
|
|
||||||
|
|
||||||
<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
|
<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
|
||||||
<div id="ajax-modal" style="display:none;"></div>
|
<div id="ajax-modal" style="display:none;"></div>
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="wrapper-footer">
|
<div class="bgl"><div class="bgr">
|
||||||
<ul class="social-menu">
|
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> © 2006-2019 Jean-Philippe Lang
|
||||||
<li class="social-link-blog"><a href="https://manuel.cillero.es" title="<%= l(:link_my_blog) %>" class="icon-blog"><span><%= l(:link_my_blog) %></span></a></li>
|
</div></div>
|
||||||
<li class="social-link-twitter"><a href="https://twitter.com/manuelcillero" title="Twitter" target="_blank" class="icon-twitter"><span>Twitter</span></a></li>
|
|
||||||
<li class="social-link-facebook"><a href="https://facebook.com/manuelcillero" title="Facebook" target="_blank" class="icon-facebook"><span>Facebook</span></a></li>
|
|
||||||
<li class="social-link-linkedin"><a href="https://es.linkedin.com/in/manuelcillero" title="Linkedin" target="_blank" class="icon-linkedin"><span>Linkedin</span></a></li>
|
|
||||||
<li class="social-link-gitlab"><a href="https://gitlab.com/manuelcillero" title="Gitlab" target="_blank" class="icon-gitlab"><span>Gitlab</span></a></li>
|
|
||||||
<li class="social-link-mail"><a href="https://manuel.cillero.es/contacto/#suitepro" title="Mail" class="icon-mail"><span>Mail</span></a></li>
|
|
||||||
</ul>
|
|
||||||
<div class="bgl"><div class="bgr">
|
|
||||||
<div id="legal">
|
|
||||||
<span class="legal-legal"><a href="/projects/suitepro/wiki/Legal"><%= l(:label_legal) %></a></span>
|
|
||||||
<span class="legal-terms"> | <a href="/projects/suitepro/wiki/Condiciones_de_uso"><%= l(:label_legal_terms) %></a></span>
|
|
||||||
<span class="legal-privacy"> | <a href="/projects/suitepro/wiki/Política_de_privacidad"><%= l(:label_legal_privacy) %></a></span>
|
|
||||||
<span class="legal-cookies"> | <a href="/projects/suitepro/wiki/Política_de_cookies"><%= l(:label_legal_cookies) %></a></span>
|
|
||||||
</div>
|
|
||||||
<%= Time.current.year %> © SuitePro (powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %>)
|
|
||||||
</div></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= call_hook :view_layouts_base_body_bottom %>
|
<%= call_hook :view_layouts_base_body_bottom %>
|
||||||
|
|
||||||
<script>
|
|
||||||
//<![CDATA[
|
|
||||||
window.addEventListener("load", function(){
|
|
||||||
window.cookieconsent.initialise({
|
|
||||||
"palette": { "popup": { "background": "rgba(20,20,20,0.8)" }, "button": { "background": "#fff" } },
|
|
||||||
"theme": "classic",
|
|
||||||
"position": "bottom-left",
|
|
||||||
"content": { "message": "<a href='https://suitepro.cillero.es'>SuitePro</a> requiere el uso de cookies para ofrecer la mejor experiencia de acceso a sus contenidos. Puedes aceptar su uso o abandonar la página si lo deseas.", "dismiss": "ACEPTO SU USO", "link": "Más información", "href": "/projects/suitepro/wiki/Pol%C3%ADtica_de_cookies", "target": "_self" }
|
|
||||||
})});
|
|
||||||
//]]>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<%= content_tag :h1, @title -%>
|
<%= content_tag :h1, @title -%>
|
||||||
<% end %></p>
|
<% end %></p>
|
||||||
|
|
||||||
<p><%= l(:field_user) %>: <strong><%= User.current.login %></strong><br/>
|
<p><%= l(:field_user) %>: <strong><%= @originator.login %></strong><br/>
|
||||||
<%= l(:field_remote_ip) %>: <strong><%= User.current.remote_ip %></strong><br/>
|
<%= l(:field_remote_ip) %>: <strong><%= @remote_ip %></strong><br/>
|
||||||
<%= l(:label_date) %>: <strong><%= format_time Time.now, true, @user %></strong></p>
|
<%= l(:label_date) %>: <strong><%= format_time Time.now, true, @user %></strong></p>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<%= @url || @title %>
|
<%= @url || @title %>
|
||||||
|
|
||||||
<%= l(:field_user) %>: <%= User.current.login %>
|
<%= l(:field_user) %>: <%= @originator.login %>
|
||||||
<%= l(:field_remote_ip) %>: <%= User.current.remote_ip %>
|
<%= l(:field_remote_ip) %>: <%= @remote_ip %>
|
||||||
<%= l(:label_date) %>: <%= format_time Time.now, true, @user %>
|
<%= l(:label_date) %>: <%= format_time Time.now, true, @user %>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="box">
|
<fieldset class="box">
|
||||||
<legend><%= l(:label_role_plural) %> <%= toggle_checkboxes_link('.roles-selection input') %></legend>
|
<legend><%= toggle_checkboxes_link('.roles-selection input') %><%= l(:label_role_plural) %></legend>
|
||||||
<div class="roles-selection">
|
<div class="roles-selection">
|
||||||
<% User.current.managed_roles(@project).each do |role| %>
|
<% User.current.managed_roles(@project).each do |role| %>
|
||||||
<label><%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %> <%= role %></label>
|
<label><%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %> <%= role %></label>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<fieldset class="box">
|
<fieldset class="box">
|
||||||
<legend><%= l(:label_project_plural) %> <%= toggle_checkboxes_link('.projects-selection input:enabled') %></legend>
|
<legend><%= toggle_checkboxes_link('.projects-selection input:enabled') %><%= l(:label_project_plural) %></legend>
|
||||||
<div class="objects-selection">
|
<div class="objects-selection">
|
||||||
<div class="projects-selection">
|
<div class="projects-selection">
|
||||||
<%= render_project_nested_lists(@projects) do |p| %>
|
<%= render_project_nested_lists(@projects) do |p| %>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="box">
|
<fieldset class="box">
|
||||||
<legend><%= l(:label_role_plural) %> <%= toggle_checkboxes_link('.roles-selection input') %></legend>
|
<legend><%= toggle_checkboxes_link('.roles-selection input') %><%= l(:label_role_plural) %></legend>
|
||||||
<div class="roles-selection">
|
<div class="roles-selection">
|
||||||
<% @roles.each do |role| %>
|
<% @roles.each do |role| %>
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -3,39 +3,41 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @project.repositories.any? %>
|
<% if @project.repositories.any? %>
|
||||||
<table class="list">
|
<div class="autoscroll">
|
||||||
<thead>
|
<table class="list">
|
||||||
<tr>
|
<thead>
|
||||||
<th><%= l(:field_identifier) %></th>
|
<tr>
|
||||||
<th><%= l(:field_repository_is_default) %></th>
|
<th><%= l(:field_identifier) %></th>
|
||||||
<th><%= l(:label_scm) %></th>
|
<th><%= l(:field_repository_is_default) %></th>
|
||||||
<th><%= l(:label_repository) %></th>
|
<th><%= l(:label_scm) %></th>
|
||||||
<th></th>
|
<th><%= l(:label_repository) %></th>
|
||||||
</tr>
|
<th></th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
<% @project.repositories.sort.each do |repository| %>
|
<tbody>
|
||||||
<tr>
|
<% @project.repositories.sort.each do |repository| %>
|
||||||
<td class="name">
|
<tr>
|
||||||
<%= link_to repository.identifier,
|
<td class="name">
|
||||||
{:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier.present? %>
|
<%= link_to repository.identifier,
|
||||||
</td>
|
{:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier.present? %>
|
||||||
<td><%= checked_image repository.is_default? %></td>
|
</td>
|
||||||
<td><%= repository.scm_name %></td>
|
<td><%= checked_image repository.is_default? %></td>
|
||||||
<td><%= repository.url %></td>
|
<td><%= repository.scm_name %></td>
|
||||||
<td class="buttons">
|
<td><%= repository.url %></td>
|
||||||
<% if User.current.allowed_to?(:manage_repository, @project) %>
|
<td class="buttons">
|
||||||
<%= link_to(l(:label_user_plural), committers_repository_path(repository),
|
<% if User.current.allowed_to?(:manage_repository, @project) %>
|
||||||
:class => 'icon icon-user') %>
|
<%= link_to(l(:label_user_plural), committers_repository_path(repository),
|
||||||
<%= link_to(l(:button_edit), edit_repository_path(repository),
|
:class => 'icon icon-user') %>
|
||||||
:class => 'icon icon-edit') %>
|
<%= link_to(l(:button_edit), edit_repository_path(repository),
|
||||||
<%= delete_link repository_path(repository) %>
|
:class => 'icon icon-edit') %>
|
||||||
<% end %>
|
<%= delete_link repository_path(repository) %>
|
||||||
</td>
|
<% end %>
|
||||||
</tr>
|
</td>
|
||||||
<% end %>
|
</tr>
|
||||||
</tbody>
|
<% end %>
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -33,7 +33,9 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wiki changeset-comments"><%= format_changeset_comments @changeset %></div>
|
<div class="wiki changeset-comments">
|
||||||
|
<%= format_changeset_comments @changeset %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<% if @changeset.issues.visible.any? || User.current.allowed_to?(:manage_related_issues, @repository.project) %>
|
<% if @changeset.issues.visible.any? || User.current.allowed_to?(:manage_related_issues, @repository.project) %>
|
||||||
<%= render :partial => 'related_issues' %>
|
<%= render :partial => 'related_issues' %>
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
</p>
|
</p>
|
||||||
<%= hidden_field_tag 'tracker[core_fields][]', '' %>
|
<%= hidden_field_tag 'tracker[core_fields][]', '' %>
|
||||||
|
|
||||||
<% if IssueCustomField.all.any? %>
|
<% @issue_custom_fields = IssueCustomField.sorted %>
|
||||||
|
<% if @issue_custom_fields.present? %>
|
||||||
<p>
|
<p>
|
||||||
<label><%= l(:label_custom_field_plural) %></label>
|
<label><%= l(:label_custom_field_plural) %></label>
|
||||||
<% IssueCustomField.all.each do |field| %>
|
<% @issue_custom_fields.each do |field| %>
|
||||||
<label class="block">
|
<label class="block">
|
||||||
<%= check_box_tag 'tracker[custom_field_ids][]',field.id, @tracker.custom_fields.to_a.include?(field), :id => nil %>
|
<%= check_box_tag 'tracker[custom_field_ids][]',field.id, @tracker.custom_fields.to_a.include?(field), :id => nil %>
|
||||||
<%= field.name %>
|
<%= field.name %>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
<% if User.current.logged? %>
|
|
||||||
|
|
||||||
<h2><%= l(:label_home) %></h2>
|
<h2><%= l(:label_home) %></h2>
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
|
@ -26,149 +24,3 @@
|
||||||
<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :key => User.current.rss_key, :format => 'atom'},
|
<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :key => User.current.rss_key, :format => 'atom'},
|
||||||
:title => "#{Setting.app_title}: #{l(:label_activity)}") %>
|
:title => "#{Setting.app_title}: #{l(:label_activity)}") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% else %><!-- Frontpage -->
|
|
||||||
|
|
||||||
<div id="fp"><%= text_field_tag 'forcetop', nil, :style => 'display: none;' %>
|
|
||||||
|
|
||||||
<!-- Banner -->
|
|
||||||
<section id="fp-banner">
|
|
||||||
<div class="inner">
|
|
||||||
<h2>SuitePro</h2>
|
|
||||||
<p><%= l(:welcome_suitepro) %></p>
|
|
||||||
<ul class="actions special">
|
|
||||||
<li><a href="#fp-login" class="button primary scrolly"><%= l(:label_login) %></a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<a href="#one" class="more scrolly"><%= l(:welcome_discover) %></a>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- One -->
|
|
||||||
<section id="one" class="frapper style1 special">
|
|
||||||
<div class="inner">
|
|
||||||
<header class="major">
|
|
||||||
<h2>A SIMPLE WAY TO GET WORK DONE ;)</h2>
|
|
||||||
<p><%= raw l(:welcome_suitepro_is_redmine, :suitepro => '<strong>SuitePro</strong>', :redmine => '<a href="https://www.redmine.org"><strong>Redmine</strong></a>') %></p>
|
|
||||||
</header>
|
|
||||||
<ul class="icons major">
|
|
||||||
<li><span class="fp-icon fp-icon_1 major style1"><span class="label">Lorem</span></span></li>
|
|
||||||
<li><span class="fp-icon fp-icon_2 major style2"><span class="label">Ipsum</span></span></li>
|
|
||||||
<li><span class="fp-icon fp-icon_3 major style3"><span class="label">Dolor</span></span></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Two -->
|
|
||||||
<section id="two" class="frapper alt style2">
|
|
||||||
<section class="spotlight">
|
|
||||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic01.jpg' %></div><div class="content">
|
|
||||||
<h2><%= raw l(:welcome_spotlight_1_title) %></h2>
|
|
||||||
<p><%= l(:welcome_spotlight_1_text) %></p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="spotlight">
|
|
||||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic02.jpg' %></div><div class="content">
|
|
||||||
<h2><%= raw l(:welcome_spotlight_2_title) %></h2>
|
|
||||||
<p><%= l(:welcome_spotlight_2_text) %></p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="spotlight">
|
|
||||||
<div class="image"><%= image_tag '/themes/circlepro/images/pic03.jpg' %></div><div class="content">
|
|
||||||
<h2><%= raw l(:welcome_spotlight_3_title) %></h2>
|
|
||||||
<p><%= l(:welcome_spotlight_3_text) %></p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Three -->
|
|
||||||
<section id="three" class="frapper style3 special">
|
|
||||||
<div class="inner">
|
|
||||||
<header class="major">
|
|
||||||
<h2><%= l(:welcome_other_features) %></h2>
|
|
||||||
</header>
|
|
||||||
<ul class="features">
|
|
||||||
<li class="fp-icon fp-icon_4">
|
|
||||||
<h3><%= l(:welcome_feature_1_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_1_text) %></p>
|
|
||||||
</li>
|
|
||||||
<li class="fp-icon fp-icon_5">
|
|
||||||
<h3><%= l(:welcome_feature_2_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_2_text) %></p>
|
|
||||||
</li>
|
|
||||||
<li class="fp-icon fp-icon_6">
|
|
||||||
<h3><%= l(:welcome_feature_3_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_3_text) %></p>
|
|
||||||
</li>
|
|
||||||
<li class="fp-icon fp-icon_7">
|
|
||||||
<h3><%= l(:welcome_feature_4_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_4_text) %></p>
|
|
||||||
</li>
|
|
||||||
<li class="fp-icon fp-icon_8">
|
|
||||||
<h3><%= l(:welcome_feature_5_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_5_text) %></p>
|
|
||||||
</li>
|
|
||||||
<li class="fp-icon fp-icon_9">
|
|
||||||
<h3><%= l(:welcome_feature_6_title) %></h3>
|
|
||||||
<p><%= l(:welcome_feature_6_text) %></p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<section id="fp-login" class="frapper style4">
|
|
||||||
<div class="inner">
|
|
||||||
<%= call_hook :view_account_login_top %>
|
|
||||||
|
|
||||||
<div id="login-form">
|
|
||||||
<h2><%= l(:label_login) %></h2>
|
|
||||||
<%= form_tag(signin_path, onsubmit: 'return keepAnchorOnSignIn(this);') do %>
|
|
||||||
<%= back_url_hidden_field_tag %>
|
|
||||||
|
|
||||||
<label for="username"><%=l(:field_login)%></label>
|
|
||||||
<%= text_field_tag 'username', params[:username], :tabindex => '1' %>
|
|
||||||
|
|
||||||
<label for="password">
|
|
||||||
<%=l(:field_password)%>
|
|
||||||
<%= link_to l(:label_password_lost), lost_password_path, :class => "lost_password" if Setting.lost_password? %>
|
|
||||||
</label>
|
|
||||||
<%= password_field_tag 'password', nil, :tabindex => '2' %>
|
|
||||||
|
|
||||||
<% if Setting.openid? %>
|
|
||||||
<label for="openid_url"><%=l(:field_identity_url)%></label>
|
|
||||||
<%= text_field_tag "openid_url", nil, :tabindex => '3' %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if Setting.autologin? %>
|
|
||||||
<label for="autologin"><%= check_box_tag 'autologin', 1, false, :tabindex => 4 %> <%= l(:label_stay_logged_in) %></label>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<input type="submit" name="login" value="<%=l(:button_login)%>" tabindex="5" id="login-submit" />
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- CTA -->
|
|
||||||
<section id="fp-cta" class="frapper style4">
|
|
||||||
<div class="inner">
|
|
||||||
<header>
|
|
||||||
<h2><%= l(:welcome_any_questions) %></h2>
|
|
||||||
<p><%= l(:welcome_please_contact) %></p>
|
|
||||||
</header>
|
|
||||||
<ul class="actions stacked">
|
|
||||||
<li><a href="https://manuel.cillero.es/contacto/#suitepro" class="button fit primary"><%= l(:welcome_contact) %></a></li>
|
|
||||||
<li><a href="https://manuel.cillero.es/sobre-mi" class="button fit"><%= l(:welcome_about_me) %></a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="/themes/circlepro/javascripts/frontpage/jquery.scrolly.min.js"></script>
|
|
||||||
<script src="/themes/circlepro/javascripts/frontpage/browser.min.js"></script>
|
|
||||||
<script src="/themes/circlepro/javascripts/frontpage/breakpoints.min.js"></script>
|
|
||||||
<script src="/themes/circlepro/javascripts/frontpage/util.js"></script>
|
|
||||||
<script src="/themes/circlepro/javascripts/frontpage/main.js"></script>
|
|
||||||
|
|
||||||
<% end %>
|
|
||||||
|
|
|
@ -46,8 +46,7 @@
|
||||||
|
|
||||||
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
|
<%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
|
||||||
|
|
||||||
<% if @page.attachments.length > 0 || (@editable && authorize_for('wiki', 'add_attachment')) %>
|
<fieldset class="collapsible collapsed hide-when-print">
|
||||||
<fieldset class="collapsible collapsed<% if @page.attachments.length == 0 %> hide-when-print<% end %>">
|
|
||||||
<legend onclick="toggleFieldset(this);"><%= l(:label_attachment_plural) %> (<%= @page.attachments.length %>)</legend>
|
<legend onclick="toggleFieldset(this);"><%= l(:label_attachment_plural) %> (<%= @page.attachments.length %>)</legend>
|
||||||
<div style="display: none;">
|
<div style="display: none;">
|
||||||
|
|
||||||
|
@ -67,7 +66,6 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% other_formats_links do |f| %>
|
<% other_formats_links do |f| %>
|
||||||
<%= f.link_to 'PDF', :url => {:id => @page.title, :version => params[:version]} %>
|
<%= f.link_to 'PDF', :url => {:id => @page.title, :version => params[:version]} %>
|
||||||
|
|
|
@ -1211,8 +1211,8 @@ de:
|
||||||
label_table_of_contents: Inhaltsverzeichnis
|
label_table_of_contents: Inhaltsverzeichnis
|
||||||
error_no_projects_with_tracker_allowed_for_new_issue: Es gibt keine Projekte mit Trackern, für welche sie Tickets erzeugen können
|
error_no_projects_with_tracker_allowed_for_new_issue: Es gibt keine Projekte mit Trackern, für welche sie Tickets erzeugen können
|
||||||
field_textarea_font: Schriftart für Textbereiche
|
field_textarea_font: Schriftart für Textbereiche
|
||||||
label_font_default: Strandardschrift
|
label_font_default: Standardschrift
|
||||||
label_font_monospace: Nichtproporzionale Schrift
|
label_font_monospace: Nichtproportionale Schrift
|
||||||
label_font_proportional: Proportionale Schrift
|
label_font_proportional: Proportionale Schrift
|
||||||
setting_commit_logs_formatting: Textformatierung für Commit Nachrichten
|
setting_commit_logs_formatting: Textformatierung für Commit Nachrichten
|
||||||
setting_mail_handler_enable_regex_delimiters: Reguläre Ausdrücke erlauben
|
setting_mail_handler_enable_regex_delimiters: Reguläre Ausdrücke erlauben
|
||||||
|
|
|
@ -1209,40 +1209,3 @@ en:
|
||||||
description_issue_category_reassign: Choose issue category
|
description_issue_category_reassign: Choose issue category
|
||||||
description_wiki_subpages_reassign: Choose new parent page
|
description_wiki_subpages_reassign: Choose new parent page
|
||||||
text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.'
|
text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.'
|
||||||
|
|
||||||
welcome_suitepro: Planning, knowledge sharing, clients support and personal productivity, with both powerful and simplicity in mind.
|
|
||||||
welcome_discover: Discover
|
|
||||||
welcome_suitepro_is_redmine: "%{suitepro} is powered by %{redmine}, the popular project management and issue tracking solution based on the Ruby on Rails framework. Redmine lets us have a powerful workflow for getting tasks done and keep information in one place."
|
|
||||||
|
|
||||||
welcome_spotlight_1_title: "The Basics: Projects,<br /> Tasks, Issue Tracking"
|
|
||||||
welcome_spotlight_1_text: Keep track of everything, with visual indicators to monitorize tasks and subtasks in order to stay up to date with milestones, track of time, workflows and all that requires attention.
|
|
||||||
welcome_spotlight_2_title: "Documents, Wikis,<br /> File Management"
|
|
||||||
welcome_spotlight_2_text: Keep documents and files availables wherever you are. Use the wiki project to save project requeriments, attached files, install and user guides, or meeting minutes at your fingertips.
|
|
||||||
welcome_spotlight_3_title: "Flexible control<br /> of user access"
|
|
||||||
welcome_spotlight_3_text: Using a role-based approach, roles are a collection of permissions outlining how users can operate with the projects. Each member of a project can have one or more roles assigned by administrators.
|
|
||||||
|
|
||||||
welcome_other_features: Other Features
|
|
||||||
welcome_feature_1_title: Gantt Chart And Calendar
|
|
||||||
welcome_feature_1_text: The gantt chart displays issues that have a start date and a due date. The calendar provides an overview of a project as a monthly view.
|
|
||||||
welcome_feature_2_title: News And Forums
|
|
||||||
welcome_feature_2_text: News to show information about the status of projects or any other subjects. The forums allow users from a project to communicate with each others.
|
|
||||||
welcome_feature_3_title: Email notifications And Feeds
|
|
||||||
welcome_feature_3_text: SuitePro can be configured to receive notifications via email. It also provides web feeds to use with external readers or aggregators.
|
|
||||||
welcome_feature_4_title: Code Repositories
|
|
||||||
welcome_feature_4_text: Version Control Systems like Git or Subversion can be used as code repositories and also keep track of changes made to the code.
|
|
||||||
welcome_feature_5_title: Responsive Design
|
|
||||||
welcome_feature_5_text: SuitePro is optimized to look great on mobile devices thanks to its responsive design. All pages adapt automatically to the screen size on a mobile phone, tablet or desktop computer.
|
|
||||||
welcome_feature_6_title: Is Open Source Software
|
|
||||||
welcome_feature_6_text: It means you are not locked into using a particular vendor’s system, and it’s continually evolving in real time as developers add to it and modify it.
|
|
||||||
|
|
||||||
welcome_any_questions: Any Questions?
|
|
||||||
welcome_please_contact: Please feel free to contact me if you need any further information.
|
|
||||||
welcome_contact: Contact
|
|
||||||
welcome_about_me: More About Me
|
|
||||||
|
|
||||||
link_my_blog: My Blog
|
|
||||||
|
|
||||||
label_legal: Legal notice
|
|
||||||
label_legal_terms: Terms of use
|
|
||||||
label_legal_privacy: Privacy policy
|
|
||||||
label_legal_cookies: Cookies policy
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ es:
|
||||||
label_loading: Cargando...
|
label_loading: Cargando...
|
||||||
label_logged_as: Conectado como
|
label_logged_as: Conectado como
|
||||||
label_login: Iniciar sesión
|
label_login: Iniciar sesión
|
||||||
label_logout: Cerrar sesión
|
label_logout: Terminar sesión
|
||||||
label_max_size: Tamaño máximo
|
label_max_size: Tamaño máximo
|
||||||
label_me: yo mismo
|
label_me: yo mismo
|
||||||
label_member: Miembro
|
label_member: Miembro
|
||||||
|
@ -543,7 +543,7 @@ es:
|
||||||
label_optional_description: Descripción opcional
|
label_optional_description: Descripción opcional
|
||||||
label_options: Opciones
|
label_options: Opciones
|
||||||
label_overall_activity: Actividad global
|
label_overall_activity: Actividad global
|
||||||
label_overview: Resumen
|
label_overview: Vistazo
|
||||||
label_password_lost: ¿Olvidaste la contraseña?
|
label_password_lost: ¿Olvidaste la contraseña?
|
||||||
label_permissions: Permisos
|
label_permissions: Permisos
|
||||||
label_permissions_report: Informe de permisos
|
label_permissions_report: Informe de permisos
|
||||||
|
@ -1217,7 +1217,7 @@ es:
|
||||||
mail_body_security_notification_notify_disabled: Se han desactivado las notificaciones para el correo electrónico %{value}
|
mail_body_security_notification_notify_disabled: Se han desactivado las notificaciones para el correo electrónico %{value}
|
||||||
mail_body_settings_updated: ! 'Las siguientes opciones han sido actualizadas:'
|
mail_body_settings_updated: ! 'Las siguientes opciones han sido actualizadas:'
|
||||||
field_remote_ip: Dirección IP
|
field_remote_ip: Dirección IP
|
||||||
label_wiki_page_new: Nueva página
|
label_wiki_page_new: Nueva pagina wiki
|
||||||
label_relations: Relaciones
|
label_relations: Relaciones
|
||||||
button_filter: Filtro
|
button_filter: Filtro
|
||||||
mail_body_password_updated: Su contraseña se ha cambiado.
|
mail_body_password_updated: Su contraseña se ha cambiado.
|
||||||
|
@ -1233,7 +1233,7 @@ es:
|
||||||
label_font_monospace: Fuente Monospaced
|
label_font_monospace: Fuente Monospaced
|
||||||
label_font_proportional: Fuente Proportional
|
label_font_proportional: Fuente Proportional
|
||||||
setting_timespan_format: Time span format
|
setting_timespan_format: Time span format
|
||||||
label_table_of_contents: Tabla de contenidos
|
label_table_of_contents: Table of contents
|
||||||
setting_commit_logs_formatting: Apply text formatting to commit messages
|
setting_commit_logs_formatting: Apply text formatting to commit messages
|
||||||
setting_mail_handler_enable_regex_delimiters: Enable regular expressions
|
setting_mail_handler_enable_regex_delimiters: Enable regular expressions
|
||||||
error_move_of_child_not_possible: 'Subtask %{child} could not be moved to the new
|
error_move_of_child_not_possible: 'Subtask %{child} could not be moved to the new
|
||||||
|
@ -1256,41 +1256,3 @@ es:
|
||||||
permission_view_news: View news
|
permission_view_news: View news
|
||||||
label_no_preview_alternative_html: No preview available. %{link} the file instead.
|
label_no_preview_alternative_html: No preview available. %{link} the file instead.
|
||||||
label_no_preview_download: Download
|
label_no_preview_download: Download
|
||||||
|
|
||||||
|
|
||||||
welcome_suitepro: Potencia y sencillez para planificar, compartir conocimiento, prestar soporte a clientes y acelerar la productividad.
|
|
||||||
welcome_discover: Descubre
|
|
||||||
welcome_suitepro_is_redmine: "%{suitepro} es %{redmine}, la conocida herramienta para la gestión de proyectos y el seguimiento de peticiones basada en Ruby on Rails. Redmine apremia la finalización de las tareas y mantiene la información en un único sitio."
|
|
||||||
|
|
||||||
welcome_spotlight_1_title: "Lo Básico: Proyectos,<br /> Tareas, Peticiones"
|
|
||||||
welcome_spotlight_1_text: Podrás hacer un seguimiento completo de todo, monitorizar tareas y subtareas para estar al día de los hitos de proyecto, controlar los tiempos, los flujos de trabajo o cualquier elemento que requiera atención.
|
|
||||||
welcome_spotlight_2_title: "Documentos, Wikis,<br /> Gestión de Archivos"
|
|
||||||
welcome_spotlight_2_text: Organizados para disponer de los documentos y los archivos allá donde se esté. Y el wiki de proyecto para estructurar los requerimientos, las guías de instalación y de usuario, o las actas de trabajo.
|
|
||||||
welcome_spotlight_3_title: "Control de accesos<br /> flexible"
|
|
||||||
welcome_spotlight_3_text: Usando permisos agrupados en roles para establecer cómo pueden operar los usuarios en los proyectos. Cada miembro de un proyecto podrá tener uno o más roles asignados por los administradores.
|
|
||||||
|
|
||||||
welcome_other_features: Otras Características
|
|
||||||
welcome_feature_1_title: Diagrama de Gantt y Calendario
|
|
||||||
welcome_feature_1_text: El diagrama de Gantt muestra las tareas que tienen fecha de inicio y vencimiento. Y el calendario da una visión general de los proyectos en una vista mensual.
|
|
||||||
welcome_feature_2_title: Noticias y Foros
|
|
||||||
welcome_feature_2_text: Las noticias muestran información sobre novedades en los proyectos u otros temas de interés. Y los foros permiten que los usuarios de un proyecto se comuniquen entre sí.
|
|
||||||
welcome_feature_3_title: Notificaciones y Sindicación
|
|
||||||
welcome_feature_3_text: SuitePro se puede configurar para recibir notificaciones por correo electrónico. Y también proporciona sindicaciones para utilizar con agregadores externos.
|
|
||||||
welcome_feature_4_title: Repositorios de Código
|
|
||||||
welcome_feature_4_text: Sistemas de Control de Versiones como Git o Subversion pueden usarse como repositorios de código y seguir desde SuitePro los cambios realizados en el código.
|
|
||||||
welcome_feature_5_title: Responsive Design
|
|
||||||
welcome_feature_5_text: SuitePro está optimizado para visualizarse en dispositivos móviles. Las páginas se adaptan automáticamente al tamaño de la pantalla, ya sea un teléfono móvil, una tableta o un ordenador.
|
|
||||||
welcome_feature_6_title: Es Software de Código Abierto
|
|
||||||
welcome_feature_6_text: Esto supone no estar limitado por ningún proveedor, y seguir en permanente evolución con desarrolladores que se involucran continuamente.
|
|
||||||
|
|
||||||
welcome_any_questions: ¿Alguna Pregunta?
|
|
||||||
welcome_please_contact: No dudar en contactar conmigo para obtener más información.
|
|
||||||
welcome_contact: Contactar
|
|
||||||
welcome_about_me: Más Sobre Mí
|
|
||||||
|
|
||||||
link_my_blog: Mi blog personal
|
|
||||||
|
|
||||||
label_legal: Aviso legal
|
|
||||||
label_legal_terms: Condiciones de uso
|
|
||||||
label_legal_privacy: Política de privacidad
|
|
||||||
label_legal_cookies: Uso de cookies
|
|
||||||
|
|
|
@ -140,8 +140,8 @@ gl:
|
||||||
invalid: "non é válido"
|
invalid: "non é válido"
|
||||||
confirmation: "non coincide coa confirmación"
|
confirmation: "non coincide coa confirmación"
|
||||||
accepted: "debe ser aceptado"
|
accepted: "debe ser aceptado"
|
||||||
empty: "non pode estar valeiro"
|
empty: "non pode estar baleiro"
|
||||||
blank: "non pode estar en blanco"
|
blank: "non pode estar en branco"
|
||||||
too_long: "é demasiado longo (non máis de %{count} carácteres)"
|
too_long: "é demasiado longo (non máis de %{count} carácteres)"
|
||||||
too_short: "é demasiado curto (non menos de %{count} carácteres)"
|
too_short: "é demasiado curto (non menos de %{count} carácteres)"
|
||||||
wrong_length: "non ten a lonxitude correcta (debe ser de %{count} carácteres)"
|
wrong_length: "non ten a lonxitude correcta (debe ser de %{count} carácteres)"
|
||||||
|
@ -426,7 +426,7 @@ gl:
|
||||||
label_f_hour: "%{value} hora"
|
label_f_hour: "%{value} hora"
|
||||||
label_f_hour_plural: "%{value} horas"
|
label_f_hour_plural: "%{value} horas"
|
||||||
label_feed_plural: Feeds
|
label_feed_plural: Feeds
|
||||||
label_feeds_access_key_created_on: "Clave de acceso por Atom creada hai %{value}"
|
label_feeds_access_key_created_on: "Chave de acceso por Atom creada hai %{value}"
|
||||||
label_file_added: Ficheiro engadido
|
label_file_added: Ficheiro engadido
|
||||||
label_file_plural: Ficheiros
|
label_file_plural: Ficheiros
|
||||||
label_filter_add: Engadir o filtro
|
label_filter_add: Engadir o filtro
|
||||||
|
@ -435,7 +435,7 @@ gl:
|
||||||
label_follows: posterior a
|
label_follows: posterior a
|
||||||
label_gantt: Gantt
|
label_gantt: Gantt
|
||||||
label_general: Xeral
|
label_general: Xeral
|
||||||
label_generate_key: Xerar clave
|
label_generate_key: Xerar chave
|
||||||
label_help: Axuda
|
label_help: Axuda
|
||||||
label_history: Histórico
|
label_history: Histórico
|
||||||
label_home: Inicio
|
label_home: Inicio
|
||||||
|
@ -648,7 +648,7 @@ gl:
|
||||||
notice_email_error: "Ocorreu un error enviando o correo (%{value})"
|
notice_email_error: "Ocorreu un error enviando o correo (%{value})"
|
||||||
notice_email_sent: "Enviouse un correo a %{value}"
|
notice_email_sent: "Enviouse un correo a %{value}"
|
||||||
notice_failed_to_save_issues: "Imposible gravar %{count} petición(s) de %{total} seleccionada(s): %{ids}."
|
notice_failed_to_save_issues: "Imposible gravar %{count} petición(s) de %{total} seleccionada(s): %{ids}."
|
||||||
notice_feeds_access_key_reseted: A súa clave de acceso para Atom reiniciouse.
|
notice_feeds_access_key_reseted: A súa chave de acceso para Atom reiniciouse.
|
||||||
notice_file_not_found: A páxina á que tenta acceder non existe.
|
notice_file_not_found: A páxina á que tenta acceder non existe.
|
||||||
notice_locking_conflict: Os datos modificáronse por outro usuario.
|
notice_locking_conflict: Os datos modificáronse por outro usuario.
|
||||||
notice_no_issue_selected: "Ningunha petición seleccionada. Por favor, comprobe a petición que quere modificar"
|
notice_no_issue_selected: "Ningunha petición seleccionada. Por favor, comprobe a petición que quere modificar"
|
||||||
|
@ -720,8 +720,8 @@ gl:
|
||||||
setting_autofetch_changesets: Autorechear as remisións do repositorio
|
setting_autofetch_changesets: Autorechear as remisións do repositorio
|
||||||
setting_autologin: "Identificarse automaticamente."
|
setting_autologin: "Identificarse automaticamente."
|
||||||
setting_bcc_recipients: Ocultar as copias de carbón (bcc)
|
setting_bcc_recipients: Ocultar as copias de carbón (bcc)
|
||||||
setting_commit_fix_keywords: Palabras clave para a corrección
|
setting_commit_fix_keywords: Palabras chave para a corrección
|
||||||
setting_commit_ref_keywords: Palabras clave para a referencia
|
setting_commit_ref_keywords: Palabras chave para a referencia
|
||||||
setting_cross_project_issue_relations: Permitir relacionar peticións de distintos proxectos
|
setting_cross_project_issue_relations: Permitir relacionar peticións de distintos proxectos
|
||||||
setting_date_format: Formato da data
|
setting_date_format: Formato da data
|
||||||
setting_default_language: Idioma predeterminado
|
setting_default_language: Idioma predeterminado
|
||||||
|
@ -738,7 +738,7 @@ gl:
|
||||||
setting_login_required: Requírese identificación
|
setting_login_required: Requírese identificación
|
||||||
setting_mail_from: Correo dende o que enviar mensaxes
|
setting_mail_from: Correo dende o que enviar mensaxes
|
||||||
setting_mail_handler_api_enabled: Activar o programa para mensaxes entrantes
|
setting_mail_handler_api_enabled: Activar o programa para mensaxes entrantes
|
||||||
setting_mail_handler_api_key: Clave da API
|
setting_mail_handler_api_key: Chave da API
|
||||||
setting_per_page_options: Obxectos por páxina
|
setting_per_page_options: Obxectos por páxina
|
||||||
setting_plain_text_mail: só texto plano (non HTML)
|
setting_plain_text_mail: só texto plano (non HTML)
|
||||||
setting_protocol: Protocolo
|
setting_protocol: Protocolo
|
||||||
|
@ -1121,118 +1121,118 @@ gl:
|
||||||
setting_link_copied_issue: "Ligar aos tíckets ao copialos"
|
setting_link_copied_issue: "Ligar aos tíckets ao copialos"
|
||||||
label_link_copied_issue: "Ligar ao tícket copiado"
|
label_link_copied_issue: "Ligar ao tícket copiado"
|
||||||
label_ask: "Preguntar"
|
label_ask: "Preguntar"
|
||||||
label_search_attachments_yes: Search attachment filenames and descriptions
|
label_search_attachments_yes: Buscar nomes e descricións dos ficheiros
|
||||||
label_search_attachments_no: Do not search attachments
|
label_search_attachments_no: Non buscar ficheiros
|
||||||
label_search_attachments_only: Search attachments only
|
label_search_attachments_only: Buscar só ficheiros
|
||||||
label_search_open_issues_only: Open issues only
|
label_search_open_issues_only: Só peticións abertas
|
||||||
field_address: Correo electrónico
|
field_address: Correo electrónico
|
||||||
setting_max_additional_emails: Maximum number of additional email addresses
|
setting_max_additional_emails: Máximo número de enderezos de correo adicionais
|
||||||
label_email_address_plural: Emails
|
label_email_address_plural: Correos
|
||||||
label_email_address_add: Add email address
|
label_email_address_add: Engadir enderezo de correo
|
||||||
label_enable_notifications: Enable notifications
|
label_enable_notifications: Activar notificacións
|
||||||
label_disable_notifications: Disable notifications
|
label_disable_notifications: Desactivar notificacións
|
||||||
setting_search_results_per_page: Search results per page
|
setting_search_results_per_page: Resultados da busca por páxina
|
||||||
label_blank_value: blank
|
label_blank_value: En branco
|
||||||
permission_copy_issues: Copy issues
|
permission_copy_issues: Copiar peticións
|
||||||
error_password_expired: Your password has expired or the administrator requires you
|
error_password_expired: A túa contrasinal caducou ou o administrador obrígate
|
||||||
to change it.
|
a cambiala.
|
||||||
field_time_entries_visibility: Time logs visibility
|
field_time_entries_visibility: Visibilidade das entradas de tempo
|
||||||
setting_password_max_age: Require password change after
|
setting_password_max_age: Obrigar a cambiar a contrasinal despois de
|
||||||
label_parent_task_attributes: Parent tasks attributes
|
label_parent_task_attributes: Atributos da tarefa pai
|
||||||
label_parent_task_attributes_derived: Calculated from subtasks
|
label_parent_task_attributes_derived: Calculada a partir das subtarefas
|
||||||
label_parent_task_attributes_independent: Independent of subtasks
|
label_parent_task_attributes_independent: Independente das subtarefas
|
||||||
label_time_entries_visibility_all: All time entries
|
label_time_entries_visibility_all: Todas as entradas de tempo
|
||||||
label_time_entries_visibility_own: Time entries created by the user
|
label_time_entries_visibility_own: Horas creadas polo usuario
|
||||||
label_member_management: Member management
|
label_member_management: Xestión de membros
|
||||||
label_member_management_all_roles: All roles
|
label_member_management_all_roles: Todos os roles
|
||||||
label_member_management_selected_roles_only: Only these roles
|
label_member_management_selected_roles_only: Só estes roles
|
||||||
label_password_required: Confirm your password to continue
|
label_password_required: Confirma a túa contrasinal para continuar
|
||||||
label_total_spent_time: "Tempo total empregado"
|
label_total_spent_time: "Tempo total empregado"
|
||||||
notice_import_finished: "%{count} items have been imported"
|
notice_import_finished: "%{count} elementos foron importados"
|
||||||
notice_import_finished_with_errors: "%{count} out of %{total} items could not be imported"
|
notice_import_finished_with_errors: "%{count} dun total de %{total} elementos non puideron ser importados"
|
||||||
error_invalid_file_encoding: The file is not a valid %{encoding} encoded file
|
error_invalid_file_encoding: O ficheiro non é un ficheiro codificado %{encoding} válido
|
||||||
error_invalid_csv_file_or_settings: The file is not a CSV file or does not match the
|
error_invalid_csv_file_or_settings: O ficheiro non é un arquivo CSV ou non coincide coas
|
||||||
settings below
|
opcións de abaixo
|
||||||
error_can_not_read_import_file: An error occurred while reading the file to import
|
error_can_not_read_import_file: Aconteceu un erro lendo o ficheiro a importar
|
||||||
permission_import_issues: Import issues
|
permission_import_issues: Importar peticións
|
||||||
label_import_issues: Import issues
|
label_import_issues: Importar peticións
|
||||||
label_select_file_to_import: Select the file to import
|
label_select_file_to_import: Selecciona o ficheiro a importar
|
||||||
label_fields_separator: Field separator
|
label_fields_separator: Separador dos campos
|
||||||
label_fields_wrapper: Field wrapper
|
label_fields_wrapper: Envoltorio dos campos
|
||||||
label_encoding: Encoding
|
label_encoding: Codificación
|
||||||
label_comma_char: Comma
|
label_comma_char: Coma
|
||||||
label_semi_colon_char: Semicolon
|
label_semi_colon_char: Punto e coma
|
||||||
label_quote_char: Quote
|
label_quote_char: Comilla simple
|
||||||
label_double_quote_char: Double quote
|
label_double_quote_char: Comilla dobre
|
||||||
label_fields_mapping: Fields mapping
|
label_fields_mapping: Mapeo de campos
|
||||||
label_file_content_preview: File content preview
|
label_file_content_preview: Vista previa do contido
|
||||||
label_create_missing_values: Create missing values
|
label_create_missing_values: Crear valores non presentes
|
||||||
button_import: Import
|
button_import: Importar
|
||||||
field_total_estimated_hours: Total estimated time
|
field_total_estimated_hours: Total de tempo estimado
|
||||||
label_api: API
|
label_api: API
|
||||||
label_total_plural: Totals
|
label_total_plural: Totais
|
||||||
label_assigned_issues: Assigned issues
|
label_assigned_issues: Peticións asignadas
|
||||||
label_field_format_enumeration: Key/value list
|
label_field_format_enumeration: Listaxe chave/valor
|
||||||
label_f_hour_short: '%{value} h'
|
label_f_hour_short: '%{value} h'
|
||||||
field_default_version: Default version
|
field_default_version: Versión predeterminada
|
||||||
error_attachment_extension_not_allowed: Attachment extension %{extension} is not allowed
|
error_attachment_extension_not_allowed: A extensión anexada %{extension} non é permitida
|
||||||
setting_attachment_extensions_allowed: Allowed extensions
|
setting_attachment_extensions_allowed: Extensións permitidas
|
||||||
setting_attachment_extensions_denied: Disallowed extensions
|
setting_attachment_extensions_denied: Extensións prohibidas
|
||||||
label_any_open_issues: any open issues
|
label_any_open_issues: Calquera petición aberta
|
||||||
label_no_open_issues: no open issues
|
label_no_open_issues: Peticións non abertas
|
||||||
label_default_values_for_new_users: Default values for new users
|
label_default_values_for_new_users: Valor predeterminado para novos usuarios
|
||||||
error_ldap_bind_credentials: Invalid LDAP Account/Password
|
error_ldap_bind_credentials: A conta/contrasinal do LDAP non é válida
|
||||||
setting_sys_api_key: Clave da API
|
setting_sys_api_key: Chave da API
|
||||||
setting_lost_password: "Esqueceu o contrasinal?"
|
setting_lost_password: Esqueceu a contrasinal?
|
||||||
mail_subject_security_notification: Security notification
|
mail_subject_security_notification: Notificación de seguridade
|
||||||
mail_body_security_notification_change: ! '%{field} was changed.'
|
mail_body_security_notification_change: ! '%{field} modificado.'
|
||||||
mail_body_security_notification_change_to: ! '%{field} was changed to %{value}.'
|
mail_body_security_notification_change_to: ! '%{field} modificado por %{value}.'
|
||||||
mail_body_security_notification_add: ! '%{field} %{value} was added.'
|
mail_body_security_notification_add: ! '%{field} %{value} engadido.'
|
||||||
mail_body_security_notification_remove: ! '%{field} %{value} was removed.'
|
mail_body_security_notification_remove: ! '%{field} %{value} eliminado.'
|
||||||
mail_body_security_notification_notify_enabled: Email address %{value} now receives
|
mail_body_security_notification_notify_enabled: O correo electrónico %{value} agora recibirá
|
||||||
notifications.
|
notificacións
|
||||||
mail_body_security_notification_notify_disabled: Email address %{value} no longer
|
mail_body_security_notification_notify_disabled: O correo electrónico %{value} deixará de recibir
|
||||||
receives notifications.
|
notificacións
|
||||||
mail_body_settings_updated: ! 'The following settings were changed:'
|
mail_body_settings_updated: ! 'As seguintes opcións foron actualizadas:'
|
||||||
field_remote_ip: IP address
|
field_remote_ip: Enderezo IP
|
||||||
label_wiki_page_new: New wiki page
|
label_wiki_page_new: Nova páxina wiki
|
||||||
label_relations: Relations
|
label_relations: Relacións
|
||||||
button_filter: Filter
|
button_filter: Filtro
|
||||||
mail_body_password_updated: Your password has been changed.
|
mail_body_password_updated: A súa contrasinal foi cambiada.
|
||||||
label_no_preview: No preview available
|
label_no_preview: Non hai vista previa dispoñible
|
||||||
error_no_tracker_allowed_for_new_issue_in_project: The project doesn't have any trackers
|
error_no_tracker_allowed_for_new_issue_in_project: O proxecto non ten ningún tipo
|
||||||
for which you can create an issue
|
para que poida crear unha petición
|
||||||
label_tracker_all: All trackers
|
label_tracker_all: Tódolos tipos
|
||||||
label_new_project_issue_tab_enabled: Display the "New issue" tab
|
label_new_project_issue_tab_enabled: Amosar a lapela "Nova petición"
|
||||||
setting_new_item_menu_tab: Project menu tab for creating new objects
|
setting_new_item_menu_tab: Lapela no menú de cada proxecto para creación de novos obxectos
|
||||||
label_new_object_tab_enabled: Display the "+" drop-down
|
label_new_object_tab_enabled: Amosar a lista despregable "+"
|
||||||
error_no_projects_with_tracker_allowed_for_new_issue: There are no projects with trackers
|
error_no_projects_with_tracker_allowed_for_new_issue: Non hai proxectos con tipos
|
||||||
for which you can create an issue
|
para as que poida crear unha petición
|
||||||
field_textarea_font: Font used for text areas
|
field_textarea_font: Fonte usada nas áreas de texto
|
||||||
label_font_default: Default font
|
label_font_default: Fonte por defecto
|
||||||
label_font_monospace: Monospaced font
|
label_font_monospace: Fonte Monospaced
|
||||||
label_font_proportional: Proportional font
|
label_font_proportional: Fonte Proporcional
|
||||||
setting_timespan_format: Time span format
|
setting_timespan_format: Formato de período temporal
|
||||||
label_table_of_contents: Table of contents
|
label_table_of_contents: Índice de contidos
|
||||||
setting_commit_logs_formatting: Apply text formatting to commit messages
|
setting_commit_logs_formatting: Aplicar formateo de texto para as mensaxes de commit
|
||||||
setting_mail_handler_enable_regex_delimiters: Enable regular expressions
|
setting_mail_handler_enable_regex_delimiters: Activar expresións regulares
|
||||||
error_move_of_child_not_possible: 'Subtask %{child} could not be moved to the new
|
error_move_of_child_not_possible: 'A subtarefa %{child} non se pode mover ao novo
|
||||||
project: %{errors}'
|
proxecto: %{errors}'
|
||||||
error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
|
error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: O tempo empregado non pode
|
||||||
be reassigned to an issue that is about to be deleted
|
ser reasignado a unha petición que vai ser eliminada
|
||||||
setting_timelog_required_fields: Required fields for time logs
|
setting_timelog_required_fields: Campos obrigatorios para as imputacións de tempo
|
||||||
label_attribute_of_object: '%{object_name}''s %{name}'
|
label_attribute_of_object: '%{object_name}''s %{name}'
|
||||||
label_user_mail_option_only_assigned: Only for things I watch or I am assigned to
|
label_user_mail_option_only_assigned: Só para as cousas que sigo ou que teño asignado
|
||||||
label_user_mail_option_only_owner: Only for things I watch or I am the owner of
|
label_user_mail_option_only_owner: Só para as cousas que sigo ou son o propietario
|
||||||
warning_fields_cleared_on_bulk_edit: Changes will result in the automatic deletion
|
warning_fields_cleared_on_bulk_edit: Os cambios provocarán o borrado automático
|
||||||
of values from one or more fields on the selected objects
|
dos valores de un ou máis campos dos obxectos seleccionados
|
||||||
field_updated_by: Updated by
|
field_updated_by: Actualizado por
|
||||||
field_last_updated_by: Last updated by
|
field_last_updated_by: Última actualización por
|
||||||
field_full_width_layout: Full width layout
|
field_full_width_layout: Deseño para ancho completo
|
||||||
label_last_notes: Last notes
|
label_last_notes: Últimas notas
|
||||||
field_digest: Checksum
|
field_digest: Suma de verificación
|
||||||
field_default_assigned_to: Default assignee
|
field_default_assigned_to: Asignado por defecto
|
||||||
setting_show_custom_fields_on_registration: Show custom fields on registration
|
setting_show_custom_fields_on_registration: Amosar os campos personalizados no rexistro
|
||||||
permission_view_news: View news
|
permission_view_news: Ver noticias
|
||||||
label_no_preview_alternative_html: No preview available. %{link} the file instead.
|
label_no_preview_alternative_html: Non hai vista previa dispoñible. %{link} o ficheiro no seu lugar.
|
||||||
label_no_preview_download: Download
|
label_no_preview_download: Descargar
|
||||||
|
|
|
@ -618,7 +618,7 @@ ja:
|
||||||
one: 1コメント
|
one: 1コメント
|
||||||
other: "%{count}コメント"
|
other: "%{count}コメント"
|
||||||
label_comment_add: コメント追加
|
label_comment_add: コメント追加
|
||||||
label_comment_added: 追加されたコメント
|
label_comment_added: コメントが追加されました
|
||||||
label_comment_delete: コメント削除
|
label_comment_delete: コメント削除
|
||||||
label_query: カスタムクエリ
|
label_query: カスタムクエリ
|
||||||
label_query_plural: カスタムクエリ
|
label_query_plural: カスタムクエリ
|
||||||
|
|
|
@ -890,7 +890,7 @@ lt:
|
||||||
label_version_sharing_none: Nesidalinama
|
label_version_sharing_none: Nesidalinama
|
||||||
label_version_sharing_descendants: Su sub-projektais
|
label_version_sharing_descendants: Su sub-projektais
|
||||||
label_version_sharing_hierarchy: Su projekto hierarchija
|
label_version_sharing_hierarchy: Su projekto hierarchija
|
||||||
label_version_sharing_tree: WiSu projekto medžiu
|
label_version_sharing_tree: Su projekto medžiu
|
||||||
label_version_sharing_system: Su visais projektais
|
label_version_sharing_system: Su visais projektais
|
||||||
label_update_issue_done_ratios: Atnaujinti darbo atlikimo progresą
|
label_update_issue_done_ratios: Atnaujinti darbo atlikimo progresą
|
||||||
label_copy_source: Šaltinis
|
label_copy_source: Šaltinis
|
||||||
|
|
|
@ -149,9 +149,9 @@ pt-BR:
|
||||||
not_same_project: "não pertence ao mesmo projeto"
|
not_same_project: "não pertence ao mesmo projeto"
|
||||||
circular_dependency: "Esta relação geraria uma dependência circular"
|
circular_dependency: "Esta relação geraria uma dependência circular"
|
||||||
cant_link_an_issue_with_a_descendant: "Uma tarefa não pode ser relacionada a uma de suas subtarefas"
|
cant_link_an_issue_with_a_descendant: "Uma tarefa não pode ser relacionada a uma de suas subtarefas"
|
||||||
earlier_than_minimum_start_date: "cannot be earlier than %{date} because of preceding issues"
|
earlier_than_minimum_start_date: "não pode ser anterior a %{date} por causa de tarefas anteriores"
|
||||||
not_a_regexp: "is not a valid regular expression"
|
not_a_regexp: "não é uma expressão regular válida"
|
||||||
open_issue_with_closed_parent: "An open issue cannot be attached to a closed parent task"
|
open_issue_with_closed_parent: "Uma tarefa aberta não pode ser associada à uma tarefa pai fechada"
|
||||||
|
|
||||||
actionview_instancetag_blank_option: Selecione
|
actionview_instancetag_blank_option: Selecione
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ pt-BR:
|
||||||
general_text_Yes: 'Sim'
|
general_text_Yes: 'Sim'
|
||||||
general_text_no: 'não'
|
general_text_no: 'não'
|
||||||
general_text_yes: 'sim'
|
general_text_yes: 'sim'
|
||||||
general_lang_name: 'Portuguese/Brasil (Português/Brasil)'
|
general_lang_name: 'Portuguese/Brazil (Português/Brasil)'
|
||||||
general_csv_separator: ';'
|
general_csv_separator: ';'
|
||||||
general_csv_decimal_separator: ','
|
general_csv_decimal_separator: ','
|
||||||
general_csv_encoding: ISO-8859-1
|
general_csv_encoding: ISO-8859-1
|
||||||
|
@ -1125,7 +1125,7 @@ pt-BR:
|
||||||
label_group_non_member: Usuários não membros
|
label_group_non_member: Usuários não membros
|
||||||
label_add_projects: Adicionar projetos
|
label_add_projects: Adicionar projetos
|
||||||
field_default_status: Situação padrão
|
field_default_status: Situação padrão
|
||||||
text_subversion_repository_note: 'Examplos: file:///, http://, https://, svn://, svn+[tunnelscheme]://'
|
text_subversion_repository_note: 'Exemplos: file:///, http://, https://, svn://, svn+[tunnelscheme]://'
|
||||||
field_users_visibility: Visibilidade do usuário
|
field_users_visibility: Visibilidade do usuário
|
||||||
label_users_visibility_all: Todos usuários ativos
|
label_users_visibility_all: Todos usuários ativos
|
||||||
label_users_visibility_members_of_visible_projects: Membros de projetos visíveis
|
label_users_visibility_members_of_visible_projects: Membros de projetos visíveis
|
||||||
|
|
|
@ -1166,7 +1166,7 @@ ru:
|
||||||
label_cross_project_system: Со всеми проектами
|
label_cross_project_system: Со всеми проектами
|
||||||
button_hide: Скрыть
|
button_hide: Скрыть
|
||||||
setting_non_working_week_days: Нерабочие дни
|
setting_non_working_week_days: Нерабочие дни
|
||||||
label_in_the_next_days: в средующие дни
|
label_in_the_next_days: в следующие дни
|
||||||
label_in_the_past_days: в прошлые дни
|
label_in_the_past_days: в прошлые дни
|
||||||
label_attribute_of_user: Пользователь %{name}
|
label_attribute_of_user: Пользователь %{name}
|
||||||
text_turning_multiple_off: Если отключить множественные значения, лишние значения из списка будут удалены, чтобы осталось только по одному значению.
|
text_turning_multiple_off: Если отключить множественные значения, лишние значения из списка будут удалены, чтобы осталось только по одному значению.
|
||||||
|
|
|
@ -134,7 +134,7 @@ sv:
|
||||||
not_same_project: "tillhör inte samma projekt"
|
not_same_project: "tillhör inte samma projekt"
|
||||||
circular_dependency: "Denna relation skulle skapa ett cirkulärt beroende"
|
circular_dependency: "Denna relation skulle skapa ett cirkulärt beroende"
|
||||||
cant_link_an_issue_with_a_descendant: "Ett ärende kan inte länkas till ett av dess underärenden"
|
cant_link_an_issue_with_a_descendant: "Ett ärende kan inte länkas till ett av dess underärenden"
|
||||||
earlier_than_minimum_start_date: "kan inte vara tidigare än% {datum} på grund av föregående ärenden"
|
earlier_than_minimum_start_date: "kan inte vara tidigare än %{date} på grund av föregående ärenden"
|
||||||
not_a_regexp: "is not a valid regular expression"
|
not_a_regexp: "is not a valid regular expression"
|
||||||
open_issue_with_closed_parent: "An open issue cannot be attached to a closed parent task"
|
open_issue_with_closed_parent: "An open issue cannot be attached to a closed parent task"
|
||||||
|
|
||||||
|
|
|
@ -1215,12 +1215,12 @@ uk:
|
||||||
field_updated_by: Оновлено
|
field_updated_by: Оновлено
|
||||||
field_last_updated_by: Востаннє оновлено
|
field_last_updated_by: Востаннє оновлено
|
||||||
field_full_width_layout: Макет на повну ширину
|
field_full_width_layout: Макет на повну ширину
|
||||||
label_user_mail_option_only_assigned: Only for things I watch or I am assigned to
|
label_user_mail_option_only_assigned: Лише для об'єктів за якими я спостерігаю або до яких прикріплений
|
||||||
label_user_mail_option_only_owner: Only for things I watch or I am the owner of
|
label_user_mail_option_only_owner: Лише для об'єктів за якими я спостерігаю або є власником
|
||||||
label_last_notes: Last notes
|
label_last_notes: Останні коментарі
|
||||||
field_digest: Checksum
|
field_digest: Контрольна сума
|
||||||
field_default_assigned_to: Default assignee
|
field_default_assigned_to: Призначити по замовчуванню
|
||||||
setting_show_custom_fields_on_registration: Show custom fields on registration
|
setting_show_custom_fields_on_registration: Показувати додаткові поля при реєстрації
|
||||||
permission_view_news: View news
|
permission_view_news: Переглядати новини
|
||||||
label_no_preview_alternative_html: No preview available. %{link} the file instead.
|
label_no_preview_alternative_html: Попередній перегляд недоступний. %{link} файл натомість.
|
||||||
label_no_preview_download: Download
|
label_no_preview_download: Завантажити
|
||||||
|
|
|
@ -304,7 +304,7 @@ zh:
|
||||||
field_comments_sorting: 显示注释
|
field_comments_sorting: 显示注释
|
||||||
field_parent_title: 上级页面
|
field_parent_title: 上级页面
|
||||||
field_editable: 可编辑
|
field_editable: 可编辑
|
||||||
field_watcher: 跟踪者
|
field_watcher: 关注者
|
||||||
field_identity_url: OpenID URL
|
field_identity_url: OpenID URL
|
||||||
field_content: 内容
|
field_content: 内容
|
||||||
field_group_by: 根据此条件分组
|
field_group_by: 根据此条件分组
|
||||||
|
@ -393,9 +393,9 @@ zh:
|
||||||
permission_save_queries: 保存查询
|
permission_save_queries: 保存查询
|
||||||
permission_view_gantt: 查看甘特图
|
permission_view_gantt: 查看甘特图
|
||||||
permission_view_calendar: 查看日历
|
permission_view_calendar: 查看日历
|
||||||
permission_view_issue_watchers: 查看跟踪者列表
|
permission_view_issue_watchers: 查看关注者列表
|
||||||
permission_add_issue_watchers: 添加跟踪者
|
permission_add_issue_watchers: 添加关注者
|
||||||
permission_delete_issue_watchers: 删除跟踪者
|
permission_delete_issue_watchers: 删除关注者
|
||||||
permission_log_time: 登记工时
|
permission_log_time: 登记工时
|
||||||
permission_view_time_entries: 查看耗时
|
permission_view_time_entries: 查看耗时
|
||||||
permission_edit_time_entries: 编辑耗时
|
permission_edit_time_entries: 编辑耗时
|
||||||
|
@ -675,7 +675,7 @@ zh:
|
||||||
label_options: 选项
|
label_options: 选项
|
||||||
label_copy_workflow_from: 从以下选项复制工作流程
|
label_copy_workflow_from: 从以下选项复制工作流程
|
||||||
label_permissions_report: 权限报表
|
label_permissions_report: 权限报表
|
||||||
label_watched_issues: 跟踪的问题
|
label_watched_issues: 关注的问题
|
||||||
label_related_issues: 相关的问题
|
label_related_issues: 相关的问题
|
||||||
label_applied_status: 应用后的状态
|
label_applied_status: 应用后的状态
|
||||||
label_loading: 载入中...
|
label_loading: 载入中...
|
||||||
|
@ -731,7 +731,7 @@ zh:
|
||||||
label_user_mail_option_all: "收取我的项目的所有通知"
|
label_user_mail_option_all: "收取我的项目的所有通知"
|
||||||
label_user_mail_option_selected: "收取选中项目的所有通知..."
|
label_user_mail_option_selected: "收取选中项目的所有通知..."
|
||||||
label_user_mail_option_none: "不收取任何通知"
|
label_user_mail_option_none: "不收取任何通知"
|
||||||
label_user_mail_option_only_my_events: "只收取我跟踪或参与的项目的通知"
|
label_user_mail_option_only_my_events: "只收取我关注或参与的项目的通知"
|
||||||
label_user_mail_no_self_notified: "不要发送对我自己提交的修改的通知"
|
label_user_mail_no_self_notified: "不要发送对我自己提交的修改的通知"
|
||||||
label_registration_activation_by_email: 通过邮件认证激活帐号
|
label_registration_activation_by_email: 通过邮件认证激活帐号
|
||||||
label_registration_manual_activation: 手动激活帐号
|
label_registration_manual_activation: 手动激活帐号
|
||||||
|
@ -751,7 +751,7 @@ zh:
|
||||||
label_reverse_chronological_order: 按时间顺序(倒序)
|
label_reverse_chronological_order: 按时间顺序(倒序)
|
||||||
label_incoming_emails: 接收邮件
|
label_incoming_emails: 接收邮件
|
||||||
label_generate_key: 生成一个key
|
label_generate_key: 生成一个key
|
||||||
label_issue_watchers: 跟踪者
|
label_issue_watchers: 关注者
|
||||||
label_example: 示例
|
label_example: 示例
|
||||||
label_display: 显示
|
label_display: 显示
|
||||||
label_sort: 排序
|
label_sort: 排序
|
||||||
|
@ -811,8 +811,8 @@ zh:
|
||||||
button_sort: 排序
|
button_sort: 排序
|
||||||
button_log_time: 登记工时
|
button_log_time: 登记工时
|
||||||
button_rollback: 恢复到这个版本
|
button_rollback: 恢复到这个版本
|
||||||
button_watch: 跟踪
|
button_watch: 关注
|
||||||
button_unwatch: 取消跟踪
|
button_unwatch: 取消关注
|
||||||
button_reply: 回复
|
button_reply: 回复
|
||||||
button_archive: 存档
|
button_archive: 存档
|
||||||
button_unarchive: 取消存档
|
button_unarchive: 取消存档
|
||||||
|
@ -866,7 +866,7 @@ zh:
|
||||||
text_issue_category_destroy_question: "有一些问题(%{count} 个)属于此类别。您想进行哪种操作?"
|
text_issue_category_destroy_question: "有一些问题(%{count} 个)属于此类别。您想进行哪种操作?"
|
||||||
text_issue_category_destroy_assignments: 删除问题的所属类别(问题变为无类别)
|
text_issue_category_destroy_assignments: 删除问题的所属类别(问题变为无类别)
|
||||||
text_issue_category_reassign_to: 为问题选择其它类别
|
text_issue_category_reassign_to: 为问题选择其它类别
|
||||||
text_user_mail_option: "对于没有选中的项目,您将只会收到您跟踪或参与的项目的通知(比如说,您是问题的报告者, 或被指派解决此问题)。"
|
text_user_mail_option: "对于没有选中的项目,您将只会收到您关注或参与的项目的通知(比如说,您是问题的报告者, 或被指派解决此问题)。"
|
||||||
text_no_configuration_data: "角色、跟踪标签、问题状态和工作流程还没有设置。\n强烈建议您先载入默认设置,然后在此基础上进行修改。"
|
text_no_configuration_data: "角色、跟踪标签、问题状态和工作流程还没有设置。\n强烈建议您先载入默认设置,然后在此基础上进行修改。"
|
||||||
text_load_default_configuration: 载入默认设置
|
text_load_default_configuration: 载入默认设置
|
||||||
text_status_changed_by_changeset: "已应用到变更列表 %{value}."
|
text_status_changed_by_changeset: "已应用到变更列表 %{value}."
|
||||||
|
@ -1008,7 +1008,7 @@ zh:
|
||||||
text_issue_conflict_resolution_cancel: 取消我所有的变更并重新刷新显示 %{link} 。
|
text_issue_conflict_resolution_cancel: 取消我所有的变更并重新刷新显示 %{link} 。
|
||||||
permission_manage_related_issues: 相关问题管理
|
permission_manage_related_issues: 相关问题管理
|
||||||
field_auth_source_ldap_filter: LDAP 过滤器
|
field_auth_source_ldap_filter: LDAP 过滤器
|
||||||
label_search_for_watchers: 通过查找方式添加跟踪者
|
label_search_for_watchers: 通过查找方式添加关注者
|
||||||
notice_account_deleted: 您的账号已被永久删除(账号已无法恢复)。
|
notice_account_deleted: 您的账号已被永久删除(账号已无法恢复)。
|
||||||
setting_unsubscribe: 允许用户退订
|
setting_unsubscribe: 允许用户退订
|
||||||
button_delete_my_account: 删除我的账号
|
button_delete_my_account: 删除我的账号
|
||||||
|
|
334
doc/CHANGELOG
334
doc/CHANGELOG
|
@ -4,6 +4,340 @@ Redmine - project management software
|
||||||
Copyright (C) 2006-2017 Jean-Philippe Lang
|
Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||||
http://www.redmine.org/
|
http://www.redmine.org/
|
||||||
|
|
||||||
|
== 2019-12-20 v3.4.13
|
||||||
|
|
||||||
|
=== [Attachments]
|
||||||
|
|
||||||
|
* Defect #20277: "Couldn't find template for digesting" error in the log when sending a thumbnail or an attachment
|
||||||
|
|
||||||
|
=== [Gems support]
|
||||||
|
|
||||||
|
* Patch #32592: Require 'mocha/minitest' instead of deprecated 'mocha/setup'
|
||||||
|
|
||||||
|
=== [Text formatting]
|
||||||
|
|
||||||
|
* Patch #25742: Improper markup sanitization in user content for space separated attribute values and different quoting styles
|
||||||
|
|
||||||
|
== 2019-10-19 v3.4.12
|
||||||
|
|
||||||
|
=== [Code cleanup/refactoring]
|
||||||
|
|
||||||
|
* Defect #32022: IssueSubtaskingTest fails with high probability
|
||||||
|
|
||||||
|
=== [Documentation]
|
||||||
|
|
||||||
|
* Defect #32170: Text enclosed in pre tag in Wiki formatting reference is not displayed in monospaced font in Chrome
|
||||||
|
* Defect #32184: Incorrect headings example in Textile help
|
||||||
|
|
||||||
|
=== [Gems support]
|
||||||
|
|
||||||
|
* Defect #32300: Don't use sprockets 4.0.0 in order to avoid Sprockets::Railtie::ManifestNeededError
|
||||||
|
* Patch #32294: Update ruby-openid to 2.9.2
|
||||||
|
|
||||||
|
=== [Issues]
|
||||||
|
|
||||||
|
* Defect #31778: Total estimated time issue query column and issue field might leak information
|
||||||
|
|
||||||
|
=== [Issues list]
|
||||||
|
|
||||||
|
* Defect #31779: Total estimated time column shown even when estimated time field is deactivated
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Defect #32290: Typo in Russian translation for label_in_the_next_days
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #32012: Broken JavaScript icon in the repository view
|
||||||
|
* Defect #32024: Broken gzip icon in the repository view
|
||||||
|
|
||||||
|
== 2019-06-10 v3.4.11
|
||||||
|
|
||||||
|
=== [Administration]
|
||||||
|
|
||||||
|
* Defect #31125: Don't output ImageMagick version information to stdout
|
||||||
|
|
||||||
|
=== [Code cleanup/refactoring]
|
||||||
|
|
||||||
|
* Defect #30811: "rake db:fixtures:load" does not work
|
||||||
|
|
||||||
|
=== [Email receiving]
|
||||||
|
|
||||||
|
* Defect #30457: MailHandler.safe_receive does not output any error log
|
||||||
|
* Defect #31503: Undefined local variable sender_email in MailHandler#receive_message_reply
|
||||||
|
|
||||||
|
=== [Issues filter]
|
||||||
|
|
||||||
|
* Patch #31276: Serialize group_by and totalable_names in Query#as_params
|
||||||
|
|
||||||
|
=== [SCM]
|
||||||
|
|
||||||
|
* Defect #31120: Garbage lines in the output of 'git branch' break git adapter
|
||||||
|
|
||||||
|
=== [Security]
|
||||||
|
|
||||||
|
* Defect #31520: Persistent XSS in textile formatting
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Defect #31264: Conflicting translation between "track" and "watch" in Simplified Chinese
|
||||||
|
|
||||||
|
=== [UI - Responsive]
|
||||||
|
|
||||||
|
* Defect #31153: Display horizontal scroll bar of files table when overflow occurs on small screen
|
||||||
|
* Defect #31311: admin/info page: text cut off in pre tag on mobile
|
||||||
|
|
||||||
|
=== [Wiki]
|
||||||
|
|
||||||
|
* Patch #31334: Do not lose content when updating a wiki page that has been renamed in the meantime
|
||||||
|
|
||||||
|
== 2019-03-31 v3.4.10
|
||||||
|
|
||||||
|
=== [Administration]
|
||||||
|
|
||||||
|
* Defect #30939: Timeout for "Check for updates" on Plugins page is too short
|
||||||
|
|
||||||
|
=== [Files]
|
||||||
|
|
||||||
|
* Defect #31087: Deleting a version silently deletes its attachments
|
||||||
|
|
||||||
|
=== [Issues filter]
|
||||||
|
|
||||||
|
* Defect #30367: "Last updated by" filter causes an SQL error with MariaDB
|
||||||
|
|
||||||
|
=== [REST API]
|
||||||
|
|
||||||
|
* Defect #29055: Searching for issue number with REST API redirects to issue HTML page
|
||||||
|
|
||||||
|
=== [Rails support]
|
||||||
|
|
||||||
|
* Feature #31027: Upgrade to Rails 4.2.11.1
|
||||||
|
|
||||||
|
=== [Search engine]
|
||||||
|
|
||||||
|
* Defect #30923: Project search should select subprojects scope when the project has subprojects
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #30872: Copyright is outdated
|
||||||
|
|
||||||
|
== 2019-02-21 v3.4.9
|
||||||
|
|
||||||
|
=== [Gems support]
|
||||||
|
|
||||||
|
* Defect #30114: Installing xpath with Bundler fails in Ruby <=2.2
|
||||||
|
* Patch #30821: Stay in RMagick 2.16.0 and don't update to 3.0.0
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Patch #30818: Issues autocomplete should respond with content type json
|
||||||
|
|
||||||
|
== 2019-01-20 v3.4.8
|
||||||
|
|
||||||
|
=== [Code cleanup/refactoring]
|
||||||
|
|
||||||
|
* Patch #30413: Add ".ruby-version" to svn:ignore, .git:ignore, and .hgignore
|
||||||
|
|
||||||
|
=== [Database]
|
||||||
|
|
||||||
|
* Defect #30171: Decrypting LDAP and SCM passwords fail if the plaintext password is longer than 31 bytes
|
||||||
|
|
||||||
|
=== [Gems support]
|
||||||
|
|
||||||
|
* Defect #30353: Installing rails with Bundler 2.0 fails in 3.x
|
||||||
|
|
||||||
|
=== [Importers]
|
||||||
|
|
||||||
|
* Patch #30412: Import UTF-8 issue CSV files with BOM and quoted strings
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Patch #30293: Ukrainian translation update for 3.4-stable
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #30426: Table rows are not highlighted on mouseover on some pages
|
||||||
|
* Patch #29951: Quick design fix/proposals for projects index page
|
||||||
|
|
||||||
|
== 2018-12-09 v3.4.7
|
||||||
|
|
||||||
|
=== [Custom fields]
|
||||||
|
|
||||||
|
* Defect #8317: Strip whitespace from integer custom field
|
||||||
|
* Defect #28925: Custom field values for enumerations not saved
|
||||||
|
* Patch #29674: Missing validation for custom field formats based on RecordList
|
||||||
|
|
||||||
|
=== [Email receiving]
|
||||||
|
|
||||||
|
* Defect #28576: Attachments are added even if validation fails when updating an issue via email
|
||||||
|
* Defect #29191: Cannot set no_notification option when receiving emails via IMAP or POP3
|
||||||
|
|
||||||
|
=== [Importers]
|
||||||
|
|
||||||
|
* Defect #30001: CSV importer ignores shared version names of other projects
|
||||||
|
|
||||||
|
=== [Issues]
|
||||||
|
|
||||||
|
* Defect #28946: If assignee is locked subtasks don't get copied
|
||||||
|
* Defect #30009: Empty sort criteria for issue query gives error
|
||||||
|
* Defect #30027: Some styles (for ex: borders for tables) in a custom field with text formatting enabled are not displayed
|
||||||
|
|
||||||
|
=== [Issues filter]
|
||||||
|
|
||||||
|
* Defect #26785: Wrong columns after CSV export
|
||||||
|
|
||||||
|
=== [PDF export]
|
||||||
|
|
||||||
|
* Defect #28125: PNG images on a wiki page don't appear in exported PDF
|
||||||
|
* Defect #28565: PDF export has too many whitespaces
|
||||||
|
|
||||||
|
=== [REST API]
|
||||||
|
|
||||||
|
* Defect #20788: REST API with JSON content missing attributes with false values
|
||||||
|
|
||||||
|
=== [Rails support]
|
||||||
|
|
||||||
|
* Feature #30043: Update Rails to 4.2.11
|
||||||
|
|
||||||
|
=== [SCM]
|
||||||
|
|
||||||
|
* Defect #29413: Mercurial 4.7 compatibility
|
||||||
|
|
||||||
|
=== [Search engine]
|
||||||
|
|
||||||
|
* Defect #28636: Cannot find an issue from a closed subproject when search scope is Project and its subprojects
|
||||||
|
|
||||||
|
=== [Text formatting]
|
||||||
|
|
||||||
|
* Defect #8395: Tags start with 'pre' are handled as 'pre' tag in Textile
|
||||||
|
* Defect #29038: Thumbnail macro causes attachment file not found and broken filename and link
|
||||||
|
* Defect #29247: Textile phrase modifiers break wiki macros
|
||||||
|
* Defect #29756: \f or \v character in Textile markup may cause RegexpError exception
|
||||||
|
|
||||||
|
=== [Time tracking]
|
||||||
|
|
||||||
|
* Patch #29308: Time entry creation: preserve 'spent on' value when using 'Create and Continue'
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Patch #29702: Brazilian wiki help translation update
|
||||||
|
* Patch #29703: Brazilian translation (jstoolbar-pt-br.js) update
|
||||||
|
* Patch #29718: Brazilian translation update for 3.4-stable
|
||||||
|
* Patch #29735: Galician translation fix for the words empty, blank, and key
|
||||||
|
* Patch #29736: Galician translation update for 3.4-stable
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #29918: Related issues section ignores the date format setting
|
||||||
|
* Defect #29950: Fix list rendering inside project description in projects#index
|
||||||
|
|
||||||
|
=== [UI - Responsive]
|
||||||
|
|
||||||
|
* Defect #24309: Setting page for repository does not scroll horizontally on small screens
|
||||||
|
|
||||||
|
=== [Wiki]
|
||||||
|
|
||||||
|
* Feature #29791: Hide "Files" section in wiki pages when printing
|
||||||
|
|
||||||
|
== 2018-06-10 v3.4.6
|
||||||
|
|
||||||
|
=== [Issues]
|
||||||
|
|
||||||
|
* Defect #27863: If version is closed or locked subtasks don't get copied
|
||||||
|
* Defect #28765: Copying an issue fails if the issue is watched by a locked user
|
||||||
|
* Patch #28649: Log automatic rescheduling of following issues to journal
|
||||||
|
|
||||||
|
=== [Permissions and roles]
|
||||||
|
|
||||||
|
* Defect #28693: Irrelevant permission is required to access some tabs in project settings page
|
||||||
|
|
||||||
|
=== [Project settings]
|
||||||
|
|
||||||
|
* Defect #27122: Filter for version name should be case-insensitive
|
||||||
|
|
||||||
|
=== [SCM]
|
||||||
|
|
||||||
|
* Defect #28725: Mercurial 4.6 compatibility
|
||||||
|
|
||||||
|
=== [Text formatting]
|
||||||
|
|
||||||
|
* Defect #28469: Syntax highlighter does not work if language name is single-quoted
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Patch #28881: Fix Japanese mistranslation for label_comment_added
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #22023: Issue id input should get focus after adding related issue
|
||||||
|
|
||||||
|
=== [UI - Responsive]
|
||||||
|
|
||||||
|
* Defect #28523: Display horizontal scroll bar of plugins table when overflow occurs on small screen
|
||||||
|
|
||||||
|
=== [Wiki]
|
||||||
|
|
||||||
|
* Patch #27090: Show the number of attachments on wiki pages
|
||||||
|
|
||||||
|
== 2018-04-07 v3.4.5
|
||||||
|
|
||||||
|
=== [Custom fields]
|
||||||
|
|
||||||
|
* Defect #28393: Sort issue custom fields by position in tracker UI
|
||||||
|
|
||||||
|
=== [Email notifications]
|
||||||
|
|
||||||
|
* Defect #28302: Security notification when changing password on password forgotten is empty
|
||||||
|
|
||||||
|
=== [Gantt]
|
||||||
|
|
||||||
|
* Defect #28204: Too large avatar breaks gantt when assignee is a group
|
||||||
|
|
||||||
|
=== [Issues]
|
||||||
|
|
||||||
|
* Defect #27862: Preformatted text overflows in preview
|
||||||
|
* Patch #28168: Allow context-menu edit of % done and priority of parent issues if the fields are not derived
|
||||||
|
|
||||||
|
=== [Issues filter]
|
||||||
|
|
||||||
|
* Defect #28180: Role-base cross-project issue query visibility calculated incorrectly
|
||||||
|
|
||||||
|
=== [Plugin API]
|
||||||
|
|
||||||
|
* Patch #27963: Remove 'unloadable' from bundled sample plugin
|
||||||
|
|
||||||
|
=== [Security]
|
||||||
|
|
||||||
|
* Defect #26857: Fix for CVE-2015-9251 in JQuery 1.11.1
|
||||||
|
|
||||||
|
=== [Text formatting]
|
||||||
|
|
||||||
|
* Defect #27884: RTL wiki class broken in Redmine 3.2.6
|
||||||
|
* Defect #28331: h4, h5 and h6 headings on wiki pages should have a paragraph mark
|
||||||
|
* Patch #28119: Enable lax_spacing for markdown formatting in order to allow markdown blocks not surrounded by empty lines
|
||||||
|
|
||||||
|
=== [Time tracking]
|
||||||
|
|
||||||
|
* Defect #28110: Don't allow reassigning reported hours to the project if issue is a required field for time logs
|
||||||
|
|
||||||
|
=== [Translations]
|
||||||
|
|
||||||
|
* Defect #28109: Incorrect interpolation in Swedish locale
|
||||||
|
* Defect #28113: Fix typo in German label_font_default
|
||||||
|
* Defect #28192: Fix typo in German label_font_monospace
|
||||||
|
* Patch #27994: Galician translation update (jstoolbar-gl.js)
|
||||||
|
* Patch #28102: Fix typo in Lithuanian label_version_sharing_tree
|
||||||
|
|
||||||
|
=== [UI]
|
||||||
|
|
||||||
|
* Defect #28079: The green tick is positioned after the label in the new member modals
|
||||||
|
* Defect #28208: Anonymous icon is wrongly displayed when assignee is a group
|
||||||
|
* Defect #28259: attachments_fields id to class change not properly reflected in all CSS
|
||||||
|
|
||||||
|
=== [Wiki]
|
||||||
|
|
||||||
|
* Defect #25299: Markdown pre-block could derive incorrect wiki sections
|
||||||
|
|
||||||
== 2018-01-08 v3.4.4
|
== 2018-01-08 v3.4.4
|
||||||
|
|
||||||
=== [Accounts / authentication]
|
=== [Accounts / authentication]
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# Sample plugin controller
|
# Sample plugin controller
|
||||||
class ExampleController < ApplicationController
|
class ExampleController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
layout 'base'
|
layout 'base'
|
||||||
before_action :find_project, :authorize
|
before_action :find_project, :authorize
|
||||||
menu_item :sample_plugin
|
menu_item :sample_plugin
|
||||||
|
|
|
@ -126,7 +126,7 @@ Redmine::AccessControl.map do |map|
|
||||||
map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
|
map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
|
||||||
map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
|
map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
|
||||||
map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
|
map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
|
||||||
map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
|
map.permission :manage_project_activities, {:projects => :settings, :project_enumerations => [:update, :destroy]}, :require => :member
|
||||||
end
|
end
|
||||||
|
|
||||||
map.project_module :news do |map|
|
map.project_module :news do |map|
|
||||||
|
@ -164,7 +164,7 @@ Redmine::AccessControl.map do |map|
|
||||||
map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
|
map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
|
||||||
map.permission :commit_access, {}
|
map.permission :commit_access, {}
|
||||||
map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
|
map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
|
||||||
map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
|
map.permission :manage_repository, {:projects => :settings, :repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
|
||||||
end
|
end
|
||||||
|
|
||||||
map.project_module :boards do |map|
|
map.project_module :boards do |map|
|
||||||
|
@ -174,7 +174,7 @@ Redmine::AccessControl.map do |map|
|
||||||
map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin
|
map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin
|
||||||
map.permission :delete_messages, {:messages => :destroy}, :require => :member
|
map.permission :delete_messages, {:messages => :destroy}, :require => :member
|
||||||
map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
|
map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
|
||||||
map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
|
map.permission :manage_boards, {:projects => :settings, :boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
|
||||||
end
|
end
|
||||||
|
|
||||||
map.project_module :calendar do |map|
|
map.project_module :calendar do |map|
|
||||||
|
|
|
@ -33,7 +33,7 @@ module Redmine
|
||||||
c.iv = iv
|
c.iv = iv
|
||||||
e = c.update(text.to_s)
|
e = c.update(text.to_s)
|
||||||
e << c.final
|
e << c.final
|
||||||
"aes-256-cbc:" + [e, iv].map {|v| Base64.encode64(v).strip}.join('--')
|
"aes-256-cbc:" + [e, iv].map {|v| Base64.strict_encode64(v)}.join('--')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -486,7 +486,7 @@ module Redmine
|
||||||
|
|
||||||
def validate_single_value(custom_field, value, customized=nil)
|
def validate_single_value(custom_field, value, customized=nil)
|
||||||
errs = super
|
errs = super
|
||||||
errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value.to_s =~ /^[+-]?\d+$/
|
errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value.to_s.strip =~ /^[+-]?\d+$/
|
||||||
errs
|
errs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -736,6 +736,16 @@ module Redmine
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_custom_value(custom_value)
|
||||||
|
values = Array.wrap(custom_value.value).reject {|value| value.to_s == ''}
|
||||||
|
invalid_values = values - possible_custom_value_options(custom_value).map(&:last)
|
||||||
|
if invalid_values.any?
|
||||||
|
[::I18n.t('activerecord.errors.messages.inclusion')]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def order_statement(custom_field)
|
def order_statement(custom_field)
|
||||||
if target_class.respond_to?(:fields_for_order_statement)
|
if target_class.respond_to?(:fields_for_order_statement)
|
||||||
target_class.fields_for_order_statement(value_join_alias(custom_field))
|
target_class.fields_for_order_statement(value_join_alias(custom_field))
|
||||||
|
|
|
@ -81,7 +81,7 @@ module Redmine
|
||||||
# below : list unreadable files, but dont link them.
|
# below : list unreadable files, but dont link them.
|
||||||
:path => utf_8_path,
|
:path => utf_8_path,
|
||||||
:kind => (File.directory?(t1) ? 'dir' : 'file'),
|
:kind => (File.directory?(t1) ? 'dir' : 'file'),
|
||||||
:size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
|
:size => (File.directory?(t1) ? nil : File.size(t1)),
|
||||||
:lastrev =>
|
:lastrev =>
|
||||||
Revision.new({:time => (File.mtime(t1)) })
|
Revision.new({:time => (File.mtime(t1)) })
|
||||||
})
|
})
|
||||||
|
|
|
@ -83,6 +83,7 @@ module Redmine
|
||||||
io.each_line do |line|
|
io.each_line do |line|
|
||||||
branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
|
branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
|
||||||
bran = GitBranch.new(branch_rev[2])
|
bran = GitBranch.new(branch_rev[2])
|
||||||
|
next unless branch_rev
|
||||||
bran.revision = branch_rev[3]
|
bran.revision = branch_rev[3]
|
||||||
bran.scmid = branch_rev[3]
|
bran.scmid = branch_rev[3]
|
||||||
bran.is_default = ( branch_rev[1] == '*' )
|
bran.is_default = ( branch_rev[1] == '*' )
|
||||||
|
|
|
@ -46,14 +46,22 @@ Output example of rhmanifest::
|
||||||
</rhmanifest>
|
</rhmanifest>
|
||||||
"""
|
"""
|
||||||
import re, time, cgi, urllib
|
import re, time, cgi, urllib
|
||||||
from mercurial import cmdutil, commands, node, error, hg
|
from mercurial import cmdutil, commands, node, error, hg, registrar
|
||||||
|
|
||||||
cmdtable = {}
|
cmdtable = {}
|
||||||
command = cmdutil.command(cmdtable)
|
command = registrar.command(cmdtable) if hasattr(registrar, 'command') else cmdutil.command(cmdtable)
|
||||||
|
|
||||||
_x = cgi.escape
|
_x = cgi.escape
|
||||||
_u = lambda s: cgi.escape(urllib.quote(s))
|
_u = lambda s: cgi.escape(urllib.quote(s))
|
||||||
|
|
||||||
|
def _changectx(repo, rev):
|
||||||
|
if isinstance(rev, str):
|
||||||
|
rev = repo.lookup(rev)
|
||||||
|
if hasattr(repo, 'changectx'):
|
||||||
|
return repo.changectx(rev)
|
||||||
|
else:
|
||||||
|
return repo[rev]
|
||||||
|
|
||||||
def _tip(ui, repo):
|
def _tip(ui, repo):
|
||||||
# see mercurial/commands.py:tip
|
# see mercurial/commands.py:tip
|
||||||
def tiprev():
|
def tiprev():
|
||||||
|
@ -61,7 +69,7 @@ def _tip(ui, repo):
|
||||||
return len(repo) - 1
|
return len(repo) - 1
|
||||||
except TypeError: # Mercurial < 1.1
|
except TypeError: # Mercurial < 1.1
|
||||||
return repo.changelog.count() - 1
|
return repo.changelog.count() - 1
|
||||||
tipctx = repo.changectx(tiprev())
|
tipctx = _changectx(repo, tiprev())
|
||||||
ui.write('<tip revision="%d" node="%s"/>\n'
|
ui.write('<tip revision="%d" node="%s"/>\n'
|
||||||
% (tipctx.rev(), _x(node.hex(tipctx.node()))))
|
% (tipctx.rev(), _x(node.hex(tipctx.node()))))
|
||||||
|
|
||||||
|
@ -94,13 +102,18 @@ def _branches(ui, repo):
|
||||||
return repo.branchheads(branch, closed=False)
|
return repo.branchheads(branch, closed=False)
|
||||||
except TypeError: # Mercurial < 1.2
|
except TypeError: # Mercurial < 1.2
|
||||||
return repo.branchheads(branch)
|
return repo.branchheads(branch)
|
||||||
|
def lookup(rev, n):
|
||||||
|
try:
|
||||||
|
return repo.lookup(rev)
|
||||||
|
except RuntimeError:
|
||||||
|
return n
|
||||||
for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
|
for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
|
||||||
if repo.lookup(r) in branchheads(t):
|
if lookup(r, n) in branchheads(t):
|
||||||
ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
|
ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
|
||||||
% (r, _x(node.hex(n)), _x(t)))
|
% (r, _x(node.hex(n)), _x(t)))
|
||||||
|
|
||||||
def _manifest(ui, repo, path, rev):
|
def _manifest(ui, repo, path, rev):
|
||||||
ctx = repo.changectx(rev)
|
ctx = _changectx(repo, rev)
|
||||||
ui.write('<manifest revision="%d" path="%s">\n'
|
ui.write('<manifest revision="%d" path="%s">\n'
|
||||||
% (ctx.rev(), _u(path)))
|
% (ctx.rev(), _u(path)))
|
||||||
|
|
||||||
|
@ -155,7 +168,7 @@ def rhdiff(ui, repo, *pats, **opts):
|
||||||
"""diff repository (or selected files)"""
|
"""diff repository (or selected files)"""
|
||||||
change = opts.pop('change', None)
|
change = opts.pop('change', None)
|
||||||
if change: # add -c option for Mercurial<1.1
|
if change: # add -c option for Mercurial<1.1
|
||||||
base = repo.changectx(change).parents()[0].rev()
|
base = _changectx(repo, change).parents()[0].rev()
|
||||||
opts['rev'] = [str(base), change]
|
opts['rev'] = [str(base), change]
|
||||||
opts['nodates'] = True
|
opts['nodates'] = True
|
||||||
return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
|
return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
|
||||||
|
|
|
@ -87,6 +87,7 @@ module Redmine
|
||||||
private
|
private
|
||||||
|
|
||||||
def normalize!
|
def normalize!
|
||||||
|
self.reject! {|s| s.first.blank? }
|
||||||
self.collect! {|s| s = Array(s); [s.first, (s.last == false || s.last.to_s == 'desc') ? 'desc' : 'asc']}
|
self.collect! {|s| s = Array(s); [s.first, (s.last == false || s.last.to_s == 'desc') ? 'desc' : 'asc']}
|
||||||
self.slice!(3)
|
self.slice!(3)
|
||||||
self
|
self
|
||||||
|
|
|
@ -49,7 +49,12 @@ module Redmine
|
||||||
|
|
||||||
def self.convert_available?
|
def self.convert_available?
|
||||||
return @convert_available if defined?(@convert_available)
|
return @convert_available if defined?(@convert_available)
|
||||||
@convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false
|
begin
|
||||||
|
`#{shell_quote CONVERT_BIN} -version`
|
||||||
|
@convert_available = $?.success?
|
||||||
|
rescue
|
||||||
|
@convert_available = false
|
||||||
|
end
|
||||||
logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
|
logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
|
||||||
@convert_available
|
@convert_available
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Redmine
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 3
|
MAJOR = 3
|
||||||
MINOR = 4
|
MINOR = 4
|
||||||
TINY = 4
|
TINY = 13
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
|
|
|
@ -48,7 +48,7 @@ module Redmine
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(sym, *args, &block)
|
def method_missing(sym, *args, &block)
|
||||||
if args.any?
|
if args.count > 0
|
||||||
if args.first.is_a?(Hash)
|
if args.first.is_a?(Hash)
|
||||||
if @struct.last.is_a?(Array)
|
if @struct.last.is_a?(Array)
|
||||||
@struct.last << args.first unless block
|
@struct.last << args.first unless block
|
||||||
|
|
|
@ -94,15 +94,13 @@ module Redmine
|
||||||
i = 0
|
i = 0
|
||||||
l = 1
|
l = 1
|
||||||
inside_pre = false
|
inside_pre = false
|
||||||
@text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|~~~.*)\s*$)/).each do |part|
|
@text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|(?:~~~|```).*)\s*$)/).each do |part|
|
||||||
level = nil
|
level = nil
|
||||||
if part =~ /\A~{3,}(\S+)?\s*$/
|
if part =~ /\A(~{3,}|`{3,})(\S+)?\s*$/
|
||||||
if $1
|
if !inside_pre
|
||||||
if !inside_pre
|
inside_pre = true
|
||||||
inside_pre = true
|
elsif !$2
|
||||||
end
|
inside_pre = false
|
||||||
else
|
|
||||||
inside_pre = !inside_pre
|
|
||||||
end
|
end
|
||||||
elsif inside_pre
|
elsif inside_pre
|
||||||
# nop
|
# nop
|
||||||
|
@ -142,7 +140,8 @@ module Redmine
|
||||||
:strikethrough => true,
|
:strikethrough => true,
|
||||||
:superscript => true,
|
:superscript => true,
|
||||||
:no_intra_emphasis => true,
|
:no_intra_emphasis => true,
|
||||||
:footnotes => true
|
:footnotes => true,
|
||||||
|
:lax_spacing => true
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,9 +120,10 @@ module Redmine
|
||||||
## replace <pre> content
|
## replace <pre> content
|
||||||
text.gsub!(/<redpre#(\d+)>/) do
|
text.gsub!(/<redpre#(\d+)>/) do
|
||||||
content = @pre_list[$1.to_i]
|
content = @pre_list[$1.to_i]
|
||||||
if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
|
# This regex must match any data produced by RedCloth3#rip_offtags
|
||||||
language = $1
|
if content.match(/<code\s+class=(?:"([^"]+)"|'([^']+)')>\s?(.*)/m)
|
||||||
text = $2
|
language = $1 || $2
|
||||||
|
text = $3
|
||||||
if Redmine::SyntaxHighlighting.language_supported?(language)
|
if Redmine::SyntaxHighlighting.language_supported?(language)
|
||||||
content = "<code class=\"#{language} syntaxhl\">" +
|
content = "<code class=\"#{language} syntaxhl\">" +
|
||||||
Redmine::SyntaxHighlighting.highlight_by_language(text, language)
|
Redmine::SyntaxHighlighting.highlight_by_language(text, language)
|
||||||
|
|
|
@ -343,7 +343,7 @@ class RedCloth3 < String
|
||||||
A_VLGN = /[\-^~]/
|
A_VLGN = /[\-^~]/
|
||||||
C_CLAS = '(?:\([^")]+\))'
|
C_CLAS = '(?:\([^")]+\))'
|
||||||
C_LNGE = '(?:\[[a-z\-_]+\])'
|
C_LNGE = '(?:\[[a-z\-_]+\])'
|
||||||
C_STYL = '(?:\{[^"}]+\})'
|
C_STYL = '(?:\{[^{][^"}]+\})'
|
||||||
S_CSPN = '(?:\\\\\d+)'
|
S_CSPN = '(?:\\\\\d+)'
|
||||||
S_RSPN = '(?:/\d+)'
|
S_RSPN = '(?:/\d+)'
|
||||||
A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)"
|
A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)"
|
||||||
|
@ -1034,7 +1034,7 @@ class RedCloth3 < String
|
||||||
def flush_left( text )
|
def flush_left( text )
|
||||||
indt = 0
|
indt = 0
|
||||||
if text =~ /^ /
|
if text =~ /^ /
|
||||||
while text !~ /^ {#{indt}}\S/
|
while text !~ /^ {#{indt}}[^ ]/
|
||||||
indt += 1
|
indt += 1
|
||||||
end unless text.empty?
|
end unless text.empty?
|
||||||
if indt.nonzero?
|
if indt.nonzero?
|
||||||
|
@ -1049,7 +1049,7 @@ class RedCloth3 < String
|
||||||
end
|
end
|
||||||
|
|
||||||
OFFTAGS = /(code|pre|kbd|notextile)/
|
OFFTAGS = /(code|pre|kbd|notextile)/
|
||||||
OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi
|
OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }\b>)|(<#{ OFFTAGS }\b[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\b\W|\Z)/mi
|
||||||
OFFTAG_OPEN = /<#{ OFFTAGS }/
|
OFFTAG_OPEN = /<#{ OFFTAGS }/
|
||||||
OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
|
OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
|
||||||
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
|
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
|
||||||
|
@ -1213,7 +1213,13 @@ class RedCloth3 < String
|
||||||
|
|
||||||
ALLOWED_TAGS = %w(redpre pre code kbd notextile)
|
ALLOWED_TAGS = %w(redpre pre code kbd notextile)
|
||||||
def escape_html_tags(text)
|
def escape_html_tags(text)
|
||||||
text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "<#{$1}#{'>' unless $3.blank?}" }
|
text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) do |m|
|
||||||
|
if ALLOWED_TAGS.include?($2) && $3.present?
|
||||||
|
"<#{$1}#{$3}"
|
||||||
|
else
|
||||||
|
"<#{$1}#{'>' unless $3.blank?}"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Nadpis 1. úrovně
|
h1. Nadpis 1. úrovně
|
||||||
|
|
||||||
h2. Nadpis 2. úrovně
|
h2. Nadpis 2. úrovně
|
||||||
|
|
||||||
h3. Nadpis 3. úrovně
|
h3. Nadpis 3. úrovně
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Titre
|
h1. Titre
|
||||||
|
|
||||||
h2. Sous-titre
|
h2. Sous-titre
|
||||||
|
|
||||||
h3. Sous-sous-titre
|
h3. Sous-sous-titre
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ http://www.redmine.org, someone@foo.bar
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
h1. Heading
|
h1. Heading
|
||||||
|
|
||||||
h2. Subheading
|
h2. Subheading
|
||||||
|
|
||||||
h3. Subsubheading
|
h3. Subsubheading
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue