Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
131b15fc7a | ||
|
|
f6b1583a1a | ||
|
|
5bea900443 | ||
|
|
81baddad00 | ||
|
|
f6b5632fec | ||
|
|
f7ede727fd | ||
|
|
b870417860 | ||
|
|
25a7838e0a | ||
|
|
7c3ddf2bc0 | ||
|
|
0f8df81b87 | ||
|
|
c5121d804d | ||
|
|
8bcbbebf65 | ||
|
|
2d2afab549 | ||
|
|
35f601e769 | ||
|
|
b84cffd62e | ||
|
|
2eba0b66d4 | ||
|
|
eb2d814344 | ||
|
|
d9385ce9a2 | ||
|
|
d3522c10e4 | ||
|
|
b9957264eb | ||
|
|
da641f4122 | ||
|
|
287d86e363 | ||
|
|
faf1f1e812 | ||
|
|
cd64338a7f | ||
|
|
1b8c5d4058 | ||
|
|
5ccbeba5c2 |
@@ -56,8 +56,6 @@ class AccountController < ApplicationController
|
|||||||
flash.now[:error] = l(:notice_account_invalid_creditentials)
|
flash.now[:error] = l(:notice_account_invalid_creditentials)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue User::OnTheFlyCreationFailure
|
|
||||||
flash.now[:error] = 'Redmine could not retrieve the required information from the LDAP to create your account. Please, contact your Redmine administrator.'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Log out current user and redirect to welcome page
|
# Log out current user and redirect to welcome page
|
||||||
|
|||||||
@@ -140,9 +140,7 @@ class IssuesController < ApplicationController
|
|||||||
requested_status = IssueStatus.find_by_id(params[:issue][:status_id])
|
requested_status = IssueStatus.find_by_id(params[:issue][:status_id])
|
||||||
# Check that the user is allowed to apply the requested status
|
# Check that the user is allowed to apply the requested status
|
||||||
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
|
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
|
||||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x,
|
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
|
||||||
:customized => @issue,
|
|
||||||
:value => (params[:custom_fields] ? params[:custom_fields][x.id.to_s] : nil)) }
|
|
||||||
@issue.custom_values = @custom_values
|
@issue.custom_values = @custom_values
|
||||||
if @issue.save
|
if @issue.save
|
||||||
attach_files(@issue, params[:attachments])
|
attach_files(@issue, params[:attachments])
|
||||||
@@ -344,8 +342,8 @@ class IssuesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def preview
|
def preview
|
||||||
@issue = @project.issues.find_by_id(params[:id]) unless params[:id].blank?
|
issue = @project.issues.find_by_id(params[:id])
|
||||||
@attachements = @issue.attachments if @issue
|
@attachements = issue.attachments if issue
|
||||||
@text = params[:notes] || (params[:issue] ? params[:issue][:description] : nil)
|
@text = params[:notes] || (params[:issue] ? params[:issue][:description] : nil)
|
||||||
render :partial => 'common/preview'
|
render :partial => 'common/preview'
|
||||||
end
|
end
|
||||||
@@ -413,7 +411,6 @@ private
|
|||||||
else
|
else
|
||||||
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
|
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
|
||||||
@query ||= Query.new(:name => "_", :project => @project, :filters => session[:query][:filters])
|
@query ||= Query.new(:name => "_", :project => @project, :filters => session[:query][:filters])
|
||||||
@query.project = @project
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -66,20 +66,20 @@ class ProjectsController < ApplicationController
|
|||||||
:conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}",
|
:conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}",
|
||||||
:order => 'name')
|
:order => 'name')
|
||||||
@project = Project.new(params[:project])
|
@project = Project.new(params[:project])
|
||||||
|
@project.enabled_module_names = Redmine::AccessControl.available_project_modules
|
||||||
if request.get?
|
if request.get?
|
||||||
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
|
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
|
||||||
@project.trackers = Tracker.all
|
@project.trackers = Tracker.all
|
||||||
@project.is_public = Setting.default_projects_public?
|
@project.is_public = Setting.default_projects_public?
|
||||||
@project.enabled_module_names = Redmine::AccessControl.available_project_modules
|
|
||||||
else
|
else
|
||||||
@project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
|
@project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
|
||||||
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||||
@project.custom_values = @custom_values
|
@project.custom_values = @custom_values
|
||||||
@project.enabled_module_names = params[:enabled_modules]
|
|
||||||
if @project.save
|
if @project.save
|
||||||
|
@project.enabled_module_names = params[:enabled_modules]
|
||||||
flash[:notice] = l(:notice_successful_create)
|
flash[:notice] = l(:notice_successful_create)
|
||||||
redirect_to :controller => 'admin', :action => 'projects'
|
redirect_to :controller => 'admin', :action => 'projects'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -204,10 +204,7 @@ class ProjectsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def list_files
|
def list_files
|
||||||
sort_init "#{Attachment.table_name}.filename", "asc"
|
@versions = @project.versions.sort.reverse
|
||||||
sort_update
|
|
||||||
@versions = @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
|
|
||||||
render :layout => !request.xhr?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Show changelog for @project
|
# Show changelog for @project
|
||||||
@@ -341,9 +338,8 @@ class ProjectsController < ApplicationController
|
|||||||
:include => [:tracker, :status, :assigned_to, :priority, :project],
|
:include => [:tracker, :status, :assigned_to, :priority, :project],
|
||||||
:conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?)) AND #{Issue.table_name}.tracker_id IN (#{@selected_tracker_ids.join(',')})", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
|
:conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?)) AND #{Issue.table_name}.tracker_id IN (#{@selected_tracker_ids.join(',')})", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
|
||||||
) unless @selected_tracker_ids.empty?
|
) unless @selected_tracker_ids.empty?
|
||||||
events += Version.find(:all, :include => :project,
|
|
||||||
:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
|
|
||||||
end
|
end
|
||||||
|
events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
|
||||||
@calendar.events = events
|
@calendar.events = events
|
||||||
|
|
||||||
render :layout => false if request.xhr?
|
render :layout => false if request.xhr?
|
||||||
@@ -387,9 +383,8 @@ class ProjectsController < ApplicationController
|
|||||||
:include => [:tracker, :status, :assigned_to, :priority, :project],
|
:include => [:tracker, :status, :assigned_to, :priority, :project],
|
||||||
:conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')}))", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to]
|
:conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')}))", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to]
|
||||||
) unless @selected_tracker_ids.empty?
|
) unless @selected_tracker_ids.empty?
|
||||||
@events += Version.find(:all, :include => :project,
|
|
||||||
:conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
|
|
||||||
end
|
end
|
||||||
|
@events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
|
||||||
@events.sort! {|x,y| x.start_date <=> y.start_date }
|
@events.sort! {|x,y| x.start_date <=> y.start_date }
|
||||||
|
|
||||||
if params[:format]=='pdf'
|
if params[:format]=='pdf'
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ require 'SVG/Graph/Bar'
|
|||||||
require 'SVG/Graph/BarHorizontal'
|
require 'SVG/Graph/BarHorizontal'
|
||||||
require 'digest/sha1'
|
require 'digest/sha1'
|
||||||
|
|
||||||
class ChangesetNotFound < Exception; end
|
class ChangesetNotFound < Exception
|
||||||
class InvalidRevisionParam < Exception; end
|
end
|
||||||
|
|
||||||
class RepositoriesController < ApplicationController
|
class RepositoriesController < ApplicationController
|
||||||
layout 'base'
|
layout 'base'
|
||||||
@@ -51,8 +51,8 @@ class RepositoriesController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
# check if new revisions have been committed in the repository
|
# check if new revisions have been committed in the repository
|
||||||
@repository.fetch_changesets if Setting.autofetch_changesets?
|
@repository.fetch_changesets if Setting.autofetch_changesets?
|
||||||
# root entries
|
# get entries for the browse frame
|
||||||
@entries = @repository.entries('', @rev)
|
@entries = @repository.entries('')
|
||||||
# latest changesets
|
# latest changesets
|
||||||
@changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
|
@changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
|
||||||
show_error_not_found unless @entries || @changesets.any?
|
show_error_not_found unless @entries || @changesets.any?
|
||||||
@@ -65,8 +65,7 @@ class RepositoriesController < ApplicationController
|
|||||||
if request.xhr?
|
if request.xhr?
|
||||||
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
|
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
|
||||||
else
|
else
|
||||||
show_error_not_found and return unless @entries
|
show_error_not_found unless @entries
|
||||||
render :action => 'browse'
|
|
||||||
end
|
end
|
||||||
rescue Redmine::Scm::Adapters::CommandFailed => e
|
rescue Redmine::Scm::Adapters::CommandFailed => e
|
||||||
show_error_command_failed(e.message)
|
show_error_command_failed(e.message)
|
||||||
@@ -96,12 +95,6 @@ class RepositoriesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def entry
|
def entry
|
||||||
@entry = @repository.scm.entry(@path, @rev)
|
|
||||||
show_error_not_found and return unless @entry
|
|
||||||
|
|
||||||
# If the entry is a dir, show the browser
|
|
||||||
browse and return if @entry.is_dir?
|
|
||||||
|
|
||||||
@content = @repository.scm.cat(@path, @rev)
|
@content = @repository.scm.cat(@path, @rev)
|
||||||
show_error_not_found and return unless @content
|
show_error_not_found and return unless @content
|
||||||
if 'raw' == params[:format] || @content.is_binary_data?
|
if 'raw' == params[:format] || @content.is_binary_data?
|
||||||
@@ -142,6 +135,7 @@ class RepositoriesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def diff
|
def diff
|
||||||
|
@rev_to = params[:rev_to]
|
||||||
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
|
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
|
||||||
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
|
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
|
||||||
|
|
||||||
@@ -186,8 +180,6 @@ private
|
|||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
REV_PARAM_RE = %r{^[a-f0-9]*$}
|
|
||||||
|
|
||||||
def find_repository
|
def find_repository
|
||||||
@project = Project.find(params[:id])
|
@project = Project.find(params[:id])
|
||||||
@repository = @project.repository
|
@repository = @project.repository
|
||||||
@@ -195,12 +187,8 @@ private
|
|||||||
@path = params[:path].join('/') unless params[:path].nil?
|
@path = params[:path].join('/') unless params[:path].nil?
|
||||||
@path ||= ''
|
@path ||= ''
|
||||||
@rev = params[:rev]
|
@rev = params[:rev]
|
||||||
@rev_to = params[:rev_to]
|
|
||||||
raise InvalidRevisionParam unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE)
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
rescue InvalidRevisionParam
|
|
||||||
show_error_not_found
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_error_not_found
|
def show_error_not_found
|
||||||
@@ -267,9 +255,6 @@ private
|
|||||||
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
|
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
|
||||||
changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
|
changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
|
||||||
|
|
||||||
# Remove email adress in usernames
|
|
||||||
fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
|
|
||||||
|
|
||||||
graph = SVG::Graph::BarHorizontal.new(
|
graph = SVG::Graph::BarHorizontal.new(
|
||||||
:height => 300,
|
:height => 300,
|
||||||
:width => 500,
|
:width => 500,
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ class TimelogController < ApplicationController
|
|||||||
include SortHelper
|
include SortHelper
|
||||||
helper :issues
|
helper :issues
|
||||||
include TimelogHelper
|
include TimelogHelper
|
||||||
helper :custom_fields
|
|
||||||
include CustomFieldsHelper
|
|
||||||
|
|
||||||
def report
|
def report
|
||||||
@available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
|
@available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
|
||||||
@@ -47,40 +45,37 @@ class TimelogController < ApplicationController
|
|||||||
:label => :label_tracker},
|
:label => :label_tracker},
|
||||||
'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
|
'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
|
||||||
:klass => Enumeration,
|
:klass => Enumeration,
|
||||||
:label => :label_activity},
|
:label => :label_activity}
|
||||||
'issue' => {:sql => "#{TimeEntry.table_name}.issue_id",
|
|
||||||
:klass => Issue,
|
|
||||||
:label => :label_issue}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add list and boolean custom fields as available criterias
|
|
||||||
@project.all_custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
|
||||||
@available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM custom_values c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = issues.id)",
|
|
||||||
:format => cf.field_format,
|
|
||||||
:label => cf.name}
|
|
||||||
end
|
|
||||||
|
|
||||||
@criterias = params[:criterias] || []
|
@criterias = params[:criterias] || []
|
||||||
@criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria}
|
@criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria}
|
||||||
@criterias.uniq!
|
@criterias.uniq!
|
||||||
@criterias = @criterias[0,3]
|
@criterias = @criterias[0,3]
|
||||||
|
|
||||||
@columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month'
|
@columns = (params[:period] && %w(year month week).include?(params[:period])) ? params[:period] : 'month'
|
||||||
|
|
||||||
retrieve_date_range
|
if params[:date_from]
|
||||||
|
begin; @date_from = params[:date_from].to_date; rescue; end
|
||||||
|
end
|
||||||
|
if params[:date_to]
|
||||||
|
begin; @date_to = params[:date_to].to_date; rescue; end
|
||||||
|
end
|
||||||
|
@date_from ||= Date.civil(Date.today.year, 1, 1)
|
||||||
|
@date_to ||= (Date.civil(Date.today.year, Date.today.month, 1) >> 1) - 1
|
||||||
|
|
||||||
unless @criterias.empty?
|
unless @criterias.empty?
|
||||||
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
|
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
|
||||||
sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
|
sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
|
||||||
|
|
||||||
sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours"
|
sql = "SELECT #{sql_select}, tyear, tmonth, tweek, SUM(hours) AS hours"
|
||||||
sql << " FROM #{TimeEntry.table_name}"
|
sql << " FROM #{TimeEntry.table_name}"
|
||||||
sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id"
|
sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id"
|
||||||
sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id"
|
sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id"
|
||||||
sql << " WHERE (%s)" % @project.project_condition(Setting.display_subprojects_issues?)
|
sql << " WHERE (%s)" % @project.project_condition(Setting.display_subprojects_issues?)
|
||||||
sql << " AND (%s)" % Project.allowed_to_condition(User.current, :view_time_entries)
|
sql << " AND (%s)" % Project.allowed_to_condition(User.current, :view_time_entries)
|
||||||
sql << " AND spent_on BETWEEN '%s' AND '%s'" % [ActiveRecord::Base.connection.quoted_date(@from.to_time), ActiveRecord::Base.connection.quoted_date(@to.to_time)]
|
sql << " AND spent_on BETWEEN '%s' AND '%s'" % [ActiveRecord::Base.connection.quoted_date(@date_from.to_time), ActiveRecord::Base.connection.quoted_date(@date_to.to_time)]
|
||||||
sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on"
|
sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek"
|
||||||
|
|
||||||
@hours = ActiveRecord::Base.connection.select_all(sql)
|
@hours = ActiveRecord::Base.connection.select_all(sql)
|
||||||
|
|
||||||
@@ -92,122 +87,36 @@ class TimelogController < ApplicationController
|
|||||||
row['month'] = "#{row['tyear']}-#{row['tmonth']}"
|
row['month'] = "#{row['tyear']}-#{row['tmonth']}"
|
||||||
when 'week'
|
when 'week'
|
||||||
row['week'] = "#{row['tyear']}-#{row['tweek']}"
|
row['week'] = "#{row['tyear']}-#{row['tweek']}"
|
||||||
when 'day'
|
|
||||||
row['day'] = "#{row['spent_on']}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
|
@total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
|
||||||
|
end
|
||||||
|
|
||||||
@periods = []
|
@periods = []
|
||||||
# Date#at_beginning_of_ not supported in Rails 1.2.x
|
date_from = @date_from
|
||||||
date_from = @from.to_time
|
# 100 columns max
|
||||||
# 100 columns max
|
while date_from < @date_to && @periods.length < 100
|
||||||
while date_from <= @to.to_time && @periods.length < 100
|
case @columns
|
||||||
case @columns
|
when 'year'
|
||||||
when 'year'
|
@periods << "#{date_from.year}"
|
||||||
@periods << "#{date_from.year}"
|
date_from = date_from >> 12
|
||||||
date_from = (date_from + 1.year).at_beginning_of_year
|
when 'month'
|
||||||
when 'month'
|
@periods << "#{date_from.year}-#{date_from.month}"
|
||||||
@periods << "#{date_from.year}-#{date_from.month}"
|
date_from = date_from >> 1
|
||||||
date_from = (date_from + 1.month).at_beginning_of_month
|
when 'week'
|
||||||
when 'week'
|
@periods << "#{date_from.year}-#{date_from.cweek}"
|
||||||
@periods << "#{date_from.year}-#{date_from.to_date.cweek}"
|
date_from = date_from + 7
|
||||||
date_from = (date_from + 7.day).at_beginning_of_week
|
|
||||||
when 'day'
|
|
||||||
@periods << "#{date_from.to_date}"
|
|
||||||
date_from = date_from + 1.day
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
render :layout => false if request.xhr?
|
||||||
format.html { render :layout => !request.xhr? }
|
|
||||||
format.csv { send_data(report_to_csv(@criterias, @periods, @hours).read, :type => 'text/csv; header=present', :filename => 'timelog.csv') }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def details
|
def details
|
||||||
sort_init 'spent_on', 'desc'
|
sort_init 'spent_on', 'desc'
|
||||||
sort_update
|
sort_update
|
||||||
|
|
||||||
cond = ARCondition.new
|
|
||||||
cond << (@issue.nil? ? @project.project_condition(Setting.display_subprojects_issues?) :
|
|
||||||
["#{TimeEntry.table_name}.issue_id = ?", @issue.id])
|
|
||||||
|
|
||||||
retrieve_date_range
|
|
||||||
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
|
|
||||||
|
|
||||||
TimeEntry.visible_by(User.current) do
|
|
||||||
respond_to do |format|
|
|
||||||
format.html {
|
|
||||||
# Paginate results
|
|
||||||
@entry_count = TimeEntry.count(:include => :project, :conditions => cond.conditions)
|
|
||||||
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
|
|
||||||
@entries = TimeEntry.find(:all,
|
|
||||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
|
||||||
:conditions => cond.conditions,
|
|
||||||
:order => sort_clause,
|
|
||||||
:limit => @entry_pages.items_per_page,
|
|
||||||
:offset => @entry_pages.current.offset)
|
|
||||||
@total_hours = TimeEntry.sum(:hours, :include => :project, :conditions => cond.conditions).to_f
|
|
||||||
|
|
||||||
render :layout => !request.xhr?
|
|
||||||
}
|
|
||||||
format.csv {
|
|
||||||
# Export all entries
|
|
||||||
@entries = TimeEntry.find(:all,
|
|
||||||
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
|
|
||||||
:conditions => cond.conditions,
|
|
||||||
:order => sort_clause)
|
|
||||||
send_data(entries_to_csv(@entries).read, :type => 'text/csv; header=present', :filename => 'timelog.csv')
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def edit
|
|
||||||
render_403 and return if @time_entry && !@time_entry.editable_by?(User.current)
|
|
||||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
|
|
||||||
@time_entry.attributes = params[:time_entry]
|
|
||||||
if request.post? and @time_entry.save
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
redirect_to(params[:back_url] || {:action => 'details', :project_id => @time_entry.project})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
@activities = Enumeration::get_values('ACTI')
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
render_404 and return unless @time_entry
|
|
||||||
render_403 and return unless @time_entry.editable_by?(User.current)
|
|
||||||
@time_entry.destroy
|
|
||||||
flash[:notice] = l(:notice_successful_delete)
|
|
||||||
redirect_to :back
|
|
||||||
rescue RedirectBackError
|
|
||||||
redirect_to :action => 'details', :project_id => @time_entry.project
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def find_project
|
|
||||||
if params[:id]
|
|
||||||
@time_entry = TimeEntry.find(params[:id])
|
|
||||||
@project = @time_entry.project
|
|
||||||
elsif params[:issue_id]
|
|
||||||
@issue = Issue.find(params[:issue_id])
|
|
||||||
@project = @issue.project
|
|
||||||
elsif params[:project_id]
|
|
||||||
@project = Project.find(params[:project_id])
|
|
||||||
else
|
|
||||||
render_404
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
|
|
||||||
# Retrieves the date range based on predefined ranges or specific from/to param dates
|
|
||||||
def retrieve_date_range
|
|
||||||
@free_period = false
|
@free_period = false
|
||||||
@from, @to = nil, nil
|
@from, @to = nil, nil
|
||||||
|
|
||||||
@@ -248,7 +157,85 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
@from, @to = @to, @from if @from && @to && @from > @to
|
@from, @to = @to, @from if @from && @to && @from > @to
|
||||||
@from ||= (TimeEntry.minimum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today) - 1
|
|
||||||
@to ||= (TimeEntry.maximum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today)
|
cond = ARCondition.new
|
||||||
|
cond << (@issue.nil? ? @project.project_condition(Setting.display_subprojects_issues?) :
|
||||||
|
["#{TimeEntry.table_name}.issue_id = ?", @issue.id])
|
||||||
|
|
||||||
|
if @from
|
||||||
|
if @to
|
||||||
|
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
|
||||||
|
else
|
||||||
|
cond << ['spent_on >= ?', @from]
|
||||||
|
end
|
||||||
|
elsif @to
|
||||||
|
cond << ['spent_on <= ?', @to]
|
||||||
|
end
|
||||||
|
|
||||||
|
TimeEntry.visible_by(User.current) do
|
||||||
|
respond_to do |format|
|
||||||
|
format.html {
|
||||||
|
# Paginate results
|
||||||
|
@entry_count = TimeEntry.count(:include => :project, :conditions => cond.conditions)
|
||||||
|
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
|
||||||
|
@entries = TimeEntry.find(:all,
|
||||||
|
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||||
|
:conditions => cond.conditions,
|
||||||
|
:order => sort_clause,
|
||||||
|
:limit => @entry_pages.items_per_page,
|
||||||
|
:offset => @entry_pages.current.offset)
|
||||||
|
@total_hours = TimeEntry.sum(:hours, :include => :project, :conditions => cond.conditions).to_f
|
||||||
|
render :layout => !request.xhr?
|
||||||
|
}
|
||||||
|
format.csv {
|
||||||
|
# Export all entries
|
||||||
|
@entries = TimeEntry.find(:all,
|
||||||
|
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
|
||||||
|
:conditions => cond.conditions,
|
||||||
|
:order => sort_clause)
|
||||||
|
send_data(entries_to_csv(@entries).read, :type => 'text/csv; header=present', :filename => 'timelog.csv')
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
render_403 and return if @time_entry && !@time_entry.editable_by?(User.current)
|
||||||
|
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
|
||||||
|
@time_entry.attributes = params[:time_entry]
|
||||||
|
if request.post? and @time_entry.save
|
||||||
|
flash[:notice] = l(:notice_successful_update)
|
||||||
|
redirect_to :action => 'details', :project_id => @time_entry.project
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@activities = Enumeration::get_values('ACTI')
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
render_404 and return unless @time_entry
|
||||||
|
render_403 and return unless @time_entry.editable_by?(User.current)
|
||||||
|
@time_entry.destroy
|
||||||
|
flash[:notice] = l(:notice_successful_delete)
|
||||||
|
redirect_to :back
|
||||||
|
rescue RedirectBackError
|
||||||
|
redirect_to :action => 'details', :project_id => @time_entry.project
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def find_project
|
||||||
|
if params[:id]
|
||||||
|
@time_entry = TimeEntry.find(params[:id])
|
||||||
|
@project = @time_entry.project
|
||||||
|
elsif params[:issue_id]
|
||||||
|
@issue = Issue.find(params[:issue_id])
|
||||||
|
@project = @issue.project
|
||||||
|
elsif params[:project_id]
|
||||||
|
@project = Project.find(params[:project_id])
|
||||||
|
else
|
||||||
|
render_404
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -83,8 +83,7 @@ class UsersController < ApplicationController
|
|||||||
end
|
end
|
||||||
if @user.update_attributes(params[:user])
|
if @user.update_attributes(params[:user])
|
||||||
flash[:notice] = l(:notice_successful_update)
|
flash[:notice] = l(:notice_successful_update)
|
||||||
# Give a string to redirect_to otherwise it would use status param as the response code
|
redirect_to :action => 'list'
|
||||||
redirect_to(url_for(:action => 'list', :status => params[:status], :page => params[:page]))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@auth_sources = AuthSource.find(:all)
|
@auth_sources = AuthSource.find(:all)
|
||||||
|
|||||||
@@ -207,10 +207,8 @@ module ApplicationHelper
|
|||||||
rf = Regexp.new(filename, Regexp::IGNORECASE)
|
rf = Regexp.new(filename, Regexp::IGNORECASE)
|
||||||
# search for the picture in attachments
|
# search for the picture in attachments
|
||||||
if found = attachments.detect { |att| att.filename =~ rf }
|
if found = attachments.detect { |att| att.filename =~ rf }
|
||||||
image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
|
image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found.id
|
||||||
desc = found.description.to_s.gsub(/^([^\(\)]*).*$/, "\\1")
|
"!#{style}#{image_url}!"
|
||||||
alt = desc.blank? ? nil : "(#{desc})"
|
|
||||||
"!#{style}#{image_url}#{alt}!"
|
|
||||||
else
|
else
|
||||||
"!#{style}#{filename}!"
|
"!#{style}#{filename}!"
|
||||||
end
|
end
|
||||||
@@ -427,10 +425,6 @@ module ApplicationHelper
|
|||||||
form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
|
form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def back_url_hidden_field_tag
|
|
||||||
hidden_field_tag 'back_url', (params[:back_url] || request.env['HTTP_REFERER'])
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_all_links(form_name)
|
def check_all_links(form_name)
|
||||||
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
|
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
|
||||||
" | " +
|
" | " +
|
||||||
@@ -469,23 +463,10 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def calendar_for(field_id)
|
def calendar_for(field_id)
|
||||||
include_calendar_headers_tags
|
|
||||||
image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
|
image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
|
||||||
javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
|
javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_calendar_headers_tags
|
|
||||||
unless @calendar_headers_tags_included
|
|
||||||
@calendar_headers_tags_included = true
|
|
||||||
content_for :header_tags do
|
|
||||||
javascript_include_tag('calendar/calendar') +
|
|
||||||
javascript_include_tag("calendar/lang/calendar-#{current_language}.js") +
|
|
||||||
javascript_include_tag('calendar/calendar-setup') +
|
|
||||||
stylesheet_link_tag('calendar')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def wikitoolbar_for(field_id)
|
def wikitoolbar_for(field_id)
|
||||||
return '' unless Setting.text_formatting == 'textile'
|
return '' unless Setting.text_formatting == 'textile'
|
||||||
|
|
||||||
|
|||||||
@@ -58,11 +58,8 @@ module RepositoriesHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def with_leading_slash(path)
|
def with_leading_slash(path)
|
||||||
path.to_s.starts_with?('/') ? path : "/#{path}"
|
path ||= ''
|
||||||
end
|
path.starts_with?('/') ? path : "/#{path}"
|
||||||
|
|
||||||
def without_leading_slash(path)
|
|
||||||
path.gsub(%r{^/+}, '')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def subversion_field_tags(form, repository)
|
def subversion_field_tags(form, repository)
|
||||||
|
|||||||
@@ -76,60 +76,4 @@ module TimelogHelper
|
|||||||
export.rewind
|
export.rewind
|
||||||
export
|
export
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_criteria_value(criteria, value)
|
|
||||||
value.blank? ? l(:label_none) : ((k = @available_criterias[criteria][:klass]) ? k.find_by_id(value.to_i) : format_value(value, @available_criterias[criteria][:format]))
|
|
||||||
end
|
|
||||||
|
|
||||||
def report_to_csv(criterias, periods, hours)
|
|
||||||
export = StringIO.new
|
|
||||||
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
|
|
||||||
# Column headers
|
|
||||||
headers = criterias.collect {|criteria| l(@available_criterias[criteria][:label]) }
|
|
||||||
headers += periods
|
|
||||||
headers << l(:label_total)
|
|
||||||
csv << headers.collect {|c| to_utf8(c) }
|
|
||||||
# Content
|
|
||||||
report_criteria_to_csv(csv, criterias, periods, hours)
|
|
||||||
# Total row
|
|
||||||
row = [ l(:label_total) ] + [''] * (criterias.size - 1)
|
|
||||||
total = 0
|
|
||||||
periods.each do |period|
|
|
||||||
sum = sum_hours(select_hours(hours, @columns, period.to_s))
|
|
||||||
total += sum
|
|
||||||
row << (sum > 0 ? "%.2f" % sum : '')
|
|
||||||
end
|
|
||||||
row << "%.2f" %total
|
|
||||||
csv << row
|
|
||||||
end
|
|
||||||
export.rewind
|
|
||||||
export
|
|
||||||
end
|
|
||||||
|
|
||||||
def report_criteria_to_csv(csv, criterias, periods, hours, level=0)
|
|
||||||
hours.collect {|h| h[criterias[level]].to_s}.uniq.each do |value|
|
|
||||||
hours_for_value = select_hours(hours, criterias[level], value)
|
|
||||||
next if hours_for_value.empty?
|
|
||||||
row = [''] * level
|
|
||||||
row << to_utf8(format_criteria_value(criterias[level], value))
|
|
||||||
row += [''] * (criterias.length - level - 1)
|
|
||||||
total = 0
|
|
||||||
periods.each do |period|
|
|
||||||
sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s))
|
|
||||||
total += sum
|
|
||||||
row << (sum > 0 ? "%.2f" % sum : '')
|
|
||||||
end
|
|
||||||
row << "%.2f" %total
|
|
||||||
csv << row
|
|
||||||
|
|
||||||
if criterias.length > level + 1
|
|
||||||
report_criteria_to_csv(csv, criterias, periods, hours_for_value, level + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_utf8(s)
|
|
||||||
@ic ||= Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
|
||||||
begin; @ic.iconv(s.to_s); rescue; s.to_s; end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,16 +22,4 @@ module UsersHelper
|
|||||||
[l(:status_registered), 2],
|
[l(:status_registered), 2],
|
||||||
[l(:status_locked), 3]], selected)
|
[l(:status_locked), 3]], selected)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_status_link(user)
|
|
||||||
url = {:action => 'edit', :id => user, :page => params[:page], :status => params[:status]}
|
|
||||||
|
|
||||||
if user.locked?
|
|
||||||
link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock'
|
|
||||||
elsif user.registered?
|
|
||||||
link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock'
|
|
||||||
else
|
|
||||||
link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :post, :class => 'icon icon-lock'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,48 +35,48 @@ class Attachment < ActiveRecord::Base
|
|||||||
errors.add_to_base :too_long if self.filesize > Setting.attachment_max_size.to_i.kilobytes
|
errors.add_to_base :too_long if self.filesize > Setting.attachment_max_size.to_i.kilobytes
|
||||||
end
|
end
|
||||||
|
|
||||||
def file=(incoming_file)
|
def file=(incomming_file)
|
||||||
unless incoming_file.nil?
|
unless incomming_file.nil?
|
||||||
@temp_file = incoming_file
|
@temp_file = incomming_file
|
||||||
if @temp_file.size > 0
|
if @temp_file.size > 0
|
||||||
self.filename = sanitize_filename(@temp_file.original_filename)
|
self.filename = sanitize_filename(@temp_file.original_filename)
|
||||||
self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
|
self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
|
||||||
self.content_type = @temp_file.content_type.to_s.chomp
|
self.content_type = @temp_file.content_type.to_s.chomp
|
||||||
self.filesize = @temp_file.size
|
self.filesize = @temp_file.size
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def file
|
def file
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Copy temp file to its final location
|
# Copy temp file to its final location
|
||||||
def before_save
|
def before_save
|
||||||
if @temp_file && (@temp_file.size > 0)
|
if @temp_file && (@temp_file.size > 0)
|
||||||
logger.debug("saving '#{self.diskfile}'")
|
logger.debug("saving '#{self.diskfile}'")
|
||||||
File.open(diskfile, "wb") do |f|
|
File.open(diskfile, "wb") do |f|
|
||||||
f.write(@temp_file.read)
|
f.write(@temp_file.read)
|
||||||
end
|
end
|
||||||
self.digest = Digest::MD5.hexdigest(File.read(diskfile))
|
self.digest = Digest::MD5.hexdigest(File.read(diskfile))
|
||||||
end
|
end
|
||||||
# Don't save the content type if it's longer than the authorized length
|
# Don't save the content type if it's longer than the authorized length
|
||||||
if self.content_type && self.content_type.length > 255
|
if self.content_type && self.content_type.length > 255
|
||||||
self.content_type = nil
|
self.content_type = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Deletes file on the disk
|
# Deletes file on the disk
|
||||||
def after_destroy
|
def after_destroy
|
||||||
if self.filename?
|
if self.filename?
|
||||||
File.delete(diskfile) if File.exist?(diskfile)
|
File.delete(diskfile) if File.exist?(diskfile)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns file's location on disk
|
# Returns file's location on disk
|
||||||
def diskfile
|
def diskfile
|
||||||
"#{@@storage_path}/#{self.disk_filename}"
|
"#{@@storage_path}/#{self.disk_filename}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def increment_download
|
def increment_download
|
||||||
increment!(:downloads)
|
increment!(:downloads)
|
||||||
@@ -87,17 +87,18 @@ class Attachment < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def image?
|
def image?
|
||||||
self.filename =~ /\.(jpe?g|gif|png)$/i
|
self.filename =~ /\.(jpeg|jpg|gif|png)$/i
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def sanitize_filename(value)
|
def sanitize_filename(value)
|
||||||
# get only the filename, not the whole path
|
# get only the filename, not the whole path
|
||||||
just_filename = value.gsub(/^.*(\\|\/)/, '')
|
just_filename = value.gsub(/^.*(\\|\/)/, '')
|
||||||
# NOTE: File.basename doesn't work right with Windows paths on Unix
|
# NOTE: File.basename doesn't work right with Windows paths on Unix
|
||||||
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
|
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
|
||||||
|
|
||||||
# Finally, replace all non alphanumeric, hyphens or periods with underscore
|
# Finally, replace all non alphanumeric, underscore or periods with underscore
|
||||||
@filename = just_filename.gsub(/[^\w\.\-]/,'_')
|
@filename = just_filename.gsub(/[^\w\.\-]/,'_')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ class Changeset < ActiveRecord::Base
|
|||||||
validates_uniqueness_of :revision, :scope => :repository_id
|
validates_uniqueness_of :revision, :scope => :repository_id
|
||||||
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
|
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
|
||||||
|
|
||||||
def revision=(r)
|
|
||||||
write_attribute :revision, (r.nil? ? nil : r.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
def comments=(comment)
|
def comments=(comment)
|
||||||
write_attribute(:comments, comment.strip)
|
write_attribute(:comments, comment.strip)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -94,10 +94,6 @@ class Issue < ActiveRecord::Base
|
|||||||
write_attribute(:priority_id, pid)
|
write_attribute(:priority_id, pid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def estimated_hours=(h)
|
|
||||||
write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
|
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
|
||||||
errors.add :due_date, :activerecord_error_not_a_date
|
errors.add :due_date, :activerecord_error_not_a_date
|
||||||
@@ -157,8 +153,6 @@ class Issue < ActiveRecord::Base
|
|||||||
# Close duplicates if the issue was closed
|
# Close duplicates if the issue was closed
|
||||||
if @issue_before_change && !@issue_before_change.closed? && self.closed?
|
if @issue_before_change && !@issue_before_change.closed? && self.closed?
|
||||||
duplicates.each do |duplicate|
|
duplicates.each do |duplicate|
|
||||||
# Reload is need in case the duplicate was updated by a previous duplicate
|
|
||||||
duplicate.reload
|
|
||||||
# Don't re-close it if it's already closed
|
# Don't re-close it if it's already closed
|
||||||
next if duplicate.closed?
|
next if duplicate.closed?
|
||||||
# Same user and notes
|
# Same user and notes
|
||||||
@@ -243,8 +237,4 @@ class Issue < ActiveRecord::Base
|
|||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
|
||||||
"#{tracker} ##{id}: #{subject}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class Journal < ActiveRecord::Base
|
|||||||
acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}" + ((s = o.new_status) ? " (#{s})" : '') },
|
acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}" + ((s = o.new_status) ? " (#{s})" : '') },
|
||||||
:description => :notes,
|
:description => :notes,
|
||||||
:author => :user,
|
:author => :user,
|
||||||
:type => Proc.new {|o| (s = o.new_status) && s.is_closed? ? 'issue-closed' : 'issue-edit' },
|
|
||||||
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
|
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
|
||||||
|
|
||||||
def save
|
def save
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ class Message < ActiveRecord::Base
|
|||||||
:date_column => 'created_on'
|
:date_column => 'created_on'
|
||||||
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
||||||
:description => :content,
|
:description => :content,
|
||||||
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
|
|
||||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}}
|
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}}
|
||||||
|
|
||||||
attr_protected :locked, :sticky
|
attr_protected :locked, :sticky
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ class MessageObserver < ActiveRecord::Observer
|
|||||||
recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author && m.author.active?}
|
recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author && m.author.active?}
|
||||||
# send notification to the board watchers
|
# send notification to the board watchers
|
||||||
recipients += message.board.watcher_recipients
|
recipients += message.board.watcher_recipients
|
||||||
# send notification to project members who want to be notified
|
|
||||||
recipients += message.board.project.recipients
|
|
||||||
recipients = recipients.compact.uniq
|
recipients = recipients.compact.uniq
|
||||||
Mailer.deliver_message_posted(message, recipients) if !recipients.empty? && Setting.notified_events.include?('message_posted')
|
Mailer.deliver_message_posted(message, recipients) if !recipients.empty? && Setting.notified_events.include?('message_posted')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Project < ActiveRecord::Base
|
|||||||
has_many :documents, :dependent => :destroy
|
has_many :documents, :dependent => :destroy
|
||||||
has_many :news, :dependent => :delete_all, :include => :author
|
has_many :news, :dependent => :delete_all, :include => :author
|
||||||
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
|
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
|
||||||
has_many :boards, :dependent => :destroy, :order => "position ASC"
|
has_many :boards, :order => "position ASC"
|
||||||
has_one :repository, :dependent => :destroy
|
has_one :repository, :dependent => :destroy
|
||||||
has_many :changesets, :through => :repository
|
has_many :changesets, :through => :repository
|
||||||
has_one :wiki, :dependent => :destroy
|
has_one :wiki, :dependent => :destroy
|
||||||
@@ -75,14 +75,12 @@ class Project < ActiveRecord::Base
|
|||||||
conditions = nil
|
conditions = nil
|
||||||
if include_subprojects && !active_children.empty?
|
if include_subprojects && !active_children.empty?
|
||||||
ids = [id] + active_children.collect {|c| c.id}
|
ids = [id] + active_children.collect {|c| c.id}
|
||||||
conditions = ["#{Project.table_name}.id IN (#{ids.join(',')})"]
|
conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
|
||||||
end
|
end
|
||||||
conditions ||= ["#{Project.table_name}.id = ?", id]
|
conditions ||= ["#{Issue.table_name}.project_id = ?", id]
|
||||||
# Quick and dirty fix for Rails 2 compatibility
|
# Quick and dirty fix for Rails 2 compatibility
|
||||||
Issue.send(:with_scope, :find => { :conditions => conditions }) do
|
Issue.send(:with_scope, :find => { :conditions => conditions }) do
|
||||||
Version.send(:with_scope, :find => { :conditions => conditions }) do
|
yield
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ class Query < ActiveRecord::Base
|
|||||||
# custom field
|
# custom field
|
||||||
db_table = CustomValue.table_name
|
db_table = CustomValue.table_name
|
||||||
db_field = 'value'
|
db_field = 'value'
|
||||||
sql << "#{Issue.table_name}.id IN (SELECT #{Issue.table_name}.id FROM #{Issue.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} WHERE "
|
sql << "#{Issue.table_name}.id IN (SELECT #{db_table}.customized_id FROM #{db_table} where #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} AND "
|
||||||
else
|
else
|
||||||
# regular field
|
# regular field
|
||||||
db_table = Issue.table_name
|
db_table = Issue.table_name
|
||||||
@@ -320,9 +320,9 @@ class Query < ActiveRecord::Base
|
|||||||
when "!"
|
when "!"
|
||||||
sql = sql + "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
|
sql = sql + "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
|
||||||
when "!*"
|
when "!*"
|
||||||
sql = sql + "#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} = ''"
|
sql = sql + "#{db_table}.#{db_field} IS NULL"
|
||||||
when "*"
|
when "*"
|
||||||
sql = sql + "#{db_table}.#{db_field} IS NOT NULL AND #{db_table}.#{db_field} <> ''"
|
sql = sql + "#{db_table}.#{db_field} IS NOT NULL"
|
||||||
when ">="
|
when ">="
|
||||||
sql = sql + "#{db_table}.#{db_field} >= #{v.first.to_i}"
|
sql = sql + "#{db_table}.#{db_field} >= #{v.first.to_i}"
|
||||||
when "<="
|
when "<="
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ class Repository::Cvs < Repository
|
|||||||
end
|
end
|
||||||
|
|
||||||
def entries(path=nil, identifier=nil)
|
def entries(path=nil, identifier=nil)
|
||||||
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
|
entries=scm.entries(path, identifier)
|
||||||
entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
|
|
||||||
if entries
|
if entries
|
||||||
entries.each() do |entry|
|
entries.each() do |entry|
|
||||||
unless entry.lastrev.nil? || entry.lastrev.identifier
|
unless entry.lastrev.nil? || entry.lastrev.identifier
|
||||||
@@ -138,18 +137,12 @@ class Repository::Cvs < Repository
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Renumber new changesets in chronological order
|
# Renumber new changesets in chronological order
|
||||||
|
c = changesets.find(:first, :order => 'committed_on DESC, id DESC', :conditions => "revision NOT LIKE '_%'")
|
||||||
|
next_rev = c.nil? ? 1 : (c.revision.to_i + 1)
|
||||||
changesets.find(:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE '_%'").each do |changeset|
|
changesets.find(:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE '_%'").each do |changeset|
|
||||||
changeset.update_attribute :revision, next_revision_number
|
changeset.update_attribute :revision, next_rev
|
||||||
|
next_rev += 1
|
||||||
end
|
end
|
||||||
end # transaction
|
end # transaction
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Returns the next revision number to assign to a CVS changeset
|
|
||||||
def next_revision_number
|
|
||||||
# Need to retrieve existing revision numbers to sort them as integers
|
|
||||||
@current_revision_number ||= (connection.select_values("SELECT revision FROM #{Changeset.table_name} WHERE repository_id = #{id} AND revision NOT LIKE '_%'").collect(&:to_i).max || 0)
|
|
||||||
@current_revision_number += 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ class Repository::Darcs < Repository
|
|||||||
end
|
end
|
||||||
|
|
||||||
def entries(path=nil, identifier=nil)
|
def entries(path=nil, identifier=nil)
|
||||||
patch = identifier.nil? ? nil : changesets.find_by_revision(identifier)
|
entries=scm.entries(path, identifier)
|
||||||
entries = scm.entries(path, patch.nil? ? nil : patch.scmid)
|
|
||||||
if entries
|
if entries
|
||||||
entries.each do |entry|
|
entries.each do |entry|
|
||||||
# Search the DB for the entry's last change
|
# Search the DB for the entry's last change
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ class Repository::Mercurial < Repository
|
|||||||
if entries
|
if entries
|
||||||
entries.each do |entry|
|
entries.each do |entry|
|
||||||
next unless entry.is_file?
|
next unless entry.is_file?
|
||||||
# Set the filesize unless browsing a specific revision
|
|
||||||
if identifier.nil?
|
|
||||||
full_path = File.join(root_url, entry.path)
|
|
||||||
entry.size = File.stat(full_path).size if File.file?(full_path)
|
|
||||||
end
|
|
||||||
# Search the DB for the entry's last change
|
# Search the DB for the entry's last change
|
||||||
change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC")
|
change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC")
|
||||||
if change
|
if change
|
||||||
@@ -58,9 +53,7 @@ class Repository::Mercurial < Repository
|
|||||||
# latest revision found in database
|
# latest revision found in database
|
||||||
db_revision = latest_changeset ? latest_changeset.revision.to_i : -1
|
db_revision = latest_changeset ? latest_changeset.revision.to_i : -1
|
||||||
# latest revision in the repository
|
# latest revision in the repository
|
||||||
latest_revision = scm_info.lastrev
|
scm_revision = scm_info.lastrev.identifier.to_i
|
||||||
return if latest_revision.nil?
|
|
||||||
scm_revision = latest_revision.identifier.to_i
|
|
||||||
if db_revision < scm_revision
|
if db_revision < scm_revision
|
||||||
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
|
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
|
||||||
identifier_from = db_revision + 1
|
identifier_from = db_revision + 1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# redMine - project management software
|
# redMine - project management software
|
||||||
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU General Public License
|
# modify it under the terms of the GNU General Public License
|
||||||
@@ -39,10 +39,6 @@ class TimeEntry < ActiveRecord::Base
|
|||||||
errors.add :issue_id, :activerecord_error_invalid if (issue_id && !issue) || (issue && project!=issue.project)
|
errors.add :issue_id, :activerecord_error_invalid if (issue_id && !issue) || (issue && project!=issue.project)
|
||||||
end
|
end
|
||||||
|
|
||||||
def hours=(h)
|
|
||||||
write_attribute :hours, (h.is_a?(String) ? h.to_hours : h)
|
|
||||||
end
|
|
||||||
|
|
||||||
# tyear, tmonth, tweek assigned where setting spent_on attributes
|
# tyear, tmonth, tweek assigned where setting spent_on attributes
|
||||||
# these attributes make time aggregations easier
|
# these attributes make time aggregations easier
|
||||||
def spent_on=(date)
|
def spent_on=(date)
|
||||||
|
|||||||
@@ -18,9 +18,6 @@
|
|||||||
require "digest/sha1"
|
require "digest/sha1"
|
||||||
|
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
|
|
||||||
class OnTheFlyCreationFailure < Exception; end
|
|
||||||
|
|
||||||
# Account statuses
|
# Account statuses
|
||||||
STATUS_ANONYMOUS = 0
|
STATUS_ANONYMOUS = 0
|
||||||
STATUS_ACTIVE = 1
|
STATUS_ACTIVE = 1
|
||||||
@@ -108,17 +105,15 @@ class User < ActiveRecord::Base
|
|||||||
onthefly.language = Setting.default_language
|
onthefly.language = Setting.default_language
|
||||||
if onthefly.save
|
if onthefly.save
|
||||||
user = find(:first, :conditions => ["login=?", login])
|
user = find(:first, :conditions => ["login=?", login])
|
||||||
logger.info("User '#{user.login}' created from the LDAP") if logger
|
logger.info("User '#{user.login}' created on the fly.") if logger
|
||||||
else
|
|
||||||
logger.error("User '#{onthefly.login}' found in LDAP but could not be created (#{onthefly.errors.full_messages.join(', ')})") if logger
|
|
||||||
raise OnTheFlyCreationFailure.new
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
user.update_attribute(:last_login_on, Time.now) if user
|
user.update_attribute(:last_login_on, Time.now) if user
|
||||||
user
|
user
|
||||||
rescue => text
|
|
||||||
raise text
|
rescue => text
|
||||||
|
raise text
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return user's full name for display
|
# Return user's full name for display
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ class WikiContent < ActiveRecord::Base
|
|||||||
acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
|
acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
|
||||||
:description => :comments,
|
:description => :comments,
|
||||||
:datetime => :updated_on,
|
:datetime => :updated_on,
|
||||||
:type => 'wiki-page',
|
|
||||||
:url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}}
|
:url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}}
|
||||||
|
|
||||||
def text=(plain)
|
def text=(plain)
|
||||||
|
|||||||
@@ -35,3 +35,10 @@
|
|||||||
|
|
||||||
<%= submit_tag l(:button_submit) %>
|
<%= submit_tag l(:button_submit) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -19,15 +19,12 @@ while day <= calendar.enddt %>
|
|||||||
elsif day == i.due_date
|
elsif day == i.due_date
|
||||||
image_tag('arrow_to.png')
|
image_tag('arrow_to.png')
|
||||||
end %>
|
end %>
|
||||||
<%= h("#{i.project} -") unless @project && @project == i.project %>
|
<%= h("#{i.project.name} -") unless @project && @project == i.project %>
|
||||||
<%= link_to_issue i %>: <%= h(truncate(i.subject, 30)) %>
|
<%= link_to_issue i %>: <%= h(truncate(i.subject, 30)) %>
|
||||||
<span class="tip"><%= render_issue_tooltip i %></span>
|
<span class="tip"><%= render_issue_tooltip i %></span>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="icon icon-package">
|
<%= link_to_version i, :class => "icon icon-package" %>
|
||||||
<%= h("#{i.project} -") unless @project && @project == i.project %>
|
|
||||||
<%= link_to_version i%>
|
|
||||||
</span>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -49,3 +49,10 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= wikitoolbar_for 'issue_description' %>
|
<%= wikitoolbar_for 'issue_description' %>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% for journal in journals %>
|
<% for journal in journals %>
|
||||||
<div id="change-<%= journal.id %>" class="journal">
|
<div id="change-<%= journal.id %>">
|
||||||
<h4><div style="float:right;"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div>
|
<h4><div style="float:right;"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div>
|
||||||
<%= content_tag('a', '', :name => "note-#{journal.indice}")%>
|
<%= content_tag('a', '', :name => "note-#{journal.indice}")%>
|
||||||
<%= format_time(journal.created_on) %> - <%= journal.user.name %></h4>
|
<%= format_time(journal.created_on) %> - <%= journal.user.name %></h4>
|
||||||
|
|||||||
@@ -47,3 +47,10 @@
|
|||||||
|
|
||||||
<p><%= submit_tag l(:button_submit) %>
|
<p><%= submit_tag l(:button_submit) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<%= submit_tag l(:button_create) %>
|
<%= submit_tag l(:button_create) %>
|
||||||
<%= link_to_remote l(:label_preview),
|
<%= link_to_remote l(:label_preview),
|
||||||
{ :url => { :controller => 'issues', :action => 'preview', :project_id => @project },
|
{ :url => { :controller => 'issues', :action => 'preview', :project_id => @project, :id => @issue },
|
||||||
:method => 'post',
|
:method => 'post',
|
||||||
:update => 'preview',
|
:update => 'preview',
|
||||||
:with => "Form.serialize('issue-form')",
|
:with => "Form.serialize('issue-form')",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<h3><%=h @issue.subject %></h3>
|
<h3><%=h @issue.subject %></h3>
|
||||||
<p class="author">
|
<p class="author">
|
||||||
<%= authoring @issue.created_on, @issue.author %>.
|
<%= authoring @issue.created_on, @issue.author %>.
|
||||||
<%= l(:label_updated_time, distance_of_time_in_words(Time.now, @issue.updated_on)) + '.' if @issue.created_on != @issue.updated_on %>
|
<%= l(:label_updated_time, distance_of_time_in_words(Time.now, @issue.updated_on)) if @issue.created_on != @issue.updated_on %>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|||||||
@@ -46,3 +46,11 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
<% end %>
|
<% end %>
|
||||||
<!--[eoform:project]-->
|
<!--[eoform:project]-->
|
||||||
|
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<h3><%= format_activity_day(day) %></h3>
|
<h3><%= format_activity_day(day) %></h3>
|
||||||
<dl>
|
<dl>
|
||||||
<% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
|
<% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
|
||||||
<dt class="<%= e.event_type %>"><span class="time"><%= format_time(e.event_datetime, false) %></span>
|
<dt class="<%= e.class.name.downcase %>"><span class="time"><%= format_time(e.event_datetime, false) %></span>
|
||||||
<%= content_tag('span', h(e.project), :class => 'project') if @project.nil? || @project != e.project %> <%= link_to h(truncate(e.event_title, 100)), e.event_url %></dt>
|
<%= content_tag('span', h(e.project), :class => 'project') if @project.nil? || @project != e.project %> <%= link_to h(truncate(e.event_title, 100)), e.event_url %></dt>
|
||||||
<dd><% unless e.event_description.blank? -%>
|
<dd><% unless e.event_description.blank? -%>
|
||||||
<span class="description"><%= format_activity_description(e.event_description) %></span><br />
|
<span class="description"><%= format_activity_description(e.event_description) %></span><br />
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
<h2><%=l(:label_confirmation)%></h2>
|
<h2><%=l(:label_confirmation)%></h2>
|
||||||
<div class="warning">
|
<div class="box">
|
||||||
<p><strong><%=h @project_to_destroy %></strong><br />
|
<center>
|
||||||
<%=l(:text_project_destroy_confirmation)%>
|
<p><strong><%=h @project_to_destroy.name %></strong><br />
|
||||||
|
<%=l(:text_project_destroy_confirmation)%></p>
|
||||||
|
|
||||||
<% if @project_to_destroy.children.any? %>
|
|
||||||
<br /><%= l(:text_subprojects_destroy_warning, content_tag('strong', h(@project_to_destroy.children.sort.collect{|p| p.to_s}.join(', ')))) %>
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
<% form_tag({:controller => 'projects', :action => 'destroy', :id => @project_to_destroy}) do %>
|
<% form_tag({:controller => 'projects', :action => 'destroy', :id => @project_to_destroy}) do %>
|
||||||
<label><%= check_box_tag 'confirm', 1 %> <%= l(:general_text_Yes) %></label>
|
<%= hidden_field_tag "confirm", 1 %>
|
||||||
<%= submit_tag l(:button_delete) %>
|
<%= submit_tag l(:button_delete) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
|
</center>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,13 +70,10 @@ top = headers_height + 8
|
|||||||
@events.each do |i| %>
|
@events.each do |i| %>
|
||||||
<div style="position: absolute;line-height:1.2em;height:16px;top:<%= top %>px;left:4px;overflow:hidden;"><small>
|
<div style="position: absolute;line-height:1.2em;height:16px;top:<%= top %>px;left:4px;overflow:hidden;"><small>
|
||||||
<% if i.is_a? Issue %>
|
<% if i.is_a? Issue %>
|
||||||
<%= h("#{i.project} -") unless @project && @project == i.project %>
|
<%= h("#{i.project.name} -") unless @project && @project == i.project %>
|
||||||
<%= link_to_issue i %>: <%=h i.subject %>
|
<%= link_to_issue i %>: <%=h i.subject %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="icon icon-package">
|
<%= link_to_version i, :class => "icon icon-package" %>
|
||||||
<%= h("#{i.project} -") unless @project && @project == i.project %>
|
|
||||||
<%= link_to_version i %>
|
|
||||||
</span>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</small></div>
|
</small></div>
|
||||||
<% top = top + 20
|
<% top = top + 20
|
||||||
@@ -200,8 +197,7 @@ top = headers_height + 10
|
|||||||
%>
|
%>
|
||||||
<div style="top:<%= top %>px;left:<%= i_left %>px;width:15px;" class="task milestone"> </div>
|
<div style="top:<%= top %>px;left:<%= i_left %>px;width:15px;" class="task milestone"> </div>
|
||||||
<div style="top:<%= top %>px;left:<%= i_left + 12 %>px;background:#fff;" class="task">
|
<div style="top:<%= top %>px;left:<%= i_left + 12 %>px;background:#fff;" class="task">
|
||||||
<%= h("#{i.project} -") unless @project && @project == i.project %>
|
<strong><%= i.name %></strong>
|
||||||
<strong><%=h i %></strong>
|
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% top = top + 20
|
<% top = top + 20
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<table class="list">
|
<table class="list">
|
||||||
<thead><tr>
|
<thead><tr>
|
||||||
<th><%=l(:field_version)%></th>
|
<th><%=l(:field_version)%></th>
|
||||||
<%= sort_header_tag("#{Attachment.table_name}.filename", :caption => l(:field_filename)) %>
|
<th><%=l(:field_filename)%></th>
|
||||||
<%= sort_header_tag("#{Attachment.table_name}.created_on", :caption => l(:label_date), :default_order => 'desc') %>
|
<th><%=l(:label_date)%></th>
|
||||||
<%= sort_header_tag("#{Attachment.table_name}.filesize", :caption => l(:field_filesize), :default_order => 'desc') %>
|
<th><%=l(:field_filesize)%></th>
|
||||||
<%= sort_header_tag("#{Attachment.table_name}.downloads", :caption => l(:label_downloads_abbr), :default_order => 'desc') %>
|
<th><%=l(:label_downloads_abbr)%></th>
|
||||||
<th>MD5</th>
|
<th>MD5</th>
|
||||||
<% if delete_allowed %><th></th><% end %>
|
<% if delete_allowed %><th></th><% end %>
|
||||||
</tr></thead>
|
</tr></thead>
|
||||||
|
|||||||
@@ -59,19 +59,19 @@ function toggle_multi_select(field) {
|
|||||||
<table width="100%">
|
<table width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<table>
|
<table style="padding:0;">
|
||||||
<% query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %>
|
<% query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %>
|
||||||
<% field = filter[0]
|
<% field = filter[0]
|
||||||
options = filter[1] %>
|
options = filter[1] %>
|
||||||
<tr <%= 'style="display:none;"' unless query.has_filter?(field) %> id="tr_<%= field %>" class="filter">
|
<tr <%= 'style="display:none;"' unless query.has_filter?(field) %> id="tr_<%= field %>">
|
||||||
<td style="width:200px;">
|
<td valign="top" style="width:200px;">
|
||||||
<%= check_box_tag 'fields[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %>
|
<%= check_box_tag 'fields[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %>
|
||||||
<label for="cb_<%= field %>"><%= filter[1][:name] || l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label>
|
<label for="cb_<%= field %>"><%= filter[1][:name] || l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:150px;">
|
<td valign="top" style="width:150px;">
|
||||||
<%= select_tag "operators[#{field}]", options_for_select(operators_for_select(options[:type]), query.operator_for(field)), :id => "operators_#{field}", :onchange => "toggle_operator('#{field}');", :class => "select-small", :style => "vertical-align: top;" %>
|
<%= select_tag "operators[#{field}]", options_for_select(operators_for_select(options[:type]), query.operator_for(field)), :id => "operators_#{field}", :onchange => "toggle_operator('#{field}');", :class => "select-small", :style => "vertical-align: top;" %>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td valign="top">
|
||||||
<div id="div_values_<%= field %>" style="display:none;">
|
<div id="div_values_<%= field %>" style="display:none;">
|
||||||
<% case options[:type]
|
<% case options[:type]
|
||||||
when :list, :list_optional, :list_status, :list_subprojects %>
|
when :list, :list_optional, :list_status, :list_subprojects %>
|
||||||
@@ -93,7 +93,7 @@ function toggle_multi_select(field) {
|
|||||||
<% end %>
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
<td class="add-filter">
|
<td align="right" valign="top">
|
||||||
<%= l(:label_filter_add) %>:
|
<%= l(:label_filter_add) %>:
|
||||||
<%= select_tag 'add_filter_select', options_for_select([["",""]] + query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.collect{|field| [ field[1][:name] || l(("field_"+field[0].to_s.gsub(/\_id$/, "")).to_sym), field[0]] unless query.has_filter?(field[0])}.compact), :onchange => "add_filter();", :class => "select-small" %>
|
<%= select_tag 'add_filter_select', options_for_select([["",""]] + query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.collect{|field| [ field[1][:name] || l(("field_"+field[0].to_s.gsub(/\_id$/, "")).to_sym), field[0]] unless query.has_filter?(field[0])}.compact), :onchange => "add_filter();", :class => "select-small" %>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
<td><div class="square action_<%= change.action %>"></div> <%= change.path %> <%= "(#{change.revision})" unless change.revision.blank? %></td>
|
<td><div class="square action_<%= change.action %>"></div> <%= change.path %> <%= "(#{change.revision})" unless change.revision.blank? %></td>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<% if change.action == "M" %>
|
<% if change.action == "M" %>
|
||||||
<%= link_to l(:label_view_diff), :action => 'diff', :id => @project, :path => without_leading_slash(change.path), :rev => @changeset.revision %>
|
<%= link_to l(:label_view_diff), :action => 'diff', :id => @project, :path => change.path, :rev => @changeset.revision %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<fieldset id="filters"><legend><%= l(:label_date_range) %></legend>
|
|
||||||
<p>
|
|
||||||
<%= radio_button_tag 'period_type', '1', !@free_period %>
|
|
||||||
<%= select_tag 'period', options_for_period_select(params[:period]),
|
|
||||||
:onchange => 'this.form.onsubmit();',
|
|
||||||
:onfocus => '$("period_type_1").checked = true;' %>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<%= radio_button_tag 'period_type', '2', @free_period %>
|
|
||||||
<span onclick="$('period_type_2').checked = true;">
|
|
||||||
<%= l(:label_date_from) %>
|
|
||||||
<%= text_field_tag 'from', @from, :size => 10 %> <%= calendar_for('from') %>
|
|
||||||
<%= l(:label_date_to) %>
|
|
||||||
<%= text_field_tag 'to', @to, :size => 10 %> <%= calendar_for('to') %>
|
|
||||||
</span>
|
|
||||||
<%= submit_tag l(:button_apply), :name => nil %>
|
|
||||||
</p>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div class="tabs">
|
|
||||||
<% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
|
|
||||||
<ul>
|
|
||||||
<li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'details', :project_id => @project }),
|
|
||||||
:class => (@controller.action_name == 'details' ? 'selected' : nil)) %></li>
|
|
||||||
<li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project}),
|
|
||||||
:class => (@controller.action_name == 'report' ? 'selected' : nil)) %></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<table class="list time-entries">
|
<table class="list time-entries">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
|
||||||
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
|
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
|
||||||
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
|
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
|
||||||
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
|
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
|
||||||
@@ -9,7 +8,6 @@
|
|||||||
<th><%= l(:field_comments) %></th>
|
<th><%= l(:field_comments) %></th>
|
||||||
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
|
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% entries.each do |entry| -%>
|
<% entries.each do |entry| -%>
|
||||||
@@ -37,5 +35,5 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</tbody>
|
</tbdoy>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
<% @hours.collect {|h| h[criterias[level]].to_s}.uniq.each do |value| %>
|
<% @hours.collect {|h| h[criterias[level]]}.uniq.each do |value| %>
|
||||||
<% hours_for_value = select_hours(hours, criterias[level], value) -%>
|
<% hours_for_value = select_hours(hours, criterias[level], value) -%>
|
||||||
<% next if hours_for_value.empty? -%>
|
<% next if hours_for_value.empty? -%>
|
||||||
<tr class="<%= cycle('odd', 'even') %> <%= 'last-level' unless criterias.length > level+1 %>">
|
<tr class="<%= cycle('odd', 'even') %> <%= 'last-level' unless criterias.length > level+1 %>">
|
||||||
<%= '<td></td>' * level %>
|
<%= '<td></td>' * level %>
|
||||||
<td><%= format_criteria_value(criterias[level], value) %></td>
|
<td><%= value.nil? ? l(:label_none) : @available_criterias[criterias[level]][:klass].find_by_id(value) %></td>
|
||||||
<%= '<td></td>' * (criterias.length - level - 1) -%>
|
<%= '<td></td>' * (criterias.length - level - 1) -%>
|
||||||
<% total = 0 -%>
|
|
||||||
<% @periods.each do |period| -%>
|
<% @periods.each do |period| -%>
|
||||||
<% sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s)); total += sum -%>
|
<% sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s)) %>
|
||||||
<td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
|
<td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
<td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% if criterias.length > level+1 -%>
|
<% if criterias.length > level+1 -%>
|
||||||
<%= render(:partial => 'report_criteria', :locals => {:criterias => criterias, :hours => hours_for_value, :level => (level + 1)}) %>
|
<%= render(:partial => 'report_criteria', :locals => {:criterias => criterias, :hours => hours_for_value, :level => (level + 1)}) %>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
|
<%= link_to(l(:label_report), {:controller => 'timelog', :action => 'report', :project_id => @project}, :class => 'icon icon-report') %>
|
||||||
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time' %>
|
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -11,7 +12,23 @@
|
|||||||
<% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %>
|
<% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %>
|
||||||
<%= hidden_field_tag 'project_id', params[:project_id] %>
|
<%= hidden_field_tag 'project_id', params[:project_id] %>
|
||||||
<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %>
|
<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %>
|
||||||
<%= render :partial => 'date_range' %>
|
|
||||||
|
<fieldset><legend><%= l(:label_date_range) %></legend>
|
||||||
|
<p>
|
||||||
|
<%= radio_button_tag 'period_type', '1', !@free_period %>
|
||||||
|
<%= select_tag 'period', options_for_period_select(params[:period]),
|
||||||
|
:onchange => 'this.form.onsubmit();',
|
||||||
|
:onfocus => '$("period_type_1").checked = true;' %>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<%= radio_button_tag 'period_type', '2', @free_period %>
|
||||||
|
<%= l(:label_date_from) %>
|
||||||
|
<%= text_field_tag 'from', @from, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('from') %>
|
||||||
|
<%= l(:label_date_to) %>
|
||||||
|
<%= text_field_tag 'to', @to, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('to') %>
|
||||||
|
<%= submit_tag l(:button_apply), :name => nil, :onclick => '$("period_type_2").checked = true;' %>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="total-hours">
|
<div class="total-hours">
|
||||||
@@ -28,4 +45,9 @@
|
|||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% html_title l(:label_spent_time), l(:label_details) %>
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
<% labelled_tabular_form_for :time_entry, @time_entry, :url => {:action => 'edit', :project_id => @time_entry.project} do |f| %>
|
<% labelled_tabular_form_for :time_entry, @time_entry, :url => {:action => 'edit', :project_id => @time_entry.project} do |f| %>
|
||||||
<%= error_messages_for 'time_entry' %>
|
<%= error_messages_for 'time_entry' %>
|
||||||
<%= back_url_hidden_field_tag %>
|
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<p><%= f.text_field :issue_id, :size => 6 %> <em><%= h("#{@time_entry.issue.tracker.name} ##{@time_entry.issue.id}: #{@time_entry.issue.subject}") if @time_entry.issue %></em></p>
|
<p><%= f.text_field :issue_id, :size => 6 %> <em><%= h("#{@time_entry.issue.tracker.name} ##{@time_entry.issue.id}: #{@time_entry.issue.subject}") if @time_entry.issue %></em></p>
|
||||||
@@ -15,3 +14,10 @@
|
|||||||
<%= submit_tag l(:button_save) %>
|
<%= submit_tag l(:button_save) %>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
@@ -1,31 +1,35 @@
|
|||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
|
<%= link_to(l(:label_details), {:controller => 'timelog', :action => 'details', :project_id => @project}, :class => 'icon icon-details') %>
|
||||||
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time' %>
|
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2><%= l(:label_spent_time) %></h2>
|
<h2><%= l(:label_spent_time) %></h2>
|
||||||
|
|
||||||
<% form_remote_tag(:url => {}, :update => 'content') do %>
|
<% form_remote_tag(:url => {:project_id => @project}, :update => 'content') do %>
|
||||||
<% @criterias.each do |criteria| %>
|
<% @criterias.each do |criteria| %>
|
||||||
<%= hidden_field_tag 'criterias[]', criteria, :id => nil %>
|
<%= hidden_field_tag 'criterias[]', criteria %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= hidden_field_tag 'project_id', params[:project_id] %>
|
<fieldset><legend><%= l(:label_date_range) %></legend>
|
||||||
<%= render :partial => 'date_range' %>
|
<p>
|
||||||
|
<%= l(:label_date_from) %>
|
||||||
|
<%= text_field_tag 'date_from', @date_from, :size => 10 %><%= calendar_for('date_from') %>
|
||||||
|
<%= l(:label_date_to) %>
|
||||||
|
<%= text_field_tag 'date_to', @date_to, :size => 10 %><%= calendar_for('date_to') %>
|
||||||
|
<%= l(:label_details) %>
|
||||||
|
<%= select_tag 'period', options_for_select([[l(:label_year), 'year'],
|
||||||
|
[l(:label_month), 'month'],
|
||||||
|
[l(:label_week), 'week']], @columns) %>
|
||||||
|
|
||||||
|
<%= submit_tag l(:button_apply) %>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<p><%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
|
<p><%= l(:button_add) %>: <%= select_tag('criterias[]', options_for_select([[]] + (@available_criterias.keys - @criterias).collect{|k| [l(@available_criterias[k][:label]), k]}),
|
||||||
[l(:label_month), 'month'],
|
|
||||||
[l(:label_week), 'week'],
|
|
||||||
[l(:label_day_plural).titleize, 'day']], @columns),
|
|
||||||
:onchange => "this.form.onsubmit();" %>
|
|
||||||
|
|
||||||
<%= l(:button_add) %>: <%= select_tag('criterias[]', options_for_select([[]] + (@available_criterias.keys - @criterias).collect{|k| [l(@available_criterias[k][:label]), k]}),
|
|
||||||
:onchange => "this.form.onsubmit();",
|
:onchange => "this.form.onsubmit();",
|
||||||
:style => 'width: 200px',
|
:style => 'width: 200px',
|
||||||
:id => nil,
|
|
||||||
:disabled => (@criterias.length >= 3)) %>
|
:disabled => (@criterias.length >= 3)) %>
|
||||||
<%= link_to_remote l(:button_clear), {:url => {:project_id => @project, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @columns},
|
<%= link_to_remote l(:button_clear), {:url => {:project_id => @project, :date_from => @date_from, :date_to => @date_to, :period => @columns}, :update => 'content'},
|
||||||
:update => 'content'
|
:class => 'icon icon-reload' %></p>
|
||||||
}, :class => 'icon icon-reload' %></p>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% unless @criterias.empty? %>
|
<% unless @criterias.empty? %>
|
||||||
<div class="total-hours">
|
<div class="total-hours">
|
||||||
@@ -37,13 +41,11 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<% @criterias.each do |criteria| %>
|
<% @criterias.each do |criteria| %>
|
||||||
<th><%= l(@available_criterias[criteria][:label]) %></th>
|
<th width="15%"><%= l(@available_criterias[criteria][:label]) %></th>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% columns_width = (40 / (@periods.length+1)).to_i %>
|
|
||||||
<% @periods.each do |period| %>
|
<% @periods.each do |period| %>
|
||||||
<th class="period" width="<%= columns_width %>%"><%= period %></th>
|
<th width="<%= ((100 - @criterias.length * 15 - 15 ) / @periods.length).to_i %>%"><%= period %></th>
|
||||||
<% end %>
|
<% end %>
|
||||||
<th class="total" width="<%= columns_width %>%"><%= l(:label_total) %></th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -51,22 +53,20 @@
|
|||||||
<tr class="total">
|
<tr class="total">
|
||||||
<td><%= l(:label_total) %></td>
|
<td><%= l(:label_total) %></td>
|
||||||
<%= '<td></td>' * (@criterias.size - 1) %>
|
<%= '<td></td>' * (@criterias.size - 1) %>
|
||||||
<% total = 0 -%>
|
|
||||||
<% @periods.each do |period| -%>
|
<% @periods.each do |period| -%>
|
||||||
<% sum = sum_hours(select_hours(@hours, @columns, period.to_s)); total += sum -%>
|
<% sum = sum_hours(select_hours(@hours, @columns, period.to_s)) %>
|
||||||
<td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
|
<td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
<td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<% end %>
|
||||||
<p class="other-formats">
|
|
||||||
<%= l(:label_export_to) %>
|
|
||||||
<span><%= link_to 'CSV', params.merge({:format => 'csv'}), :class => 'csv' %></span>
|
|
||||||
</p>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% html_title l(:label_spent_time), l(:label_report) %>
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -30,3 +30,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--[eoform:user]-->
|
<!--[eoform:user]-->
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
@@ -33,7 +33,17 @@
|
|||||||
<td align="center"><%= image_tag('true.png') if user.admin? %></td>
|
<td align="center"><%= image_tag('true.png') if user.admin? %></td>
|
||||||
<td class="created_on" align="center"><%= format_time(user.created_on) %></td>
|
<td class="created_on" align="center"><%= format_time(user.created_on) %></td>
|
||||||
<td class="last_login_on" align="center"><%= format_time(user.last_login_on) unless user.last_login_on.nil? %></td>
|
<td class="last_login_on" align="center"><%= format_time(user.last_login_on) unless user.last_login_on.nil? %></td>
|
||||||
<td><small><%= change_status_link(user) %></small></td>
|
<td>
|
||||||
|
<small>
|
||||||
|
<% if user.locked? -%>
|
||||||
|
<%= link_to l(:button_unlock), {:action => 'edit', :id => user, :user => {:status => User::STATUS_ACTIVE}}, :method => :post, :class => 'icon icon-unlock' %>
|
||||||
|
<% elsif user.registered? -%>
|
||||||
|
<%= link_to l(:button_activate), {:action => 'edit', :id => user, :user => {:status => User::STATUS_ACTIVE}}, :method => :post, :class => 'icon icon-unlock' %>
|
||||||
|
<% else -%>
|
||||||
|
<%= link_to l(:button_lock), {:action => 'edit', :id => user, :user => {:status => User::STATUS_LOCKED}}, :method => :post, :class => 'icon icon-lock' %>
|
||||||
|
<% end -%>
|
||||||
|
</small>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -6,3 +6,10 @@
|
|||||||
<p><%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %></p>
|
<p><%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %></p>
|
||||||
<p><%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %></p>
|
<p><%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar' %>
|
||||||
|
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||||
|
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||||
|
<%= stylesheet_link_tag 'calendar' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
# you don't control web/app server and can't set it the proper way
|
# you don't control web/app server and can't set it the proper way
|
||||||
# ENV['RAILS_ENV'] ||= 'production'
|
# ENV['RAILS_ENV'] ||= 'production'
|
||||||
|
|
||||||
# Specifies gem version of Rails to use when vendor/rails is not present
|
|
||||||
RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION
|
|
||||||
|
|
||||||
# Bootstrap the Rails environment, frameworks, and default configuration
|
# Bootstrap the Rails environment, frameworks, and default configuration
|
||||||
require File.join(File.dirname(__FILE__), 'boot')
|
require File.join(File.dirname(__FILE__), 'boot')
|
||||||
|
|
||||||
|
|||||||
@@ -5,38 +5,6 @@ Copyright (C) 2006-2008 Jean-Philippe Lang
|
|||||||
http://www.redmine.org/
|
http://www.redmine.org/
|
||||||
|
|
||||||
|
|
||||||
== 2008-04-28 v0.7.0
|
|
||||||
|
|
||||||
* Forces Redmine to use rails 2.0.2 gem when vendor/rails is not present
|
|
||||||
* Queries can be marked as 'For all projects'. Such queries will be available on all projects and on the global issue list.
|
|
||||||
* Add predefined date ranges to the time report
|
|
||||||
* Time report can be done at issue level
|
|
||||||
* Various timelog report enhancements
|
|
||||||
* Accept the following formats for "hours" field: 1h, 1 h, 1 hour, 2 hours, 30m, 30min, 1h30, 1h30m, 1:30
|
|
||||||
* Display the context menu above and/or to the left of the click if needed
|
|
||||||
* Make the admin project files list sortable
|
|
||||||
* Mercurial: display working directory files sizes unless browsing a specific revision
|
|
||||||
* Preserve status filter and page number when using lock/unlock/activate links on the users list
|
|
||||||
* Redmine.pm support for LDAP authentication
|
|
||||||
* Better error message and AR errors in log for failed LDAP on-the-fly user creation
|
|
||||||
* Redirected user to where he is coming from after logging hours
|
|
||||||
* Warn user that subprojects are also deleted when deleting a project
|
|
||||||
* Include subprojects versions on calendar and gantt
|
|
||||||
* Notify project members when a message is posted if they want to receive notifications
|
|
||||||
* Fixed: Feed content limit setting has no effect
|
|
||||||
* Fixed: Priorities not ordered when displayed as a filter in issue list
|
|
||||||
* Fixed: can not display attached images inline in message replies
|
|
||||||
* Fixed: Boards are not deleted when project is deleted
|
|
||||||
* Fixed: trying to preview a new issue raises an exception with postgresql
|
|
||||||
* Fixed: single file 'View difference' links do not work because of duplicate slashes in url
|
|
||||||
* Fixed: inline image not displayed when including a wiki page
|
|
||||||
* Fixed: CVS duplicate key violation
|
|
||||||
* Fixed: ActiveRecord::StaleObjectError exception on closing a set of circular duplicate issues
|
|
||||||
* Fixed: custom field filters behaviour
|
|
||||||
* Fixed: Postgresql 8.3 compatibility
|
|
||||||
* Fixed: Links to repository directories don't work
|
|
||||||
|
|
||||||
|
|
||||||
== 2008-03-29 v0.7.0-rc1
|
== 2008-03-29 v0.7.0-rc1
|
||||||
|
|
||||||
* Overall activity view and feed added, link is available on the project list
|
* Overall activity view and feed added, link is available on the project list
|
||||||
|
|||||||
@@ -36,10 +36,9 @@ Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
|
|||||||
|
|
||||||
=head1 CONFIGURATION
|
=head1 CONFIGURATION
|
||||||
|
|
||||||
## if the module isn't in your perl path
|
## This module has to be in your perl path
|
||||||
PerlRequire /usr/local/apache/Redmine.pm
|
## eg: /usr/lib/perl5/Apache/Authn/Redmine.pm
|
||||||
## else
|
PerlLoadModule Apache::Authn::Redmine
|
||||||
# PerlModule Apache::Authn::Redmine
|
|
||||||
<Location /svn>
|
<Location /svn>
|
||||||
DAV svn
|
DAV svn
|
||||||
SVNParentPath "/var/svn"
|
SVNParentPath "/var/svn"
|
||||||
@@ -52,12 +51,19 @@ Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
|
|||||||
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
|
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
|
||||||
|
|
||||||
## for mysql
|
## for mysql
|
||||||
PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
|
RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
|
||||||
## for postgres
|
## for postgres
|
||||||
# PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
|
# RedmineDSN "DBI:Pg:dbname=databasename;host=my.db.server"
|
||||||
|
|
||||||
PerlSetVar db_user redmine
|
RedmineDbUser "redmine"
|
||||||
PerlSetVar db_pass password
|
RedmineDbPass "password"
|
||||||
|
## Optional where clause (fulltext search would be slow and
|
||||||
|
## database dependant).
|
||||||
|
# RedmineDbWhereClause "and members.role_id IN (1,2)"
|
||||||
|
## Configuration for memcached
|
||||||
|
# RedmineMemcacheServers "127.0.0.1:112211"
|
||||||
|
# RedmineMemcacheExpirySec "60"
|
||||||
|
# RedmineMemcacheNamespace "RedmineCreds:"
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
To be able to browse repository inside redmine, you must add something
|
To be able to browse repository inside redmine, you must add something
|
||||||
@@ -92,20 +98,119 @@ And you need to upgrade at least reposman.rb (after r860).
|
|||||||
=cut
|
=cut
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
use warnings FATAL => 'all', NONFATAL => 'redefine';
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
use Digest::SHA1;
|
use Digest::SHA1;
|
||||||
# optional module for LDAP authentication
|
# optional module for LDAP authentication
|
||||||
my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
|
my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
|
||||||
|
my $CanUseMemcached = eval("use Cache::Memcached; 1");
|
||||||
|
|
||||||
use Apache2::Module;
|
use Apache2::Module;
|
||||||
use Apache2::Access;
|
use Apache2::Access;
|
||||||
use Apache2::ServerRec qw();
|
use Apache2::ServerRec qw();
|
||||||
use Apache2::RequestRec qw();
|
use Apache2::RequestRec qw();
|
||||||
use Apache2::RequestUtil qw();
|
use Apache2::RequestUtil qw();
|
||||||
use Apache2::Const qw(:common);
|
use Apache2::Const qw(:common :override :cmd_how);
|
||||||
|
|
||||||
# use Apache2::Directive qw();
|
# use Apache2::Directive qw();
|
||||||
|
|
||||||
|
my @directives = (
|
||||||
|
{
|
||||||
|
name => 'RedmineDSN',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
errmsg => 'Dsn in format used by Perl DBI. eg: "DBI:Pg:dbname=databasename;host=my.db.server"',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbUser',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbPass',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineDbWhereClause',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheServers',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheExpirySec',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'RedmineMemcacheNamespace',
|
||||||
|
req_override => OR_AUTHCFG,
|
||||||
|
args_how => TAKE1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sub RedmineDSN {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
$self->{RedmineDSN} = $arg;
|
||||||
|
my $query = "SELECT
|
||||||
|
hashed_password, auth_source_id
|
||||||
|
FROM members, projects, users
|
||||||
|
WHERE
|
||||||
|
projects.id=members.project_id
|
||||||
|
AND users.id=members.user_id
|
||||||
|
AND users.status=1
|
||||||
|
AND login=?
|
||||||
|
AND identifier=? ";
|
||||||
|
$self->{RedmineQuery} = trim($query);
|
||||||
|
}
|
||||||
|
sub RedmineDbUser { set_val('RedmineDbUser', @_); }
|
||||||
|
sub RedmineDbPass { set_val('RedmineDbPass', @_); }
|
||||||
|
sub RedmineDbWhereClause {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
$self->{RedmineQuery} = trim($self->{RedmineQuery}.($arg ? $arg : "")." ");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RedmineMemcacheServers {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
if ($arg && $CanUseMemcached) {
|
||||||
|
$self->{RedmineMemcached} = new Cache::Memcached {
|
||||||
|
'servers' => [ $arg, ],
|
||||||
|
'debug' => 0,
|
||||||
|
};
|
||||||
|
$self->{RedmineMemcache} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RedmineMemcacheExpirySec { set_val('RedmineMemcacheExpirySec', @_); }
|
||||||
|
|
||||||
|
sub RedmineMemcacheNamespace {
|
||||||
|
my ($self, $parms, $arg) = @_;
|
||||||
|
if ($self->{RedmineMemcache}) {
|
||||||
|
# Undocumented feature of Cache::Memcached, please don't kill me
|
||||||
|
$self->{RedmineMemcached}->{namespace} = $arg;
|
||||||
|
$self->{RedmineMemcached}->{namespace_len} = length $self->{RedmineMemcached}->{namespace};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub trim {
|
||||||
|
my $string = shift;
|
||||||
|
$string =~ s/\s{2,}/ /g;
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_val {
|
||||||
|
my ($key, $self, $parms, $arg) = @_;
|
||||||
|
$self->{$key} = $arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Apache2::Module::add(__PACKAGE__, \@directives);
|
||||||
|
|
||||||
|
|
||||||
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
|
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
|
||||||
|
|
||||||
sub access_handler {
|
sub access_handler {
|
||||||
@@ -117,7 +222,7 @@ sub access_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $method = $r->method;
|
my $method = $r->method;
|
||||||
return OK unless 1 == $read_only_methods{$method};
|
return OK if defined $read_only_methods{$method};
|
||||||
|
|
||||||
my $project_id = get_project_identifier($r);
|
my $project_id = get_project_identifier($r);
|
||||||
|
|
||||||
@@ -133,7 +238,11 @@ sub authen_handler {
|
|||||||
my ($res, $redmine_pass) = $r->get_basic_auth_pw();
|
my ($res, $redmine_pass) = $r->get_basic_auth_pw();
|
||||||
return $res unless $res == OK;
|
return $res unless $res == OK;
|
||||||
|
|
||||||
if (is_member($r->user, $redmine_pass, $r)) {
|
my $project_id = get_project_identifier($r);
|
||||||
|
if (!$project_id) {
|
||||||
|
return FORBIDDEN;
|
||||||
|
}
|
||||||
|
if (is_member($r->user, $redmine_pass, $r, $project_id)) {
|
||||||
return OK;
|
return OK;
|
||||||
} else {
|
} else {
|
||||||
$r->note_auth_failure();
|
$r->note_auth_failure();
|
||||||
@@ -145,6 +254,10 @@ sub is_public_project {
|
|||||||
my $project_id = shift;
|
my $project_id = shift;
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
|
||||||
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
return 1 if ($cfg->{RedmineMemcached}->get($project_id));
|
||||||
|
}
|
||||||
my $dbh = connect_database($r);
|
my $dbh = connect_database($r);
|
||||||
my $sth = $dbh->prepare(
|
my $sth = $dbh->prepare(
|
||||||
"SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
|
"SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
|
||||||
@@ -152,7 +265,16 @@ sub is_public_project {
|
|||||||
|
|
||||||
$sth->execute($project_id);
|
$sth->execute($project_id);
|
||||||
my $ret = $sth->fetchrow_array ? 1 : 0;
|
my $ret = $sth->fetchrow_array ? 1 : 0;
|
||||||
|
$sth->finish();
|
||||||
$dbh->disconnect();
|
$dbh->disconnect();
|
||||||
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
if ($cfg->{RedmineMemcacheExpirySec}) {
|
||||||
|
$cfg->{RedmineMemcached}->set($project_id, $ret, $cfg->{RedmineMemcacheExpirySec});
|
||||||
|
} else {
|
||||||
|
$cfg->{RedmineMemcached}->set($project_id, $ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$ret;
|
$ret;
|
||||||
}
|
}
|
||||||
@@ -176,15 +298,20 @@ sub is_member {
|
|||||||
my $redmine_user = shift;
|
my $redmine_user = shift;
|
||||||
my $redmine_pass = shift;
|
my $redmine_pass = shift;
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
my $project_id = shift;
|
||||||
|
|
||||||
my $dbh = connect_database($r);
|
my $dbh = connect_database($r);
|
||||||
my $project_id = get_project_identifier($r);
|
|
||||||
|
|
||||||
my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
|
my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
|
||||||
|
|
||||||
my $sth = $dbh->prepare(
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
"SELECT hashed_password, auth_source_id FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND users.status=1 AND login=? AND identifier=?;"
|
my $usrprojpass;
|
||||||
);
|
if ($cfg->{RedmineMemcache}) {
|
||||||
|
$usrprojpass = $cfg->{RedmineMemcached}->get($redmine_user.":".$project_id);
|
||||||
|
return 1 if (defined $usrprojpass and ($usrprojpass eq $pass_digest));
|
||||||
|
}
|
||||||
|
my $query = $cfg->{RedmineQuery};
|
||||||
|
my $sth = $dbh->prepare($query);
|
||||||
$sth->execute($redmine_user, $project_id);
|
$sth->execute($redmine_user, $project_id);
|
||||||
|
|
||||||
my $ret;
|
my $ret;
|
||||||
@@ -216,6 +343,14 @@ sub is_member {
|
|||||||
$sth->finish();
|
$sth->finish();
|
||||||
$dbh->disconnect();
|
$dbh->disconnect();
|
||||||
|
|
||||||
|
if ($cfg->{RedmineMemcache} and $ret) {
|
||||||
|
if ($cfg->{RedmineMemcacheExpirySec}) {
|
||||||
|
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest, $cfg->{RedmineMemcacheExpirySec});
|
||||||
|
} else {
|
||||||
|
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$ret;
|
$ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,8 +365,8 @@ sub get_project_identifier {
|
|||||||
sub connect_database {
|
sub connect_database {
|
||||||
my $r = shift;
|
my $r = shift;
|
||||||
|
|
||||||
my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
|
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
|
||||||
return DBI->connect($dsn, $db_user, $db_pass);
|
return DBI->connect($cfg->{RedmineDSN}, $cfg->{RedmineDbUser}, $cfg->{RedmineDbPass});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ general_text_no: 'не'
|
|||||||
general_text_yes: 'да'
|
general_text_yes: 'да'
|
||||||
general_lang_name: 'Bulgarian'
|
general_lang_name: 'Bulgarian'
|
||||||
general_csv_separator: ','
|
general_csv_separator: ','
|
||||||
general_csv_encoding: UTF-8
|
general_csv_encoding: cp1251
|
||||||
general_pdf_encoding: UTF-8
|
general_pdf_encoding: cp1251
|
||||||
general_day_names: Понеделник,Вторник,Сряда,Четвъртък,Петък,Събота,Неделя
|
general_day_names: Понеделник,Вторник,Сряда,Четвъртък,Петък,Събота,Неделя
|
||||||
general_first_day_of_week: '1'
|
general_first_day_of_week: '1'
|
||||||
|
|
||||||
@@ -57,11 +57,11 @@ notice_account_updated: Профилът е обновен успешно.
|
|||||||
notice_account_invalid_creditentials: Невалиден потребител или парола.
|
notice_account_invalid_creditentials: Невалиден потребител или парола.
|
||||||
notice_account_password_updated: Паролата е успешно променена.
|
notice_account_password_updated: Паролата е успешно променена.
|
||||||
notice_account_wrong_password: Грешна парола
|
notice_account_wrong_password: Грешна парола
|
||||||
notice_account_register_done: Профилът е създаден успешно.
|
notice_account_register_done: Акаунтът е създаден успешно.
|
||||||
notice_account_unknown_email: Непознат e-mail.
|
notice_account_unknown_email: Непознат потребител.
|
||||||
notice_can_t_change_password: Този профил е с външен метод за оторизация. Невъзможна смяна на паролата.
|
notice_can_t_change_password: Този акаунт е с външен метод за оторизация. Невъзможна смяна на паролата.
|
||||||
notice_account_lost_email_sent: Изпратен ви е e-mail с инструкции за избор на нова парола.
|
notice_account_lost_email_sent: Изпратен ви е e-mail с инструкции за избор на нова парола.
|
||||||
notice_account_activated: Профилът ви е активиран. Вече може да влезете в системата.
|
notice_account_activated: Акаунтът ви е активиран. Вече може да влезете.
|
||||||
notice_successful_create: Успешно създаване.
|
notice_successful_create: Успешно създаване.
|
||||||
notice_successful_update: Успешно обновяване.
|
notice_successful_update: Успешно обновяване.
|
||||||
notice_successful_delete: Успешно изтриване.
|
notice_successful_delete: Успешно изтриване.
|
||||||
@@ -78,8 +78,8 @@ error_scm_command_failed: "Грешка при опит за комуникац
|
|||||||
|
|
||||||
mail_subject_lost_password: Вашата парола (%s)
|
mail_subject_lost_password: Вашата парола (%s)
|
||||||
mail_body_lost_password: 'За да смените паролата си, използвайте следния линк:'
|
mail_body_lost_password: 'За да смените паролата си, използвайте следния линк:'
|
||||||
mail_subject_register: Активация на профил (%s)
|
mail_subject_register: Активация на акаунт (%s)
|
||||||
mail_body_register: 'За да активирате профила си използвайте следния линк:'
|
mail_body_register: 'За да активирате акаунта си използвайте следния линк:'
|
||||||
|
|
||||||
gui_validation_error: 1 грешка
|
gui_validation_error: 1 грешка
|
||||||
gui_validation_error_plural: %d грешки
|
gui_validation_error_plural: %d грешки
|
||||||
@@ -113,11 +113,11 @@ field_notes: Бележка
|
|||||||
field_is_closed: Затворена задача
|
field_is_closed: Затворена задача
|
||||||
field_is_default: Статус по подразбиране
|
field_is_default: Статус по подразбиране
|
||||||
field_tracker: Тракер
|
field_tracker: Тракер
|
||||||
field_subject: Относно
|
field_subject: Тема
|
||||||
field_due_date: Крайна дата
|
field_due_date: Крайна дата
|
||||||
field_assigned_to: Възложена на
|
field_assigned_to: Възложена на
|
||||||
field_priority: Приоритет
|
field_priority: Приоритет
|
||||||
field_fixed_version: Планувана версия
|
field_fixed_version: Target version
|
||||||
field_user: Потребител
|
field_user: Потребител
|
||||||
field_role: Роля
|
field_role: Роля
|
||||||
field_homepage: Начална страница
|
field_homepage: Начална страница
|
||||||
@@ -138,7 +138,7 @@ field_version: Версия
|
|||||||
field_type: Тип
|
field_type: Тип
|
||||||
field_host: Хост
|
field_host: Хост
|
||||||
field_port: Порт
|
field_port: Порт
|
||||||
field_account: Профил
|
field_account: Акаунт
|
||||||
field_base_dn: Base DN
|
field_base_dn: Base DN
|
||||||
field_attr_login: Login attribute
|
field_attr_login: Login attribute
|
||||||
field_attr_firstname: Firstname attribute
|
field_attr_firstname: Firstname attribute
|
||||||
@@ -163,7 +163,7 @@ field_delay: Отместване
|
|||||||
field_assignable: Възможно е възлагане на задачи за тази роля
|
field_assignable: Възможно е възлагане на задачи за тази роля
|
||||||
field_redirect_existing_links: Пренасочване на съществуващи линкове
|
field_redirect_existing_links: Пренасочване на съществуващи линкове
|
||||||
field_estimated_hours: Изчислено време
|
field_estimated_hours: Изчислено време
|
||||||
field_default_value: Стойност по подразбиране
|
field_default_value: Статус по подразбиране
|
||||||
|
|
||||||
setting_app_title: Заглавие
|
setting_app_title: Заглавие
|
||||||
setting_app_subtitle: Описание
|
setting_app_subtitle: Описание
|
||||||
@@ -171,15 +171,15 @@ setting_welcome_text: Допълнителен текст
|
|||||||
setting_default_language: Език по подразбиране
|
setting_default_language: Език по подразбиране
|
||||||
setting_login_required: Изискване за вход в системата
|
setting_login_required: Изискване за вход в системата
|
||||||
setting_self_registration: Регистрация от потребители
|
setting_self_registration: Регистрация от потребители
|
||||||
setting_attachment_max_size: Максимална големина на прикачен файл
|
setting_attachment_max_size: Максимално голям приложен файл
|
||||||
setting_issues_export_limit: Лимит за експорт на задачи
|
setting_issues_export_limit: Лимит за експорт на задачи
|
||||||
setting_mail_from: E-mail адрес за емисии
|
setting_mail_from: E-mail адрес за емисии
|
||||||
setting_host_name: Хост
|
setting_host_name: Хост
|
||||||
setting_text_formatting: Форматиране на текста
|
setting_text_formatting: Форматиране на текста
|
||||||
setting_wiki_compression: Wiki компресиране на историята
|
setting_wiki_compression: Wiki компресиране на историята
|
||||||
setting_feeds_limit: Лимит на Feeds
|
setting_feeds_limit: Лимит на Feeds
|
||||||
setting_autofetch_changesets: Автоматично обработване на ревизиите
|
setting_autofetch_changesets: Автоматично обработване на commits в хранилището
|
||||||
setting_sys_api_enabled: Разрешаване на WS за управление
|
setting_sys_api_enabled: Разрешаване на WS за управление на хранилището
|
||||||
setting_commit_ref_keywords: Отбелязващи ключови думи
|
setting_commit_ref_keywords: Отбелязващи ключови думи
|
||||||
setting_commit_fix_keywords: Приключващи ключови думи
|
setting_commit_fix_keywords: Приключващи ключови думи
|
||||||
setting_autologin: Автоматичен вход
|
setting_autologin: Автоматичен вход
|
||||||
@@ -231,7 +231,7 @@ label_password_lost: Забравена парола
|
|||||||
label_home: Начало
|
label_home: Начало
|
||||||
label_my_page: Лична страница
|
label_my_page: Лична страница
|
||||||
label_my_account: Профил
|
label_my_account: Профил
|
||||||
label_my_projects: Проекти, в които участвам
|
label_my_projects: Моите проекти
|
||||||
label_administration: Администрация
|
label_administration: Администрация
|
||||||
label_login: Вход
|
label_login: Вход
|
||||||
label_logout: Изход
|
label_logout: Изход
|
||||||
@@ -375,8 +375,8 @@ label_f_hour_plural: %.2f часа
|
|||||||
label_time_tracking: Отделяне на време
|
label_time_tracking: Отделяне на време
|
||||||
label_change_plural: Промени
|
label_change_plural: Промени
|
||||||
label_statistics: Статистики
|
label_statistics: Статистики
|
||||||
label_commits_per_month: Ревизии по месеци
|
label_commits_per_month: Commits за месец
|
||||||
label_commits_per_author: Ревизии по автор
|
label_commits_per_author: Commits за автор
|
||||||
label_view_diff: Виж разликите
|
label_view_diff: Виж разликите
|
||||||
label_diff_inline: хоризонтално
|
label_diff_inline: хоризонтално
|
||||||
label_diff_side_by_side: вертикално
|
label_diff_side_by_side: вертикално
|
||||||
@@ -389,7 +389,7 @@ label_applied_status: Промени статуса на
|
|||||||
label_loading: Зареждане...
|
label_loading: Зареждане...
|
||||||
label_relation_new: Нова релация
|
label_relation_new: Нова релация
|
||||||
label_relation_delete: Изтриване на релация
|
label_relation_delete: Изтриване на релация
|
||||||
label_relates_to: свързана със
|
label_relates_to: Свързана със
|
||||||
label_duplicates: дублира
|
label_duplicates: дублира
|
||||||
label_blocks: блокира
|
label_blocks: блокира
|
||||||
label_blocked_by: блокирана от
|
label_blocked_by: блокирана от
|
||||||
@@ -427,10 +427,10 @@ label_updated_time: Обновена преди %s
|
|||||||
label_jump_to_a_project: Проект...
|
label_jump_to_a_project: Проект...
|
||||||
|
|
||||||
button_login: Вход
|
button_login: Вход
|
||||||
button_submit: Прикачване
|
button_submit: Приложи
|
||||||
button_save: Запис
|
button_save: Запис
|
||||||
button_check_all: Избор на всички
|
button_check_all: Маркирай всички
|
||||||
button_uncheck_all: Изчистване на всички
|
button_uncheck_all: Изчисти всички
|
||||||
button_delete: Изтриване
|
button_delete: Изтриване
|
||||||
button_create: Създаване
|
button_create: Създаване
|
||||||
button_test: Тест
|
button_test: Тест
|
||||||
@@ -481,9 +481,9 @@ text_length_between: От %d до %d символа.
|
|||||||
text_tracker_no_workflow: Няма дефиниран работен процес за този тракер
|
text_tracker_no_workflow: Няма дефиниран работен процес за този тракер
|
||||||
text_unallowed_characters: Непозволени символи
|
text_unallowed_characters: Непозволени символи
|
||||||
text_comma_separated: Позволено е изброяване (с разделител запетая).
|
text_comma_separated: Позволено е изброяване (с разделител запетая).
|
||||||
text_issues_ref_in_commit_messages: Отбелязване и приключване на задачи от ревизии
|
text_issues_ref_in_commit_messages: Отбелязване и приключване на задачи от commit съобщения
|
||||||
text_issue_added: Публикувана е нова задача с номер %s (от %s).
|
text_issue_added: Публикувана е нова задача с номер %s (by %s).
|
||||||
text_issue_updated: Задача %s е обновена (от %s).
|
text_issue_updated: Задача %s е обновена (by %s).
|
||||||
text_wiki_destroy_confirmation: Сигурни ли сте, че искате да изтриете това Wiki и цялото му съдържание?
|
text_wiki_destroy_confirmation: Сигурни ли сте, че искате да изтриете това Wiki и цялото му съдържание?
|
||||||
text_issue_category_destroy_question: Има задачи (%d) обвързани с тази категория. Какво ще изберете?
|
text_issue_category_destroy_question: Има задачи (%d) обвързани с тази категория. Какво ще изберете?
|
||||||
text_issue_category_destroy_assignments: Премахване на връзките с категорията
|
text_issue_category_destroy_assignments: Премахване на връзките с категорията
|
||||||
@@ -515,11 +515,11 @@ enumeration_issue_priorities: Приоритети на задачи
|
|||||||
enumeration_doc_categories: Категории документи
|
enumeration_doc_categories: Категории документи
|
||||||
enumeration_activities: Дейности (time tracking)
|
enumeration_activities: Дейности (time tracking)
|
||||||
label_file_plural: Файлове
|
label_file_plural: Файлове
|
||||||
label_changeset_plural: Ревизии
|
label_changeset_plural: Changesets
|
||||||
field_column_names: Колони
|
field_column_names: Колони
|
||||||
label_default_columns: По подразбиране
|
label_default_columns: По подразбиране
|
||||||
setting_issue_list_default_columns: Показвани колони по подразбиране
|
setting_issue_list_default_columns: Показвани колони по подразбиране
|
||||||
setting_repositories_encodings: Кодови таблици
|
setting_repositories_encodings: Кодови таблици на хранилищата
|
||||||
notice_no_issue_selected: "Няма избрани задачи."
|
notice_no_issue_selected: "Няма избрани задачи."
|
||||||
label_bulk_edit_selected_issues: Редактиране на задачи
|
label_bulk_edit_selected_issues: Редактиране на задачи
|
||||||
label_no_change_option: (Без промяна)
|
label_no_change_option: (Без промяна)
|
||||||
@@ -536,20 +536,20 @@ label_user_mail_option_none: "Само за наблюдавани или в к
|
|||||||
setting_emails_footer: Подтекст за e-mail
|
setting_emails_footer: Подтекст за e-mail
|
||||||
label_float: Дробно
|
label_float: Дробно
|
||||||
button_copy: Копиране
|
button_copy: Копиране
|
||||||
mail_body_account_information_external: Можете да използвате вашия "%s" профил за вход.
|
mail_body_account_information_external: Можете да използвате вашия "%s" акаунт за вход.
|
||||||
mail_body_account_information: Информацията за профила ви
|
mail_body_account_information: Информацията за акаунта
|
||||||
setting_protocol: Протокол
|
setting_protocol: Протокол
|
||||||
label_user_mail_no_self_notified: "Не искам известия за извършени от мен промени"
|
label_user_mail_no_self_notified: "Не искам известия за извършени от мен промени"
|
||||||
setting_time_format: Формат на часа
|
setting_time_format: Формат на часа
|
||||||
label_registration_activation_by_email: активиране на профила по email
|
label_registration_activation_by_email: активиране на акаунта по email
|
||||||
mail_subject_account_activation_request: Заявка за активиране на профил в %s
|
mail_subject_account_activation_request: Заявка за активиране на акаунт в %s
|
||||||
mail_body_account_activation_request: 'Има новорегистриран потребител (%s), очакващ вашето одобрение:'
|
mail_body_account_activation_request: 'Има новорегистриран потребител (%s), очакващ вашето одобрение:'
|
||||||
label_registration_automatic_activation: автоматично активиране
|
label_registration_automatic_activation: автоматично активиране
|
||||||
label_registration_manual_activation: ръчно активиране
|
label_registration_manual_activation: ръчно активиране
|
||||||
notice_account_pending: "Профилът Ви е създаден и очаква одобрение от администратор."
|
notice_account_pending: "Акаунтът Ви е създаден и очаква одобрение от администратор."
|
||||||
field_time_zone: Часова зона
|
field_time_zone: Часова зона
|
||||||
text_caracters_minimum: Минимум %d символа.
|
text_caracters_minimum: Минимум %d символа.
|
||||||
setting_bcc_recipients: Получатели на скрито копие (bcc)
|
setting_bcc_recipients: Blind carbon copy (bcc) получатели
|
||||||
button_annotate: Анотация
|
button_annotate: Анотация
|
||||||
label_issues_by: Задачи по %s
|
label_issues_by: Задачи по %s
|
||||||
field_searchable: С възможност за търсене
|
field_searchable: С възможност за търсене
|
||||||
@@ -566,55 +566,54 @@ label_general: Основни
|
|||||||
label_repository_plural: Хранилища
|
label_repository_plural: Хранилища
|
||||||
label_associated_revisions: Асоциирани ревизии
|
label_associated_revisions: Асоциирани ревизии
|
||||||
setting_user_format: Потребителски формат
|
setting_user_format: Потребителски формат
|
||||||
text_status_changed_by_changeset: Приложено с ревизия %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
label_more: Още
|
label_more: More
|
||||||
text_issues_destroy_confirmation: 'Сигурни ли сте, че искате да изтриете избраните задачи?'
|
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s) ?'
|
||||||
label_scm: SCM (Система за контрол на кода)
|
label_scm: SCM
|
||||||
text_select_project_modules: 'Изберете активните модули за този проект:'
|
text_select_project_modules: 'Select modules to enable for this project:'
|
||||||
label_issue_added: Добавена задача
|
label_issue_added: Issue added
|
||||||
label_issue_updated: Обновена задача
|
label_issue_updated: Issue updated
|
||||||
label_document_added: Добавен документ
|
label_document_added: Document added
|
||||||
label_message_posted: Добавено съобщение
|
label_message_posted: Message added
|
||||||
label_file_added: Добавен файл
|
label_file_added: File added
|
||||||
label_news_added: Добавена новина
|
label_news_added: News added
|
||||||
project_module_boards: Форуми
|
project_module_boards: Boards
|
||||||
project_module_issue_tracking: Тракинг
|
project_module_issue_tracking: Issue tracking
|
||||||
project_module_wiki: Wiki
|
project_module_wiki: Wiki
|
||||||
project_module_files: Файлове
|
project_module_files: Files
|
||||||
project_module_documents: Документи
|
project_module_documents: Documents
|
||||||
project_module_repository: Хранилище
|
project_module_repository: Repository
|
||||||
project_module_news: Новини
|
project_module_news: News
|
||||||
project_module_time_tracking: Отделяне на време
|
project_module_time_tracking: Time tracking
|
||||||
text_file_repository_writable: Възможност за писане в хранилището с файлове
|
text_file_repository_writable: File repository writable
|
||||||
text_default_administrator_account_changed: Сменен фабричния администраторски профил
|
text_default_administrator_account_changed: Default administrator account changed
|
||||||
text_rmagick_available: Наличен RMagick (по избор)
|
text_rmagick_available: RMagick available (optional)
|
||||||
button_configure: Конфигуриране
|
button_configure: Configure
|
||||||
label_plugins: Плъгини
|
label_plugins: Plugins
|
||||||
label_ldap_authentication: LDAP оторизация
|
label_ldap_authentication: LDAP authentication
|
||||||
label_downloads_abbr: D/L
|
label_downloads_abbr: D/L
|
||||||
label_this_month: текущия месец
|
label_this_month: this month
|
||||||
label_last_n_days: последните %d дни
|
label_last_n_days: last %d days
|
||||||
label_all_time: всички
|
label_all_time: all time
|
||||||
label_this_year: текущата година
|
label_this_year: this year
|
||||||
label_date_range: Период
|
label_date_range: Date range
|
||||||
label_last_week: последната седмица
|
label_last_week: last week
|
||||||
label_yesterday: вчера
|
label_yesterday: yesterday
|
||||||
label_last_month: последния месец
|
label_last_month: last month
|
||||||
label_add_another_file: Добавяне на друг файл
|
label_add_another_file: Add another file
|
||||||
label_optional_description: Незадължително описание
|
label_optional_description: Optional description
|
||||||
text_destroy_time_entries_question: %.02f часа са отделени на задачите, които искате да изтриете. Какво избирате?
|
text_destroy_time_entries_question: %.02f hours were reported on the issues you are about to delete. What do you want to do ?
|
||||||
error_issue_not_found_in_project: 'Задачата не е намерена или не принадлежи на този проект'
|
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
|
||||||
text_assign_time_entries_to_project: Прехвърляне на отделеното време към проект
|
text_assign_time_entries_to_project: Assign reported hours to the project
|
||||||
text_destroy_time_entries: Изтриване на отделеното време
|
text_destroy_time_entries: Delete reported hours
|
||||||
text_reassign_time_entries: 'Прехвърляне на отделеното време към задача:'
|
text_reassign_time_entries: 'Reassign reported hours to this issue:'
|
||||||
setting_activity_days_default: Брой дни показвани на таб Дейност
|
setting_activity_days_default: Days displayed on project activity
|
||||||
label_chronological_order: Хронологичен ред
|
label_chronological_order: In chronological order
|
||||||
field_comments_sorting: Сортиране на коментарите
|
field_comments_sorting: Display comments
|
||||||
label_reverse_chronological_order: Обратен хронологичен ред
|
label_reverse_chronological_order: In reverse chronological order
|
||||||
label_preferences: Предпочитания
|
label_preferences: Preferences
|
||||||
setting_display_subprojects_issues: Показване на подпроектите в проектите по подразбиране
|
setting_display_subprojects_issues: Display subprojects issues on main projects by default
|
||||||
label_overall_activity: Цялостна дейност
|
label_overall_activity: Overall activity
|
||||||
setting_default_projects_public: Новите проекти са публични по подразбиране
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "Обектът не съществува или не може да бъде анотиран."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Планиране
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ actionview_datehelper_select_month_prefix:
|
|||||||
actionview_datehelper_select_year_prefix:
|
actionview_datehelper_select_year_prefix:
|
||||||
actionview_datehelper_time_in_words_day: 1 den
|
actionview_datehelper_time_in_words_day: 1 den
|
||||||
actionview_datehelper_time_in_words_day_plural: %d dny
|
actionview_datehelper_time_in_words_day_plural: %d dny
|
||||||
actionview_datehelper_time_in_words_hour_about: asi hodinou
|
actionview_datehelper_time_in_words_hour_about: asi hodinu
|
||||||
actionview_datehelper_time_in_words_hour_about_plural: asi %d hodinami
|
actionview_datehelper_time_in_words_hour_about_plural: asi %d hodin
|
||||||
actionview_datehelper_time_in_words_hour_about_single: asi hodinou
|
actionview_datehelper_time_in_words_hour_about_single: asi hodinu
|
||||||
actionview_datehelper_time_in_words_minute: 1 minutou
|
actionview_datehelper_time_in_words_minute: 1 minuta
|
||||||
actionview_datehelper_time_in_words_minute_half: půl minutou
|
actionview_datehelper_time_in_words_minute_half: půl minuty
|
||||||
actionview_datehelper_time_in_words_minute_less_than: méně než minutou
|
actionview_datehelper_time_in_words_minute_less_than: méně než minutu
|
||||||
actionview_datehelper_time_in_words_minute_plural: %d minutami
|
actionview_datehelper_time_in_words_minute_plural: %d minut
|
||||||
actionview_datehelper_time_in_words_minute_single: 1 minutou
|
actionview_datehelper_time_in_words_minute_single: 1 minuta
|
||||||
actionview_datehelper_time_in_words_second_less_than: méně než sekundou
|
actionview_datehelper_time_in_words_second_less_than: méně než sekunda
|
||||||
actionview_datehelper_time_in_words_second_less_than_plural: méně než %d sekundami
|
actionview_datehelper_time_in_words_second_less_than_plural: méně než %d sekund
|
||||||
actionview_instancetag_blank_option: Prosím vyberte
|
actionview_instancetag_blank_option: Prosím vyberte
|
||||||
|
|
||||||
activerecord_error_inclusion: není zahrnuto v seznamu
|
activerecord_error_inclusion: není zahrnuto v seznamu
|
||||||
@@ -98,7 +98,7 @@ mail_body_account_activation_request: Byl zaregistrován nový uživatel "%s". A
|
|||||||
gui_validation_error: 1 chyba
|
gui_validation_error: 1 chyba
|
||||||
gui_validation_error_plural: %d chyb(y)
|
gui_validation_error_plural: %d chyb(y)
|
||||||
|
|
||||||
field_name: Název
|
field_name: Jméno
|
||||||
field_description: Popis
|
field_description: Popis
|
||||||
field_summary: Přehled
|
field_summary: Přehled
|
||||||
field_is_required: Povinné pole
|
field_is_required: Povinné pole
|
||||||
@@ -306,7 +306,7 @@ label_attribute: Atribut
|
|||||||
label_attribute_plural: Atributy
|
label_attribute_plural: Atributy
|
||||||
label_download: %d Download
|
label_download: %d Download
|
||||||
label_download_plural: %d Downloads
|
label_download_plural: %d Downloads
|
||||||
label_no_data: Žádné položky
|
label_no_data: Žádná data k zobrazení
|
||||||
label_change_status: Změnit stav
|
label_change_status: Změnit stav
|
||||||
label_history: Historie
|
label_history: Historie
|
||||||
label_attachment: Soubor
|
label_attachment: Soubor
|
||||||
@@ -480,8 +480,8 @@ label_sort_by: Seřadit podle %s
|
|||||||
label_send_test_email: Poslat testovací email
|
label_send_test_email: Poslat testovací email
|
||||||
label_feeds_access_key_created_on: Přístupový klíč pro RSS byl vytvořen před %s
|
label_feeds_access_key_created_on: Přístupový klíč pro RSS byl vytvořen před %s
|
||||||
label_module_plural: Moduly
|
label_module_plural: Moduly
|
||||||
label_added_time_by: 'Přidáno uživatelem %s před %s'
|
label_added_time_by: 'Přidáno před: %s %s'
|
||||||
label_updated_time: 'Aktualizováno před %s'
|
label_updated_time: 'Aktualizováno před: %s'
|
||||||
label_jump_to_a_project: Zvolit projekt...
|
label_jump_to_a_project: Zvolit projekt...
|
||||||
label_file_plural: Soubory
|
label_file_plural: Soubory
|
||||||
label_changeset_plural: Changesety
|
label_changeset_plural: Changesety
|
||||||
@@ -586,7 +586,7 @@ text_no_configuration_data: "Role, fronty, stavy úkolů ani workflow nebyly zat
|
|||||||
text_load_default_configuration: Nahrát výchozí konfiguraci
|
text_load_default_configuration: Nahrát výchozí konfiguraci
|
||||||
text_status_changed_by_changeset: Použito v changesetu %s.
|
text_status_changed_by_changeset: Použito v changesetu %s.
|
||||||
text_issues_destroy_confirmation: 'Opravdu si přejete odstranit všechny zvolené úkoly?'
|
text_issues_destroy_confirmation: 'Opravdu si přejete odstranit všechny zvolené úkoly?'
|
||||||
text_select_project_modules: 'Aktivní moduly v tomto projektu:'
|
text_select_project_modules: 'Zvolte moduly aktivní v tomto projektu:'
|
||||||
text_default_administrator_account_changed: Výchozí nastavení administrátorského účtu změněno
|
text_default_administrator_account_changed: Výchozí nastavení administrátorského účtu změněno
|
||||||
text_file_repository_writable: Povolen zápis do repository
|
text_file_repository_writable: Povolen zápis do repository
|
||||||
text_rmagick_available: RMagick k dispozici (volitelné)
|
text_rmagick_available: RMagick k dispozici (volitelné)
|
||||||
@@ -620,6 +620,5 @@ default_activity_development: Vývoj
|
|||||||
enumeration_issue_priorities: Priority úkolů
|
enumeration_issue_priorities: Priority úkolů
|
||||||
enumeration_doc_categories: Kategorie dokumentů
|
enumeration_doc_categories: Kategorie dokumentů
|
||||||
enumeration_activities: Aktivity (sledování času)
|
enumeration_activities: Aktivity (sledování času)
|
||||||
error_scm_annotate: "Položka neexistuje nebo nemůže být komentována."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Plánování
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -619,4 +619,3 @@ label_overall_activity: Overordnet aktivitet
|
|||||||
setting_default_projects_public: Nye projekter er offentlige som default
|
setting_default_projects_public: Nye projekter er offentlige som default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planlægning
|
label_planning: Planlægning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ notice_locking_conflict: Datum wurde von einem anderen Benutzer geändert.
|
|||||||
notice_not_authorized: Sie sind nicht berechtigt, auf diese Seite zuzugreifen.
|
notice_not_authorized: Sie sind nicht berechtigt, auf diese Seite zuzugreifen.
|
||||||
notice_email_sent: Eine E-Mail wurde an %s gesendet.
|
notice_email_sent: Eine E-Mail wurde an %s gesendet.
|
||||||
notice_email_error: Beim Senden einer E-Mail ist ein Fehler aufgetreten (%s).
|
notice_email_error: Beim Senden einer E-Mail ist ein Fehler aufgetreten (%s).
|
||||||
notice_feeds_access_key_reseted: Ihr Atom-Zugriffsschlüssel wurde zurückgesetzt.
|
notice_feeds_access_key_reseted: Ihr RSS-Zugriffsschlüssel wurde zurückgesetzt.
|
||||||
notice_failed_to_save_issues: "%d von %d ausgewählten Tickets konnte(n) nicht gespeichert werden: %s."
|
notice_failed_to_save_issues: "%d von %d ausgewählten Tickets konnte(n) nicht gespeichert werden: %s."
|
||||||
notice_no_issue_selected: "Kein Ticket ausgewählt! Bitte wählen Sie die Tickets, die Sie bearbeiten möchten."
|
notice_no_issue_selected: "Kein Ticket ausgewählt! Bitte wählen Sie die Tickets, die Sie bearbeiten möchten."
|
||||||
notice_account_pending: "Ihr Konto wurde erstellt und wartet jetzt auf die Genehmigung des Administrators."
|
notice_account_pending: "Ihr Konto wurde erstellt und wartet jetzt auf die Genehmigung des Administrators."
|
||||||
@@ -80,7 +80,6 @@ notice_default_data_loaded: Die Standard-Konfiguration wurde erfolgreich geladen
|
|||||||
error_can_t_load_default_data: "Die Standard-Konfiguration konnte nicht geladen werden: %s"
|
error_can_t_load_default_data: "Die Standard-Konfiguration konnte nicht geladen werden: %s"
|
||||||
error_scm_not_found: Eintrag und/oder Revision besteht nicht im Projektarchiv.
|
error_scm_not_found: Eintrag und/oder Revision besteht nicht im Projektarchiv.
|
||||||
error_scm_command_failed: "Beim Zugriff auf das Projektarchiv ist ein Fehler aufgetreten: %s"
|
error_scm_command_failed: "Beim Zugriff auf das Projektarchiv ist ein Fehler aufgetreten: %s"
|
||||||
error_scm_annotate: "Der Eintrag existiert nicht oder kann nicht annotiert werden."
|
|
||||||
error_issue_not_found_in_project: 'Das Ticket wurde nicht gefunden oder gehört nicht zu diesem Projekt.'
|
error_issue_not_found_in_project: 'Das Ticket wurde nicht gefunden oder gehört nicht zu diesem Projekt.'
|
||||||
|
|
||||||
mail_subject_lost_password: Ihr %s Kennwort
|
mail_subject_lost_password: Ihr %s Kennwort
|
||||||
@@ -121,8 +120,8 @@ field_project: Projekt
|
|||||||
field_issue: Ticket
|
field_issue: Ticket
|
||||||
field_status: Status
|
field_status: Status
|
||||||
field_notes: Kommentare
|
field_notes: Kommentare
|
||||||
field_is_closed: Ticket geschlossen
|
field_is_closed: Problem erledigt
|
||||||
field_is_default: Standardeinstellung
|
field_is_default: Default
|
||||||
field_tracker: Tracker
|
field_tracker: Tracker
|
||||||
field_subject: Thema
|
field_subject: Thema
|
||||||
field_due_date: Abgabedatum
|
field_due_date: Abgabedatum
|
||||||
@@ -134,8 +133,8 @@ field_role: Rolle
|
|||||||
field_homepage: Projekt-Homepage
|
field_homepage: Projekt-Homepage
|
||||||
field_is_public: Öffentlich
|
field_is_public: Öffentlich
|
||||||
field_parent: Unterprojekt von
|
field_parent: Unterprojekt von
|
||||||
field_is_in_chlog: Im Change-Log anzeigen
|
field_is_in_chlog: Ansicht im Change-Log
|
||||||
field_is_in_roadmap: In der Roadmap anzeigen
|
field_is_in_roadmap: Ansicht in der Roadmap
|
||||||
field_login: Mitgliedsname
|
field_login: Mitgliedsname
|
||||||
field_mail_notification: Mailbenachrichtigung
|
field_mail_notification: Mailbenachrichtigung
|
||||||
field_admin: Administrator
|
field_admin: Administrator
|
||||||
@@ -178,7 +177,6 @@ field_column_names: Spalten
|
|||||||
field_time_zone: Zeitzone
|
field_time_zone: Zeitzone
|
||||||
field_searchable: Durchsuchbar
|
field_searchable: Durchsuchbar
|
||||||
field_default_value: Standardwert
|
field_default_value: Standardwert
|
||||||
field_comments_sorting: Kommentare anzeigen
|
|
||||||
|
|
||||||
setting_app_title: Applikations-Titel
|
setting_app_title: Applikations-Titel
|
||||||
setting_app_subtitle: Applikations-Untertitel
|
setting_app_subtitle: Applikations-Untertitel
|
||||||
@@ -193,8 +191,7 @@ setting_bcc_recipients: E-Mails als Blindkopie (BCC) senden
|
|||||||
setting_host_name: Hostname
|
setting_host_name: Hostname
|
||||||
setting_text_formatting: Textformatierung
|
setting_text_formatting: Textformatierung
|
||||||
setting_wiki_compression: Wiki-Historie komprimieren
|
setting_wiki_compression: Wiki-Historie komprimieren
|
||||||
setting_feeds_limit: Max. Anzahl Einträge pro Atom-Feed
|
setting_feeds_limit: Feed-Inhalt begrenzen
|
||||||
setting_default_projects_public: Neue Projekte sind standardmäßig öffentlich
|
|
||||||
setting_autofetch_changesets: Changesets automatisch abrufen
|
setting_autofetch_changesets: Changesets automatisch abrufen
|
||||||
setting_sys_api_enabled: Webservice zur Verwaltung der Projektarchive benutzen
|
setting_sys_api_enabled: Webservice zur Verwaltung der Projektarchive benutzen
|
||||||
setting_commit_ref_keywords: Schlüsselwörter (Beziehungen)
|
setting_commit_ref_keywords: Schlüsselwörter (Beziehungen)
|
||||||
@@ -209,8 +206,6 @@ setting_emails_footer: E-Mail-Fußzeile
|
|||||||
setting_protocol: Protokoll
|
setting_protocol: Protokoll
|
||||||
setting_per_page_options: Objekte pro Seite
|
setting_per_page_options: Objekte pro Seite
|
||||||
setting_user_format: Benutzer-Anzeigeformat
|
setting_user_format: Benutzer-Anzeigeformat
|
||||||
setting_activity_days_default: Anzahl Tage pro Seite der Projekt-Aktivität
|
|
||||||
setting_display_subprojects_issues: Tickets von Unterprojekten im Hauptprojekt anzeigen
|
|
||||||
|
|
||||||
project_module_issue_tracking: Ticket-Verfolgung
|
project_module_issue_tracking: Ticket-Verfolgung
|
||||||
project_module_time_tracking: Zeiterfassung
|
project_module_time_tracking: Zeiterfassung
|
||||||
@@ -232,7 +227,7 @@ label_project_latest: Neueste Projekte
|
|||||||
label_issue: Ticket
|
label_issue: Ticket
|
||||||
label_issue_new: Neues Ticket
|
label_issue_new: Neues Ticket
|
||||||
label_issue_plural: Tickets
|
label_issue_plural: Tickets
|
||||||
label_issue_view_all: Alle Tickets anzeigen
|
label_issue_view_all: Alle Tickets ansehen
|
||||||
label_issues_by: Tickets von %s
|
label_issues_by: Tickets von %s
|
||||||
label_issue_added: Ticket hinzugefügt
|
label_issue_added: Ticket hinzugefügt
|
||||||
label_issue_updated: Ticket aktualisiert
|
label_issue_updated: Ticket aktualisiert
|
||||||
@@ -282,7 +277,6 @@ label_last_updates: zuletzt aktualisiert
|
|||||||
label_last_updates_plural: %d zuletzt aktualisierten
|
label_last_updates_plural: %d zuletzt aktualisierten
|
||||||
label_registered_on: Angemeldet am
|
label_registered_on: Angemeldet am
|
||||||
label_activity: Aktivität
|
label_activity: Aktivität
|
||||||
label_overall_activity: Aktivität aller Projekte anzeigen
|
|
||||||
label_new: Neu
|
label_new: Neu
|
||||||
label_logged_as: Angemeldet als
|
label_logged_as: Angemeldet als
|
||||||
label_environment: Environment
|
label_environment: Environment
|
||||||
@@ -326,7 +320,7 @@ label_version: Version
|
|||||||
label_version_new: Neue Version
|
label_version_new: Neue Version
|
||||||
label_version_plural: Versionen
|
label_version_plural: Versionen
|
||||||
label_confirmation: Bestätigung
|
label_confirmation: Bestätigung
|
||||||
label_export_to: "Auch abrufbar als:"
|
label_export_to: Export zu
|
||||||
label_read: Lesen...
|
label_read: Lesen...
|
||||||
label_public_projects: Öffentliche Projekte
|
label_public_projects: Öffentliche Projekte
|
||||||
label_open_issues: offen
|
label_open_issues: offen
|
||||||
@@ -351,7 +345,7 @@ label_months_from: Monate ab
|
|||||||
label_gantt: Gantt
|
label_gantt: Gantt
|
||||||
label_internal: Intern
|
label_internal: Intern
|
||||||
label_last_changes: %d letzte Änderungen
|
label_last_changes: %d letzte Änderungen
|
||||||
label_change_view_all: Alle Änderungen anzeigen
|
label_change_view_all: Alle Änderungen ansehen
|
||||||
label_personalize_page: Diese Seite anpassen
|
label_personalize_page: Diese Seite anpassen
|
||||||
label_comment: Kommentar
|
label_comment: Kommentar
|
||||||
label_comment_plural: Kommentare
|
label_comment_plural: Kommentare
|
||||||
@@ -475,7 +469,7 @@ label_date_to: Bis
|
|||||||
label_language_based: Sprachabhängig
|
label_language_based: Sprachabhängig
|
||||||
label_sort_by: Sortiert nach %s
|
label_sort_by: Sortiert nach %s
|
||||||
label_send_test_email: Test-E-Mail senden
|
label_send_test_email: Test-E-Mail senden
|
||||||
label_feeds_access_key_created_on: Atom-Zugriffsschlüssel vor %s erstellt
|
label_feeds_access_key_created_on: RSS-Zugriffsschlüssel vor %s erstellt
|
||||||
label_module_plural: Module
|
label_module_plural: Module
|
||||||
label_added_time_by: Von %s vor %s hinzugefügt
|
label_added_time_by: Von %s vor %s hinzugefügt
|
||||||
label_updated_time: Vor %s aktualisiert
|
label_updated_time: Vor %s aktualisiert
|
||||||
@@ -506,10 +500,6 @@ label_ldap_authentication: LDAP-Authentifizierung
|
|||||||
label_downloads_abbr: D/L
|
label_downloads_abbr: D/L
|
||||||
label_optional_description: Beschreibung (optional)
|
label_optional_description: Beschreibung (optional)
|
||||||
label_add_another_file: Eine weitere Datei hinzufügen
|
label_add_another_file: Eine weitere Datei hinzufügen
|
||||||
label_preferences: Präferenzen
|
|
||||||
label_chronological_order: in zeitlicher Reihenfolge
|
|
||||||
label_reverse_chronological_order: in umgekehrter zeitlicher Reihenfolge
|
|
||||||
label_planning: Terminplanung
|
|
||||||
|
|
||||||
button_login: Anmelden
|
button_login: Anmelden
|
||||||
button_submit: OK
|
button_submit: OK
|
||||||
@@ -528,7 +518,7 @@ button_lock: Sperren
|
|||||||
button_unlock: Entsperren
|
button_unlock: Entsperren
|
||||||
button_download: Download
|
button_download: Download
|
||||||
button_list: Liste
|
button_list: Liste
|
||||||
button_view: Anzeigen
|
button_view: Ansehen
|
||||||
button_move: Verschieben
|
button_move: Verschieben
|
||||||
button_back: Zurück
|
button_back: Zurück
|
||||||
button_cancel: Abbrechen
|
button_cancel: Abbrechen
|
||||||
@@ -545,7 +535,7 @@ button_reset: Zurücksetzen
|
|||||||
button_rename: Umbenennen
|
button_rename: Umbenennen
|
||||||
button_change_password: Kennwort ändern
|
button_change_password: Kennwort ändern
|
||||||
button_copy: Kopieren
|
button_copy: Kopieren
|
||||||
button_annotate: Annotieren
|
button_annotate: Mit Anmerkungen versehen
|
||||||
button_update: Aktualisieren
|
button_update: Aktualisieren
|
||||||
button_configure: Konfigurieren
|
button_configure: Konfigurieren
|
||||||
|
|
||||||
@@ -618,4 +608,13 @@ default_activity_development: Entwicklung
|
|||||||
enumeration_issue_priorities: Ticket-Prioritäten
|
enumeration_issue_priorities: Ticket-Prioritäten
|
||||||
enumeration_doc_categories: Dokumentenkategorien
|
enumeration_doc_categories: Dokumentenkategorien
|
||||||
enumeration_activities: Aktivitäten (Zeiterfassung)
|
enumeration_activities: Aktivitäten (Zeiterfassung)
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
setting_activity_days_default: Days displayed on project activity
|
||||||
|
label_chronological_order: In chronological order
|
||||||
|
field_comments_sorting: Display comments
|
||||||
|
label_reverse_chronological_order: In reverse chronological order
|
||||||
|
label_preferences: Preferences
|
||||||
|
setting_display_subprojects_issues: Display subprojects issues on main projects by default
|
||||||
|
label_overall_activity: Overall activity
|
||||||
|
setting_default_projects_public: New projects are public by default
|
||||||
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
|
label_planning: Planning
|
||||||
|
|||||||
@@ -557,7 +557,6 @@ text_select_mail_notifications: Select actions for which email notifications sho
|
|||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
text_min_max_length_info: 0 means no restriction
|
text_min_max_length_info: 0 means no restriction
|
||||||
text_project_destroy_confirmation: Are you sure you want to delete this project and related data ?
|
text_project_destroy_confirmation: Are you sure you want to delete this project and related data ?
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
text_workflow_edit: Select a role and a tracker to edit the workflow
|
text_workflow_edit: Select a role and a tracker to edit the workflow
|
||||||
text_are_you_sure: Are you sure ?
|
text_are_you_sure: Are you sure ?
|
||||||
text_journal_changed: changed from %s to %s
|
text_journal_changed: changed from %s to %s
|
||||||
|
|||||||
@@ -333,8 +333,8 @@ label_revision_plural: Revisiones
|
|||||||
label_added: añadido
|
label_added: añadido
|
||||||
label_modified: modificado
|
label_modified: modificado
|
||||||
label_deleted: suprimido
|
label_deleted: suprimido
|
||||||
label_latest_revision: Última revisión
|
label_latest_revision: La revisión más actual
|
||||||
label_latest_revision_plural: Últimas revisiones
|
label_latest_revision_plural: Las revisiones más actuales
|
||||||
label_view_revisions: Ver las revisiones
|
label_view_revisions: Ver las revisiones
|
||||||
label_max_size: Tamaño máximo
|
label_max_size: Tamaño máximo
|
||||||
label_on: de
|
label_on: de
|
||||||
@@ -372,7 +372,7 @@ label_view_diff: Ver diferencias
|
|||||||
label_diff_inline: en línea
|
label_diff_inline: en línea
|
||||||
label_diff_side_by_side: cara a cara
|
label_diff_side_by_side: cara a cara
|
||||||
label_options: Opciones
|
label_options: Opciones
|
||||||
label_copy_workflow_from: Copiar flujo de trabajo desde
|
label_copy_workflow_from: Copiar workflow desde
|
||||||
label_permissions_report: Informe de permisos
|
label_permissions_report: Informe de permisos
|
||||||
label_watched_issues: Peticiones monitorizadas
|
label_watched_issues: Peticiones monitorizadas
|
||||||
label_related_issues: Peticiones relacionadas
|
label_related_issues: Peticiones relacionadas
|
||||||
@@ -432,7 +432,7 @@ button_move: Mover
|
|||||||
button_back: Atrás
|
button_back: Atrás
|
||||||
button_cancel: Cancelar
|
button_cancel: Cancelar
|
||||||
button_activate: Activar
|
button_activate: Activar
|
||||||
button_sort: Ordenar
|
button_sort: Clasificar
|
||||||
button_log_time: Tiempo dedicado
|
button_log_time: Tiempo dedicado
|
||||||
button_rollback: Volver a esta versión
|
button_rollback: Volver a esta versión
|
||||||
button_watch: Monitorizar
|
button_watch: Monitorizar
|
||||||
@@ -448,7 +448,7 @@ status_locked: bloqueado
|
|||||||
text_select_mail_notifications: Seleccionar los eventos a notificar
|
text_select_mail_notifications: Seleccionar los eventos a notificar
|
||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
text_min_max_length_info: 0 para ninguna restricción
|
text_min_max_length_info: 0 para ninguna restricción
|
||||||
text_project_destroy_confirmation: ¿Estás seguro de querer eliminar el proyecto?
|
text_project_destroy_confirmation: ¿ Estás seguro de querer eliminar el proyecto ?
|
||||||
text_workflow_edit: Seleccionar un flujo de trabajo para actualizar
|
text_workflow_edit: Seleccionar un flujo de trabajo para actualizar
|
||||||
text_are_you_sure: ¿ Estás seguro ?
|
text_are_you_sure: ¿ Estás seguro ?
|
||||||
text_journal_changed: cambiado de %s a %s
|
text_journal_changed: cambiado de %s a %s
|
||||||
@@ -460,7 +460,7 @@ text_tip_task_begin_end_day: tarea que comienza y termina este día
|
|||||||
text_project_identifier_info: 'Letras minúsculas (a-z), números y signos de puntuación permitidos.<br />Una vez guardado, el identificador no puede modificarse.'
|
text_project_identifier_info: 'Letras minúsculas (a-z), números y signos de puntuación permitidos.<br />Una vez guardado, el identificador no puede modificarse.'
|
||||||
text_caracters_maximum: %d carácteres como máximo.
|
text_caracters_maximum: %d carácteres como máximo.
|
||||||
text_length_between: Longitud entre %d y %d carácteres.
|
text_length_between: Longitud entre %d y %d carácteres.
|
||||||
text_tracker_no_workflow: No hay ningún flujo de trabajo definido para este tracker
|
text_tracker_no_workflow: No hay ningún workflow definido para este tracker
|
||||||
text_unallowed_characters: Carácteres no permitidos
|
text_unallowed_characters: Carácteres no permitidos
|
||||||
text_comma_separated: Múltiples valores permitidos (separados por coma).
|
text_comma_separated: Múltiples valores permitidos (separados por coma).
|
||||||
text_issues_ref_in_commit_messages: Referencia y petición de corrección en los mensajes
|
text_issues_ref_in_commit_messages: Referencia y petición de corrección en los mensajes
|
||||||
@@ -559,65 +559,64 @@ field_searchable: Incluir en las búsquedas
|
|||||||
label_display_per_page: 'Por página: %s'
|
label_display_per_page: 'Por página: %s'
|
||||||
setting_per_page_options: Objetos por página
|
setting_per_page_options: Objetos por página
|
||||||
label_age: Edad
|
label_age: Edad
|
||||||
notice_default_data_loaded: Configuración por defecto cargada correctamente.
|
notice_default_data_loaded: Default configuration successfully loaded.
|
||||||
text_load_default_configuration: Cargar la configuración por defecto
|
text_load_default_configuration: Load the default configuration
|
||||||
text_no_configuration_data: "Todavía no se han configurado roles, ni trackers, ni estados y flujo de trabajo asociado a peticiones. Se recomiendo encarecidamente cargar la configuración por defecto. Una vez cargada, podrá modificarla."
|
text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded."
|
||||||
error_can_t_load_default_data: "No se ha podido cargar la configuración por defecto: %s"
|
error_can_t_load_default_data: "Default configuration could not be loaded: %s"
|
||||||
button_update: Actualizar
|
button_update: Update
|
||||||
label_change_properties: Cambiar propiedades
|
label_change_properties: Change properties
|
||||||
label_general: General
|
label_general: General
|
||||||
label_repository_plural: Repositorios
|
label_repository_plural: Repositories
|
||||||
label_associated_revisions: Revisiones asociadas
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Formato de nombre de usuario
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Aplicado en los cambios %s
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
label_more: Más
|
label_more: More
|
||||||
text_issues_destroy_confirmation: '¿Seguro que quiere borrar las peticiones seleccionadas?'
|
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s) ?'
|
||||||
label_scm: SCM
|
label_scm: SCM
|
||||||
text_select_project_modules: 'Seleccione los módulos a activar para este proyecto:'
|
text_select_project_modules: 'Select modules to enable for this project:'
|
||||||
label_issue_added: Petición añadida
|
label_issue_added: Issue added
|
||||||
label_issue_updated: Petición actualizada
|
label_issue_updated: Issue updated
|
||||||
label_document_added: Documento añadido
|
label_document_added: Document added
|
||||||
label_message_posted: Mensaje añadido
|
label_message_posted: Message added
|
||||||
label_file_added: Fichero añadido
|
label_file_added: File added
|
||||||
label_news_added: Noticia añadida
|
label_news_added: News added
|
||||||
project_module_boards: Foros
|
project_module_boards: Boards
|
||||||
project_module_issue_tracking: Peticiones
|
project_module_issue_tracking: Issue tracking
|
||||||
project_module_wiki: Wiki
|
project_module_wiki: Wiki
|
||||||
project_module_files: Ficheros
|
project_module_files: Files
|
||||||
project_module_documents: Documentos
|
project_module_documents: Documents
|
||||||
project_module_repository: Repositorio
|
project_module_repository: Repository
|
||||||
project_module_news: Noticias
|
project_module_news: News
|
||||||
project_module_time_tracking: Control de tiempo
|
project_module_time_tracking: Time tracking
|
||||||
text_file_repository_writable: Se puede escribir en el repositorio
|
text_file_repository_writable: File repository writable
|
||||||
text_default_administrator_account_changed: Cuenta de administrador por defecto modificada
|
text_default_administrator_account_changed: Default administrator account changed
|
||||||
text_rmagick_available: RMagick disponible (opcional)
|
text_rmagick_available: RMagick available (optional)
|
||||||
button_configure: Configurar
|
button_configure: Configure
|
||||||
label_plugins: Plugins
|
label_plugins: Plugins
|
||||||
label_ldap_authentication: Autenticación LDAP
|
label_ldap_authentication: LDAP authentication
|
||||||
label_downloads_abbr: D/L
|
label_downloads_abbr: D/L
|
||||||
label_this_month: este mes
|
label_this_month: this month
|
||||||
label_last_n_days: últimos %d días
|
label_last_n_days: last %d days
|
||||||
label_all_time: todo el tiempo
|
label_all_time: all time
|
||||||
label_this_year: este año
|
label_this_year: this year
|
||||||
label_date_range: Rango de fechas
|
label_date_range: Date range
|
||||||
label_last_week: última semana
|
label_last_week: last week
|
||||||
label_yesterday: ayer
|
label_yesterday: yesterday
|
||||||
label_last_month: último mes
|
label_last_month: last month
|
||||||
label_add_another_file: Añadir otro fichero
|
label_add_another_file: Add another file
|
||||||
label_optional_description: Descripción opcional
|
label_optional_description: Optional description
|
||||||
text_destroy_time_entries_question: Existen %.02f horas asignadas a la petición que quiere borrar. ¿Qué quiere hacer ?
|
text_destroy_time_entries_question: %.02f hours were reported on the issues you are about to delete. What do you want to do ?
|
||||||
error_issue_not_found_in_project: 'La petición no se encuentra o no está asociada a este proyecto'
|
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
|
||||||
text_assign_time_entries_to_project: Asignar las horas al proyecto
|
text_assign_time_entries_to_project: Assign reported hours to the project
|
||||||
text_destroy_time_entries: Borrar las horas
|
text_destroy_time_entries: Delete reported hours
|
||||||
text_reassign_time_entries: 'Reasignar las horas a esta petición:'
|
text_reassign_time_entries: 'Reassign reported hours to this issue:'
|
||||||
setting_activity_days_default: Días a mostrar en la actividad de proyecto
|
setting_activity_days_default: Days displayed on project activity
|
||||||
label_chronological_order: En orden cronológico
|
label_chronological_order: In chronological order
|
||||||
field_comments_sorting: Mostrar comentarios
|
field_comments_sorting: Display comments
|
||||||
label_reverse_chronological_order: En orden cronológico inverso
|
label_reverse_chronological_order: In reverse chronological order
|
||||||
label_preferences: Preferencias
|
label_preferences: Preferences
|
||||||
setting_display_subprojects_issues: Mostrar peticiones de un subproyecto en el proyecto padre por defecto
|
setting_display_subprojects_issues: Display subprojects issues on main projects by default
|
||||||
label_overall_activity: Actividad global
|
label_overall_activity: Overall activity
|
||||||
setting_default_projects_public: Los proyectos nuevos son públicos por defecto
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "No existe la entrada o no ha podido ser anotada"
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planificación
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Sus subprojectos: %s también se eliminarán'
|
|
||||||
|
|||||||
@@ -614,7 +614,6 @@ field_comments_sorting: Näytä kommentit
|
|||||||
label_reverse_chronological_order: Käänteisessä aikajärjestyksessä
|
label_reverse_chronological_order: Käänteisessä aikajärjestyksessä
|
||||||
label_preferences: Asetukset
|
label_preferences: Asetukset
|
||||||
setting_default_projects_public: Uudet projektit ovat oletuksena julkisia
|
setting_default_projects_public: Uudet projektit ovat oletuksena julkisia
|
||||||
label_overall_activity: Kokonaishistoria
|
label_overall_activity: Kokonaisaktiviteetti
|
||||||
error_scm_annotate: "Merkintää ei ole tai siihen ei voi lisätä selityksiä."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Suunnittelu
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -556,8 +556,7 @@ status_locked: vérouillé
|
|||||||
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
||||||
text_regexp_info: ex. ^[A-Z0-9]+$
|
text_regexp_info: ex. ^[A-Z0-9]+$
|
||||||
text_min_max_length_info: 0 pour aucune restriction
|
text_min_max_length_info: 0 pour aucune restriction
|
||||||
text_project_destroy_confirmation: Etes-vous sûr de vouloir supprimer ce projet et toutes ses données ?
|
text_project_destroy_confirmation: Etes-vous sûr de vouloir supprimer ce projet et tout ce qui lui est rattaché ?
|
||||||
text_subprojects_destroy_warning: 'Ses sous-projets: %s seront également supprimés.'
|
|
||||||
text_workflow_edit: Sélectionner un tracker et un rôle pour éditer le workflow
|
text_workflow_edit: Sélectionner un tracker et un rôle pour éditer le workflow
|
||||||
text_are_you_sure: Etes-vous sûr ?
|
text_are_you_sure: Etes-vous sûr ?
|
||||||
text_journal_changed: changé de %s à %s
|
text_journal_changed: changé de %s à %s
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ notice_failed_to_save_issues: "נכשרת בשמירת %d נושא\ים ב %d נ
|
|||||||
notice_no_issue_selected: "לא נבחר אף נושא! בחר בבקשה את הנושאים שברצונך לערוך."
|
notice_no_issue_selected: "לא נבחר אף נושא! בחר בבקשה את הנושאים שברצונך לערוך."
|
||||||
|
|
||||||
error_scm_not_found: כניסה ו\או גירסא אינם קיימים במאגר.
|
error_scm_not_found: כניסה ו\או גירסא אינם קיימים במאגר.
|
||||||
error_scm_command_failed: "ארעה שגיאה בעת ניסון גישה למאגר: %s"
|
error_scm_command_failed: "An error occurred when trying to access the repository: %s"
|
||||||
|
|
||||||
mail_subject_lost_password: סיסמת ה-%s שלך
|
mail_subject_lost_password: סיסמת ה-%s שלך
|
||||||
mail_body_lost_password: 'לשינו סיסמת ה-Redmine שלך,לחץ על הקישור הבא:'
|
mail_body_lost_password: 'לשינו סיסמת ה-Redmine שלך,לחץ על הקישור הבא:'
|
||||||
@@ -98,7 +98,7 @@ field_filesize: גודל
|
|||||||
field_downloads: הורדות
|
field_downloads: הורדות
|
||||||
field_author: כותב
|
field_author: כותב
|
||||||
field_created_on: נוצר
|
field_created_on: נוצר
|
||||||
field_updated_on: עודכן
|
field_updated_on: עודגן
|
||||||
field_field_format: פורמט
|
field_field_format: פורמט
|
||||||
field_is_for_all: לכל הפרויקטים
|
field_is_for_all: לכל הפרויקטים
|
||||||
field_possible_values: ערכים אפשריים
|
field_possible_values: ערכים אפשריים
|
||||||
@@ -119,7 +119,7 @@ field_subject: שם נושא
|
|||||||
field_due_date: תאריך סיום
|
field_due_date: תאריך סיום
|
||||||
field_assigned_to: מוצב ל
|
field_assigned_to: מוצב ל
|
||||||
field_priority: עדיפות
|
field_priority: עדיפות
|
||||||
field_fixed_version: גירסאת יעד
|
field_fixed_version: Target version
|
||||||
field_user: מתשמש
|
field_user: מתשמש
|
||||||
field_role: תפקיד
|
field_role: תפקיד
|
||||||
field_homepage: דף הבית
|
field_homepage: דף הבית
|
||||||
@@ -140,7 +140,7 @@ field_version: גירסא
|
|||||||
field_type: סוג
|
field_type: סוג
|
||||||
field_host: שרת
|
field_host: שרת
|
||||||
field_port: פורט
|
field_port: פורט
|
||||||
field_account: חשבון
|
field_account: חשבום
|
||||||
field_base_dn: בסיס DN
|
field_base_dn: בסיס DN
|
||||||
field_attr_login: תכונת התחברות
|
field_attr_login: תכונת התחברות
|
||||||
field_attr_firstname: תכונת שם פרטים
|
field_attr_firstname: תכונת שם פרטים
|
||||||
@@ -182,7 +182,7 @@ setting_text_formatting: עיצוב טקסט
|
|||||||
setting_wiki_compression: כיווץ היסטורית WIKI
|
setting_wiki_compression: כיווץ היסטורית WIKI
|
||||||
setting_feeds_limit: גבול תוכן הזנות
|
setting_feeds_limit: גבול תוכן הזנות
|
||||||
setting_autofetch_changesets: משיכה אוטומתי של עידכונים
|
setting_autofetch_changesets: משיכה אוטומתי של עידכונים
|
||||||
setting_sys_api_enabled: אפשר WS לניהול המאגר
|
setting_sys_api_enabled: Enable WS for repository management
|
||||||
setting_commit_ref_keywords: מילות מפתח מקשרות
|
setting_commit_ref_keywords: מילות מפתח מקשרות
|
||||||
setting_commit_fix_keywords: מילות מפתח מתקנות
|
setting_commit_fix_keywords: מילות מפתח מתקנות
|
||||||
setting_autologin: חיבור אוטומטי
|
setting_autologin: חיבור אוטומטי
|
||||||
@@ -233,7 +233,7 @@ label_information_plural: מידע
|
|||||||
label_please_login: התחבר בבקשה
|
label_please_login: התחבר בבקשה
|
||||||
label_register: הרשמה
|
label_register: הרשמה
|
||||||
label_password_lost: אבדה הסיסמה?
|
label_password_lost: אבדה הסיסמה?
|
||||||
label_home: דף הבית
|
label_home: דך הבית
|
||||||
label_my_page: הדף שלי
|
label_my_page: הדף שלי
|
||||||
label_my_account: השבון שלי
|
label_my_account: השבון שלי
|
||||||
label_my_projects: הפרויקטים שלי
|
label_my_projects: הפרויקטים שלי
|
||||||
@@ -259,7 +259,7 @@ label_subproject_plural: תת-פרויקטים
|
|||||||
label_min_max_length: אורך מינימאלי - מקסימאלי
|
label_min_max_length: אורך מינימאלי - מקסימאלי
|
||||||
label_list: רשימה
|
label_list: רשימה
|
||||||
label_date: תאריך
|
label_date: תאריך
|
||||||
label_integer: מספר שלם
|
label_integer: מספר שלים
|
||||||
label_boolean: ערך בוליאני
|
label_boolean: ערך בוליאני
|
||||||
label_string: טקסט
|
label_string: טקסט
|
||||||
label_text: טקסט ארוך
|
label_text: טקסט ארוך
|
||||||
@@ -269,7 +269,7 @@ label_download: הורדה %d
|
|||||||
label_download_plural: %d הורדות
|
label_download_plural: %d הורדות
|
||||||
label_no_data: אין מידע להציג
|
label_no_data: אין מידע להציג
|
||||||
label_change_status: שנה מצב
|
label_change_status: שנה מצב
|
||||||
label_history: היסטוריה
|
label_history: הידטוריה
|
||||||
label_attachment: קובץ
|
label_attachment: קובץ
|
||||||
label_attachment_new: קובץ חדש
|
label_attachment_new: קובץ חדש
|
||||||
label_attachment_delete: מחק קובץ
|
label_attachment_delete: מחק קובץ
|
||||||
@@ -279,7 +279,7 @@ label_report_plural: דו"חות
|
|||||||
label_news: חדשות
|
label_news: חדשות
|
||||||
label_news_new: הוסף חדשות
|
label_news_new: הוסף חדשות
|
||||||
label_news_plural: חדשות
|
label_news_plural: חדשות
|
||||||
label_news_latest: חדשות אחרונות
|
label_news_latest: חדשות חדשות
|
||||||
label_news_view_all: צפה בכל החדשות
|
label_news_view_all: צפה בכל החדשות
|
||||||
label_change_log: דו"ח שינויים
|
label_change_log: דו"ח שינויים
|
||||||
label_settings: הגדרות
|
label_settings: הגדרות
|
||||||
@@ -419,7 +419,7 @@ label_reply_plural: השבות
|
|||||||
label_send_information: שלח מידע על חשבון למשתמש
|
label_send_information: שלח מידע על חשבון למשתמש
|
||||||
label_year: שנה
|
label_year: שנה
|
||||||
label_month: חודש
|
label_month: חודש
|
||||||
label_week: שבוע
|
label_week: שבו
|
||||||
label_date_from: מאת
|
label_date_from: מאת
|
||||||
label_date_to: אל
|
label_date_to: אל
|
||||||
label_language_based: מבוסס שפה
|
label_language_based: מבוסס שפה
|
||||||
@@ -444,7 +444,7 @@ button_save: שמור
|
|||||||
button_check_all: בחר הכל
|
button_check_all: בחר הכל
|
||||||
button_uncheck_all: בחר כלום
|
button_uncheck_all: בחר כלום
|
||||||
button_delete: מחק
|
button_delete: מחק
|
||||||
button_create: צור
|
button_create: צוק
|
||||||
button_test: בדוק
|
button_test: בדוק
|
||||||
button_edit: ערוך
|
button_edit: ערוך
|
||||||
button_add: הוסף
|
button_add: הוסף
|
||||||
@@ -454,13 +454,13 @@ button_clear: נקה
|
|||||||
button_lock: נעל
|
button_lock: נעל
|
||||||
button_unlock: בטל נעילה
|
button_unlock: בטל נעילה
|
||||||
button_download: הורד
|
button_download: הורד
|
||||||
button_list: רשימה
|
button_list: קשימה
|
||||||
button_view: צפה
|
button_view: צפה
|
||||||
button_move: הזז
|
button_move: הזז
|
||||||
button_back: הקודם
|
button_back: הקודם
|
||||||
button_cancel: בטח
|
button_cancel: בטח
|
||||||
button_activate: הפעל
|
button_activate: הפעל
|
||||||
button_sort: מיין
|
button_sort: מין
|
||||||
button_log_time: זמן לוג
|
button_log_time: זמן לוג
|
||||||
button_rollback: חזור לגירסא זו
|
button_rollback: חזור לגירסא זו
|
||||||
button_watch: צפה
|
button_watch: צפה
|
||||||
@@ -526,95 +526,94 @@ default_activity_development: פיתוח
|
|||||||
enumeration_issue_priorities: עדיפות נושאים
|
enumeration_issue_priorities: עדיפות נושאים
|
||||||
enumeration_doc_categories: קטגוריות מסמכים
|
enumeration_doc_categories: קטגוריות מסמכים
|
||||||
enumeration_activities: פעילויות (מעקב אחר זמנים)
|
enumeration_activities: פעילויות (מעקב אחר זמנים)
|
||||||
label_search_titles_only: חפש בכותרות בלבד
|
label_search_titles_only: Search titles only
|
||||||
label_nobody: אף אחד
|
label_nobody: nobody
|
||||||
button_change_password: שנה סיסמא
|
button_change_password: Change password
|
||||||
text_user_mail_option: "בפרויקטים שלא בחרת, אתה רק תקבל התרעות על שאתה צופה או קשור אליהם (לדוגמא:נושאים שאתה היוצר שלהם או מוצבים אליך)."
|
text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
|
||||||
label_user_mail_option_selected: "לכל אירוע בפרויקטים שבחרתי בלבד..."
|
label_user_mail_option_selected: "For any event on the selected projects only..."
|
||||||
label_user_mail_option_all: "לכל אירוע בכל הפרויקטים שלי"
|
label_user_mail_option_all: "For any event on all my projects"
|
||||||
label_user_mail_option_none: "רק לנושאים שאני צופה או קשור אליהם"
|
label_user_mail_option_none: "Only for things I watch or I'm involved in"
|
||||||
setting_emails_footer: תחתית דוא"ל
|
setting_emails_footer: Emails footer
|
||||||
label_float: צף
|
label_float: Float
|
||||||
button_copy: העתק
|
button_copy: Copy
|
||||||
mail_body_account_information_external: אתה יכול להשתמש בחשבון "%s" כדי להתחבר
|
mail_body_account_information_external: You can use your "%s" account to log in.
|
||||||
mail_body_account_information: פרטי החשבון שלך
|
mail_body_account_information: Your account information
|
||||||
setting_protocol: פרוטוקול
|
setting_protocol: Protocol
|
||||||
label_user_mail_no_self_notified: "אני לא רוצה שיודיעו לי על שינויים שאני מבצע"
|
label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself"
|
||||||
setting_time_format: פורמט זמן
|
setting_time_format: Time format
|
||||||
label_registration_activation_by_email: הפעל חשבון באמצעות דוא"ל
|
label_registration_activation_by_email: account activation by email
|
||||||
mail_subject_account_activation_request: בקשת הפעלה לחשבון %s
|
mail_subject_account_activation_request: %s account activation request
|
||||||
mail_body_account_activation_request: 'משתמש חדש (%s) נרשם. החשבון שלו מחכה לאישור שלך:'
|
mail_body_account_activation_request: 'A new user (%s) has registered. His account his pending your approval:'
|
||||||
label_registration_automatic_activation: הפעלת חשבון אוטומטית
|
label_registration_automatic_activation: automatic account activation
|
||||||
label_registration_manual_activation: הפעלת חשבון ידנית
|
label_registration_manual_activation: manual account activation
|
||||||
notice_account_pending: "החשבון שלך נוצר ועתה מחכה לאישור מנהל המערכת."
|
notice_account_pending: "Your account was created and is now pending administrator approval."
|
||||||
field_time_zone: איזור זמן
|
field_time_zone: Time zone
|
||||||
text_caracters_minimum: חייב להיות לפחות באורך של %d תווים.
|
text_caracters_minimum: Must be at least %d characters long.
|
||||||
setting_bcc_recipients: מוסתר (bcc)
|
setting_bcc_recipients: Blind carbon copy recipients (bcc)
|
||||||
button_annotate: הוסף תיאור מסגרת
|
button_annotate: Annotate
|
||||||
label_issues_by: נושאים של %s
|
label_issues_by: Issues by %s
|
||||||
field_searchable: ניתן לחיפוש
|
field_searchable: Searchable
|
||||||
label_display_per_page: 'לכל דף: %s'
|
label_display_per_page: 'Per page: %s'
|
||||||
setting_per_page_options: אפשרויות אוביקטים לפי דף
|
setting_per_page_options: Objects per page options
|
||||||
label_age: גיל
|
label_age: Age
|
||||||
notice_default_data_loaded: אפשרויות ברירת מחדל מופעלות.
|
notice_default_data_loaded: Default configuration successfully loaded.
|
||||||
text_load_default_configuration: טען את אפשרויות ברירת המחדל
|
text_load_default_configuration: Load the default configuration
|
||||||
text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. יהיה באפשרותך לשנותו לאחר שיטען."
|
text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded."
|
||||||
error_can_t_load_default_data: "אפשרויות ברירת המחדל לא הצליחו להיטען: %s"
|
error_can_t_load_default_data: "Default configuration could not be loaded: %s"
|
||||||
button_update: עדכן
|
button_update: Update
|
||||||
label_change_properties: שנה מאפיינים
|
label_change_properties: Change properties
|
||||||
label_general: כללי
|
label_general: General
|
||||||
label_repository_plural: מאגרים
|
label_repository_plural: Repositories
|
||||||
label_associated_revisions: שינויים קשורים
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: פורמט הצגת משתמשים
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: הוחל בסדרת השינויים %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
label_more: עוד
|
label_more: More
|
||||||
text_issues_destroy_confirmation: 'האם את\ה בטוח שברצונך למחוק את הנושא\ים ?'
|
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s) ?'
|
||||||
label_scm: SCM
|
label_scm: SCM
|
||||||
text_select_project_modules: 'בחר מודולים להחיל על פקרויקט זה:'
|
text_select_project_modules: 'Select modules to enable for this project:'
|
||||||
label_issue_added: נושא הוסף
|
label_issue_added: Issue added
|
||||||
label_issue_updated: נושא עודכן
|
label_issue_updated: Issue updated
|
||||||
label_document_added: מוסמך הוסף
|
label_document_added: Document added
|
||||||
label_message_posted: הודעה הוספה
|
label_message_posted: Message added
|
||||||
label_file_added: קובץ הוסף
|
label_file_added: File added
|
||||||
label_news_added: חדשות הוספו
|
label_news_added: News added
|
||||||
project_module_boards: לוחות
|
project_module_boards: Boards
|
||||||
project_module_issue_tracking: מעקב נושאים
|
project_module_issue_tracking: Issue tracking
|
||||||
project_module_wiki: Wiki
|
project_module_wiki: Wiki
|
||||||
project_module_files: קבצים
|
project_module_files: Files
|
||||||
project_module_documents: מסמכים
|
project_module_documents: Documents
|
||||||
project_module_repository: מאגר
|
project_module_repository: Repository
|
||||||
project_module_news: חדשות
|
project_module_news: News
|
||||||
project_module_time_tracking: מעקב אחר זמנים
|
project_module_time_tracking: Time tracking
|
||||||
text_file_repository_writable: מאגר הקבצים ניתן לכתיבה
|
text_file_repository_writable: File repository writable
|
||||||
text_default_administrator_account_changed: מנהל המערכת ברירת המחדל שונה
|
text_default_administrator_account_changed: Default administrator account changed
|
||||||
text_rmagick_available: RMagick available (optional)
|
text_rmagick_available: RMagick available (optional)
|
||||||
button_configure: אפשרויות
|
button_configure: Configure
|
||||||
label_plugins: פלאגינים
|
label_plugins: Plugins
|
||||||
label_ldap_authentication: אימות LDAP
|
label_ldap_authentication: LDAP authentication
|
||||||
label_downloads_abbr: D/L
|
label_downloads_abbr: D/L
|
||||||
label_this_month: החודש
|
label_this_month: this month
|
||||||
label_last_n_days: ב-%d ימים אחרונים
|
label_last_n_days: last %d days
|
||||||
label_all_time: תמיד
|
label_all_time: all time
|
||||||
label_this_year: השנה
|
label_this_year: this year
|
||||||
label_date_range: טווח תאריכים
|
label_date_range: Date range
|
||||||
label_last_week: שבוע שעבר
|
label_last_week: last week
|
||||||
label_yesterday: אתמול
|
label_yesterday: yesterday
|
||||||
label_last_month: חודש שעבר
|
label_last_month: last month
|
||||||
label_add_another_file: הוסף עוד קובץ
|
label_add_another_file: Add another file
|
||||||
label_optional_description: תיאור רשות
|
label_optional_description: Optional description
|
||||||
text_destroy_time_entries_question: %.02f שעות דווחו על הנושים שאת\ה עומד\ת למחוק. מה ברצונך לעשות ?
|
text_destroy_time_entries_question: %.02f hours were reported on the issues you are about to delete. What do you want to do ?
|
||||||
error_issue_not_found_in_project: 'הנושאים לא נמצאו או אינם שיכים לפרויקט'
|
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
|
||||||
text_assign_time_entries_to_project: הצב שעות שדווחו לפרויקט הזה
|
text_assign_time_entries_to_project: Assign reported hours to the project
|
||||||
text_destroy_time_entries: מחק שעות שדווחו
|
text_destroy_time_entries: Delete reported hours
|
||||||
text_reassign_time_entries: 'הצב מחדש שעות שדווחו לפרויקט הזה:'
|
text_reassign_time_entries: 'Reassign reported hours to this issue:'
|
||||||
setting_activity_days_default: ימים המוצגים על פעילות הפרויקט
|
setting_activity_days_default: Days displayed on project activity
|
||||||
label_chronological_order: בסדר כרונולוגי
|
label_chronological_order: In chronological order
|
||||||
field_comments_sorting: הצג הערות
|
field_comments_sorting: Display comments
|
||||||
label_reverse_chronological_order: בסדר כרונולוגי הפוך
|
label_reverse_chronological_order: In reverse chronological order
|
||||||
label_preferences: העדפות
|
label_preferences: Preferences
|
||||||
setting_display_subprojects_issues: הצג נושאים של תת פרויקטים כברירת מחדל
|
setting_display_subprojects_issues: Display subprojects issues on main projects by default
|
||||||
label_overall_activity: פעילות כוללת
|
label_overall_activity: Overall activity
|
||||||
setting_default_projects_public: פרויקטים חדשים הינם פומביים כברירת מחדל
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "הכניסה לא קיימת או שלא ניתן לתאר אותה."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: תכנון
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ label_overall_activity: 全ての活動
|
|||||||
setting_default_projects_public: デフォルトで新しいプロジェクトは公開にする
|
setting_default_projects_public: デフォルトで新しいプロジェクトは公開にする
|
||||||
error_scm_annotate: "エントリが存在しない、もしくはアノテートできません。"
|
error_scm_annotate: "エントリが存在しない、もしくはアノテートできません。"
|
||||||
label_planning: 計画
|
label_planning: 計画
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ notice_default_data_loaded: Standardkonfigurasjonen lastet inn.
|
|||||||
error_can_t_load_default_data: "Standardkonfigurasjonen kunne ikke lastes inn: %s"
|
error_can_t_load_default_data: "Standardkonfigurasjonen kunne ikke lastes inn: %s"
|
||||||
error_scm_not_found: "Elementet og/eller revisjonen eksisterer ikke i depoet."
|
error_scm_not_found: "Elementet og/eller revisjonen eksisterer ikke i depoet."
|
||||||
error_scm_command_failed: "En feil oppstod under tilkobling til depoet: %s"
|
error_scm_command_failed: "En feil oppstod under tilkobling til depoet: %s"
|
||||||
error_scm_annotate: "Elementet eksisterer ikke, eller kan ikke noteres."
|
error_scm_annotate: "Elementet eksisterer ikke, eller kan ikke annoteres."
|
||||||
error_issue_not_found_in_project: 'Saken eksisterer ikke, eller hører ikke til dette prosjektet'
|
error_issue_not_found_in_project: 'Saken eksisterer ikke, eller hører ikke til dette prosjektet'
|
||||||
|
|
||||||
mail_subject_lost_password: Ditt %s passord
|
mail_subject_lost_password: Ditt %s passord
|
||||||
@@ -137,7 +137,7 @@ field_parent: Underprosjekt til
|
|||||||
field_is_in_chlog: Vises i endringslogg
|
field_is_in_chlog: Vises i endringslogg
|
||||||
field_is_in_roadmap: Vises i veikart
|
field_is_in_roadmap: Vises i veikart
|
||||||
field_login: Brukernavn
|
field_login: Brukernavn
|
||||||
field_mail_notification: E-post-varsling
|
field_mail_notification: E-post varsling
|
||||||
field_admin: Administrator
|
field_admin: Administrator
|
||||||
field_last_login_on: Sist innlogget
|
field_last_login_on: Sist innlogget
|
||||||
field_language: Språk
|
field_language: Språk
|
||||||
@@ -165,7 +165,7 @@ field_url: URL
|
|||||||
field_start_page: Startside
|
field_start_page: Startside
|
||||||
field_subproject: Underprosjekt
|
field_subproject: Underprosjekt
|
||||||
field_hours: Timer
|
field_hours: Timer
|
||||||
field_activity: Aktivitet
|
field_activity: Activitet
|
||||||
field_spent_on: Dato
|
field_spent_on: Dato
|
||||||
field_identifier: Identifikasjon
|
field_identifier: Identifikasjon
|
||||||
field_is_filter: Brukes som filter
|
field_is_filter: Brukes som filter
|
||||||
@@ -282,7 +282,7 @@ label_last_updates: Sist oppdatert
|
|||||||
label_last_updates_plural: %d siste oppdaterte
|
label_last_updates_plural: %d siste oppdaterte
|
||||||
label_registered_on: Registrert
|
label_registered_on: Registrert
|
||||||
label_activity: Aktivitet
|
label_activity: Aktivitet
|
||||||
label_overall_activity: All aktivitet
|
label_overall_activity: Total aktivitet
|
||||||
label_new: Ny
|
label_new: Ny
|
||||||
label_logged_as: Innlogget som
|
label_logged_as: Innlogget som
|
||||||
label_environment: Miljø
|
label_environment: Miljø
|
||||||
@@ -352,7 +352,7 @@ label_gantt: Gantt
|
|||||||
label_internal: Intern
|
label_internal: Intern
|
||||||
label_last_changes: siste %d endringer
|
label_last_changes: siste %d endringer
|
||||||
label_change_view_all: Vis alle endringer
|
label_change_view_all: Vis alle endringer
|
||||||
label_personalize_page: Tilpass denne siden
|
label_personalize_page: Tilrettelegg denne siden
|
||||||
label_comment: Kommentar
|
label_comment: Kommentar
|
||||||
label_comment_plural: Kommentarer
|
label_comment_plural: Kommentarer
|
||||||
label_comment_add: Legg til kommentar
|
label_comment_add: Legg til kommentar
|
||||||
@@ -545,7 +545,7 @@ button_reset: Nullstill
|
|||||||
button_rename: Endre navn
|
button_rename: Endre navn
|
||||||
button_change_password: Endre passord
|
button_change_password: Endre passord
|
||||||
button_copy: Kopier
|
button_copy: Kopier
|
||||||
button_annotate: Notér
|
button_annotate: Annotér
|
||||||
button_update: Oppdater
|
button_update: Oppdater
|
||||||
button_configure: Konfigurer
|
button_configure: Konfigurer
|
||||||
|
|
||||||
@@ -557,7 +557,6 @@ text_select_mail_notifications: Velg hendelser som skal varsles med e-post.
|
|||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
text_min_max_length_info: 0 betyr ingen begrensning
|
text_min_max_length_info: 0 betyr ingen begrensning
|
||||||
text_project_destroy_confirmation: Er du sikker på at du vil slette dette prosjekter og alle relatert data ?
|
text_project_destroy_confirmation: Er du sikker på at du vil slette dette prosjekter og alle relatert data ?
|
||||||
text_subprojects_destroy_warning: 'Underprojekt(ene): %s vil også bli slettet.'
|
|
||||||
text_workflow_edit: Velg en rolle og en sakstype for å endre arbeidsflyten
|
text_workflow_edit: Velg en rolle og en sakstype for å endre arbeidsflyten
|
||||||
text_are_you_sure: Er du sikker ?
|
text_are_you_sure: Er du sikker ?
|
||||||
text_journal_changed: endret fra %s til %s
|
text_journal_changed: endret fra %s til %s
|
||||||
@@ -566,7 +565,7 @@ text_journal_deleted: slettet
|
|||||||
text_tip_task_begin_day: oppgaven starter denne dagen
|
text_tip_task_begin_day: oppgaven starter denne dagen
|
||||||
text_tip_task_end_day: oppgaven avsluttes denne dagen
|
text_tip_task_end_day: oppgaven avsluttes denne dagen
|
||||||
text_tip_task_begin_end_day: oppgaven starter og avsluttes denne dagen
|
text_tip_task_begin_end_day: oppgaven starter og avsluttes denne dagen
|
||||||
text_project_identifier_info: 'Små bokstaver (a-z), nummer og bindestrek tillatt.<br />Identifikatoren kan ikke endres etter den er lagret.'
|
text_project_identifier_info: 'Små bokstaver (a-z), nummer og binde-/understrek tillat.<br />Identifikatoren kan ikke endres etter den er lagret.'
|
||||||
text_caracters_maximum: %d tegn maksimum.
|
text_caracters_maximum: %d tegn maksimum.
|
||||||
text_caracters_minimum: Må være minst %d tegn langt.
|
text_caracters_minimum: Må være minst %d tegn langt.
|
||||||
text_length_between: Lengde mellom %d og %d tegn.
|
text_length_between: Lengde mellom %d og %d tegn.
|
||||||
@@ -587,8 +586,8 @@ text_status_changed_by_changeset: Brukt i endringssett %s.
|
|||||||
text_issues_destroy_confirmation: 'Er du sikker på at du vil slette valgte sak(er) ?'
|
text_issues_destroy_confirmation: 'Er du sikker på at du vil slette valgte sak(er) ?'
|
||||||
text_select_project_modules: 'Velg moduler du vil aktivere for dette prosjektet:'
|
text_select_project_modules: 'Velg moduler du vil aktivere for dette prosjektet:'
|
||||||
text_default_administrator_account_changed: Standard administrator-konto er endret
|
text_default_administrator_account_changed: Standard administrator-konto er endret
|
||||||
text_file_repository_writable: Fil-arkivet er skrivbart
|
text_file_repository_writable: Fil-depotet er skrivbart
|
||||||
text_rmagick_available: RMagick er tilgjengelig (valgfritt)
|
text_rmagick_available: RMagick tilgjengelig (valgfritt)
|
||||||
text_destroy_time_entries_question: %.02f timer er ført på sakene du er i ferd med å slette. Hva vil du gjøre ?
|
text_destroy_time_entries_question: %.02f timer er ført på sakene du er i ferd med å slette. Hva vil du gjøre ?
|
||||||
text_destroy_time_entries: Slett førte timer
|
text_destroy_time_entries: Slett førte timer
|
||||||
text_assign_time_entries_to_project: Overfør førte timer til prosjektet
|
text_assign_time_entries_to_project: Overfør førte timer til prosjektet
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Ogólna aktywność
|
|||||||
setting_default_projects_public: Nowe projekty są domyślnie publiczne
|
setting_default_projects_public: Nowe projekty są domyślnie publiczne
|
||||||
error_scm_annotate: "Wpis nie istnieje lub nie można do niego dodawać adnotacji."
|
error_scm_annotate: "Wpis nie istnieje lub nie można do niego dodawać adnotacji."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -617,4 +617,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -619,6 +619,5 @@ label_preferences: Предпочтения
|
|||||||
setting_display_subprojects_issues: Отображение подпроектов по умолчанию
|
setting_display_subprojects_issues: Отображение подпроектов по умолчанию
|
||||||
label_overall_activity: Сводная активность
|
label_overall_activity: Сводная активность
|
||||||
setting_default_projects_public: Новые проекты являются публичными
|
setting_default_projects_public: Новые проекты являются публичными
|
||||||
error_scm_annotate: "Данные отсутствуют или не могут быть подписаны."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Планирование
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -619,4 +619,3 @@ label_overall_activity: Overall activity
|
|||||||
setting_default_projects_public: New projects are public by default
|
setting_default_projects_public: New projects are public by default
|
||||||
error_scm_annotate: "The entry does not exist or can not be annotated."
|
error_scm_annotate: "The entry does not exist or can not be annotated."
|
||||||
label_planning: Planning
|
label_planning: Planning
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ default_activity_development: 開發
|
|||||||
enumeration_issue_priorities: 項目優先權
|
enumeration_issue_priorities: 項目優先權
|
||||||
enumeration_doc_categories: 文件分類
|
enumeration_doc_categories: 文件分類
|
||||||
enumeration_activities: 活動 (時間追蹤)
|
enumeration_activities: 活動 (時間追蹤)
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -618,4 +618,3 @@ default_activity_development: 开发
|
|||||||
enumeration_issue_priorities: 问题优先级
|
enumeration_issue_priorities: 问题优先级
|
||||||
enumeration_doc_categories: 文档类别
|
enumeration_doc_categories: 文档类别
|
||||||
enumeration_activities: 活动(时间跟踪)
|
enumeration_activities: 活动(时间跟踪)
|
||||||
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
|
|
||||||
|
|||||||
@@ -1134,7 +1134,7 @@ class RedCloth < String
|
|||||||
ALLOWED_TAGS = %w(redpre pre code)
|
ALLOWED_TAGS = %w(redpre pre code)
|
||||||
|
|
||||||
def escape_html_tags(text)
|
def escape_html_tags(text)
|
||||||
text.gsub!(%r{<(\/?(\w+)[^>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "<#{$1}#{'>' if $3}" }
|
text.gsub!(%r{<((\/?)(\w+))}) {|m| ALLOWED_TAGS.include?($3) ? "<#{$1}" : "<#{$1}" }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
require 'redmine/access_control'
|
require 'redmine/access_control'
|
||||||
require 'redmine/menu_manager'
|
require 'redmine/menu_manager'
|
||||||
require 'redmine/mime_type'
|
require 'redmine/mime_type'
|
||||||
require 'redmine/core_ext'
|
|
||||||
require 'redmine/themes'
|
require 'redmine/themes'
|
||||||
require 'redmine/plugin'
|
require 'redmine/plugin'
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) }
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require File.dirname(__FILE__) + '/string/conversions'
|
|
||||||
|
|
||||||
class String #:nodoc:
|
|
||||||
include Redmine::CoreExtensions::String::Conversions
|
|
||||||
end
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# redMine - project management software
|
|
||||||
# Copyright (C) 2008 Jean-Philippe Lang
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
|
|
||||||
module Redmine #:nodoc:
|
|
||||||
module CoreExtensions #:nodoc:
|
|
||||||
module String #:nodoc:
|
|
||||||
# Custom string conversions
|
|
||||||
module Conversions
|
|
||||||
# Parses hours format and returns a float
|
|
||||||
def to_hours
|
|
||||||
s = self.dup
|
|
||||||
s.strip!
|
|
||||||
unless s =~ %r{^[\d\.,]+$}
|
|
||||||
# 2:30 => 2.5
|
|
||||||
s.gsub!(%r{^(\d+):(\d+)$}) { $1.to_i + $2.to_i / 60.0 }
|
|
||||||
# 2h30, 2h, 30m => 2.5, 2, 0.5
|
|
||||||
s.gsub!(%r{^((\d+)\s*(h|hours?))?\s*((\d+)\s*(m|min)?)?$}) { |m| ($1 || $4) ? ($2.to_i + $5.to_i / 60.0) : m[0] }
|
|
||||||
end
|
|
||||||
# 2,5 => 2.5
|
|
||||||
s.gsub!(',', '.')
|
|
||||||
s.to_f
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -59,17 +59,8 @@ module Redmine
|
|||||||
# Returns the entry identified by path and revision identifier
|
# Returns the entry identified by path and revision identifier
|
||||||
# or nil if entry doesn't exist in the repository
|
# or nil if entry doesn't exist in the repository
|
||||||
def entry(path=nil, identifier=nil)
|
def entry(path=nil, identifier=nil)
|
||||||
parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
|
e = entries(path, identifier)
|
||||||
search_path = parts[0..-2].join('/')
|
e ? e.first : nil
|
||||||
search_name = parts[-1]
|
|
||||||
if search_path.blank? && search_name.blank?
|
|
||||||
# Root entry
|
|
||||||
Entry.new(:path => '', :kind => 'dir')
|
|
||||||
else
|
|
||||||
# Search for the entry in the parent directory
|
|
||||||
es = entries(search_path, identifier)
|
|
||||||
es ? es.detect {|e| e.name == search_name} : nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an Entries collection
|
# Returns an Entries collection
|
||||||
|
|||||||
@@ -44,6 +44,18 @@ module Redmine
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the entry identified by path and revision identifier
|
||||||
|
# or nil if entry doesn't exist in the repository
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
path ||= ''
|
||||||
|
parts = path.split(%r{[\/\\]}).select {|p| !p.blank?}
|
||||||
|
if parts.size > 0
|
||||||
|
parent = parts[0..-2].join('/')
|
||||||
|
entries = entries(parent, identifier)
|
||||||
|
entries ? entries.detect {|e| e.name == parts.last} : nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Returns an Entries collection
|
# Returns an Entries collection
|
||||||
# or nil if the given path doesn't exist in the repository
|
# or nil if the given path doesn't exist in the repository
|
||||||
def entries(path=nil, identifier=nil)
|
def entries(path=nil, identifier=nil)
|
||||||
|
|||||||
@@ -56,6 +56,15 @@ module Redmine
|
|||||||
CvsRevisionHelper.new(revision).prevRev
|
CvsRevisionHelper.new(revision).prevRev
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the entry identified by path and revision identifier
|
||||||
|
# or nil if entry doesn't exist in the repository
|
||||||
|
# this method returns all revisions from one single SCM-Entry
|
||||||
|
def entry(path=nil, identifier="HEAD")
|
||||||
|
e = entries(path, identifier)
|
||||||
|
logger.debug("<cvs-result> #{e.first.inspect}") if e
|
||||||
|
e ? e.first : nil
|
||||||
|
end
|
||||||
|
|
||||||
# Returns an Entries collection
|
# Returns an Entries collection
|
||||||
# or nil if the given path doesn't exist in the repository
|
# or nil if the given path doesn't exist in the repository
|
||||||
# this method is used by the repository-browser (aka LIST)
|
# this method is used by the repository-browser (aka LIST)
|
||||||
@@ -63,9 +72,7 @@ module Redmine
|
|||||||
logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
|
logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
|
||||||
path_with_project="#{url}#{with_leading_slash(path)}"
|
path_with_project="#{url}#{with_leading_slash(path)}"
|
||||||
entries = Entries.new
|
entries = Entries.new
|
||||||
cmd = "#{CVS_BIN} -d #{root_url} rls -ed"
|
cmd = "#{CVS_BIN} -d #{root_url} rls -ed #{path_with_project}"
|
||||||
cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
|
|
||||||
cmd << " #{path_with_project}"
|
|
||||||
shellout(cmd) do |io|
|
shellout(cmd) do |io|
|
||||||
io.each_line(){|line|
|
io.each_line(){|line|
|
||||||
fields=line.chop.split('/',-1)
|
fields=line.chop.split('/',-1)
|
||||||
|
|||||||
@@ -40,15 +40,20 @@ module Redmine
|
|||||||
rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
|
rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the entry identified by path and revision identifier
|
||||||
|
# or nil if entry doesn't exist in the repository
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
e = entries(path, identifier)
|
||||||
|
e ? e.first : nil
|
||||||
|
end
|
||||||
|
|
||||||
# Returns an Entries collection
|
# Returns an Entries collection
|
||||||
# or nil if the given path doesn't exist in the repository
|
# or nil if the given path doesn't exist in the repository
|
||||||
def entries(path=nil, identifier=nil)
|
def entries(path=nil, identifier=nil)
|
||||||
path_prefix = (path.blank? ? '' : "#{path}/")
|
path_prefix = (path.blank? ? '' : "#{path}/")
|
||||||
path = '.' if path.blank?
|
path = '.' if path.blank?
|
||||||
entries = Entries.new
|
entries = Entries.new
|
||||||
cmd = "#{DARCS_BIN} annotate --repodir #{@url} --xml-output"
|
cmd = "#{DARCS_BIN} annotate --repodir #{@url} --xml-output #{path}"
|
||||||
cmd << " --match \"hash #{identifier}\"" if identifier
|
|
||||||
cmd << " #{path}"
|
|
||||||
shellout(cmd) do |io|
|
shellout(cmd) do |io|
|
||||||
begin
|
begin
|
||||||
doc = REXML::Document.new(io)
|
doc = REXML::Document.new(io)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ module Redmine
|
|||||||
rev = Revision.new({:identifier => changeset[:commit],
|
rev = Revision.new({:identifier => changeset[:commit],
|
||||||
:scmid => changeset[:commit],
|
:scmid => changeset[:commit],
|
||||||
:author => changeset[:author],
|
:author => changeset[:author],
|
||||||
:time => (changeset[:date] ? Time.parse(changeset[:date]) : nil),
|
:time => Time.parse(changeset[:date]),
|
||||||
:message => changeset[:description],
|
:message => changeset[:description],
|
||||||
:paths => files
|
:paths => files
|
||||||
})
|
})
|
||||||
@@ -132,6 +132,14 @@ module Redmine
|
|||||||
entries.sort_by_name
|
entries.sort_by_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
path ||= ''
|
||||||
|
search_path = path.split('/')[0..-2].join('/')
|
||||||
|
entry_name = path.split('/').last
|
||||||
|
e = entries(search_path, identifier)
|
||||||
|
e ? e.detect{|entry| entry.name == entry_name} : nil
|
||||||
|
end
|
||||||
|
|
||||||
def revisions(path, identifier_from, identifier_to, options={})
|
def revisions(path, identifier_from, identifier_to, options={})
|
||||||
revisions = Revisions.new
|
revisions = Revisions.new
|
||||||
cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw "
|
cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw "
|
||||||
|
|||||||
@@ -60,6 +60,14 @@ module Redmine
|
|||||||
entries.sort_by_name
|
entries.sort_by_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
path ||= ''
|
||||||
|
search_path = path.split('/')[0..-2].join('/')
|
||||||
|
entry_name = path.split('/').last
|
||||||
|
e = entries(search_path, identifier)
|
||||||
|
e ? e.detect{|entry| entry.name == entry_name} : nil
|
||||||
|
end
|
||||||
|
|
||||||
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
||||||
revisions = Revisions.new
|
revisions = Revisions.new
|
||||||
cmd = "#{HG_BIN} -v --encoding utf8 -R #{target('')} log"
|
cmd = "#{HG_BIN} -v --encoding utf8 -R #{target('')} log"
|
||||||
@@ -80,7 +88,13 @@ module Redmine
|
|||||||
value = $2
|
value = $2
|
||||||
if parsing_descr && line_feeds > 1
|
if parsing_descr && line_feeds > 1
|
||||||
parsing_descr = false
|
parsing_descr = false
|
||||||
revisions << build_revision_from_changeset(changeset)
|
revisions << Revision.new({:identifier => changeset[:changeset].split(':').first.to_i,
|
||||||
|
:scmid => changeset[:changeset].split(':').last,
|
||||||
|
:author => changeset[:user],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => changeset[:files].to_s.split.collect{|path| {:action => 'X', :path => "/#{path}"}}
|
||||||
|
})
|
||||||
changeset = {}
|
changeset = {}
|
||||||
end
|
end
|
||||||
if !parsing_descr
|
if !parsing_descr
|
||||||
@@ -97,8 +111,13 @@ module Redmine
|
|||||||
line_feeds += 1 if line.chomp.empty?
|
line_feeds += 1 if line.chomp.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Add the last changeset if there is one left
|
revisions << Revision.new({:identifier => changeset[:changeset].split(':').first.to_i,
|
||||||
revisions << build_revision_from_changeset(changeset) if changeset[:date]
|
:scmid => changeset[:changeset].split(':').last,
|
||||||
|
:author => changeset[:user],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => changeset[:files].to_s.split.collect{|path| {:action => 'X', :path => "/#{path}"}}
|
||||||
|
})
|
||||||
end
|
end
|
||||||
return nil if $? && $?.exitstatus != 0
|
return nil if $? && $?.exitstatus != 0
|
||||||
revisions
|
revisions
|
||||||
@@ -152,47 +171,6 @@ module Redmine
|
|||||||
return nil if $? && $?.exitstatus != 0
|
return nil if $? && $?.exitstatus != 0
|
||||||
blame
|
blame
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Builds a revision objet from the changeset returned by hg command
|
|
||||||
def build_revision_from_changeset(changeset)
|
|
||||||
rev_id = changeset[:changeset].to_s.split(':').first.to_i
|
|
||||||
|
|
||||||
# Changes
|
|
||||||
paths = (rev_id == 0) ?
|
|
||||||
# Can't get changes for revision 0 with hg status
|
|
||||||
changeset[:files].to_s.split.collect{|path| {:action => 'A', :path => "/#{path}"}} :
|
|
||||||
status(rev_id)
|
|
||||||
|
|
||||||
Revision.new({:identifier => rev_id,
|
|
||||||
:scmid => changeset[:changeset].to_s.split(':').last,
|
|
||||||
:author => changeset[:user],
|
|
||||||
:time => Time.parse(changeset[:date]),
|
|
||||||
:message => changeset[:description],
|
|
||||||
:paths => paths
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the file changes for a given revision
|
|
||||||
def status(rev_id)
|
|
||||||
cmd = "#{HG_BIN} -R #{target('')} status --rev #{rev_id.to_i - 1}:#{rev_id.to_i}"
|
|
||||||
result = []
|
|
||||||
shellout(cmd) do |io|
|
|
||||||
io.each_line do |line|
|
|
||||||
action, file = line.chomp.split
|
|
||||||
next unless action && file
|
|
||||||
file.gsub!("\\", "/")
|
|
||||||
case action
|
|
||||||
when 'R'
|
|
||||||
result << { :action => 'D' , :path => "/#{file}" }
|
|
||||||
else
|
|
||||||
result << { :action => action, :path => "/#{file}" }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -51,11 +51,18 @@ module Redmine
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the entry identified by path and revision identifier
|
||||||
|
# or nil if entry doesn't exist in the repository
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
e = entries(path, identifier)
|
||||||
|
e ? e.first : nil
|
||||||
|
end
|
||||||
|
|
||||||
# Returns an Entries collection
|
# Returns an Entries collection
|
||||||
# or nil if the given path doesn't exist in the repository
|
# or nil if the given path doesn't exist in the repository
|
||||||
def entries(path=nil, identifier=nil)
|
def entries(path=nil, identifier=nil)
|
||||||
path ||= ''
|
path ||= ''
|
||||||
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
|
identifier = 'HEAD' unless identifier and identifier > 0
|
||||||
entries = Entries.new
|
entries = Entries.new
|
||||||
cmd = "#{SVN_BIN} list --xml #{target(path)}@#{identifier}"
|
cmd = "#{SVN_BIN} list --xml #{target(path)}@#{identifier}"
|
||||||
cmd << credentials_string
|
cmd << credentials_string
|
||||||
@@ -87,8 +94,8 @@ module Redmine
|
|||||||
|
|
||||||
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
||||||
path ||= ''
|
path ||= ''
|
||||||
identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD"
|
identifier_from = 'HEAD' unless identifier_from and identifier_from.to_i > 0
|
||||||
identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1
|
identifier_to = 1 unless identifier_to and identifier_to.to_i > 0
|
||||||
revisions = Revisions.new
|
revisions = Revisions.new
|
||||||
cmd = "#{SVN_BIN} log --xml -r #{identifier_from}:#{identifier_to}"
|
cmd = "#{SVN_BIN} log --xml -r #{identifier_from}:#{identifier_to}"
|
||||||
cmd << credentials_string
|
cmd << credentials_string
|
||||||
@@ -124,9 +131,11 @@ module Redmine
|
|||||||
|
|
||||||
def diff(path, identifier_from, identifier_to=nil, type="inline")
|
def diff(path, identifier_from, identifier_to=nil, type="inline")
|
||||||
path ||= ''
|
path ||= ''
|
||||||
identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : ''
|
if identifier_to and identifier_to.to_i > 0
|
||||||
identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1)
|
identifier_to = identifier_to.to_i
|
||||||
|
else
|
||||||
|
identifier_to = identifier_from.to_i - 1
|
||||||
|
end
|
||||||
cmd = "#{SVN_BIN} diff -r "
|
cmd = "#{SVN_BIN} diff -r "
|
||||||
cmd << "#{identifier_to}:"
|
cmd << "#{identifier_to}:"
|
||||||
cmd << "#{identifier_from}"
|
cmd << "#{identifier_from}"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 0
|
MAJOR = 0
|
||||||
MINOR = 7
|
MINOR = 7
|
||||||
TINY = 0
|
TINY = 'devel'
|
||||||
|
|
||||||
def self.revision
|
def self.revision
|
||||||
revision = nil
|
revision = nil
|
||||||
|
|||||||
@@ -77,24 +77,21 @@ module Redmine
|
|||||||
content_tag('dl', out)
|
content_tag('dl', out)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Include a wiki page. Example:\n\n !{{include(Foo)}}\n\nor to include a page of a specific project wiki:\n\n !{{include(projectname:Foo)}}"
|
desc "Include a wiki page. Example:\n\n !{{include(Foo)}}"
|
||||||
macro :include do |obj, args|
|
macro :include do |obj, args|
|
||||||
project = @project
|
if @project && !@project.wiki.nil?
|
||||||
title = args.first.to_s
|
page = @project.wiki.find_page(args.first)
|
||||||
if title =~ %r{^([^\:]+)\:(.*)$}
|
if page && page.content
|
||||||
project_identifier, title = $1, $2
|
@included_wiki_pages ||= []
|
||||||
project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
|
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
|
||||||
|
@included_wiki_pages << page.title
|
||||||
|
out = textilizable(page.content, :text)
|
||||||
|
@included_wiki_pages.pop
|
||||||
|
out
|
||||||
|
else
|
||||||
|
raise "Page #{args.first} doesn't exist"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
raise 'Unknow project' unless project && User.current.allowed_to?(:view_wiki_pages, project)
|
|
||||||
raise 'No wiki for this project' unless !project.wiki.nil?
|
|
||||||
page = project.wiki.find_page(title)
|
|
||||||
raise "Page #{args.first} doesn't exist" unless page && page.content
|
|
||||||
@included_wiki_pages ||= []
|
|
||||||
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
|
|
||||||
@included_wiki_pages << page.title
|
|
||||||
out = textilizable(page.content, :text, :attachments => page.attachments)
|
|
||||||
@included_wiki_pages.pop
|
|
||||||
out
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 995 B After Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 512 B |
|
Before Width: | Height: | Size: 557 B |
|
Before Width: | Height: | Size: 458 B |
|
Before Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 658 B |
|
Before Width: | Height: | Size: 500 B |
|
Before Width: | Height: | Size: 598 B |
|
Before Width: | Height: | Size: 731 B |
|
Before Width: | Height: | Size: 626 B |
@@ -93,55 +93,14 @@ ContextMenu.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
showMenu: function(e) {
|
showMenu: function(e) {
|
||||||
var mouse_x = Event.pointerX(e);
|
$('context-menu').style['left'] = (Event.pointerX(e) + 'px');
|
||||||
var mouse_y = Event.pointerY(e);
|
$('context-menu').style['top'] = (Event.pointerY(e) + 'px');
|
||||||
var render_x = mouse_x;
|
Element.update('context-menu', '');
|
||||||
var render_y = mouse_y;
|
new Ajax.Updater({success:'context-menu'}, this.url,
|
||||||
var dims;
|
|
||||||
var menu_width;
|
|
||||||
var menu_height;
|
|
||||||
var window_width;
|
|
||||||
var window_height;
|
|
||||||
var max_width;
|
|
||||||
var max_height;
|
|
||||||
|
|
||||||
$('context-menu').style['left'] = (render_x + 'px');
|
|
||||||
$('context-menu').style['top'] = (render_y + 'px');
|
|
||||||
Element.update('context-menu', '');
|
|
||||||
|
|
||||||
new Ajax.Updater({success:'context-menu'}, this.url,
|
|
||||||
{asynchronous:true,
|
{asynchronous:true,
|
||||||
evalScripts:true,
|
evalScripts:true,
|
||||||
parameters:Form.serialize(Event.findElement(e, 'form')),
|
parameters:Form.serialize(Event.findElement(e, 'form')),
|
||||||
onComplete:function(request){
|
onComplete:function(request){
|
||||||
dims = $('context-menu').getDimensions();
|
|
||||||
menu_width = dims.width;
|
|
||||||
menu_height = dims.height;
|
|
||||||
max_width = mouse_x + 2*menu_width;
|
|
||||||
max_height = mouse_y + menu_height;
|
|
||||||
|
|
||||||
var ws = window_size();
|
|
||||||
window_width = ws.width;
|
|
||||||
window_height = ws.height;
|
|
||||||
|
|
||||||
/* display the menu above and/or to the left of the click if needed */
|
|
||||||
if (max_width > window_width) {
|
|
||||||
render_x -= menu_width;
|
|
||||||
$('context-menu').addClassName('reverse-x');
|
|
||||||
} else {
|
|
||||||
$('context-menu').removeClassName('reverse-x');
|
|
||||||
}
|
|
||||||
if (max_height > window_height) {
|
|
||||||
render_y -= menu_height;
|
|
||||||
$('context-menu').addClassName('reverse-y');
|
|
||||||
} else {
|
|
||||||
$('context-menu').removeClassName('reverse-y');
|
|
||||||
}
|
|
||||||
if (render_x <= 0) render_x = 1;
|
|
||||||
if (render_y <= 0) render_y = 1;
|
|
||||||
$('context-menu').style['left'] = (render_x + 'px');
|
|
||||||
$('context-menu').style['top'] = (render_y + 'px');
|
|
||||||
|
|
||||||
Effect.Appear('context-menu', {duration: 0.20});
|
Effect.Appear('context-menu', {duration: 0.20});
|
||||||
if (window.parseStylesheets) { window.parseStylesheets(); } // IE
|
if (window.parseStylesheets) { window.parseStylesheets(); } // IE
|
||||||
}})
|
}})
|
||||||
@@ -200,19 +159,3 @@ function toggleIssuesSelection(el) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function window_size() {
|
|
||||||
var w;
|
|
||||||
var h;
|
|
||||||
if (window.innerWidth) {
|
|
||||||
w = window.innerWidth;
|
|
||||||
h = window.innerHeight;
|
|
||||||
} else if (document.documentElement) {
|
|
||||||
w = document.documentElement.clientWidth;
|
|
||||||
h = document.documentElement.clientHeight;
|
|
||||||
} else {
|
|
||||||
w = document.body.clientWidth;
|
|
||||||
h = document.body.clientHeight;
|
|
||||||
}
|
|
||||||
return {width: w, height: h};
|
|
||||||
}
|
|
||||||
|
|||||||