# HG changeset patch # User Toshi MARUYAMA # Date 1354592875 -32400 # Node ID 4bd9e13ad4e14c905a603b15207460a346065567 # Parent 3ebf2ed02a399e420fde6c7c39bc7763b687e8e9 gantt: (#3436, #12122) diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -1,3 +1,11 @@ +<% content_for :header_tags do %> + <%= javascript_include_tag 'raphael' %> + <%= javascript_include_tag 'gantt' %> +<% end %> +<%= javascript_tag do %> + $(document).ready(drawGanttHandler); + $(window).resize(drawGanttHandler); +<% end %> <% @gantt.view = self %>
<%= gantt_zoom_link(@gantt, :in) %> diff --git a/lib/redmine/helpers/gantt.rb b/lib/redmine/helpers/gantt.rb --- a/lib/redmine/helpers/gantt.rb +++ b/lib/redmine/helpers/gantt.rb @@ -705,6 +705,17 @@ module Redmine params[:image].text(params[:indent], params[:top] + 2, subject) end + def issue_relations(issue) + relations = {} + issue.relations_to.each do |relation| + relation_type = relation.relation_type_for(relation.issue_to) + if !IssueRelation::DRAW_TYPES[relation_type].nil? + (relations[relation_type] ||= []) << relation.issue_from_id + end + end + relations + end + def html_task(params, coords, options={}) output = '' # Renders the task bar, with progress and late @@ -714,9 +725,18 @@ module Redmine style << "top:#{params[:top]}px;" style << "left:#{coords[:bar_start]}px;" style << "width:#{width}px;" - output << view.content_tag(:div, ' '.html_safe, - :style => style, - :class => "#{options[:css]} task_todo") + html_id = "task-todo-issue-#{options[:issue].id}" if options[:issue] + content_opt = {:style => style, + :class => "#{options[:css]} task_todo", + :id => html_id} + if options[:issue] + rels_hash = {} + issue_relations(options[:issue]).each do |k, v| + rels_hash[k] = v.join(',') + end + content_opt[:data] = {"rels" => rels_hash} + end + output << view.content_tag(:div, ' '.html_safe, content_opt) if coords[:bar_late_end] width = coords[:bar_late_end] - coords[:bar_start] - 2 style = "" diff --git a/public/javascripts/gantt.js b/public/javascripts/gantt.js --- a/public/javascripts/gantt.js +++ b/public/javascripts/gantt.js @@ -9,6 +9,99 @@ function setDrawArea() { draw_left = $("#gantt_area").scrollLeft(); } +function getRelationsArray() { + var arr = new Array(); + $.each($('div.task_todo'), function(index_div, element) { + var element_id = $(element).attr("id"); + if (element_id != null) { + var issue_id = element_id.replace("task-todo-issue-", ""); + var data_rels = $(element).data("rels"); + if (data_rels != null) { + for (rel_type_key in issue_relation_type) { + if (rel_type_key in data_rels) { + var issue_arr = data_rels[rel_type_key].toString().split(","); + if ("reverse" in issue_relation_type[rel_type_key]) { + $.each(issue_arr, function(index_issue, element_issue) { + arr.push({issue_from: element_issue, issue_to: issue_id, + rel_type: issue_relation_type[rel_type_key]["reverse"]}); + }); + } else { + $.each(issue_arr, function(index_issue, element_issue) { + arr.push({issue_from: issue_id, issue_to: element_issue, + rel_type: rel_type_key}); + }); + } + } + } + } + } + }); + return arr; +} + +function drawRelations() { + var arr = getRelationsArray(); + $.each(arr, function(index_issue, element_issue) { + var issue_from = $("#task-todo-issue-" + element_issue["issue_from"]); + var issue_to = $("#task-todo-issue-" + element_issue["issue_to"]); + if (issue_from.size() == 0 || issue_to.size() == 0) { + return; + } + var issue_height = issue_from.height(); + var issue_from_top = issue_from.position().top + (issue_height / 2) - draw_top; + var issue_from_right = issue_from.position().left + issue_from.width(); + var issue_to_top = issue_to.position().top + (issue_height / 2) - draw_top; + var issue_to_left = issue_to.position().left; + var color = $("#gantt_draw_rel_color_" + element_issue["rel_type"]) + .css("background-color"); + var landscape_margin = issue_relation_type[element_issue["rel_type"]]["landscape_margin"]; + var issue_from_right_rel = issue_from_right + landscape_margin; + var issue_to_left_rel = issue_to_left - landscape_margin; + draw_gantt.path(["M", issue_from_right + draw_left, issue_from_top, + "L", issue_from_right_rel + draw_left, issue_from_top]) + .attr({stroke: color, "stroke-width": 2}); + if (issue_from_right_rel < issue_to_left_rel) { + draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top, + "L", issue_from_right_rel + draw_left, issue_to_top]) + .attr({stroke: color, "stroke-width": 2}); + draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_to_top, + "L", issue_to_left + draw_left, issue_to_top]) + .attr({stroke: color, + "stroke-width": 2, + "stroke-linecap": "butt", + "stroke-linejoin": "miter", + }); + } else { + var issue_middle_top = issue_to_top + + (issue_height * + ((issue_from_top > issue_to_top) ? 1 : -1)); + draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top, + "L", issue_from_right_rel + draw_left, issue_middle_top]) + .attr({stroke: color, "stroke-width": 2}); + draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_middle_top, + "L", issue_to_left_rel + draw_left, issue_middle_top]) + .attr({stroke:color, "stroke-width": 2}); + draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_middle_top, + "L", issue_to_left_rel + draw_left, issue_to_top]) + .attr({stroke: color, "stroke-width": 2}); + draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_to_top, + "L", issue_to_left + draw_left, issue_to_top]) + .attr({stroke: color, + "stroke-width": 2, + "stroke-linecap": "butt", + "stroke-linejoin": "miter", + }); + } + draw_gantt.path(["M", issue_to_left + draw_left, issue_to_top, + "l", -8, -4, "l", 0, 8, "z"]) + .attr({stroke: "none", + fill: color, + "stroke-linecap": "butt", + "stroke-linejoin": "miter", + }); + }); +} + function drawGanttHandler() { var folder = document.getElementById('gantt_draw_area'); if(draw_gantt != null) @@ -16,4 +109,6 @@ function drawGanttHandler() { else draw_gantt = Raphael(folder); setDrawArea(); + if ($("#draw_rels").attr('checked')) + drawRelations(); } diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -879,6 +879,9 @@ a.close-icon { a.close-icon:hover {background-image:url('../images/close_hl.png');} /***** Gantt chart *****/ +#gantt_draw_rel_color_blocks {background-color:#fb7d2f;} +#gantt_draw_rel_color_precedes {background-color:#df347c;} + .gantt_hdr { position:absolute; top:0;