Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87e8b02828 | ||
|
|
342b3302cf | ||
|
|
32e3d6e1b1 | ||
|
|
8d2d46bd8e | ||
|
|
7f03576b8d | ||
|
|
e757600b39 | ||
|
|
68560c13fe | ||
|
|
309f7b75fd | ||
|
|
dbb93692ff | ||
|
|
5f6289d6be | ||
|
|
081ee54bee | ||
|
|
1d0fb85179 | ||
|
|
887e7f8647 | ||
|
|
df05edff3d | ||
|
|
67057ea3e9 | ||
|
|
381e7156c2 | ||
|
|
f9ee57f2c1 | ||
|
|
fc13aef5bb | ||
|
|
4973350243 | ||
|
|
fcbb8acdb7 | ||
|
|
d79258f17f | ||
|
|
c4736ed42b | ||
|
|
47fb2eb998 | ||
|
|
e9813791cb | ||
|
|
5f23ebc31c | ||
|
|
b88c95b0fb | ||
|
|
93d8f99884 | ||
|
|
07edb10518 | ||
|
|
0512a30368 | ||
|
|
bc945d78a6 | ||
|
|
8cd0626075 | ||
|
|
035bd65a5a | ||
|
|
955d2b134d | ||
|
|
743b55a3f9 | ||
|
|
881595f7f0 | ||
|
|
7f51bab0fc | ||
|
|
84d5092508 | ||
|
|
352d177f7e | ||
|
|
821ea2a757 | ||
|
|
7cd7b1bd8b | ||
|
|
cf139e25a7 | ||
|
|
8b09f5d27d | ||
|
|
d138df5241 |
@@ -1,6 +1,6 @@
|
|||||||
source 'http://rubygems.org'
|
source 'http://rubygems.org'
|
||||||
|
|
||||||
gem 'rails', '3.2.3'
|
gem 'rails', '3.2.6'
|
||||||
gem 'prototype-rails', '3.2.1'
|
gem 'prototype-rails', '3.2.1'
|
||||||
gem "i18n", "~> 0.6.0"
|
gem "i18n", "~> 0.6.0"
|
||||||
gem "coderay", "~> 1.0.6"
|
gem "coderay", "~> 1.0.6"
|
||||||
@@ -69,6 +69,7 @@ end
|
|||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem "rdoc", ">= 2.4.2"
|
gem "rdoc", ">= 2.4.2"
|
||||||
|
gem "yard"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class ActivitiesController < ApplicationController
|
|||||||
if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
|
if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
@events_by_day = events.group_by(&:event_date)
|
@events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
|
||||||
render :layout => false if request.xhr?
|
render :layout => false if request.xhr?
|
||||||
}
|
}
|
||||||
format.atom {
|
format.atom {
|
||||||
|
|||||||
@@ -445,9 +445,9 @@ class ApplicationController < ActionController::Base
|
|||||||
# Returns the API key present in the request
|
# Returns the API key present in the request
|
||||||
def api_key_from_request
|
def api_key_from_request
|
||||||
if params[:key].present?
|
if params[:key].present?
|
||||||
params[:key]
|
params[:key].to_s
|
||||||
elsif request.headers["X-Redmine-API-Key"].present?
|
elsif request.headers["X-Redmine-API-Key"].present?
|
||||||
request.headers["X-Redmine-API-Key"]
|
request.headers["X-Redmine-API-Key"].to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ class BoardsController < ApplicationController
|
|||||||
|
|
||||||
@topic_count = @board.topics.count
|
@topic_count = @board.topics.count
|
||||||
@topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
|
@topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
|
||||||
@topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '),
|
@topics = @board.topics.reorder("#{Message.table_name}.sticky DESC").order(sort_clause).all(
|
||||||
:include => [:author, {:last_reply => :author}],
|
:include => [:author, {:last_reply => :author}],
|
||||||
:limit => @topic_pages.items_per_page,
|
:limit => @topic_pages.items_per_page,
|
||||||
:offset => @topic_pages.current.offset
|
:offset => @topic_pages.current.offset)
|
||||||
@message = Message.new(:board => @board)
|
@message = Message.new(:board => @board)
|
||||||
render :action => 'show', :layout => !request.xhr?
|
render :action => 'show', :layout => !request.xhr?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
class TimelogController < ApplicationController
|
class TimelogController < ApplicationController
|
||||||
menu_item :issues
|
menu_item :issues
|
||||||
|
|
||||||
before_filter :find_project, :only => [:create]
|
before_filter :find_project_for_new_time_entry, :only => [:create]
|
||||||
before_filter :find_time_entry, :only => [:show, :edit, :update]
|
before_filter :find_time_entry, :only => [:show, :edit, :update]
|
||||||
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
|
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
|
||||||
before_filter :authorize, :except => [:new, :index, :report]
|
before_filter :authorize, :except => [:new, :index, :report]
|
||||||
|
|
||||||
before_filter :find_optional_project, :only => [:new, :index, :report]
|
before_filter :find_optional_project, :only => [:index, :report]
|
||||||
|
before_filter :find_optional_project_for_new_time_entry, :only => [:new]
|
||||||
before_filter :authorize_global, :only => [:new, :index, :report]
|
before_filter :authorize_global, :only => [:new, :index, :report]
|
||||||
|
|
||||||
accept_rss_auth :index
|
accept_rss_auth :index
|
||||||
@@ -38,7 +39,7 @@ class TimelogController < ApplicationController
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
sort_init 'spent_on', 'desc'
|
sort_init 'spent_on', 'desc'
|
||||||
sort_update 'spent_on' => 'spent_on',
|
sort_update 'spent_on' => ['spent_on', "#{TimeEntry.table_name}.created_on"],
|
||||||
'user' => 'user_id',
|
'user' => 'user_id',
|
||||||
'activity' => 'activity_id',
|
'activity' => 'activity_id',
|
||||||
'project' => "#{Project.table_name}.name",
|
'project' => "#{Project.table_name}.name",
|
||||||
@@ -133,9 +134,13 @@ class TimelogController < ApplicationController
|
|||||||
flash[:notice] = l(:notice_successful_create)
|
flash[:notice] = l(:notice_successful_create)
|
||||||
if params[:continue]
|
if params[:continue]
|
||||||
if params[:project_id]
|
if params[:project_id]
|
||||||
redirect_to :action => 'new', :project_id => @time_entry.project, :issue_id => @time_entry.issue, :back_url => params[:back_url]
|
redirect_to :action => 'new', :project_id => @time_entry.project, :issue_id => @time_entry.issue,
|
||||||
|
:time_entry => {:issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
|
||||||
|
:back_url => params[:back_url]
|
||||||
else
|
else
|
||||||
redirect_to :action => 'new', :back_url => params[:back_url]
|
redirect_to :action => 'new',
|
||||||
|
:time_entry => {:project_id => @time_entry.project_id, :issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
|
||||||
|
:back_url => params[:back_url]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
redirect_back_or_default :action => 'index', :project_id => @time_entry.project
|
||||||
@@ -258,7 +263,7 @@ private
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_project
|
def find_optional_project_for_new_time_entry
|
||||||
if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
|
if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
|
||||||
@project = Project.find(project_id)
|
@project = Project.find(project_id)
|
||||||
end
|
end
|
||||||
@@ -266,14 +271,17 @@ private
|
|||||||
@issue = Issue.find(issue_id)
|
@issue = Issue.find(issue_id)
|
||||||
@project ||= @issue.project
|
@project ||= @issue.project
|
||||||
end
|
end
|
||||||
if @project.nil?
|
|
||||||
render_404
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_project_for_new_time_entry
|
||||||
|
find_optional_project_for_new_time_entry
|
||||||
|
if @project.nil?
|
||||||
|
render_404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def find_optional_project
|
def find_optional_project
|
||||||
if !params[:issue_id].blank?
|
if !params[:issue_id].blank?
|
||||||
@issue = Issue.find(params[:issue_id])
|
@issue = Issue.find(params[:issue_id])
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def format_activity_day(date)
|
def format_activity_day(date)
|
||||||
date == Date.today ? l(:label_today).titleize : format_date(date)
|
date == User.current.today ? l(:label_today).titleize : format_date(date)
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_activity_description(text)
|
def format_activity_description(text)
|
||||||
@@ -352,7 +352,7 @@ module ApplicationHelper
|
|||||||
def time_tag(time)
|
def time_tag(time)
|
||||||
text = distance_of_time_in_words(Time.now, time)
|
text = distance_of_time_in_words(Time.now, time)
|
||||||
if @project
|
if @project
|
||||||
link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time))
|
link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)}, :title => format_time(time))
|
||||||
else
|
else
|
||||||
content_tag('acronym', text, :title => format_time(time))
|
content_tag('acronym', text, :title => format_time(time))
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -46,17 +46,17 @@ module RepositoriesHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_changeset_changes
|
def render_changeset_changes
|
||||||
changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change|
|
changes = @changeset.filechanges.find(:all, :limit => 1000, :order => 'path').collect do |change|
|
||||||
case change.action
|
case change.action
|
||||||
when 'A'
|
when 'A'
|
||||||
# Detects moved/copied files
|
# Detects moved/copied files
|
||||||
if !change.from_path.blank?
|
if !change.from_path.blank?
|
||||||
change.action =
|
change.action =
|
||||||
@changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
|
@changeset.filechanges.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
|
||||||
end
|
end
|
||||||
change
|
change
|
||||||
when 'D'
|
when 'D'
|
||||||
@changeset.changes.detect {|c| c.from_path == change.path} ? nil : change
|
@changeset.filechanges.detect {|c| c.from_path == change.path} ? nil : change
|
||||||
else
|
else
|
||||||
change
|
change
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -45,23 +45,27 @@ module WatchersHelper
|
|||||||
# Returns a comma separated list of users watching the given object
|
# Returns a comma separated list of users watching the given object
|
||||||
def watchers_list(object)
|
def watchers_list(object)
|
||||||
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
|
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
|
||||||
|
content = ''.html_safe
|
||||||
lis = object.watcher_users.collect do |user|
|
lis = object.watcher_users.collect do |user|
|
||||||
s = avatar(user, :size => "16").to_s + link_to_user(user, :class => 'user').to_s
|
s = ''.html_safe
|
||||||
|
s << avatar(user, :size => "16").to_s
|
||||||
|
s << link_to_user(user, :class => 'user')
|
||||||
if remove_allowed
|
if remove_allowed
|
||||||
url = {:controller => 'watchers',
|
url = {:controller => 'watchers',
|
||||||
:action => 'destroy',
|
:action => 'destroy',
|
||||||
:object_type => object.class.to_s.underscore,
|
:object_type => object.class.to_s.underscore,
|
||||||
:object_id => object.id,
|
:object_id => object.id,
|
||||||
:user_id => user}
|
:user_id => user}
|
||||||
s += ' ' + link_to_remote(image_tag('delete.png'),
|
s << ' '
|
||||||
|
s << link_to_remote(image_tag('delete.png'),
|
||||||
{:url => url},
|
{:url => url},
|
||||||
:href => url_for(url),
|
:href => url_for(url),
|
||||||
:style => "vertical-align: middle",
|
:style => "vertical-align: middle",
|
||||||
:class => "delete")
|
:class => "delete")
|
||||||
end
|
end
|
||||||
content_tag :li, s.html_safe
|
content << content_tag('li', s)
|
||||||
end
|
end
|
||||||
(lis.empty? ? "" : "<ul>#{ lis.join("\n") }</ul>").html_safe
|
content.present? ? content_tag('ul', content) : content
|
||||||
end
|
end
|
||||||
|
|
||||||
def watchers_checkboxes(object, users, checked=nil)
|
def watchers_checkboxes(object, users, checked=nil)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ require 'iconv'
|
|||||||
class Changeset < ActiveRecord::Base
|
class Changeset < ActiveRecord::Base
|
||||||
belongs_to :repository
|
belongs_to :repository
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :changes, :dependent => :delete_all
|
has_many :filechanges, :class_name => 'Change', :dependent => :delete_all
|
||||||
has_and_belongs_to_many :issues
|
has_and_belongs_to_many :issues
|
||||||
has_and_belongs_to_many :parents,
|
has_and_belongs_to_many :parents,
|
||||||
:class_name => "Changeset",
|
:class_name => "Changeset",
|
||||||
|
|||||||
+30
-3
@@ -75,7 +75,7 @@ class Issue < ActiveRecord::Base
|
|||||||
:conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
|
:conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
|
||||||
|
|
||||||
before_create :default_assign
|
before_create :default_assign
|
||||||
before_save :close_duplicates, :update_done_ratio_from_issue_status
|
before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change
|
||||||
after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?}
|
after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?}
|
||||||
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal
|
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal
|
||||||
after_destroy :update_parent_attributes
|
after_destroy :update_parent_attributes
|
||||||
@@ -124,6 +124,28 @@ class Issue < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# AR#Persistence#destroy would raise and RecordNotFound exception
|
||||||
|
# if the issue was already deleted or updated (non matching lock_version).
|
||||||
|
# This is a problem when bulk deleting issues or deleting a project
|
||||||
|
# (because an issue may already be deleted if its parent was deleted
|
||||||
|
# first).
|
||||||
|
# The issue is reloaded by the nested_set before being deleted so
|
||||||
|
# the lock_version condition should not be an issue but we handle it.
|
||||||
|
def destroy
|
||||||
|
super
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
# Stale or already deleted
|
||||||
|
begin
|
||||||
|
reload
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
# The issue was actually already deleted
|
||||||
|
@destroyed = true
|
||||||
|
return freeze
|
||||||
|
end
|
||||||
|
# The issue was stale, retry to destroy
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
||||||
def available_custom_fields
|
def available_custom_fields
|
||||||
(project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : []
|
(project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : []
|
||||||
@@ -432,8 +454,6 @@ class Issue < ActiveRecord::Base
|
|||||||
@custom_values_before_change = {}
|
@custom_values_before_change = {}
|
||||||
self.custom_field_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
|
self.custom_field_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
|
||||||
end
|
end
|
||||||
# Make sure updated_on is updated when adding a note.
|
|
||||||
updated_on_will_change!
|
|
||||||
@current_journal
|
@current_journal
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -994,6 +1014,13 @@ class Issue < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Make sure updated_on is updated when adding a note
|
||||||
|
def force_updated_on_change
|
||||||
|
if @current_journal
|
||||||
|
self.updated_on = current_time_from_proper_timezone
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Saves the changes in a Journal
|
# Saves the changes in a Journal
|
||||||
# Called after_save
|
# Called after_save
|
||||||
def create_journal
|
def create_journal
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ class MailHandler < ActionMailer::Base
|
|||||||
issue = Issue.new(:author => user, :project => project)
|
issue = Issue.new(:author => user, :project => project)
|
||||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||||
issue.subject = email.subject.to_s.chomp[0,255]
|
issue.subject = cleaned_up_subject
|
||||||
if issue.subject.blank?
|
if issue.subject.blank?
|
||||||
issue.subject = '(no subject)'
|
issue.subject = '(no subject)'
|
||||||
end
|
end
|
||||||
@@ -223,7 +223,7 @@ class MailHandler < ActionMailer::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
if !message.locked?
|
if !message.locked?
|
||||||
reply = Message.new(:subject => email.subject.gsub(%r{^.*msg\d+\]}, '').strip,
|
reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
|
||||||
:content => cleaned_up_text_body)
|
:content => cleaned_up_text_body)
|
||||||
reply.author = user
|
reply.author = user
|
||||||
reply.board = message.board
|
reply.board = message.board
|
||||||
@@ -364,6 +364,23 @@ class MailHandler < ActionMailer::Base
|
|||||||
cleanup_body(plain_text_body)
|
cleanup_body(plain_text_body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cleaned_up_subject
|
||||||
|
subject = email.subject.to_s
|
||||||
|
unless subject.respond_to?(:encoding)
|
||||||
|
# try to reencode to utf8 manually with ruby1.8
|
||||||
|
begin
|
||||||
|
if h = email.header[:subject]
|
||||||
|
if m = h.value.match(/^=\?([^\?]+)\?/)
|
||||||
|
subject = Redmine::CodesetUtil.to_utf8(subject, m[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
# nop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
subject.strip[0,255]
|
||||||
|
end
|
||||||
|
|
||||||
def self.full_sanitizer
|
def self.full_sanitizer
|
||||||
@full_sanitizer ||= HTML::FullSanitizer.new
|
@full_sanitizer ||= HTML::FullSanitizer.new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ class Project < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def identifier_frozen?
|
def identifier_frozen?
|
||||||
errors[:identifier].nil? && !(new_record? || identifier.blank?)
|
errors[:identifier].blank? && !(new_record? || identifier.blank?)
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns latest created projects
|
# returns latest created projects
|
||||||
|
|||||||
+10
-4
@@ -848,12 +848,18 @@ class Query < ActiveRecord::Base
|
|||||||
s = []
|
s = []
|
||||||
if from
|
if from
|
||||||
from_yesterday = from - 1
|
from_yesterday = from - 1
|
||||||
from_yesterday_utc = Time.gm(from_yesterday.year, from_yesterday.month, from_yesterday.day)
|
from_yesterday_time = Time.local(from_yesterday.year, from_yesterday.month, from_yesterday.day)
|
||||||
s << ("#{table}.#{field} > '%s'" % [connection.quoted_date(from_yesterday_utc.end_of_day)])
|
if self.class.default_timezone == :utc
|
||||||
|
from_yesterday_time = from_yesterday_time.utc
|
||||||
|
end
|
||||||
|
s << ("#{table}.#{field} > '%s'" % [connection.quoted_date(from_yesterday_time.end_of_day)])
|
||||||
end
|
end
|
||||||
if to
|
if to
|
||||||
to_utc = Time.gm(to.year, to.month, to.day)
|
to_time = Time.local(to.year, to.month, to.day)
|
||||||
s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to_utc.end_of_day)])
|
if self.class.default_timezone == :utc
|
||||||
|
to_time = to_time.utc
|
||||||
|
end
|
||||||
|
s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to_time.end_of_day)])
|
||||||
end
|
end
|
||||||
s.join(' AND ')
|
s.join(' AND ')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class Repository < ActiveRecord::Base
|
|||||||
|
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
|
has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
|
||||||
has_many :changes, :through => :changesets
|
has_many :filechanges, :class_name => 'Change', :through => :changesets
|
||||||
|
|
||||||
serialize :extra_info
|
serialize :extra_info
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ class Repository < ActiveRecord::Base
|
|||||||
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
|
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
|
||||||
:limit => limit)
|
:limit => limit)
|
||||||
else
|
else
|
||||||
changes.find(
|
filechanges.find(
|
||||||
:all,
|
:all,
|
||||||
:include => {:changeset => :user},
|
:include => {:changeset => :user},
|
||||||
:conditions => ["path = ?", path.with_leading_slash],
|
:conditions => ["path = ?", path.with_leading_slash],
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class Repository::Cvs < Repository
|
|||||||
if entries
|
if entries
|
||||||
entries.each() do |entry|
|
entries.each() do |entry|
|
||||||
if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
|
if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
|
||||||
change=changes.find_by_revision_and_path(
|
change = filechanges.find_by_revision_and_path(
|
||||||
entry.lastrev.revision,
|
entry.lastrev.revision,
|
||||||
scm.with_leading_slash(entry.path) )
|
scm.with_leading_slash(entry.path) )
|
||||||
if change
|
if change
|
||||||
@@ -94,7 +94,7 @@ class Repository::Cvs < Repository
|
|||||||
if rev_to.to_i > 0
|
if rev_to.to_i > 0
|
||||||
changeset_to = changesets.find_by_revision(rev_to)
|
changeset_to = changesets.find_by_revision(rev_to)
|
||||||
end
|
end
|
||||||
changeset_from.changes.each() do |change_from|
|
changeset_from.filechanges.each() do |change_from|
|
||||||
revision_from = nil
|
revision_from = nil
|
||||||
revision_to = nil
|
revision_to = nil
|
||||||
if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
|
if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
|
||||||
@@ -102,7 +102,7 @@ class Repository::Cvs < Repository
|
|||||||
end
|
end
|
||||||
if revision_from
|
if revision_from
|
||||||
if changeset_to
|
if changeset_to
|
||||||
changeset_to.changes.each() do |change_to|
|
changeset_to.filechanges.each() do |change_to|
|
||||||
revision_to = change_to.revision if change_to.path == change_from.path
|
revision_to = change_to.revision if change_to.path == change_from.path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -133,7 +133,7 @@ class Repository::Cvs < Repository
|
|||||||
# only add the change to the database, if it doen't exists. the cvs log
|
# only add the change to the database, if it doen't exists. the cvs log
|
||||||
# is not exclusive at all.
|
# is not exclusive at all.
|
||||||
tmp_time = revision.time.clone
|
tmp_time = revision.time.clone
|
||||||
unless changes.find_by_path_and_revision(
|
unless filechanges.find_by_path_and_revision(
|
||||||
scm.with_leading_slash(revision.paths[0][:path]),
|
scm.with_leading_slash(revision.paths[0][:path]),
|
||||||
revision.paths[0][:revision]
|
revision.paths[0][:revision]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class Repository::Darcs < Repository
|
|||||||
return nil if patch_from.nil?
|
return nil if patch_from.nil?
|
||||||
patch_to = changesets.find_by_revision(rev_to) if rev_to
|
patch_to = changesets.find_by_revision(rev_to) if rev_to
|
||||||
if path.blank?
|
if path.blank?
|
||||||
path = patch_from.changes.collect{|change| change.path}.join(' ')
|
path = patch_from.filechanges.collect{|change| change.path}.join(' ')
|
||||||
end
|
end
|
||||||
patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
|
patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class TimeEntry < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values'
|
safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values', 'custom_fields'
|
||||||
|
|
||||||
def initialize(attributes=nil, *args)
|
def initialize(attributes=nil, *args)
|
||||||
super
|
super
|
||||||
|
|||||||
+16
-4
@@ -130,8 +130,11 @@ class User < Principal
|
|||||||
|
|
||||||
# Returns the user that matches provided login and password, or nil
|
# Returns the user that matches provided login and password, or nil
|
||||||
def self.try_to_login(login, password)
|
def self.try_to_login(login, password)
|
||||||
|
login = login.to_s
|
||||||
|
password = password.to_s
|
||||||
|
|
||||||
# Make sure no one can sign in with an empty password
|
# Make sure no one can sign in with an empty password
|
||||||
return nil if password.to_s.empty?
|
return nil if password.empty?
|
||||||
user = find_by_login(login)
|
user = find_by_login(login)
|
||||||
if user
|
if user
|
||||||
# user is already in local database
|
# user is already in local database
|
||||||
@@ -164,7 +167,7 @@ class User < Principal
|
|||||||
|
|
||||||
# Returns the user who matches the given autologin +key+ or nil
|
# Returns the user who matches the given autologin +key+ or nil
|
||||||
def self.try_to_autologin(key)
|
def self.try_to_autologin(key)
|
||||||
tokens = Token.find_all_by_action_and_value('autologin', key)
|
tokens = Token.find_all_by_action_and_value('autologin', key.to_s)
|
||||||
# Make sure there's only 1 token that matches the key
|
# Make sure there's only 1 token that matches the key
|
||||||
if tokens.size == 1
|
if tokens.size == 1
|
||||||
token = tokens.first
|
token = tokens.first
|
||||||
@@ -338,12 +341,12 @@ class User < Principal
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.find_by_rss_key(key)
|
def self.find_by_rss_key(key)
|
||||||
token = Token.find_by_value(key)
|
token = Token.find_by_action_and_value('feeds', key.to_s)
|
||||||
token && token.user.active? ? token.user : nil
|
token && token.user.active? ? token.user : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_by_api_key(key)
|
def self.find_by_api_key(key)
|
||||||
token = Token.find_by_action_and_value('api', key)
|
token = Token.find_by_action_and_value('api', key.to_s)
|
||||||
token && token.user.active? ? token.user : nil
|
token && token.user.active? ? token.user : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -370,6 +373,15 @@ class User < Principal
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the day of +time+ according to user's time zone
|
||||||
|
def time_to_date(time)
|
||||||
|
if time_zone.nil?
|
||||||
|
time.to_date
|
||||||
|
else
|
||||||
|
time.in_time_zone(time_zone).to_date
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def logged?
|
def logged?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class WikiPage < ActiveRecord::Base
|
|||||||
if time = read_attribute(:updated_on)
|
if time = read_attribute(:updated_on)
|
||||||
# content updated_on was eager loaded with the page
|
# content updated_on was eager loaded with the page
|
||||||
begin
|
begin
|
||||||
@updated_on = Time.zone ? Time.zone.parse(time.to_s) : Time.parse(time.to_s)
|
@updated_on = (self.class.default_timezone == :utc ? Time.parse(time.to_s).utc : Time.parse(time.to_s).localtime)
|
||||||
rescue
|
rescue
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)) %></h2>
|
<h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)).html_safe %></h2>
|
||||||
<p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p>
|
<p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p>
|
||||||
|
|
||||||
<div id="activity">
|
<div id="activity">
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
<div class="next-prev-links contextual">
|
<div class="next-prev-links contextual">
|
||||||
<%= link_to_if @prev_issue_id,
|
<%= link_to_if @prev_issue_id,
|
||||||
"\xc2\xab #{l(:label_previous)}",
|
"\xc2\xab #{l(:label_previous)}",
|
||||||
issue_path(@prev_issue_id),
|
(@prev_issue_id ? issue_path(@prev_issue_id) : nil),
|
||||||
:title => "##{@prev_issue_id}" %> |
|
:title => "##{@prev_issue_id}" %> |
|
||||||
<% if @issue_position && @issue_count %>
|
<% if @issue_position && @issue_count %>
|
||||||
<span class="position"><%= l(:label_item_position, :position => @issue_position, :count => @issue_count) %></span> |
|
<span class="position"><%= l(:label_item_position, :position => @issue_position, :count => @issue_count) %></span> |
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= link_to_if @next_issue_id,
|
<%= link_to_if @next_issue_id,
|
||||||
"#{l(:label_next)} \xc2\xbb",
|
"#{l(:label_next)} \xc2\xbb",
|
||||||
issue_path(@next_issue_id),
|
(@next_issue_id ? issue_path(@next_issue_id) : nil),
|
||||||
:title => "##{@next_issue_id}" %>
|
:title => "##{@next_issue_id}" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ entries_by_day = entries.group_by(&:spent_on)
|
|||||||
<% entries_by_day[day].each do |entry| -%>
|
<% entries_by_day[day].each do |entry| -%>
|
||||||
<tr class="time-entry" style="border-bottom: 1px solid #f5f5f5;">
|
<tr class="time-entry" style="border-bottom: 1px solid #f5f5f5;">
|
||||||
<td class="activity"><%=h entry.activity %></td>
|
<td class="activity"><%=h entry.activity %></td>
|
||||||
<td class="subject"><%=h entry.project %> <%= ' - ' + link_to_issue(entry.issue, :truncate => 50) if entry.issue %></td>
|
<td class="subject"><%=h entry.project %> <%= h(' - ') + link_to_issue(entry.issue, :truncate => 50) if entry.issue %></td>
|
||||||
<td class="comments"><%=h entry.comments %></td>
|
<td class="comments"><%=h entry.comments %></td>
|
||||||
<td class="hours"><%= html_hours("%.2f" % entry.hours) %></td>
|
<td class="hours"><%= html_hours("%.2f" % entry.hours) %></td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
|
|||||||
@@ -38,4 +38,4 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p><%= link_to l(:label_version_new), new_project_version_path(@project), :class => 'icon icon-add' if User.current.allowed_to?(:manage_versions, @project) %></p>
|
<p><%= link_to l(:label_version_new), new_project_version_path(@project, :back_url => ''), :class => 'icon icon-add' if User.current.allowed_to?(:manage_versions, @project) %></p>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<%= labelled_remote_form_for @wiki,
|
<%= labelled_remote_form_for @wiki,
|
||||||
:as => :wiki,
|
:as => :wiki,
|
||||||
:url => { :controller => 'wikis', :action => 'edit', :id => @project } do |f| %>
|
:url => { :controller => 'wikis', :action => 'edit', :id => @project }, :method => 'post' do |f| %>
|
||||||
|
|
||||||
<%= error_messages_for 'wiki' %>
|
<%= error_messages_for 'wiki' %>
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<% content_tag 'fieldset', :id => 'columns', :style => (query.has_default_columns? ? 'display:none;' : nil) do %>
|
<%= content_tag 'fieldset', :id => 'columns', :style => (query.has_default_columns? ? 'display:none;' : nil) do %>
|
||||||
<legend><%= l(:field_column_names) %></legend>
|
<legend><%= l(:field_column_names) %></legend>
|
||||||
<%= render :partial => 'queries/columns', :locals => {:query => query}%>
|
<%= render :partial => 'queries/columns', :locals => {:query => query}%>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<h2><%= l(:label_repository) %></h2>
|
<h2><%= l(:label_repository) %></h2>
|
||||||
|
|
||||||
<%= labelled_form_for :repository, @repository, :url => repository_path(@path), :html => {:method => :put} do |f| %>
|
<%= labelled_form_for :repository, @repository, :url => repository_path(@repository), :html => {:method => :put} do |f| %>
|
||||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
:id => @project,
|
:id => @project,
|
||||||
:repository_id => @repository.identifier_param,
|
:repository_id => @repository.identifier_param,
|
||||||
:path => "",
|
:path => "",
|
||||||
:rev => @changeset.identifier) if @changeset.changes.any? %></p>
|
:rev => @changeset.identifier) if @changeset.filechanges.any? %></p>
|
||||||
|
|
||||||
<div class="changeset-changes">
|
<div class="changeset-changes">
|
||||||
<%= render_changeset_changes %>
|
<%= render_changeset_changes %>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<h2><%= l(:label_spent_time) %></h2>
|
<h2><%= l(:label_spent_time) %></h2>
|
||||||
|
|
||||||
<%= labelled_form_for @time_entry, :url => time_entries_path do |f| %>
|
<%= labelled_form_for @time_entry, :url => time_entries_path do |f| %>
|
||||||
|
<%= hidden_field_tag 'project_id', params[:project_id] if params[:project_id] %>
|
||||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||||
<%= submit_tag l(:button_create) %>
|
<%= submit_tag l(:button_create) %>
|
||||||
<%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
|
<%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<%= select_tag 'user[mail_notification]', options_for_select(user_mail_notification_options(@user), @user.mail_notification),
|
<%= select_tag 'user[mail_notification]', options_for_select(user_mail_notification_options(@user), @user.mail_notification),
|
||||||
:onchange => 'if (this.value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
|
:onchange => 'if (this.value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
|
||||||
</p>
|
</p>
|
||||||
<% content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %>
|
<%= content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %>
|
||||||
<p><% @user.projects.each do |project| %>
|
<p><% @user.projects.each do |project| %>
|
||||||
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
|
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
|
||||||
<% end %></p>
|
<% end %></p>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ module RedmineApp
|
|||||||
config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer
|
config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer
|
||||||
|
|
||||||
config.active_record.store_full_sti_class = true
|
config.active_record.store_full_sti_class = true
|
||||||
|
config.active_record.default_timezone = :local
|
||||||
|
|
||||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ module ActionView
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
|
ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
|
||||||
|
|
||||||
require 'mail'
|
require 'mail'
|
||||||
|
|
||||||
|
|||||||
@@ -76,14 +76,14 @@ ar:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ bg:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ bs:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ ca:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ cs:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Bajt"
|
one: "Bajt"
|
||||||
other: "Bajtů"
|
other: "Bajtů"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ da:
|
|||||||
format:
|
format:
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ de:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
@@ -1036,7 +1036,7 @@ de:
|
|||||||
label_copy_attachments: Anhänge Kopieren
|
label_copy_attachments: Anhänge Kopieren
|
||||||
label_item_position: "%{position}/%{count}"
|
label_item_position: "%{position}/%{count}"
|
||||||
label_completed_versions: Abgeschlossene Versionen
|
label_completed_versions: Abgeschlossene Versionen
|
||||||
field_multiple: Mehrer Werte
|
field_multiple: Mehrere Werte
|
||||||
setting_commit_cross_project_ref: Erlauben auf Tickets aller anderen Projekte zu referenzieren
|
setting_commit_cross_project_ref: Erlauben auf Tickets aller anderen Projekte zu referenzieren
|
||||||
text_issue_conflict_resolution_add_notes: Meine Änderungen übernehmen und alle anderen Änderungen verwerfen
|
text_issue_conflict_resolution_add_notes: Meine Änderungen übernehmen und alle anderen Änderungen verwerfen
|
||||||
text_issue_conflict_resolution_overwrite: Meine Änderungen trotzdem übernehmen (vorherige Notizen bleiben erhalten aber manche können überschrieben werden)
|
text_issue_conflict_resolution_overwrite: Meine Änderungen trotzdem übernehmen (vorherige Notizen bleiben erhalten aber manche können überschrieben werden)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ el:
|
|||||||
precision: 3
|
precision: 3
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ en-GB:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ en:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ es:
|
|||||||
# These three are to override number.format and are optional
|
# These three are to override number.format and are optional
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ et:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ eu:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ fa:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ fi:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ fr:
|
|||||||
format: '%n %u'
|
format: '%n %u'
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 2
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ gl:
|
|||||||
format:
|
format:
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ hr:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ id:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ ja:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ ko:
|
|||||||
# These three are to override number.format and are optional
|
# These three are to override number.format and are optional
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ lt:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
# Storage units output formatting.
|
# Storage units output formatting.
|
||||||
# %u is the storage unit, %n is the number (default: 2 MB)
|
# %u is the storage unit, %n is the number (default: 2 MB)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ lv:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: " "
|
delimiter: " "
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ mk:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ mn:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ nl:
|
|||||||
precision: 3
|
precision: 3
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
other: "nesten %{count} år"
|
other: "nesten %{count} år"
|
||||||
number:
|
number:
|
||||||
format:
|
format:
|
||||||
precision: 2
|
precision: 3
|
||||||
separator: "."
|
separator: "."
|
||||||
delimiter: ","
|
delimiter: ","
|
||||||
currency:
|
currency:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ pl:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ pt-BR:
|
|||||||
delimiter: '.'
|
delimiter: '.'
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: '.'
|
delimiter: '.'
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ pt:
|
|||||||
delimiter: ''
|
delimiter: ''
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ''
|
delimiter: ''
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ ro:
|
|||||||
|
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ ru:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 2
|
precision: 3
|
||||||
# Rails 2.2
|
# Rails 2.2
|
||||||
# storage_units: [байт, КБ, МБ, ГБ, ТБ]
|
# storage_units: [байт, КБ, МБ, ГБ, ТБ]
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ sk:
|
|||||||
|
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ sl:
|
|||||||
precision: 3
|
precision: 3
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ sq:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ sr-YU:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ sr:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ sv:
|
|||||||
# These three are to override number.format and are optional
|
# These three are to override number.format and are optional
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
# precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ th:
|
|||||||
precision: 3
|
precision: 3
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ tr:
|
|||||||
format:
|
format:
|
||||||
delimiter: '.'
|
delimiter: '.'
|
||||||
separator: ','
|
separator: ','
|
||||||
precision: 2
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ uk:
|
|||||||
precision: 3
|
precision: 3
|
||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
precision: 1
|
precision: 3
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ vi:
|
|||||||
# These three are to override number.format and are optional
|
# These three are to override number.format and are optional
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
# 下列三個選項設定, 若有設定值將會取代 number.format 成為預設值
|
# 下列三個選項設定, 若有設定值將會取代 number.format 成為預設值
|
||||||
# separator:
|
# separator:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
# 儲存單位輸出格式.
|
# 儲存單位輸出格式.
|
||||||
# %u 是儲存單位, %n 是數值 (預設值: 2 MB)
|
# %u 是儲存單位, %n 是數值 (預設值: 2 MB)
|
||||||
storage_units:
|
storage_units:
|
||||||
|
|||||||
@@ -79,14 +79,14 @@ zh:
|
|||||||
human:
|
human:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
precision: 1
|
precision: 3
|
||||||
storage_units:
|
storage_units:
|
||||||
format: "%n %u"
|
format: "%n %u"
|
||||||
units:
|
units:
|
||||||
byte:
|
byte:
|
||||||
one: "Byte"
|
one: "Byte"
|
||||||
other: "Bytes"
|
other: "Bytes"
|
||||||
kb: "kB"
|
kb: "KB"
|
||||||
mb: "MB"
|
mb: "MB"
|
||||||
gb: "GB"
|
gb: "GB"
|
||||||
tb: "TB"
|
tb: "TB"
|
||||||
|
|||||||
@@ -4,6 +4,54 @@ Redmine - project management software
|
|||||||
Copyright (C) 2006-2012 Jean-Philippe Lang
|
Copyright (C) 2006-2012 Jean-Philippe Lang
|
||||||
http://www.redmine.org/
|
http://www.redmine.org/
|
||||||
|
|
||||||
|
== 2012-06-18 v2.0.3
|
||||||
|
|
||||||
|
* Defect #10688: PDF export from Wiki - Problems with tables
|
||||||
|
* Defect #11061: Cannot choose commit versions to view differences in Git/Mercurial repository view
|
||||||
|
* Defect #11065: E-Mail submitted tickets: German umlauts in 'Subject' get malformed (ruby 1.8)
|
||||||
|
* Defect #11098: Default priorities have the same position and can't be reordered
|
||||||
|
* Defect #11105: <% content_for :header_tags do %> doesn't work inside hook
|
||||||
|
* Defect #11112: REST API - custom fields in POST/PUT ignored for time_entries
|
||||||
|
* Defect #11118: "Maximum file size" displayed on upload forms is incorrect
|
||||||
|
* Defect #11124: Link to user is escaped in activity title
|
||||||
|
* Defect #11133: Wiki-page section edit link can point to incorrect section
|
||||||
|
* Defect #11160: SQL Error on time report if a custom field has multiple values for an entry
|
||||||
|
* Defect #11170: Topics sort order is broken in Redmine 2.x
|
||||||
|
* Defect #11178: Spent time sorted by date-descending order lists same-date entries in physical order (not-reverse)
|
||||||
|
* Defect #11185: Redmine fails to delete a project with parent/child task
|
||||||
|
* Feature #11162: Upgrade to Rails 3.2.6
|
||||||
|
* Patch #11113: Small glitch in German localization
|
||||||
|
|
||||||
|
== 2012-06-05 v2.0.2
|
||||||
|
|
||||||
|
* Defect #11032: Project list is not shown when "For any event on the selected projects only..." is selected on user edit panel
|
||||||
|
* Defect #11038: "Create and continue" should preserve project, issue and activity when logging time
|
||||||
|
* Defect #11046: Redmine.pm does not support "bind as user" ldap authentication
|
||||||
|
* Defect #11051: reposman.rb fails in 1.4.2 because of missing require for rubygems
|
||||||
|
* Defect #11085: Wiki start page can't be changed
|
||||||
|
* Feature #11084: Update Rails to 3.2.5
|
||||||
|
|
||||||
|
== 2012-05-28 v2.0.1
|
||||||
|
|
||||||
|
* Defect #10923: After creating a new Version Redmine jumps back to "Information"
|
||||||
|
* Defect #10932: Links to delete watchers are escaped when gravatars are enabled
|
||||||
|
* Defect #10964: Updated column doesn't get updated on issues
|
||||||
|
* Defect #10965: rake yard does not work for generating documentation.
|
||||||
|
* Defect #10972: Columns selection not displayed on the custom query form
|
||||||
|
* Defect #10991: My page > Spent time 'project' column is html-encoded
|
||||||
|
* Defect #10996: Time zones lost when upgrading from Redmine 1.4 to 2.0
|
||||||
|
* Defect #11013: Fetching Email from IMAP/POP3 - uninitialized constant RAILS_DEFAULT_LOGGER error
|
||||||
|
* Defect #11024: redmine_plugin_model generator does not create the migration
|
||||||
|
* Defect #11027: Saving new query without name causes escaping of input field
|
||||||
|
* Defect #11028: Project identifier can be updated
|
||||||
|
|
||||||
|
== 2012-05-15 v2.0.0
|
||||||
|
|
||||||
|
* Feature #4796: Rails 3 support
|
||||||
|
* Feature #7720: Limit the pagination-limit when max-results is fewer than max-pagination-limit
|
||||||
|
* Feature #9034: Add an id to the flash messages
|
||||||
|
* Patch #10782: Better translation for Estonian language
|
||||||
|
|
||||||
== 2012-05-13 v1.4.2
|
== 2012-05-13 v1.4.2
|
||||||
|
|
||||||
* Defect #10744: rake task redmine:email:test broken
|
* Defect #10744: rake task redmine:email:test broken
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ Optional:
|
|||||||
8. Test the installation by running the WEBrick web server
|
8. Test the installation by running the WEBrick web server
|
||||||
|
|
||||||
Under the main application directory run:
|
Under the main application directory run:
|
||||||
ruby script/server -e production
|
ruby script/rails server -e production
|
||||||
|
|
||||||
Once WEBrick has started, point your browser to http://localhost:3000/
|
Once WEBrick has started, point your browser to http://localhost:3000/
|
||||||
You should now see the application welcome page.
|
You should now see the application welcome page.
|
||||||
|
|||||||
@@ -366,12 +366,19 @@ sub is_member {
|
|||||||
);
|
);
|
||||||
$sthldap->execute($auth_source_id);
|
$sthldap->execute($auth_source_id);
|
||||||
while (my @rowldap = $sthldap->fetchrow_array) {
|
while (my @rowldap = $sthldap->fetchrow_array) {
|
||||||
|
my $bind_as = $rowldap[3] ? $rowldap[3] : "";
|
||||||
|
my $bind_pw = $rowldap[4] ? $rowldap[4] : "";
|
||||||
|
if ($bind_as =~ m/\$login/) {
|
||||||
|
# replace $login with $redmine_user and use $redmine_pass
|
||||||
|
$bind_as =~ s/\$login/$redmine_user/g;
|
||||||
|
$bind_pw = $redmine_pass
|
||||||
|
}
|
||||||
my $ldap = Authen::Simple::LDAP->new(
|
my $ldap = Authen::Simple::LDAP->new(
|
||||||
host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0],
|
host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0],
|
||||||
port => $rowldap[1],
|
port => $rowldap[1],
|
||||||
basedn => $rowldap[5],
|
basedn => $rowldap[5],
|
||||||
binddn => $rowldap[3] ? $rowldap[3] : "",
|
binddn => $bind_as,
|
||||||
bindpw => $rowldap[4] ? $rowldap[4] : "",
|
bindpw => $bind_pw,
|
||||||
filter => "(".$rowldap[6]."=%s)"
|
filter => "(".$rowldap[6]."=%s)"
|
||||||
);
|
);
|
||||||
my $method = $r->method;
|
my $method = $r->method;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
require 'optparse'
|
require 'optparse'
|
||||||
require 'find'
|
require 'find'
|
||||||
require 'etc'
|
require 'etc'
|
||||||
|
require 'rubygems'
|
||||||
|
|
||||||
Version = "1.4"
|
Version = "1.4"
|
||||||
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
|
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
class RedminePluginModelGenerator < Rails::Generators::NamedBase
|
class RedminePluginModelGenerator < Rails::Generators::NamedBase
|
||||||
|
|
||||||
source_root File.expand_path("../templates", __FILE__)
|
source_root File.expand_path("../templates", __FILE__)
|
||||||
argument :model, :type => :string
|
argument :model, :type => :string
|
||||||
|
argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
|
||||||
|
class_option :migration, :type => :boolean
|
||||||
|
class_option :timestamps, :type => :boolean
|
||||||
|
class_option :parent, :type => :string, :desc => "The parent class for the generated model"
|
||||||
|
class_option :indexes, :type => :boolean, :default => true, :desc => "Add indexes for references and belongs_to columns"
|
||||||
|
|
||||||
attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
|
attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
|
||||||
|
|
||||||
@@ -10,10 +16,26 @@ class RedminePluginModelGenerator < Rails::Generators::NamedBase
|
|||||||
@plugin_pretty_name = plugin_name.titleize
|
@plugin_pretty_name = plugin_name.titleize
|
||||||
@plugin_path = "plugins/#{plugin_name}"
|
@plugin_path = "plugins/#{plugin_name}"
|
||||||
@model_class = model.camelize
|
@model_class = model.camelize
|
||||||
|
@table_name = @model_class.tableize
|
||||||
|
@migration_filename = "create_#{@table_name}"
|
||||||
|
@migration_class_name = @migration_filename.camelize
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy_templates
|
def copy_templates
|
||||||
template 'model.rb.erb', "#{plugin_path}/app/models/#{model}.rb"
|
template 'model.rb.erb', "#{plugin_path}/app/models/#{model.underscore}.rb"
|
||||||
template 'unit_test.rb.erb', "#{plugin_path}/test/unit/#{model}_test.rb"
|
template 'unit_test.rb.erb', "#{plugin_path}/test/unit/#{model.underscore}_test.rb"
|
||||||
|
|
||||||
|
migration_filename = "%03i_#{@migration_filename}.rb" % (migration_number + 1)
|
||||||
|
template "migration.rb", "#{plugin_path}/db/migrate/#{migration_filename}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attributes_with_index
|
||||||
|
attributes.select { |a| a.has_index? || (a.reference? && options[:indexes]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def migration_number
|
||||||
|
current = Dir.glob("#{plugin_path}/db/migrate/*.rb").map do |file|
|
||||||
|
File.basename(file).split("_").first.to_i
|
||||||
|
end.max.to_i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class <%= @migration_class_name %> < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :<%= @table_name %> do |t|
|
||||||
|
<% attributes.each do |attribute| -%>
|
||||||
|
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
|
||||||
|
<% end -%>
|
||||||
|
<% if options[:timestamps] %>
|
||||||
|
t.timestamps
|
||||||
|
<% end -%>
|
||||||
|
end
|
||||||
|
<% attributes_with_index.each do |attribute| -%>
|
||||||
|
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
||||||
|
<% end -%>
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -131,6 +131,15 @@ module ActiveRecord
|
|||||||
when 'lowest'
|
when 'lowest'
|
||||||
move_to_bottom
|
move_to_bottom
|
||||||
end
|
end
|
||||||
|
reset_positions_in_list
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_positions_in_list
|
||||||
|
acts_as_list_class.where(scope_condition).reorder("#{position_column} ASC, id ASC").each_with_index do |item, i|
|
||||||
|
unless item.send(position_column) == (i + 1)
|
||||||
|
acts_as_list_class.update_all({position_column => (i + 1)}, {:id => item.id})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the item from the list.
|
# Removes the item from the list.
|
||||||
@@ -209,7 +218,7 @@ module ActiveRecord
|
|||||||
def bottom_item(except = nil)
|
def bottom_item(except = nil)
|
||||||
conditions = scope_condition
|
conditions = scope_condition
|
||||||
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
|
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
|
||||||
acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
|
acts_as_list_class.where(conditions).reorder("#{position_column} DESC").first
|
||||||
end
|
end
|
||||||
|
|
||||||
# Forces item to assume the bottom position in the list.
|
# Forces item to assume the bottom position in the list.
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ class TCPDF
|
|||||||
@state ||= 0
|
@state ||= 0
|
||||||
@tableborder ||= 0
|
@tableborder ||= 0
|
||||||
@tdbegin ||= false
|
@tdbegin ||= false
|
||||||
|
@tdtext ||= ''
|
||||||
@tdwidth ||= 0
|
@tdwidth ||= 0
|
||||||
@tdheight ||= 0
|
@tdheight ||= 0
|
||||||
@tdalign ||= "L"
|
@tdalign ||= "L"
|
||||||
@@ -3510,28 +3511,12 @@ class TCPDF
|
|||||||
|
|
||||||
else
|
else
|
||||||
#Text
|
#Text
|
||||||
if (@href)
|
if (@tdbegin)
|
||||||
|
element.gsub!(/[\t\r\n\f]/, "");
|
||||||
|
@tdtext << element.gsub(/ /, " ");
|
||||||
|
elsif (@href)
|
||||||
element.gsub!(/[\t\r\n\f]/, "");
|
element.gsub!(/[\t\r\n\f]/, "");
|
||||||
addHtmlLink(@href, element, fill);
|
addHtmlLink(@href, element, fill);
|
||||||
elsif (@tdbegin)
|
|
||||||
element.gsub!(/[\t\r\n\f]/, "");
|
|
||||||
element.gsub!(/ /, " ");
|
|
||||||
base_page = @page;
|
|
||||||
base_x = @x;
|
|
||||||
base_y = @y;
|
|
||||||
|
|
||||||
MultiCell(@tdwidth, @tdheight, unhtmlentities(element.strip), @tableborder, @tdalign, @tdfill, 1);
|
|
||||||
tr_end = @t_cells[@table_id][@tr_id][@td_id]['j1'] + 1;
|
|
||||||
if @max_td_page[tr_end].nil? or (@max_td_page[tr_end] < @page)
|
|
||||||
@max_td_page[tr_end] = @page
|
|
||||||
@max_td_y[tr_end] = @y
|
|
||||||
elsif (@max_td_page[tr_end] == @page)
|
|
||||||
@max_td_y[tr_end] = @y if @max_td_y[tr_end].nil? or (@max_td_y[tr_end] < @y)
|
|
||||||
end
|
|
||||||
|
|
||||||
@page = base_page;
|
|
||||||
@x = base_x + @tdwidth;
|
|
||||||
@y = base_y;
|
|
||||||
elsif (@pre_state == true and element.length > 0)
|
elsif (@pre_state == true and element.length > 0)
|
||||||
Write(@lasth, unhtmlentities(element), '', fill);
|
Write(@lasth, unhtmlentities(element), '', fill);
|
||||||
elsif (element.strip.length > 0)
|
elsif (element.strip.length > 0)
|
||||||
@@ -3825,6 +3810,7 @@ class TCPDF
|
|||||||
@x += 5;
|
@x += 5;
|
||||||
|
|
||||||
when 'table'
|
when 'table'
|
||||||
|
Ln();
|
||||||
if @default_table_columns < @max_table_columns[@table_id]
|
if @default_table_columns < @max_table_columns[@table_id]
|
||||||
@table_columns = @max_table_columns[@table_id];
|
@table_columns = @max_table_columns[@table_id];
|
||||||
else
|
else
|
||||||
@@ -3921,6 +3907,11 @@ class TCPDF
|
|||||||
|
|
||||||
when 'img'
|
when 'img'
|
||||||
if (!attrs['src'].nil?)
|
if (!attrs['src'].nil?)
|
||||||
|
# Don't generates image inside table tag
|
||||||
|
if (@tdbegin)
|
||||||
|
@tdtext << attrs['src'];
|
||||||
|
return
|
||||||
|
end
|
||||||
# Only generates image include a pdf if RMagick is avalaible
|
# Only generates image include a pdf if RMagick is avalaible
|
||||||
unless Object.const_defined?(:Magick)
|
unless Object.const_defined?(:Magick)
|
||||||
Write(@lasth, attrs['src'], '', fill);
|
Write(@lasth, attrs['src'], '', fill);
|
||||||
@@ -4079,6 +4070,23 @@ class TCPDF
|
|||||||
Ln();
|
Ln();
|
||||||
|
|
||||||
when 'td','th'
|
when 'td','th'
|
||||||
|
base_page = @page;
|
||||||
|
base_x = @x;
|
||||||
|
base_y = @y;
|
||||||
|
|
||||||
|
MultiCell(@tdwidth, @tdheight, unhtmlentities(@tdtext.strip), @tableborder, @tdalign, @tdfill, 1);
|
||||||
|
tr_end = @t_cells[@table_id][@tr_id][@td_id]['j1'] + 1;
|
||||||
|
if @max_td_page[tr_end].nil? or (@max_td_page[tr_end] < @page)
|
||||||
|
@max_td_page[tr_end] = @page
|
||||||
|
@max_td_y[tr_end] = @y
|
||||||
|
elsif (@max_td_page[tr_end] == @page)
|
||||||
|
@max_td_y[tr_end] = @y if @max_td_y[tr_end].nil? or (@max_td_y[tr_end] < @y)
|
||||||
|
end
|
||||||
|
|
||||||
|
@page = base_page;
|
||||||
|
@x = base_x + @tdwidth;
|
||||||
|
@y = base_y;
|
||||||
|
@tdtext = '';
|
||||||
@tdbegin = false;
|
@tdbegin = false;
|
||||||
@tdwidth = 0;
|
@tdwidth = 0;
|
||||||
@tdheight = 0;
|
@tdheight = 0;
|
||||||
@@ -4126,7 +4134,6 @@ class TCPDF
|
|||||||
@l_margin -= 5;
|
@l_margin -= 5;
|
||||||
@r_margin -= 5;
|
@r_margin -= 5;
|
||||||
@tableborder=0;
|
@tableborder=0;
|
||||||
Ln();
|
|
||||||
@table_id += 1;
|
@table_id += 1;
|
||||||
|
|
||||||
when 'strong'
|
when 'strong'
|
||||||
|
|||||||
@@ -138,21 +138,21 @@ module Redmine
|
|||||||
# Add list and boolean custom fields as available criteria
|
# Add list and boolean custom fields as available criteria
|
||||||
custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
|
custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
|
||||||
custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
||||||
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)",
|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id ORDER BY c.value LIMIT 1)",
|
||||||
:format => cf.field_format,
|
:format => cf.field_format,
|
||||||
:label => cf.name}
|
:label => cf.name}
|
||||||
end if @project
|
end if @project
|
||||||
|
|
||||||
# Add list and boolean time entry custom fields
|
# Add list and boolean time entry custom fields
|
||||||
TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
||||||
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)",
|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id ORDER BY c.value LIMIT 1)",
|
||||||
:format => cf.field_format,
|
:format => cf.field_format,
|
||||||
:label => cf.name}
|
:label => cf.name}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add list and boolean time entry activity custom fields
|
# Add list and boolean time entry activity custom fields
|
||||||
TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
|
||||||
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)",
|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id ORDER BY c.value LIMIT 1)",
|
||||||
:format => cf.field_format,
|
:format => cf.field_format,
|
||||||
:label => cf.name}
|
:label => cf.name}
|
||||||
end
|
end
|
||||||
|
|||||||
+10
-3
@@ -107,7 +107,13 @@ module Redmine
|
|||||||
#
|
#
|
||||||
def self.render_on(hook, options={})
|
def self.render_on(hook, options={})
|
||||||
define_method hook do |context|
|
define_method hook do |context|
|
||||||
context[:controller].send(:render_to_string, {:locals => context}.merge(options))
|
if context[:hook_caller].respond_to?(:render)
|
||||||
|
context[:hook_caller].send(:render, {:locals => context}.merge(options))
|
||||||
|
elsif context[:controller].is_a?(ActionController::Base)
|
||||||
|
context[:controller].send(:render_to_string, {:locals => context}.merge(options))
|
||||||
|
else
|
||||||
|
raise "Cannot render #{self.name} hook from #{context[:hook_caller].class.name}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -138,14 +144,15 @@ module Redmine
|
|||||||
# * project => current project
|
# * project => current project
|
||||||
# * request => Request instance
|
# * request => Request instance
|
||||||
# * controller => current Controller instance
|
# * controller => current Controller instance
|
||||||
|
# * hook_caller => object that called the hook
|
||||||
#
|
#
|
||||||
module Helper
|
module Helper
|
||||||
def call_hook(hook, context={})
|
def call_hook(hook, context={})
|
||||||
if is_a?(ActionController::Base)
|
if is_a?(ActionController::Base)
|
||||||
default_context = {:controller => self, :project => @project, :request => request}
|
default_context = {:controller => self, :project => @project, :request => request, :hook_caller => self}
|
||||||
Redmine::Hook.call_hook(hook, default_context.merge(context))
|
Redmine::Hook.call_hook(hook, default_context.merge(context))
|
||||||
else
|
else
|
||||||
default_context = { :project => @project }
|
default_context = { :project => @project, :hook_caller => self }
|
||||||
default_context[:controller] = controller if respond_to?(:controller)
|
default_context[:controller] = controller if respond_to?(:controller)
|
||||||
default_context[:request] = request if respond_to?(:request)
|
default_context[:request] = request if respond_to?(:request)
|
||||||
Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
|
Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ module Redmine
|
|||||||
private
|
private
|
||||||
|
|
||||||
def logger
|
def logger
|
||||||
RAILS_DEFAULT_LOGGER
|
::Rails.logger
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ module Redmine
|
|||||||
private
|
private
|
||||||
|
|
||||||
def logger
|
def logger
|
||||||
RAILS_DEFAULT_LOGGER
|
::Rails.logger
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 0
|
MINOR = 0
|
||||||
TINY = 0
|
TINY = 3
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
# * stable branch: stable
|
# * stable branch: stable
|
||||||
# * trunk: devel
|
# * trunk: devel
|
||||||
BRANCH = 'devel'
|
BRANCH = 'stable'
|
||||||
|
|
||||||
def self.revision
|
def self.revision
|
||||||
revision = nil
|
revision = nil
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ module Redmine
|
|||||||
l = 1
|
l = 1
|
||||||
started = false
|
started = false
|
||||||
ended = false
|
ended = false
|
||||||
text.scan(/(((?:.*?)(\A|\r?\n\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))? (.*?)$)|.*)/m).each do |all, content, lf, heading, level|
|
text.scan(/(((?:.*?)(\A|\r?\n\s*\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))? (.*?)$)|.*)/m).each do |all, content, lf, heading, level|
|
||||||
if heading.nil?
|
if heading.nil?
|
||||||
if ended
|
if ended
|
||||||
after << all
|
after << all
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace :redmine do
|
|||||||
set_inheritance_column :none
|
set_inheritance_column :none
|
||||||
|
|
||||||
# ticket changes: only migrate status changes and comments
|
# ticket changes: only migrate status changes and comments
|
||||||
has_many :changes, :class_name => "TracTicketChange", :foreign_key => :ticket
|
has_many :ticket_changes, :class_name => "TracTicketChange", :foreign_key => :ticket
|
||||||
has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
|
has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
|
||||||
|
|
||||||
def attachments
|
def attachments
|
||||||
@@ -487,7 +487,7 @@ namespace :redmine do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Comments and status/resolution changes
|
# Comments and status/resolution changes
|
||||||
ticket.changes.group_by(&:time).each do |time, changeset|
|
ticket.ticket_changes.group_by(&:time).each do |time, changeset|
|
||||||
status_change = changeset.select {|change| change.field == 'status'}.first
|
status_change = changeset.select {|change| change.field == 'status'}.first
|
||||||
resolution_change = changeset.select {|change| change.field == 'resolution'}.first
|
resolution_change = changeset.select {|change| change.field == 'resolution'}.first
|
||||||
comment_change = changeset.select {|change| change.field == 'comment'}.first
|
comment_change = changeset.select {|change| change.field == 'comment'}.first
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ table.revision-info td {
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.revision-graph { position: absolute; }
|
div.revision-graph { position: absolute; min-width: 1px; }
|
||||||
|
|
||||||
div.changeset-changes ul { margin: 0; padding: 0; }
|
div.changeset-changes ul { margin: 0; padding: 0; }
|
||||||
div.changeset-changes ul > ul { margin-left: 18px; padding: 0; }
|
div.changeset-changes ul > ul { margin-left: 18px; padding: 0; }
|
||||||
|
|||||||
Vendored
+24
-24
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
issues_001:
|
issues_001:
|
||||||
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 3.days.ago.to_s(:db) %>
|
||||||
project_id: 1
|
project_id: 1
|
||||||
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.day.ago.to_s(:db) %>
|
||||||
priority_id: 4
|
priority_id: 4
|
||||||
subject: Can't print recipes
|
subject: Can't print recipes
|
||||||
id: 1
|
id: 1
|
||||||
@@ -60,9 +60,9 @@ issues_003:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_004:
|
issues_004:
|
||||||
created_on: <%= 5.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 5.days.ago.to_s(:db) %>
|
||||||
project_id: 2
|
project_id: 2
|
||||||
updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 2.days.ago.to_s(:db) %>
|
||||||
priority_id: 4
|
priority_id: 4
|
||||||
subject: Issue on project 2
|
subject: Issue on project 2
|
||||||
id: 4
|
id: 4
|
||||||
@@ -77,9 +77,9 @@ issues_004:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_005:
|
issues_005:
|
||||||
created_on: <%= 5.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 5.days.ago.to_s(:db) %>
|
||||||
project_id: 3
|
project_id: 3
|
||||||
updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 2.days.ago.to_s(:db) %>
|
||||||
priority_id: 4
|
priority_id: 4
|
||||||
subject: Subproject issue
|
subject: Subproject issue
|
||||||
id: 5
|
id: 5
|
||||||
@@ -94,9 +94,9 @@ issues_005:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_006:
|
issues_006:
|
||||||
created_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
created_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
project_id: 5
|
project_id: 5
|
||||||
updated_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
priority_id: 4
|
priority_id: 4
|
||||||
subject: Issue of a private subproject
|
subject: Issue of a private subproject
|
||||||
id: 6
|
id: 6
|
||||||
@@ -113,9 +113,9 @@ issues_006:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_007:
|
issues_007:
|
||||||
created_on: <%= 10.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 10.days.ago.to_s(:db) %>
|
||||||
project_id: 1
|
project_id: 1
|
||||||
updated_on: <%= 10.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 10.days.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Issue due today
|
subject: Issue due today
|
||||||
id: 7
|
id: 7
|
||||||
@@ -133,9 +133,9 @@ issues_007:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_008:
|
issues_008:
|
||||||
created_on: <%= 10.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 10.days.ago.to_s(:db) %>
|
||||||
project_id: 1
|
project_id: 1
|
||||||
updated_on: <%= 10.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 10.days.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Closed issue
|
subject: Closed issue
|
||||||
id: 8
|
id: 8
|
||||||
@@ -153,9 +153,9 @@ issues_008:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_009:
|
issues_009:
|
||||||
created_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
created_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
project_id: 5
|
project_id: 5
|
||||||
updated_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Blocked Issue
|
subject: Blocked Issue
|
||||||
id: 9
|
id: 9
|
||||||
@@ -172,9 +172,9 @@ issues_009:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_010:
|
issues_010:
|
||||||
created_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
created_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
project_id: 5
|
project_id: 5
|
||||||
updated_on: <%= 1.minute.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.minute.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Issue Doing the Blocking
|
subject: Issue Doing the Blocking
|
||||||
id: 10
|
id: 10
|
||||||
@@ -191,9 +191,9 @@ issues_010:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_011:
|
issues_011:
|
||||||
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 3.days.ago.to_s(:db) %>
|
||||||
project_id: 1
|
project_id: 1
|
||||||
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.day.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Closed issue on a closed version
|
subject: Closed issue on a closed version
|
||||||
id: 11
|
id: 11
|
||||||
@@ -210,9 +210,9 @@ issues_011:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_012:
|
issues_012:
|
||||||
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 3.days.ago.to_s(:db) %>
|
||||||
project_id: 1
|
project_id: 1
|
||||||
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
|
updated_on: <%= 1.day.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Closed issue on a locked version
|
subject: Closed issue on a locked version
|
||||||
id: 12
|
id: 12
|
||||||
@@ -229,9 +229,9 @@ issues_012:
|
|||||||
lft: 1
|
lft: 1
|
||||||
rgt: 2
|
rgt: 2
|
||||||
issues_013:
|
issues_013:
|
||||||
created_on: <%= 5.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 5.days.ago.to_s(:db) %>
|
||||||
project_id: 3
|
project_id: 3
|
||||||
updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 2.days.ago.to_s(:db) %>
|
||||||
priority_id: 4
|
priority_id: 4
|
||||||
subject: Subproject issue two
|
subject: Subproject issue two
|
||||||
id: 13
|
id: 13
|
||||||
@@ -247,9 +247,9 @@ issues_013:
|
|||||||
rgt: 2
|
rgt: 2
|
||||||
issues_014:
|
issues_014:
|
||||||
id: 14
|
id: 14
|
||||||
created_on: <%= 15.days.ago.to_date.to_s(:db) %>
|
created_on: <%= 15.days.ago.to_s(:db) %>
|
||||||
project_id: 3
|
project_id: 3
|
||||||
updated_on: <%= 15.days.ago.to_date.to_s(:db) %>
|
updated_on: <%= 15.days.ago.to_s(:db) %>
|
||||||
priority_id: 5
|
priority_id: 5
|
||||||
subject: Private issue on public project
|
subject: Private issue on public project
|
||||||
fixed_version_id:
|
fixed_version_id:
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Content-Type: application/ms-tnef; name="winmail.dat"
|
||||||
|
Content-Transfer-Encoding: binary
|
||||||
|
From: John Smith <JSmith@somenet.foo>
|
||||||
|
To: "redmine@somenet.foo" <redmine@somenet.foo>
|
||||||
|
Subject: =?iso-8859-1?Q?Testmail_from_Webmail:_=E4_=F6_=FC...?=
|
||||||
|
Date: Fri, 1 Jun 2012 14:39:38 +0200
|
||||||
|
Message-ID: <87C31D42249DD0489D1A1444E3232DD7019D6183@foo.bar>
|
||||||
|
Accept-Language: de-CH, en-US
|
||||||
|
Content-Language: de-CH
|
||||||
|
|
||||||
|
Fixture
|
||||||
@@ -73,13 +73,19 @@ class ActivitiesControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_user_index
|
def test_user_index
|
||||||
|
@request.session[:user_id] = 1
|
||||||
get :index, :user_id => 2
|
get :index, :user_id => 2
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'index'
|
assert_template 'index'
|
||||||
assert_not_nil assigns(:events_by_day)
|
assert_not_nil assigns(:events_by_day)
|
||||||
|
|
||||||
|
assert_select 'h2 a[href=/users/2]', :text => 'John Smith'
|
||||||
|
|
||||||
|
i1 = Issue.find(1)
|
||||||
|
d1 = User.find(1).time_to_date(i1.created_on)
|
||||||
|
|
||||||
assert_tag :tag => "h3",
|
assert_tag :tag => "h3",
|
||||||
:content => /#{3.day.ago.to_date.day}/,
|
:content => /#{d1.day}/,
|
||||||
:sibling => { :tag => "dl",
|
:sibling => { :tag => "dl",
|
||||||
:child => { :tag => "dt",
|
:child => { :tag => "dt",
|
||||||
:attributes => { :class => /issue/ },
|
:attributes => { :class => /issue/ },
|
||||||
|
|||||||
@@ -55,6 +55,20 @@ class BoardsControllerTest < ActionController::TestCase
|
|||||||
assert_not_nil assigns(:topics)
|
assert_not_nil assigns(:topics)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_show_should_display_sticky_messages_first
|
||||||
|
Message.update_all(:sticky => 0)
|
||||||
|
Message.update_all({:sticky => 1}, {:id => 1})
|
||||||
|
|
||||||
|
get :show, :project_id => 1, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
|
topics = assigns(:topics)
|
||||||
|
assert_not_nil topics
|
||||||
|
assert topics.size > 1, "topics size was #{topics.size}"
|
||||||
|
assert topics.first.sticky?
|
||||||
|
assert topics.first.updated_on < topics.second.updated_on
|
||||||
|
end
|
||||||
|
|
||||||
def test_show_with_permission_should_display_the_new_message_form
|
def test_show_with_permission_should_display_the_new_message_form
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
get :show, :project_id => 1, :id => 1
|
get :show, :project_id => 1, :id => 1
|
||||||
|
|||||||
@@ -1126,6 +1126,36 @@ class IssuesControllerTest < ActionController::TestCase
|
|||||||
assert_tag 'a', :attributes => {:href => "/projects/ecookbook/repository/revisions/3"}
|
assert_tag 'a', :attributes => {:href => "/projects/ecookbook/repository/revisions/3"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_show_should_display_watchers
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
Issue.find(1).add_watcher User.find(2)
|
||||||
|
|
||||||
|
get :show, :id => 1
|
||||||
|
assert_select 'div#watchers ul' do
|
||||||
|
assert_select 'li' do
|
||||||
|
assert_select 'a[href=/users/2]'
|
||||||
|
assert_select 'a img[alt=Delete]'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_should_display_watchers_with_gravatars
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
Issue.find(1).add_watcher User.find(2)
|
||||||
|
|
||||||
|
with_settings :gravatar_enabled => '1' do
|
||||||
|
get :show, :id => 1
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_select 'div#watchers ul' do
|
||||||
|
assert_select 'li' do
|
||||||
|
assert_select 'img.gravatar'
|
||||||
|
assert_select 'a[href=/users/2]'
|
||||||
|
assert_select 'a img[alt=Delete]'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_show_with_multi_custom_field
|
def test_show_with_multi_custom_field
|
||||||
field = CustomField.find(1)
|
field = CustomField.find(1)
|
||||||
field.update_attribute :multiple, true
|
field.update_attribute :multiple, true
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ require 'my_controller'
|
|||||||
class MyController; def rescue_action(e) raise e end; end
|
class MyController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
class MyControllerTest < ActionController::TestCase
|
class MyControllerTest < ActionController::TestCase
|
||||||
fixtures :users, :user_preferences, :roles, :projects, :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
|
fixtures :users, :user_preferences, :roles, :projects, :members, :member_roles,
|
||||||
|
:issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@controller = MyController.new
|
@controller = MyController.new
|
||||||
@@ -43,6 +44,20 @@ class MyControllerTest < ActionController::TestCase
|
|||||||
assert_template 'page'
|
assert_template 'page'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_page_with_timelog_block
|
||||||
|
preferences = User.find(2).pref
|
||||||
|
preferences[:my_page_layout] = {'top' => ['timelog']}
|
||||||
|
preferences.save!
|
||||||
|
TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :issue_id => 1, :hours => 2.5, :activity_id => 10)
|
||||||
|
|
||||||
|
get :page
|
||||||
|
assert_response :success
|
||||||
|
assert_select 'tr.time-entry' do
|
||||||
|
assert_select 'td.subject a[href=/issues/1]'
|
||||||
|
assert_select 'td.hours', :text => '2.50'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_my_account_should_show_editable_custom_fields
|
def test_my_account_should_show_editable_custom_fields
|
||||||
get :account
|
get :account
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ class QueriesControllerTest < ActionController::TestCase
|
|||||||
:name => 'query_is_for_all',
|
:name => 'query_is_for_all',
|
||||||
:checked => nil,
|
:checked => nil,
|
||||||
:disabled => nil }
|
:disabled => nil }
|
||||||
|
assert_select 'select[name=?]', 'c[]' do
|
||||||
|
assert_select 'option[value=tracker]'
|
||||||
|
assert_select 'option[value=subject]'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_new_global_query
|
def test_new_global_query
|
||||||
@@ -145,6 +149,7 @@ class QueriesControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'new'
|
assert_template 'new'
|
||||||
|
assert_select 'input[name=?]', 'query[name]'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_edit_global_public_query
|
def test_edit_global_public_query
|
||||||
|
|||||||
@@ -87,6 +87,16 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
if File.directory?(REPOSITORY_PATH)
|
if File.directory?(REPOSITORY_PATH)
|
||||||
|
## Ruby uses ANSI api to fork a process on Windows.
|
||||||
|
## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
|
||||||
|
## and these are incompatible with ASCII.
|
||||||
|
## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
|
||||||
|
## http://code.google.com/p/msysgit/issues/detail?id=80
|
||||||
|
## So, Latin-1 path tests fail on Japanese Windows
|
||||||
|
WINDOWS_PASS = (Redmine::Platform.mswin? &&
|
||||||
|
Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
|
||||||
|
WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
|
||||||
|
|
||||||
def test_get_new
|
def test_get_new
|
||||||
@request.session[:user_id] = 1
|
@request.session[:user_id] = 1
|
||||||
@project.repository.destroy
|
@project.repository.destroy
|
||||||
@@ -214,6 +224,8 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
def test_entry_show_latin_1
|
def test_entry_show_latin_1
|
||||||
if @ruby19_non_utf8_pass
|
if @ruby19_non_utf8_pass
|
||||||
puts_ruby19_non_utf8_pass()
|
puts_ruby19_non_utf8_pass()
|
||||||
|
elsif WINDOWS_PASS
|
||||||
|
puts WINDOWS_SKIP_STR
|
||||||
elsif JRUBY_SKIP
|
elsif JRUBY_SKIP
|
||||||
puts JRUBY_SKIP_STR
|
puts JRUBY_SKIP_STR
|
||||||
else
|
else
|
||||||
@@ -435,6 +447,8 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
def test_annotate_latin_1
|
def test_annotate_latin_1
|
||||||
if @ruby19_non_utf8_pass
|
if @ruby19_non_utf8_pass
|
||||||
puts_ruby19_non_utf8_pass()
|
puts_ruby19_non_utf8_pass()
|
||||||
|
elsif WINDOWS_PASS
|
||||||
|
puts WINDOWS_SKIP_STR
|
||||||
elsif JRUBY_SKIP
|
elsif JRUBY_SKIP
|
||||||
puts JRUBY_SKIP_STR
|
puts JRUBY_SKIP_STR
|
||||||
else
|
else
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user