Skip to content

Commit

Permalink
(continued with modified files) All changes currently applied at TT (…
Browse files Browse the repository at this point in the history
…except Trac migration changes), rebased up to r1778
  • Loading branch information
unknown committed Sep 2, 2008
1 parent ad632ca commit e472221
Show file tree
Hide file tree
Showing 78 changed files with 2,163 additions and 853 deletions.
15 changes: 14 additions & 1 deletion app/controllers/application.rb
Expand Up @@ -21,6 +21,12 @@ class ApplicationController < ActionController::Base
layout 'base'

before_filter :user_setup, :check_if_login_required, :set_localization
before_filter :set_time_zone

def set_time_zone
Time.zone = User.current.time_zone if User.current
end

filter_parameter_logging :password

include Redmine::MenuManager::MenuController
Expand Down Expand Up @@ -102,7 +108,9 @@ def deny_access

# Authorize the user for the requested action
def authorize(ctrl = params[:controller], action = params[:action])
allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project)
options = {}
options.merge!(:global => true) if !@project
allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project, options)
allowed ? true : deny_access
end

Expand Down Expand Up @@ -222,4 +230,9 @@ def parse_qvalues(value)
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
end

def url_path(url_parameters)
rs = ::ActionController::Routing::Routes
rs.generate url_parameters
end
end
11 changes: 6 additions & 5 deletions app/controllers/attachments_controller.rb
Expand Up @@ -31,12 +31,13 @@ def show
end

def download
@attachment.increment_download if @attachment.container.is_a?(Version)

# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => @attachment.content_type,
:disposition => (@attachment.image? ? 'inline' : 'attachment')
options = {:filename =>
filename_for_content_disposition(@attachment.filename),
:disposition => (@attachment.image? ? 'inline' : 'attachment')}

options.merge!(:type => @attachment.content_type) if @attachment.content_type
send_file @attachment.diskfile, options
end

private
Expand Down
40 changes: 34 additions & 6 deletions app/controllers/issues_controller.rb
Expand Up @@ -21,7 +21,10 @@ class IssuesController < ApplicationController
before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
before_filter :find_project, :only => [:new, :update_form, :preview]
before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]

before_filter :authorize, :except => [:index, :changes, :preview,
:update_form, :context_menu, :diff]

before_filter :find_optional_project, :only => [:index, :changes]
accept_key_auth :index, :changes

Expand Down Expand Up @@ -100,7 +103,7 @@ def show
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = Enumeration::get_values('IPRI')
@time_entry = TimeEntry.new
@time_entry = @issue.time_entry_in_progress(User.current) || TimeEntry.new
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
Expand Down Expand Up @@ -133,9 +136,7 @@ def new
@issue.status = default_status
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)).uniq

if request.get? || request.xhr?
@issue.start_date ||= Date.today
else
if !request.get? && !request.xhr?
requested_status = IssueStatus.find_by_id(params[:issue][:status_id])
# Check that the user is allowed to apply the requested status
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
Expand All @@ -156,6 +157,7 @@ def new
UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)

def edit
@issue = flash[:error_issue] if flash[:error_issue]
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = Enumeration::get_values('IPRI')
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
Expand All @@ -172,7 +174,10 @@ def edit
end

if request.post?
@time_entry = TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
@time_entry = TimeEntry.find_by_id(params[:time_entry][:id]) if params[:time_entry]
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue,
:user => User.current, :spent_on => Date.today)

@time_entry.attributes = params[:time_entry]
attachments = attach_files(@issue, params[:attachments])
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
Expand Down Expand Up @@ -277,7 +282,10 @@ def move
if unsaved_issue_ids.empty?
flash[:notice] = l(:notice_successful_update) unless @issues.empty?
else
flash[:error_issue] = @issues[0]
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, @issues.size, '#' + unsaved_issue_ids.join(', #'))
redirect_to :controller => 'issues', :action => :edit, :id => @issues[0]
return
end
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
return
Expand Down Expand Up @@ -361,6 +369,20 @@ def preview
render :partial => 'common/preview'
end

def diff
@detail = JournalDetail.find(params[:id])
@issue = @detail.journal.issue
Tempfile.open 'issue_description_oldval', 'tmp' do |old_val_file|
old_val_file.write normalize(@detail.old_value)
Tempfile.open 'issue_description_oldval', 'tmp' do |new_val_file|
new_val_file.write normalize(@detail.value)
old_val_file.close
new_val_file.close
@diff = `diff #{old_val_file.path} #{new_val_file.path} -U 3`
end
end
end

private
def find_issue
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
Expand Down Expand Up @@ -428,4 +450,10 @@ def retrieve_query
end
end
end

def normalize(long_string)
return long_string if long_string["\r\n"]
long_string.split("\n").join("\r\n")
end

end
5 changes: 5 additions & 0 deletions app/controllers/my_controller.rb
Expand Up @@ -74,6 +74,11 @@ def account
@notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected')
end

def show_account
@user = User.current
redirect_to :controller => 'account', :action => 'show', :id => @user.id
end

# Manage user's password
def password
@user = User.current
Expand Down
60 changes: 57 additions & 3 deletions app/controllers/timelog_controller.rb
Expand Up @@ -148,9 +148,10 @@ def details
else
cond << ["#{TimeEntry.table_name}.issue_id = ?", @issue.id]
end
cond << ["#{TimeEntry.table_name}.user_id = ?", @user.id] if @user

retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
cond << ['spent_on BETWEEN ? AND ?', @from, @to] if @apply_date_filter

TimeEntry.visible_by(User.current) do
respond_to do |format|
Expand Down Expand Up @@ -189,11 +190,39 @@ def details
end

def edit
return if redirect_if_in_progress

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 !@time_entry.hours
if !@time_entry.start_time
@activate_field = 'time_entry_start_time'
else
@activate_field = 'time_entry_end_time'
end
end

url_writer = lambda do |entry|
"<a href = \"#{url_path(:controller => :timelog, :action => :edit,
:id => entry.id)}\">##{entry.issue_id}-#{entry.id}</a>"
end

if request.post? and @time_entry.save
flash[:notice] = l(:notice_successful_update)
intersecting = @time_entry.find_intersecting_entries
logger.debug "intersecting = #{intersecting.inspect}"
msg = l(:notice_successful_update)
if !intersecting.empty?

list = lwr(:text_time_entry_intersecting_notice_entry,
intersecting.size) + ' ' + intersecting.
map { |entry| url_writer.call(entry) }.
to_sentence(:skip_last_comma => true, :connector => l(:text_and))

msg += ' ' + l(:text_time_entry_intersecting_notice,
url_writer.call(@time_entry), list)
end
flash[:notice] = msg
redirect_to(params[:back_url].blank? ? {:action => 'details', :project_id => @time_entry.project} : params[:back_url])
return
end
Expand All @@ -217,8 +246,10 @@ def find_project
elsif params[:issue_id]
@issue = Issue.find(params[:issue_id])
@project = @issue.project
elsif params[:project_id]
elsif params[:project_id] && !params[:project_id].empty?
@project = Project.find(params[:project_id])
elsif params[:user_id]
@user = User.find(params[:user_id])
else
render_404
return false
Expand All @@ -241,7 +272,12 @@ def find_optional_project
def retrieve_date_range
@free_period = false
@from, @to = nil, nil
@apply_date_filter = true

if !params[:period_type] && !params[:period] && !params[:from] && !params[:to]
@apply_date_filter = false
end

if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?)
case params[:period].to_s
when 'today'
Expand Down Expand Up @@ -269,6 +305,8 @@ def retrieve_date_range
when 'current_year'
@from = Date.civil(Date.today.year, 1, 1)
@to = Date.civil(Date.today.year, 12, 31)
when 'all'
@apply_date_filter = false
end
elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?))
begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end
Expand All @@ -281,5 +319,21 @@ def retrieve_date_range
@from, @to = @to, @from if @from && @to && @from > @to
@from ||= (TimeEntry.minimum(:spent_on, :include => :project, :conditions => Project.allowed_to_condition(User.current, :view_time_entries)) || Date.today) - 1
@to ||= (TimeEntry.maximum(:spent_on, :include => :project, :conditions => Project.allowed_to_condition(User.current, :view_time_entries)) || Date.today)

@from ||= Date.today - 1
@to ||= Date.today
end

def redirect_if_in_progress
if !@time_entry && @issue
in_progress_entry = @issue.time_entry_in_progress(User.current)
if in_progress_entry
#in order to avoid :id form parameter and not complicate :find_project filter
redirect_to(:controller => 'timelog', :action => 'edit',
:id => in_progress_entry)
return true
end
end
false
end
end
10 changes: 6 additions & 4 deletions app/helpers/application_helper.rb
Expand Up @@ -90,15 +90,17 @@ def format_date(date)
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
date.strftime(@date_format)
end

def format_time(time, include_date = true)
return nil unless time
time = time.to_time if time.is_a?(String)
zone = User.current.time_zone
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.utc_to_local : time)
local = time
#zone = User.current.time_zone
#local = zone ? time.in_time_zone(zone) : (time.utc? ? time.utc_to_local : time)
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
@time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
format = include_date ? "#{@date_format} #{@time_format}" : @time_format
local.strftime(format)
end

# Truncates and returns the string as a single line
Expand Down
10 changes: 10 additions & 0 deletions app/helpers/issues_helper.rb
Expand Up @@ -75,6 +75,9 @@ def show_detail(detail, no_html=false)
when 'fixed_version_id'
v = Version.find_by_id(detail.value) and value = v.name if detail.value
v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
when 'description'
return content_tag('strong', 'Description') + ' ' + link_to('changed', :controller => 'issues', :action => 'diff', :id => detail.id)

when 'estimated_hours'
value = "%0.02f" % detail.value.to_f unless detail.value.blank?
old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
Expand Down Expand Up @@ -184,4 +187,11 @@ def issues_to_csv(issues, project = nil)
export.rewind
export
end

def spent_hours(issue)
return '-' if issue.time_entries.empty?
spent_hours = lwr(:label_f_hour, issue.spent_hours)
spent_hours += " (#{l(:text_in_progress)})" if issue.time_entry_in_progress
link_to spent_hours, {:controller => 'timelog', :action => 'details', :project_id => issue.project, :issue_id => issue}, :class => 'icon icon-time'
end
end
5 changes: 5 additions & 0 deletions app/helpers/timelog_helper.rb
Expand Up @@ -44,6 +44,11 @@ def sum_hours(data)
sum
end

def hours(entry)
return '<span class="hours hours-dec">[%s]</span>' % l(:text_in_progress) if !entry.hours
html_hours("%.2f" % entry.hours)
end

def options_for_period_select(value)
options_for_select([[l(:label_all_time), 'all'],
[l(:label_today), 'today'],
Expand Down
37 changes: 23 additions & 14 deletions app/helpers/versions_helper.rb
Expand Up @@ -23,22 +23,31 @@ def render_issue_status_by(version, criteria)
criteria ||= 'category'
raise 'Unknown criteria' unless STATUS_BY_CRITERIAS.include?(criteria)

h = Hash.new {|k,v| k[v] = [0, 0]}
begin
# Total issue count
Issue.count(:group => criteria,
:conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s}
# Open issues count
Issue.count(:group => criteria,
:include => :status,
:conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s}
rescue ActiveRecord::RecordNotFound
# When grouping by an association, Rails throws this exception if there's no result (bug)
#sort them alphabetically by category name
metrics = version.get_grouped_metrics(criteria).to_a.sort {|x, y| x[0].to_s <=> y[0].to_s}
max = {}

[{:count => :total}, {:time => :total}].each do |metric_info|
metrics_group, total_metric = metric_info.to_a.flatten
max[metrics_group] = metrics.map{|item| item[1]}.map {|item| item[metrics_group]}.map {|item| item[total_metric]}.max
max[metrics_group] = 1 if max[metrics_group] == 0
end
counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
max = counts.collect {|c| c[:total]}.max

render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
render :partial => 'issue_counts', :locals => {:version => version,
:criteria => criteria, :grouped_metrics => metrics, :max => max,
:spent_time_allowed => User.current.allowed_to?(:view_time_entries, @project),
}
end

def time_progress(time_info)
logger.debug "time_info[:spent] = #{time_info[:spent].inspect}"
logger.debug "time_info[:total] = #{time_info[:total].inspect}"
if (time_info[:total] != 0)
time_progress = time_info[:spent].to_f / time_info[:total]
else
time_progress = 0 #no total also means there's no spent time
end
time_progress
end

def status_by_options_for_select(value)
Expand Down
11 changes: 11 additions & 0 deletions app/models/attachment.rb
Expand Up @@ -108,6 +108,17 @@ def is_diff?
self.filename =~ /\.(patch|diff)$/i
end

def guess_and_fill_mime_type(save = true)
require 'mime/types'
types = MIME::Types.type_for(self.filename)
if !types.empty?
content_type = types[0].content_type
self.content_type = content_type
self.save! if save
true
end
end

private
def sanitize_filename(value)
# get only the filename, not the whole path
Expand Down

0 comments on commit e472221

Please sign in to comment.