Associating graphs display with the issues tab

This commit is contained in:
Brad Beattie 2009-04-02 09:53:30 -07:00
parent bf61b20956
commit 263391e6ce

View File

@ -2,213 +2,215 @@ require 'SVG/Graph/TimeSeries'
class GraphsController < ApplicationController class GraphsController < ApplicationController
before_filter :find_version, :only => [:target_version_graph] menu_item :issues, :only => [:issue_growth, :old_issues]
before_filter :find_open_issues, :only => [:old_issues, :issue_age_graph]
before_filter :find_optional_project, :only => [:issue_growth, :issue_growth_graph]
helper IssuesHelper
def issue_growth
end
# Displays projects by total issues over time
def issue_growth_graph
# Initialize the graph
graph = SVG::Graph::TimeSeries.new({
:area_fill => true,
:height => 300,
:min_y_value => 0,
:no_css => true,
:show_x_guidelines => true,
:scale_x_integers => true,
:scale_y_integers => true,
:show_data_points => false,
:show_data_values => false,
:stagger_x_labels => true,
:style_sheet => "/plugin_assets/redmine_graphs/stylesheets/issue_growth.css",
:timescale_divisions => "1 months",
:width => 720,
:x_label_format => "%b %Y"
})
# Get the top visible projects by issue count
sql = "SELECT project_id, COUNT(*) as issue_count"
sql << " FROM issues"
sql << " LEFT JOIN #{Project.table_name} ON #{Issue.table_name}.project_id = #{Project.table_name}.id"
sql << " WHERE (%s)" % Project.allowed_to_condition(User.current, :view_issues)
sql << " AND (project_id = #{@project.id})" unless @project.nil?
sql << " GROUP BY project_id"
sql << " ORDER BY issue_count DESC"
sql << " LIMIT 6"
top_projects = ActiveRecord::Base.connection.select_all(sql).collect { |p| p["project_id"] }
# Get the issues created per project, per day
sql = "SELECT project_id, date(#{Issue.table_name}.created_on) as date, COUNT(*) as issue_count"
sql << " FROM #{Issue.table_name}"
sql << " WHERE project_id IN (%s)" % top_projects.compact.join(',')
sql << " GROUP BY project_id, date"
issue_counts = ActiveRecord::Base.connection.select_all(sql).group_by { |c| c["project_id"] }
# Generate the created_on lines before_filter :find_version, :only => [:target_version_graph]
top_projects.each do |project_id, total_count| before_filter :find_open_issues, :only => [:old_issues, :issue_age_graph]
counts = issue_counts[project_id].sort { |a,b| a["date"]<=>b["date"] } before_filter :find_optional_project, :only => [:issue_growth, :issue_growth_graph]
created_count = 0
created_on_line = Hash.new helper IssuesHelper
created_on_line[(Date.parse(counts.first["date"])-1).to_s] = 0
counts.each { |count| created_count += count["issue_count"].to_i; created_on_line[count["date"]] = created_count } def issue_growth
created_on_line[Date.today.to_s] = created_count end
graph.add_data({
:data => created_on_line.sort.flatten, # Displays projects by total issues over time
:title => Project.find(project_id).to_s def issue_growth_graph
})
end # Initialize the graph
graph = SVG::Graph::TimeSeries.new({
# Compile the graph :area_fill => true,
headers["Content-Type"] = "image/svg+xml" :height => 300,
send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline") :min_y_value => 0,
end :no_css => true,
:show_x_guidelines => true,
def old_issues :scale_x_integers => true,
@issues_by_created_on = @issues.sort {|a,b| a.created_on<=>b.created_on} :scale_y_integers => true,
@issues_by_updated_on = @issues.sort {|a,b| a.updated_on<=>b.updated_on} :show_data_points => false,
end :show_data_values => false,
:stagger_x_labels => true,
:style_sheet => "/plugin_assets/redmine_graphs/stylesheets/issue_growth.css",
:timescale_divisions => "1 months",
:width => 720,
:x_label_format => "%b %Y"
})
# Get the top visible projects by issue count
sql = "SELECT project_id, COUNT(*) as issue_count"
sql << " FROM issues"
sql << " LEFT JOIN #{Project.table_name} ON #{Issue.table_name}.project_id = #{Project.table_name}.id"
sql << " WHERE (%s)" % Project.allowed_to_condition(User.current, :view_issues)
sql << " AND (project_id = #{@project.id})" unless @project.nil?
sql << " GROUP BY project_id"
sql << " ORDER BY issue_count DESC"
sql << " LIMIT 6"
top_projects = ActiveRecord::Base.connection.select_all(sql).collect { |p| p["project_id"] }
# Get the issues created per project, per day
sql = "SELECT project_id, date(#{Issue.table_name}.created_on) as date, COUNT(*) as issue_count"
sql << " FROM #{Issue.table_name}"
sql << " WHERE project_id IN (%s)" % top_projects.compact.join(',')
sql << " GROUP BY project_id, date"
issue_counts = ActiveRecord::Base.connection.select_all(sql).group_by { |c| c["project_id"] }
# Displays issues by creation date, cumulatively # Generate the created_on lines
def issue_age_graph top_projects.each do |project_id, total_count|
counts = issue_counts[project_id].sort { |a,b| a["date"]<=>b["date"] }
# Initialize the graph created_count = 0
graph = SVG::Graph::TimeSeries.new({ created_on_line = Hash.new
:area_fill => true, created_on_line[(Date.parse(counts.first["date"])-1).to_s] = 0
:height => 300, counts.each { |count| created_count += count["issue_count"].to_i; created_on_line[count["date"]] = created_count }
:min_y_value => 0, created_on_line[Date.today.to_s] = created_count
:no_css => true, graph.add_data({
:show_x_guidelines => true, :data => created_on_line.sort.flatten,
:scale_x_integers => true, :title => Project.find(project_id).to_s
:scale_y_integers => true, })
:show_data_points => false, end
:show_data_values => false,
:stagger_x_labels => true, # Compile the graph
:style_sheet => "/plugin_assets/redmine_graphs/stylesheets/issue_age.css", headers["Content-Type"] = "image/svg+xml"
:timescale_divisions => "1 weeks", send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline")
:width => 720, end
:x_label_format => "%b %d"
}) def old_issues
@issues_by_created_on = @issues.sort {|a,b| a.created_on<=>b.created_on}
@issues_by_updated_on = @issues.sort {|a,b| a.updated_on<=>b.updated_on}
end
# Group issues # Displays issues by creation date, cumulatively
issues_by_created_on = @issues.group_by {|issue| issue.created_on.to_date }.sort def issue_age_graph
issues_by_updated_on = @issues.group_by {|issue| issue.updated_on.to_date }.sort
# Initialize the graph
# Generate the created_on line graph = SVG::Graph::TimeSeries.new({
created_count = 0 :area_fill => true,
created_on_line = Hash.new :height => 300,
issues_by_created_on.each { |created_on, issues| created_on_line[(created_on-1).to_s] = created_count; created_count += issues.size; created_on_line[created_on.to_s] = created_count } :min_y_value => 0,
created_on_line[Date.today.to_s] = created_count :no_css => true,
graph.add_data({ :show_x_guidelines => true,
:data => created_on_line.sort.flatten, :scale_x_integers => true,
:title => l(:field_created_on) :scale_y_integers => true,
}) :show_data_points => false,
:show_data_values => false,
# Generate the closed_on line :stagger_x_labels => true,
updated_count = 0 :style_sheet => "/plugin_assets/redmine_graphs/stylesheets/issue_age.css",
updated_on_line = Hash.new :timescale_divisions => "1 weeks",
issues_by_updated_on.each { |updated_on, issues| updated_on_line[(updated_on-1).to_s] = updated_count; updated_count += issues.size; updated_on_line[updated_on.to_s] = updated_count } :width => 720,
updated_on_line[Date.today.to_s] = updated_count :x_label_format => "%b %d"
graph.add_data({ })
:data => updated_on_line.sort.flatten,
:title => l(:field_updated_on)
})
# Compile the graph
headers["Content-Type"] = "image/svg+xml"
send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline")
end
# Displays open and total issue counts over time
def target_version_graph
# Initialize the graph # Group issues
graph = SVG::Graph::TimeSeries.new({ issues_by_created_on = @issues.group_by {|issue| issue.created_on.to_date }.sort
:area_fill => true, issues_by_updated_on = @issues.group_by {|issue| issue.updated_on.to_date }.sort
:height => 300,
:no_css => true, # Generate the created_on line
:show_x_guidelines => true, created_count = 0
:scale_x_integers => true, created_on_line = Hash.new
:scale_y_integers => true, issues_by_created_on.each { |created_on, issues| created_on_line[(created_on-1).to_s] = created_count; created_count += issues.size; created_on_line[created_on.to_s] = created_count }
:show_data_points => true, created_on_line[Date.today.to_s] = created_count
:show_data_values => false, graph.add_data({
:stagger_x_labels => true, :data => created_on_line.sort.flatten,
:style_sheet => "/plugin_assets/redmine_graphs/stylesheets/target_version.css", :title => l(:field_created_on)
:width => 800, })
:x_label_format => "%b %d"
}) # Generate the closed_on line
updated_count = 0
updated_on_line = Hash.new
issues_by_updated_on.each { |updated_on, issues| updated_on_line[(updated_on-1).to_s] = updated_count; updated_count += issues.size; updated_on_line[updated_on.to_s] = updated_count }
updated_on_line[Date.today.to_s] = updated_count
graph.add_data({
:data => updated_on_line.sort.flatten,
:title => l(:field_updated_on)
})
# Compile the graph
headers["Content-Type"] = "image/svg+xml"
send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline")
end
# Displays open and total issue counts over time
def target_version_graph
# Group issues # Initialize the graph
issues_by_created_on = @version.fixed_issues.group_by {|issue| issue.created_on.to_date }.sort graph = SVG::Graph::TimeSeries.new({
issues_by_updated_on = @version.fixed_issues.group_by {|issue| issue.updated_on.to_date }.sort :area_fill => true,
issues_by_closed_on = @version.fixed_issues.collect { |issue| issue if issue.closed? }.compact.group_by {|issue| issue.updated_on.to_date }.sort :height => 300,
:no_css => true,
# Set the scope of the graph :show_x_guidelines => true,
scope_end_date = issues_by_updated_on.keys.last :scale_x_integers => true,
scope_end_date = @version.effective_date if !@version.effective_date.nil? && @version.effective_date > scope_end_date :scale_y_integers => true,
scope_end_date = Date.today if !@version.completed? :show_data_points => true,
line_end_date = Date.today :show_data_values => false,
line_end_date = scope_end_date if scope_end_date < line_end_date :stagger_x_labels => true,
:style_sheet => "/plugin_assets/redmine_graphs/stylesheets/target_version.css",
# Generate the created_on line :width => 800,
created_count = 0 :x_label_format => "%b %d"
created_on_line = Hash.new })
issues_by_created_on.each { |created_on, issues| created_on_line[(created_on-1).to_s] = created_count; created_count += issues.size; created_on_line[created_on.to_s] = created_count }
created_on_line[scope_end_date.to_s] = created_count # Group issues
graph.add_data({ issues_by_created_on = @version.fixed_issues.group_by {|issue| issue.created_on.to_date }.sort
:data => created_on_line.sort.flatten, issues_by_updated_on = @version.fixed_issues.group_by {|issue| issue.updated_on.to_date }.sort
:title => l(:label_total).capitalize issues_by_closed_on = @version.fixed_issues.collect { |issue| issue if issue.closed? }.compact.group_by {|issue| issue.updated_on.to_date }.sort
})
# Set the scope of the graph
# Generate the closed_on line scope_end_date = issues_by_updated_on.keys.last
closed_count = 0 scope_end_date = @version.effective_date if !@version.effective_date.nil? && @version.effective_date > scope_end_date
closed_on_line = Hash.new scope_end_date = Date.today if !@version.completed?
issues_by_closed_on.each { |closed_on, issues| closed_on_line[(closed_on-1).to_s] = closed_count; closed_count += issues.size; closed_on_line[closed_on.to_s] = closed_count } line_end_date = Date.today
closed_on_line[line_end_date.to_s] = closed_count line_end_date = scope_end_date if scope_end_date < line_end_date
graph.add_data({
:data => closed_on_line.sort.flatten, # Generate the created_on line
:title => l(:label_closed_issues).capitalize created_count = 0
}) created_on_line = Hash.new
issues_by_created_on.each { |created_on, issues| created_on_line[(created_on-1).to_s] = created_count; created_count += issues.size; created_on_line[created_on.to_s] = created_count }
# Add the version due date marker created_on_line[scope_end_date.to_s] = created_count
graph.add_data({ graph.add_data({
:data => [@version.effective_date.to_s, created_count], :data => created_on_line.sort.flatten,
:title => l(:field_due_date).capitalize :title => l(:label_total).capitalize
}) unless @version.effective_date.nil? })
# Generate the closed_on line
# Compile the graph closed_count = 0
headers["Content-Type"] = "image/svg+xml" closed_on_line = Hash.new
send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline") issues_by_closed_on.each { |closed_on, issues| closed_on_line[(closed_on-1).to_s] = closed_count; closed_count += issues.size; closed_on_line[closed_on.to_s] = closed_count }
end closed_on_line[line_end_date.to_s] = closed_count
graph.add_data({
:data => closed_on_line.sort.flatten,
private :title => l(:label_closed_issues).capitalize
})
def find_open_issues
find_optional_project # Add the version due date marker
@issues = Issue.visible.find(:all, :include => [:status], :conditions => ["#{IssueStatus.table_name}.is_closed=?", false]) if @project.nil? graph.add_data({
@issues = @project.issues.collect { |issue| issue unless issue.closed? }.compact unless @project.nil? :data => [@version.effective_date.to_s, created_count],
rescue ActiveRecord::RecordNotFound :title => l(:field_due_date).capitalize
render_404 }) unless @version.effective_date.nil?
end
def find_optional_project # Compile the graph
@project = Project.find(params[:project_id]) unless params[:project_id].blank? headers["Content-Type"] = "image/svg+xml"
deny_access unless User.current.allowed_to?(:view_issues, @project, :global => true) send_data(graph.burn, :type => "image/svg+xml", :disposition => "inline")
rescue ActiveRecord::RecordNotFound end
render_404
end
private
def find_version
@version = Version.find(params[:id]) def find_open_issues
deny_access unless User.current.allowed_to?(:view_issues, @version.project) find_optional_project
rescue ActiveRecord::RecordNotFound @issues = Issue.visible.find(:all, :include => [:status], :conditions => ["#{IssueStatus.table_name}.is_closed=?", false]) if @project.nil?
render_404 @issues = @project.issues.collect { |issue| issue unless issue.closed? }.compact unless @project.nil?
end rescue ActiveRecord::RecordNotFound
render_404
end
def find_optional_project
@project = Project.find(params[:project_id]) unless params[:project_id].blank?
deny_access unless User.current.allowed_to?(:view_issues, @project, :global => true)
rescue ActiveRecord::RecordNotFound
render_404
end
def find_version
@version = Version.find(params[:id])
deny_access unless User.current.allowed_to?(:view_issues, @version.project)
rescue ActiveRecord::RecordNotFound
render_404
end
end end