| 70 | 70 |          | 
  | 71 | 71 |         @subjects = '' | 
  | 72 | 72 |         @lines = '' | 
  |  | 73 |         @calendars = '' | 
  | 73 | 74 |         @number_of_rows = nil | 
  | 74 | 75 |          | 
  | 75 | 76 |         @issue_ancestors = [] | 
  | ... | ... |  | 
  | 154 | 155 |         render(options.merge(:only => :lines)) unless @lines_rendered | 
  | 155 | 156 |         @lines | 
  | 156 | 157 |       end | 
  |  | 158 |  | 
  |  | 159 |       # Renders the calendars of the Gantt chart, the right side | 
  |  | 160 |       def calendars(options={}) | 
  |  | 161 |         render(options.merge(:only => :calendars)) unless @calendars_rendered | 
  |  | 162 |         @calendars | 
  |  | 163 |       end | 
  | 157 | 164 |        | 
  | 158 | 165 |       def render(options={}) | 
  | 159 | 166 |         options = {:indent => 4, :render => :subject, :format => :html}.merge(options) | 
  | 160 | 167 |          | 
  | 161 |  |         @subjects = '' unless options[:only] == :lines | 
  | 162 |  |         @lines = '' unless options[:only] == :subjects | 
  |  | 168 |         @subjects = '' unless options[:only] == :lines && options[:only] == :calendars | 
  |  | 169 |         @lines = '' unless options[:only] == :subjects && options[:only] == :calendars | 
  |  | 170 |         @calendars = '' unless options[:only] == :lines && options[:only] == :subjects | 
  | 163 | 171 |         @number_of_rows = 0 | 
  | 164 | 172 |          | 
  | 165 | 173 |         if @project | 
  | ... | ... |  | 
  | 171 | 179 |           end | 
  | 172 | 180 |         end | 
  | 173 | 181 |          | 
  | 174 |  |         @subjects_rendered = true unless options[:only] == :lines | 
  | 175 |  |         @lines_rendered = true unless options[:only] == :subjects | 
  |  | 182 |         @subjects_rendered = true unless options[:only] == :lines && options[:only] == :calendars | 
  |  | 183 |         @lines_rendered = true unless options[:only] == :subjects && options[:only] == :calendars | 
  |  | 184 |         @calendars_rendered = true unless options[:only] == :lines && options[:only] == :subjects | 
  | 176 | 185 |          | 
  | 177 | 186 |         render_end(options) | 
  | 178 | 187 |       end | 
  | ... | ... |  | 
  | 182 | 191 |         options[:indent_increment] = 20 unless options.key? :indent_increment | 
  | 183 | 192 |         options[:top_increment] = 20 unless options.key? :top_increment | 
  | 184 | 193 |  | 
  | 185 |  |         subject_for_project(project, options) unless options[:only] == :lines | 
  | 186 |  |         line_for_project(project, options) unless options[:only] == :subjects | 
  |  | 194 |         subject_for_project(project, options) unless options[:only] == :lines && options[:only] == :calendars | 
  |  | 195 |         line_for_project(project, options) unless options[:only] == :subjects && options[:only] == :calendars | 
  |  | 196 |         calendar_for_project(project, options) unless options[:only] == :lines && options[:only] == :subjects | 
  | 187 | 197 |          | 
  | 188 | 198 |         options[:top] += options[:top_increment] | 
  | 189 | 199 |         options[:indent] += options[:indent_increment] | 
  | ... | ... |  | 
  | 218 | 228 |         @issue_ancestors = [] | 
  | 219 | 229 |          | 
  | 220 | 230 |         issues.each do |i| | 
  | 221 |  |           subject_for_issue(i, options) unless options[:only] == :lines | 
  | 222 |  |           line_for_issue(i, options) unless options[:only] == :subjects | 
  |  | 231 |           subject_for_issue(i, options) unless options[:only] == :lines && options[:only] == :calendars | 
  |  | 232 |           line_for_issue(i, options) unless options[:only] == :subjects && options[:only] == :calendars | 
  |  | 233 |           calendar_for_issue(i, options) unless options[:only] == :lines && options[:only] == :subjects | 
  | 223 | 234 |            | 
  | 224 | 235 |           options[:top] += options[:top_increment] | 
  | 225 | 236 |           @number_of_rows += 1 | 
  | ... | ... |  | 
  | 231 | 242 |  | 
  | 232 | 243 |       def render_version(version, options={}) | 
  | 233 | 244 |         # Version header | 
  | 234 |  |         subject_for_version(version, options) unless options[:only] == :lines | 
  | 235 |  |         line_for_version(version, options) unless options[:only] == :subjects | 
  | 236 |  |          | 
  |  | 245 |         subject_for_version(version, options) unless options[:only] == :lines && options[:only] == :calendars | 
  |  | 246 |         line_for_version(version, options) unless options[:only] == :subjects && options[:only] == :calendars | 
  |  | 247 |         calendar_for_version(version, options) unless options[:only] == :lines && options[:only] == :subjects | 
  |  | 248 |  | 
  | 237 | 249 |         options[:top] += options[:top_increment] | 
  | 238 | 250 |         @number_of_rows += 1 | 
  | 239 | 251 |         return if abort? | 
  | ... | ... |  | 
  | 286 | 298 |            | 
  | 287 | 299 |           case options[:format] | 
  | 288 | 300 |           when :html | 
  | 289 |  |             html_task(options, coords, :css => "project task", :label => label, :markers => true) | 
  |  | 301 |             html_task(options, coords, :css => "project task", :label => label, :markers => true, :id => project.id, :kind => "p") | 
  | 290 | 302 |           when :image | 
  | 291 | 303 |             image_task(options, coords, :label => label, :markers => true, :height => 3) | 
  | 292 | 304 |           when :pdf | 
  | ... | ... |  | 
  | 325 | 337 |  | 
  | 326 | 338 |           case options[:format] | 
  | 327 | 339 |           when :html | 
  | 328 |  |             html_task(options, coords, :css => "version task", :label => label, :markers => true) | 
  |  | 340 |             html_task(options, coords, :css => "version task", :label => label, :markers => true, :id => version.id, :kind => "v") | 
  | 329 | 341 |           when :image | 
  | 330 | 342 |             image_task(options, coords, :label => label, :markers => true, :height => 3) | 
  | 331 | 343 |           when :pdf | 
  | ... | ... |  | 
  | 378 | 390 |         if issue.is_a?(Issue) && issue.due_before | 
  | 379 | 391 |           coords = coordinates(issue.start_date, issue.due_before, issue.done_ratio, options[:zoom]) | 
  | 380 | 392 |           label = "#{ issue.status.name } #{ issue.done_ratio }%" | 
  |  | 393 |           if !issue.due_date && issue.fixed_version | 
  |  | 394 |             label += "- <strong>#{h(issue.fixed_version.name)}</strong>" | 
  |  | 395 |           end | 
  | 381 | 396 |            | 
  | 382 | 397 |           case options[:format] | 
  | 383 | 398 |           when :html | 
  | 384 |  |             html_task(options, coords, :css => "task " + (issue.leaf? ? 'leaf' : 'parent'), :label => label, :issue => issue, :markers => !issue.leaf?) | 
  |  | 399 |             html_task(options, coords, :css => "task " + (issue.leaf? ? 'leaf' : 'parent'), :label => label, :issue => issue, :markers => !issue.leaf?, :id => issue.id, :kind => "i") | 
  | 385 | 400 |           when :image | 
  | 386 | 401 |             image_task(options, coords, :label => label) | 
  | 387 | 402 |           when :pdf | 
  | ... | ... |  | 
  | 393 | 408 |         end | 
  | 394 | 409 |       end | 
  | 395 | 410 |  | 
  | 396 |  |       # Generates a gantt image | 
  |  | 411 |     # Generates a gantt image | 
  | 397 | 412 |       # Only defined if RMagick is avalaible | 
  | 398 | 413 |       def to_image(format='PNG') | 
  | 399 | 414 |         date_to = (@date_from >> @months)-1     | 
  | ... | ... |  | 
  | 621 | 636 |         pdf.Output | 
  | 622 | 637 |       end | 
  | 623 | 638 |        | 
  |  | 639 |       def edit(pms) | 
  |  | 640 |         id = pms[:id] | 
  |  | 641 |         kind = id.slice!(0).chr | 
  |  | 642 |         begin | 
  |  | 643 |           case kind | 
  |  | 644 |           when 'i' | 
  |  | 645 |             @issue = Issue.find(pms[:id], :include => [:project, :tracker, :status, :author, :priority, :category]) | 
  |  | 646 |           when 'p' | 
  |  | 647 |             @issue = Project.find(pms[:id]) | 
  |  | 648 |           when 'v' | 
  |  | 649 |             @issue = Version.find(pms[:id], :include => [:project]) | 
  |  | 650 |           end | 
  |  | 651 |         rescue ActiveRecord::RecordNotFound | 
  |  | 652 |           return "issue not found : #{pms[:id]}", 400 | 
  |  | 653 |         end | 
  |  | 654 |  | 
  |  | 655 |         if !@issue.start_date || !@issue.due_before | 
  |  | 656 |           #render :text=>l(:notice_locking_conflict), :status=>400 | 
  |  | 657 |           return l(:notice_locking_conflict), 400 | 
  |  | 658 |         end | 
  |  | 659 |         @issue.init_journal(User.current) | 
  |  | 660 |         date_from = Date.parse(pms[:date_from]) | 
  |  | 661 |         old_start_date = @issue.start_date | 
  |  | 662 |         o = get_issue_position(@issue, pms[:zoom]) | 
  |  | 663 |         text_for_revert = "#{kind}#{id}=#{format_date(@issue.start_date)},#{@issue.start_date},#{format_date(@issue.due_before)},#{@issue.due_before},#{o[0]},#{o[1]},#{o[2]},#{o[3]}" | 
  |  | 664 |  | 
  |  | 665 |         if pms[:day] | 
  |  | 666 |           #bar moved | 
  |  | 667 |           day = pms[:day].to_i | 
  |  | 668 |           duration = @issue.due_before - @issue.start_date | 
  |  | 669 |           @issue.start_date = date_from + day | 
  |  | 670 |           @issue.due_date = @issue.start_date + duration.to_i if @issue.due_date | 
  |  | 671 |         elsif pms[:start_date] | 
  |  | 672 |           #start date changed | 
  |  | 673 |           start_date = Date.parse(pms[:start_date]) | 
  |  | 674 |           if @issue.start_date == start_date | 
  |  | 675 |             #render :text=>"" | 
  |  | 676 |             return "", 200 #nothing has changed | 
  |  | 677 |           end | 
  |  | 678 |           @issue.start_date = start_date | 
  |  | 679 |           @issue.due_date = start_date if @issue.due_date && start_date > @issue.due_date | 
  |  | 680 |         elsif pms[:due_date] | 
  |  | 681 |           #due date changed | 
  |  | 682 |           due_date = Date.parse(pms[:due_date]) | 
  |  | 683 |           if @issue.due_date == due_date | 
  |  | 684 |             #render :text=>"" | 
  |  | 685 |             return "", 200 #nothing has changed | 
  |  | 686 |           end | 
  |  | 687 |           @issue.due_date = due_date | 
  |  | 688 |           @issue.start_date = due_date if due_date < @issue.start_date | 
  |  | 689 |         end | 
  |  | 690 |         fv = @issue.fixed_version | 
  |  | 691 |         if fv && fv.effective_date && !@issue.due_date && fv.effective_date < @issue.start_date | 
  |  | 692 |           @issue.start_date = old_start_date | 
  |  | 693 |         end | 
  |  | 694 |  | 
  |  | 695 |         begin | 
  |  | 696 |           @issue.save! | 
  |  | 697 |           o = get_issue_position(@issue, pms[:zoom]) | 
  |  | 698 |           text = "#{kind}#{id}=#{format_date(@issue.start_date)},#{@issue.start_date},#{format_date(@issue.due_before)},#{@issue.due_before},#{o[0]},#{o[1]},#{o[2]},#{o[3]}" | 
  |  | 699 |  | 
  |  | 700 |           prj_map = {} | 
  |  | 701 |           text = set_project_data(@issue.project, pms[:zoom], text, prj_map) | 
  |  | 702 |           version_map = {} | 
  |  | 703 |           text = set_version_data(@issue.fixed_version, pms[:zoom], text, version_map) | 
  |  | 704 |  | 
  |  | 705 |           #check dependencies | 
  |  | 706 |           issues = @issue.all_precedes_issues | 
  |  | 707 |           issues.each do |i| | 
  |  | 708 |             o = get_issue_position(i, pms[:zoom]) | 
  |  | 709 |             text += "|i#{i.id}=#{format_date(i.start_date)},#{i.start_date},#{format_date(i.due_before)},#{i.due_before},#{o[0]},#{o[1]},#{o[2]},#{o[3]}" | 
  |  | 710 |             text = set_project_data(i.project, pms[:zoom], text, prj_map) | 
  |  | 711 |             text = set_version_data(i.fixed_version, pms[:zoom], text, version_map) | 
  |  | 712 |           end | 
  |  | 713 |           #render :text=>text | 
  |  | 714 |           return text, 200 | 
  |  | 715 |         rescue => e | 
  |  | 716 |           #render :text=>@issue.errors.full_messages.join("\n") + "|" + text_for_revert  , :status=>400 | 
  |  | 717 |           if @issue.errors.full_messages.to_s == "" | 
  |  | 718 |             return e.to_s + "\n" + [$!,$@.join("\n")].join("\n") + "\n" + @issue.errors.full_messages.join("\n") + "|" + text_for_revert, 400 | 
  |  | 719 |           else | 
  |  | 720 |             return @issue.errors.full_messages.join("\n") + "|" + text_for_revert, 400 | 
  |  | 721 |           end | 
  |  | 722 |         end | 
  |  | 723 |       end | 
  |  | 724 |  | 
  | 624 | 725 |       private | 
  | 625 | 726 |        | 
  | 626 | 727 |       def coordinates(start_date, end_date, progress, zoom=nil) | 
  | ... | ... |  | 
  | 739 | 840 |         output = '' | 
  | 740 | 841 |         # Renders the task bar, with progress and late | 
  | 741 | 842 |         if coords[:bar_start] && coords[:bar_end] | 
  | 742 |  |           output << "<div style='top:#{ params[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_end] - coords[:bar_start] - 2}px;' class='#{options[:css]} task_todo'> </div>" | 
  |  | 843 |           i_width = coords[:bar_end] - coords[:bar_start] - 2 | 
  |  | 844 |           output << "<div id='ev_#{options[:kind]}#{options[:id]}' style='position:absolute;left:#{coords[:bar_start]}px;top:#{params[:top]}px;padding-top:3px;height:18px;width:#{ i_width + 100}px;' #{options[:kind] == 'i' ? "class='handle'" : ""}>" | 
  |  | 845 |           output << "<div id='task_todo_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:#{ i_width}px;' class='#{options[:css]} task_todo'> </div>" | 
  | 743 | 846 |            | 
  | 744 | 847 |           if coords[:bar_late_end] | 
  | 745 |  |             output << "<div style='top:#{ params[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_late_end] - coords[:bar_start] - 2}px;' class='#{options[:css]} task_late'> </div>" | 
  |  | 848 |             l_width = coords[:bar_late_end] - coords[:bar_start] - 2 | 
  |  | 849 |             output << "<div id='task_late_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:#{ l_width}px;' class='#{ l_width == 0 ? options[:css] + " task_none" : options[:css] + " task_late"}'> </div>" | 
  |  | 850 |           else | 
  |  | 851 |             output << "<div id='task_late_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:0px;' class='#{ options[:css] + " task_none"}'> </div>" | 
  | 746 | 852 |           end | 
  | 747 | 853 |           if coords[:bar_progress_end] | 
  | 748 |  |             output << "<div style='top:#{ params[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_progress_end] - coords[:bar_start] - 2}px;' class='#{options[:css]} task_done'> </div>" | 
  |  | 854 |             d_width = coords[:bar_progress_end] - coords[:bar_start] - 2 | 
  |  | 855 |             output << "<div id='task_done_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:#{ d_width}px;' class='#{ d_width == 0 ? options[:css] + " task_none" : options[:css] + " task_done"}'> </div>" | 
  |  | 856 |           else | 
  |  | 857 |             output << "<div id='task_done_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:0px;' class='#{ options[:css] + " task_none"}'> </div>" | 
  | 749 | 858 |           end | 
  |  | 859 |           output << "</div>" | 
  |  | 860 |         else | 
  |  | 861 |           output << "<div id='ev_#{options[:kind]}#{options[:id]}' style='position:absolute;left:0px;top:#{params[:top]}px;padding-top:3px;height:18px;width:0px;' #{options[:kind] == 'i' ? "class='handle'" : ""}>" | 
  |  | 862 |           output << "<div id='task_todo_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:0px;' class='#{ options[:css]} task_todo'> </div>" | 
  |  | 863 |           output << "<div id='task_late_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:0px;' class='#{ options[:css] + " task_none"}'> </div>" | 
  |  | 864 |           output << "<div id='task_done_#{options[:kind]}#{options[:id]}' style='float:left:0px; width:0px;' class='#{ options[:css] + " task_none"}'> </div>" | 
  |  | 865 |           output << "</div>" | 
  | 750 | 866 |         end | 
  | 751 | 867 |         # Renders the markers | 
  | 752 | 868 |         if options[:markers] | 
  | 753 | 869 |           if coords[:start] | 
  | 754 |  |             output << "<div style='top:#{ params[:top] }px;left:#{ coords[:start] }px;width:15px;' class='#{options[:css]} marker starting'> </div>" | 
  |  | 870 |             output << "<div id='marker_start_#{options[:kind]}#{options[:id]}' style='top:#{ params[:top] }px;left:#{ coords[:start] }px;width:15px;' class='#{options[:css]} marker starting'> </div>" | 
  | 755 | 871 |           end | 
  | 756 | 872 |           if coords[:end] | 
  | 757 |  |             output << "<div style='top:#{ params[:top] }px;left:#{ coords[:end] + params[:zoom] }px;width:15px;' class='#{options[:css]} marker ending'> </div>" | 
  |  | 873 |             output << "<div id='marker_end_#{options[:kind]}#{options[:id]}' style='top:#{ params[:top] }px;left:#{ coords[:end] + params[:zoom] }px;width:15px;' class='#{options[:css]} marker ending'> </div>" | 
  | 758 | 874 |           end | 
  | 759 | 875 |         end | 
  | 760 | 876 |         # Renders the label on the right | 
  | 761 | 877 |         if options[:label] | 
  | 762 |  |           output << "<div style='top:#{ params[:top] }px;left:#{ (coords[:bar_end] || 0) + 8 }px;' class='#{options[:css]} label'>" | 
  |  | 878 |           output << "<div id='label_#{options[:kind]}#{options[:id]}' style='top:#{ params[:top] }px;left:#{ (coords[:bar_end] || 0) + 8 }px;' class='#{options[:css]} label'>" | 
  | 763 | 879 |           output << options[:label] | 
  | 764 | 880 |           output << "</div>" | 
  | 765 | 881 |         end | 
  | 766 | 882 |         # Renders the tooltip | 
  | 767 | 883 |         if options[:issue] && coords[:bar_start] && coords[:bar_end] | 
  | 768 |  |           output << "<div class='tooltip' style='position: absolute;top:#{ params[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_end] - coords[:bar_start] }px;height:12px;'>" | 
  |  | 884 |           output << "<div id='tt_#{options[:kind]}#{options[:id]}' class='tooltip' style='position: absolute;top:#{ params[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_end] - coords[:bar_start] }px;height:12px;'>" | 
  | 769 | 885 |           output << '<span class="tip">' | 
  | 770 | 886 |           output << view.render_issue_tooltip(options[:issue]) | 
  | 771 | 887 |           output << "</span></div>" | 
  |  | 888 |  | 
  |  | 889 |           output << view.draggable_element("ev_#{options[:kind]}#{options[:id]}", :revert =>false, :scroll=>"'gantt-container'", :constraint => "'horizontal'", :snap=>params[:zoom],:onEnd=>'function( draggable, event )  {issue_moved(draggable.element);}') | 
  | 772 | 890 |         end | 
  | 773 | 891 |         @lines << output | 
  | 774 | 892 |         output | 
  | ... | ... |  | 
  | 857 | 975 |           params[:image].text(params[:subject_width] + (coords[:bar_end] || 0) + 5,params[:top] + 1, options[:label]) | 
  | 858 | 976 |         end | 
  | 859 | 977 |       end | 
  |  | 978 |  | 
  |  | 979 |       ## | 
  |  | 980 |       ##  for edit gantt | 
  |  | 981 |       ## | 
  |  | 982 |       def set_project_data(prj, zoom, text, prj_map = {}) | 
  |  | 983 |         if !prj | 
  |  | 984 |           return text | 
  |  | 985 |         end | 
  |  | 986 |         if !prj_map[prj.id] | 
  |  | 987 |           o = get_project_position(prj, zoom) | 
  |  | 988 |           text += "|p#{prj.id}=#{format_date(prj.start_date)},#{prj.start_date},#{format_date(prj.due_date)},#{prj.due_date},#{o[0]},#{o[1]},#{o[2]},#{o[3]},#{o[4]},#{o[5]}" | 
  |  | 989 |           prj_map[prj.id] = prj | 
  |  | 990 |         end | 
  |  | 991 |         text = set_project_data(prj.parent, zoom, text, prj_map) | 
  |  | 992 |       end | 
  |  | 993 |  | 
  |  | 994 |       def set_version_data(version, zoom, text, version_map = {}) | 
  |  | 995 |         if !version | 
  |  | 996 |           return text | 
  |  | 997 |         end | 
  |  | 998 |         if !version_map[version.id] | 
  |  | 999 |           o = get_version_position(version, zoom) | 
  |  | 1000 |           text += "|v#{version.id}=#{format_date(version.start_date)},#{version.start_date},#{format_date(version.due_date)},#{version.due_date},#{o[0]},#{o[1]},#{o[2]},#{o[3]},#{o[4]},#{o[5]}" | 
  |  | 1001 |           version_map[version.id] = version | 
  |  | 1002 |         end | 
  |  | 1003 |         return text | 
  |  | 1004 |       end | 
  |  | 1005 |  | 
  |  | 1006 |       def get_pos(coords) | 
  |  | 1007 |         i_left = 0 | 
  |  | 1008 |         i_width = 0 | 
  |  | 1009 |         l_width = 0 | 
  |  | 1010 |         d_width = 0 | 
  |  | 1011 |         if coords[:bar_start] | 
  |  | 1012 |           i_left = coords[:bar_start] | 
  |  | 1013 |           if coords[:bar_end] | 
  |  | 1014 |             i_width = coords[:bar_end] - coords[:bar_start] - 2 | 
  |  | 1015 |             i_width = 0 if i_width < 0 | 
  |  | 1016 |           end | 
  |  | 1017 |           if coords[:bar_late_end] | 
  |  | 1018 |             l_width = coords[:bar_late_end] - coords[:bar_start] - 2 | 
  |  | 1019 |           end | 
  |  | 1020 |           if coords[:bar_progress_end] | 
  |  | 1021 |             d_width = coords[:bar_progress_end] - coords[:bar_start] - 2 | 
  |  | 1022 |           end | 
  |  | 1023 |         end | 
  |  | 1024 |         return i_left, i_width, l_width, d_width | 
  |  | 1025 |       end | 
  |  | 1026 |  | 
  |  | 1027 |       def get_issue_position(issue, zoom_str) | 
  |  | 1028 |         zoom = zoom_str.to_i | 
  |  | 1029 |         id = issue.due_before | 
  |  | 1030 |         if id && @date_to < id | 
  |  | 1031 |           id = @date_to | 
  |  | 1032 |         end | 
  |  | 1033 |         coords = coordinates(issue.start_date, id, issue.done_ratio, zoom) | 
  |  | 1034 |  | 
  |  | 1035 |         return get_pos(coords) | 
  |  | 1036 |       end | 
  |  | 1037 |  | 
  |  | 1038 |       def get_project_position(project, zoom_str) | 
  |  | 1039 |         zoom = zoom_str.to_i | 
  |  | 1040 |         pd = project.due_date | 
  |  | 1041 |         if pd && @date_to < pd | 
  |  | 1042 |           pd = @date_to | 
  |  | 1043 |         end | 
  |  | 1044 |         coords = coordinates(project.start_date, pd, nil, zoom) | 
  |  | 1045 |         i_left, i_width, l_width, d_width = get_pos(coords) | 
  |  | 1046 |         if coords[:end] | 
  |  | 1047 |           return i_left, i_width, l_width, d_width, coords[:start], coords[:end] + zoom | 
  |  | 1048 |         else | 
  |  | 1049 |           return i_left, i_width, l_width, d_width, coords[:start], nil | 
  |  | 1050 |         end | 
  |  | 1051 |       end | 
  |  | 1052 |  | 
  |  | 1053 |       def get_version_position(version, zoom_str) | 
  |  | 1054 |         zoom = zoom_str.to_i | 
  |  | 1055 |         vd = version.due_date | 
  |  | 1056 |         if vd &&  @date_to < vd | 
  |  | 1057 |           vd = @date_to | 
  |  | 1058 |         end | 
  |  | 1059 |         coords = coordinates(version.start_date, vd, version.completed_pourcent, zoom) | 
  |  | 1060 |         i_left, i_width, l_width, d_width = get_pos(coords) | 
  |  | 1061 |         if coords[:end] | 
  |  | 1062 |           return i_left, i_width, l_width, d_width, coords[:start], coords[:end] + zoom | 
  |  | 1063 |         else | 
  |  | 1064 |           return i_left, i_width, l_width, d_width, coords[:start], nil | 
  |  | 1065 |         end | 
  |  | 1066 |       end | 
  |  | 1067 |  | 
  |  | 1068 |       def calendar_for_issue(issue, options) | 
  |  | 1069 |         # Skip issues that don't have a due_before (due_date or version's due_date) | 
  |  | 1070 |         if issue.is_a?(Issue) && issue.due_before | 
  |  | 1071 |  | 
  |  | 1072 |           case options[:format] | 
  |  | 1073 |           when :html | 
  |  | 1074 |             start_date = issue.start_date | 
  |  | 1075 |             if start_date | 
  |  | 1076 |               @calendars << "<div style='position: absolute;line-height:1.2em;height:16px;top:#{options[:top]}px;left:4px;overflow:hidden;'>" | 
  |  | 1077 |               @calendars << "<span id='i#{issue.id}_start_date_str'>" | 
  |  | 1078 |               @calendars << format_date(start_date) | 
  |  | 1079 |               @calendars << "</span>" | 
  |  | 1080 |               @calendars << "<input type='hidden' size='12' id='i#{issue.id}_hidden_start_date' value='#{start_date}' />" | 
  |  | 1081 |               @calendars << "<input type='hidden' size='12' id='i#{issue.id}_start_date' value='#{start_date}'>#{view.calendar_for('i' + issue.id.to_s + '_start_date')}" | 
  |  | 1082 |               @calendars << observe_date_field("i#{issue.id}", 'start') | 
  |  | 1083 |             end | 
  |  | 1084 |             due_date = issue.due_date | 
  |  | 1085 |             if due_date | 
  |  | 1086 |               @calendars << "<span id='i#{issue.id}_due_date_str'>" | 
  |  | 1087 |               @calendars << format_date(due_date) | 
  |  | 1088 |               @calendars << "</span>" | 
  |  | 1089 |               @calendars << "<input type='hidden' size='12' id='i#{issue.id}_hidden_due_date' value='#{due_date}' />" | 
  |  | 1090 |               @calendars << "<input type='hidden' size='12' id='i#{issue.id}_due_date' value='#{due_date}'>#{view.calendar_for('i' + issue.id.to_s + '_due_date')}" | 
  |  | 1091 |               @calendars << observe_date_field("i#{issue.id}", 'due') | 
  |  | 1092 |               @calendars << "</div>" | 
  |  | 1093 |             end | 
  |  | 1094 |           when :image | 
  |  | 1095 |             #nop | 
  |  | 1096 |           when :pdf | 
  |  | 1097 |             #nop | 
  |  | 1098 |           end | 
  |  | 1099 |         else | 
  |  | 1100 |           ActiveRecord::Base.logger.debug "GanttHelper#line_for_issue was not given an issue with a due_before" | 
  |  | 1101 |           '' | 
  |  | 1102 |         end | 
  |  | 1103 |       end | 
  |  | 1104 |  | 
  |  | 1105 |       def calendar_for_version(version, options) | 
  |  | 1106 |         # Skip version that don't have a due_before (due_date or version's due_date) | 
  |  | 1107 |         if version.is_a?(Version) && version.start_date && version.due_date | 
  |  | 1108 |  | 
  |  | 1109 |           case options[:format] | 
  |  | 1110 |           when :html | 
  |  | 1111 |             @calendars << "<div style='position: absolute;line-height:1.2em;height:16px;top:#{options[:top]}px;left:4px;overflow:hidden;'>" | 
  |  | 1112 |             @calendars << "<span id='v#{version.id}_start_date_str'>" | 
  |  | 1113 |             @calendars << format_date(version.effective_date) | 
  |  | 1114 |             @calendars << "</span>" | 
  |  | 1115 |             @calendars << "</div>" | 
  |  | 1116 |           when :image | 
  |  | 1117 |             #nop | 
  |  | 1118 |           when :pdf | 
  |  | 1119 |             #nop | 
  |  | 1120 |           end | 
  |  | 1121 |         else | 
  |  | 1122 |           ActiveRecord::Base.logger.debug "GanttHelper#line_for_issue was not given an issue with a due_before" | 
  |  | 1123 |           '' | 
  |  | 1124 |         end | 
  |  | 1125 |       end | 
  |  | 1126 |  | 
  |  | 1127 |       def calendar_for_project(project, options) | 
  |  | 1128 |         case options[:format] | 
  |  | 1129 |         when :html | 
  |  | 1130 |           @calendars << "<div style='position: absolute;line-height:1.2em;height:16px;top:#{options[:top]}px;left:4px;overflow:hidden;'>" | 
  |  | 1131 |           @calendars << "<span id='p#{project.id}_start_date_str'>" | 
  |  | 1132 |           @calendars << format_date(project.start_date) if project.start_date | 
  |  | 1133 |           @calendars << "</span>" | 
  |  | 1134 |           @calendars << "   " | 
  |  | 1135 |           @calendars << "<span id='p#{project.id}_due_date_str'>" | 
  |  | 1136 |           @calendars << format_date(project.due_date) if project.due_date | 
  |  | 1137 |           @calendars << "</span>" | 
  |  | 1138 |           @calendars << "</div>" | 
  |  | 1139 |         when :image | 
  |  | 1140 |           # nop | 
  |  | 1141 |         when :pdf | 
  |  | 1142 |           # nop | 
  |  | 1143 |         end | 
  |  | 1144 |       end | 
  |  | 1145 |  | 
  |  | 1146 |       def observe_date_field(id, type) | 
  |  | 1147 |         output = '' | 
  |  | 1148 |         prj_id = '' | 
  |  | 1149 |         prj_id = @project.to_param if @project | 
  |  | 1150 |         output << "<script type='text/javascript'>\n" | 
  |  | 1151 |         output << "//<![CDATA[\n" | 
  |  | 1152 |         output << "new Form.Element.Observer('#{id}_#{type}_date', 0.25,\n" | 
  |  | 1153 |         output << "  function(element, value) {\n" | 
  |  | 1154 |         output << "    if (value == document.getElementById('#{id}_hidden_#{type}_date').value) {\n" | 
  |  | 1155 |         output << "      return ;\n" | 
  |  | 1156 |         output << "    }\n" | 
  |  | 1157 |         output << "    new Ajax.Request('#{view.url_for(:controller=>:gantts, :action => :edit_gantt, :id=>id, :date_from=>self.date_from.strftime("%Y-%m-%d"), :date_to=>self.date_to.strftime("%Y-%m-%d"), :zoom=>self.zoom*4, :escape => false, :project_id=>prj_id)}', {asynchronous:true, evalScripts:true, onFailure:function(request){handle_failure(request.responseText)}, onSuccess:function(request){change_dates(request.responseText)}, parameters:'#{type}_date=' + encodeURIComponent(value)});" | 
  |  | 1158 |         output << "  })\n" | 
  |  | 1159 |         output << "//]]>\n" | 
  |  | 1160 |         output << "</script>" | 
  |  | 1161 |       end | 
  | 860 | 1162 |     end | 
  | 861 | 1163 |   end | 
  | 862 | 1164 | end |