Project

General

Profile

Feature #3436 » gantt-relations-r10973.diff

Toshi MARUYAMA, 2012-12-10 11:04

View differences:

app/views/gantts/show.html.erb
1
<% content_for :header_tags do %>
2
  <%= javascript_include_tag 'raphael' %>
3
  <%= javascript_include_tag 'gantt' %>
4
<% end %>
5
<%= javascript_tag do %>
6
  $(document).ready(drawGanttHandler);
7
  $(window).resize(drawGanttHandler);
8
<% end %>
1 9
<% @gantt.view = self %>
2 10
<h2><%= @query.new_record? ? l(:label_gantt) : h(@query.name) %></h2>
3 11

  
......
102 110
</td>
103 111

  
104 112
<td>
105
<div style="position:relative;height:<%= t_height + 24 %>px;overflow:auto;">
113
<div style="position:relative;height:<%= t_height + 24 %>px;overflow:auto;" id="gantt_area">
106 114
<%
107 115
  style  = ""
108 116
  style += "width: #{g_width - 1}px;"
......
231 239
  %>
232 240
  <%= content_tag(:div, '&nbsp;'.html_safe, :style => style) %>
233 241
<% end %>
234

  
242
<%
243
  style  = ""
244
  style += "position: absolute;"
245
  style += "height: #{g_height}px;"
246
  style += "top: #{headers_height + 1}px;"
247
  style += "left: 0px;"
248
  style += "width: #{g_width - 1}px;"
249
%>
250
<%= content_tag(:div, '', :style => style, :id => "gantt_draw_area") %>
235 251
</div>
236 252
</td>
237 253
</tr>
public/javascripts/gantt.js
1
var draw_gantt = null;
2
var draw_top;
3
var draw_right;
4
var draw_left;
5

  
6
function setDrawArea() {
7
  draw_top   = $("#gantt_draw_area").position().top;
8
  draw_right = $("#gantt_draw_area").width();
9
  draw_left  = $("#gantt_area").scrollLeft();
10
}
11

  
12
function drawGanttHandler() {
13
  var folder = document.getElementById('gantt_draw_area');
14
  if(draw_gantt != null)
15
    draw_gantt.clear();
16
  else
17
    draw_gantt = Raphael(folder);
18
  setDrawArea();
19
}
app/views/gantts/show.html.erb
3 3
  <%= javascript_include_tag 'gantt' %>
4 4
<% end %>
5 5
<%= javascript_tag do %>
6
  var issue_relation_type = <%= IssueRelation::TYPES.to_json.html_safe %>;
6 7
  $(document).ready(drawGanttHandler);
7 8
  $(window).resize(drawGanttHandler);
9
  $(function() {
10
    $.each($("#draw_rels").children("label").children("input"), function(index, element) {
11
      $(element).change(drawGanttHandler);
12
    });
13
  });
8 14
<% end %>
9 15
<% @gantt.view = self %>
10 16
<h2><%= @query.new_record? ? l(:label_gantt) : h(@query.name) %></h2>
......
20 26
    <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
21 27
  </div>
22 28
</fieldset>
29
<fieldset id="filters" class="collapsible">
30
  <legend onclick="toggleFieldset(this);"><%= l(:label_display) %></legend>
31
  <div>
32
    <fieldset id = "draw_rels">
33
      <legend><%= l(:label_related_issues) %></legend>
34
      <%
35
        rels = IssueRelation::TYPES.to_a.select {|rel|
36
          rel[1][:reverse].nil?
37
        }
38
        rels_sorted = rels.sort {|x, y|
39
                        x[1][:order] <=> y[1][:order]
40
                      }.collect{|v| [v[0], l(v[1][:name])]}
41
      %>
42
      <% rels_sorted.each do |rel| %>
43
        <label>
44
          <%= check_box_tag "draw_#{rel[0]}", 0, params["draw_#{rel[0]}"] %>
45
          <%= content_tag(:span, '&nbsp;&nbsp;&nbsp;'.html_safe,
46
                          :id => "gantt_draw_rel_color_#{rel[0]}") %>
47
          <%= rel[1] %>
48
        </label>
49
      <% end %>
50
    </fieldset>
51
  </div>
52
</fieldset>
23 53

  
24 54
<p class="contextual">
25 55
  <%= gantt_zoom_link(@gantt, :in) %>
lib/redmine/helpers/gantt.rb
705 705
        params[:image].text(params[:indent], params[:top] + 2, subject)
706 706
      end
707 707

  
708
      def issue_relations(issue)
709
        relations = {}
710
        issue.relations_to.each do |relation|
711
          relation_type = relation.relation_type_for(relation.issue_to)
712
          (relations[relation_type] ||= []) << relation.issue_from_id
713
        end
714
        relations
715
      end
716

  
708 717
      def html_task(params, coords, options={})
709 718
        output = ''
710 719
        # Renders the task bar, with progress and late
......
714 723
          style << "top:#{params[:top]}px;"
715 724
          style << "left:#{coords[:bar_start]}px;"
716 725
          style << "width:#{width}px;"
717
          output << view.content_tag(:div, '&nbsp;'.html_safe,
718
                                     :style => style,
719
                                     :class => "#{options[:css]} task_todo")
726
          html_id = "task-todo-issue-#{options[:issue].id}" if options[:issue]
727
          content_opt = {:style => style,
728
                         :class => "#{options[:css]} task_todo",
729
                         :id => html_id}
730
          if options[:issue]
731
            rels_hash = {}
732
            issue_relations(options[:issue]).each do |k, v|
733
              rels_hash[k] = v.join(',')
734
            end
735
            content_opt[:data] = {"rels" => rels_hash}
736
          end
737
          output << view.content_tag(:div, '&nbsp;'.html_safe, content_opt)
720 738
          if coords[:bar_late_end]
721 739
            width = coords[:bar_late_end] - coords[:bar_start] - 2
722 740
            style = ""
public/javascripts/gantt.js
3 3
var draw_right;
4 4
var draw_left;
5 5

  
6
var draw_relations = {
7
  "relates": {
8
    "landscape_margin": 8,
9
    "no_arrow": true,
10
  },
11
  "duplicates": {
12
    "landscape_margin": 12,
13
  },
14
  "blocks": {
15
    "landscape_margin": 16,
16
  },
17
  "precedes": {
18
    "landscape_margin": 20,
19
  },
20
  "copied_to": {
21
    "landscape_margin": 24,
22
  },
23
};
24

  
6 25
function setDrawArea() {
7 26
  draw_top   = $("#gantt_draw_area").position().top;
8 27
  draw_right = $("#gantt_draw_area").width();
9 28
  draw_left  = $("#gantt_area").scrollLeft();
10 29
}
11 30

  
31
function getRelationsArray() {
32
  var arr = new Array();
33
  $.each($('div.task_todo'), function(index_div, element) {
34
    var element_id = $(element).attr("id");
35
    if (element_id != null) {
36
      var issue_id = element_id.replace("task-todo-issue-", "");
37
      var data_rels = $(element).data("rels");
38
      if (data_rels != null) {
39
        for (rel_type_key in issue_relation_type) {
40
          if (rel_type_key in data_rels) {
41
            var issue_arr = data_rels[rel_type_key].toString().split(",");
42
            if ("reverse" in issue_relation_type[rel_type_key]) {
43
              $.each(issue_arr, function(index_issue, element_issue) {
44
                arr.push({issue_from: element_issue, issue_to: issue_id,
45
                          rel_type: issue_relation_type[rel_type_key]["reverse"]});
46
              });
47
            } else {
48
              $.each(issue_arr, function(index_issue, element_issue) {
49
                arr.push({issue_from: issue_id, issue_to: element_issue,
50
                          rel_type: rel_type_key});
51
              });
52
            }
53
          }
54
        }
55
      }
56
    }
57
  });
58
  return arr;
59
}
60

  
61
function drawRelations() {
62
  var arr = getRelationsArray();
63
  $.each(arr, function(index_issue, element_issue) {
64
    if (!$("#draw_" + element_issue["rel_type"]).attr('checked')) {
65
      return;
66
    }
67
    var issue_from = $("#task-todo-issue-" + element_issue["issue_from"]);
68
    var issue_to   = $("#task-todo-issue-" + element_issue["issue_to"]);
69
    if (issue_from.size() == 0 || issue_to.size() == 0) {
70
      return;
71
    }
72
    var issue_height = issue_from.height();
73
    var issue_from_top   = issue_from.position().top  + (issue_height / 2) - draw_top;
74
    var issue_from_right = issue_from.position().left + issue_from.width();
75
    var issue_to_top   = issue_to.position().top  + (issue_height / 2) - draw_top;
76
    var issue_to_left  = issue_to.position().left;
77
    var color = $("#gantt_draw_rel_color_" + element_issue["rel_type"])
78
                    .css("background-color");
79
    var landscape_margin = draw_relations[element_issue["rel_type"]]["landscape_margin"];
80
    var issue_from_right_rel = issue_from_right + landscape_margin;
81
    var issue_to_left_rel    = issue_to_left    - landscape_margin;
82
    var x1, y1, x2, y2;
83
    draw_gantt.path(["M", issue_from_right + draw_left,     issue_from_top,
84
                     "L", issue_from_right_rel + draw_left, issue_from_top])
85
                   .attr({stroke: color, "stroke-width": 2});
86
    if (issue_from_right_rel < issue_to_left_rel) {
87
      draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top,
88
                       "L", issue_from_right_rel + draw_left, issue_to_top])
89
                   .attr({stroke: color, "stroke-width": 2});
90
      draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_to_top,
91
                       "L", issue_to_left + draw_left,        issue_to_top])
92
                   .attr({stroke: color,
93
                          "stroke-width": 2,
94
                          "stroke-linecap": "butt",
95
                          "stroke-linejoin": "miter",
96
                          });
97
    } else {
98
      var issue_middle_top = issue_to_top +
99
                                (issue_height *
100
                                   ((issue_from_top > issue_to_top) ? 1 : -1));
101
      draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top,
102
                       "L", issue_from_right_rel + draw_left, issue_middle_top])
103
                   .attr({stroke: color, "stroke-width": 2});
104
      draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_middle_top,
105
                       "L", issue_to_left_rel + draw_left,    issue_middle_top])
106
                   .attr({stroke:color, "stroke-width": 2});
107
      draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_middle_top,
108
                       "L", issue_to_left_rel + draw_left, issue_to_top])
109
                   .attr({stroke: color, "stroke-width": 2});
110
      draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_to_top,
111
                       "L", issue_to_left + draw_left,     issue_to_top])
112
                   .attr({stroke: color,
113
                          "stroke-width": 2,
114
                          "stroke-linecap": "butt",
115
                          "stroke-linejoin": "miter",
116
                          });
117
    }
118
    if (!("no_arrow" in draw_relations[element_issue["rel_type"]])) {
119
      draw_gantt.path(["M", issue_to_left + draw_left, issue_to_top,
120
                       "l", -8, -4, "l", 0, 8, "z"])
121
                   .attr({stroke: "none",
122
                          fill: color,
123
                          "stroke-linecap": "butt",
124
                          "stroke-linejoin": "miter",
125
                          });
126
    }
127
  });
128
}
129

  
12 130
function drawGanttHandler() {
13 131
  var folder = document.getElementById('gantt_draw_area');
14 132
  if(draw_gantt != null)
......
16 134
  else
17 135
    draw_gantt = Raphael(folder);
18 136
  setDrawArea();
137
  drawRelations();
19 138
}
public/stylesheets/application.css
872 872
a.close-icon:hover {background-image:url('../images/close_hl.png');}
873 873

  
874 874
/***** Gantt chart *****/
875
#gantt_draw_rel_color_relates    {background-color:#00c551;}
876
#gantt_draw_rel_color_duplicates {background-color:#4f52c3;}
877
#gantt_draw_rel_color_blocks     {background-color:#fb7d2f;}
878
#gantt_draw_rel_color_precedes   {background-color:#df347c;}
879
#gantt_draw_rel_color_copied_to  {background-color:#00c5c2;}
880

  
875 881
.gantt_hdr {
876 882
  position:absolute;
877 883
  top:0;
(5-5/13)