Index: app/controllers/issues_controller.rb =================================================================== --- app/controllers/issues_controller.rb (revision 1928) +++ app/controllers/issues_controller.rb (working copy) @@ -18,10 +18,10 @@ class IssuesController < ApplicationController menu_item :new_issue, :only => :new - before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment] + before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment, :edit_gantt] before_filter :find_issues, :only => [:bulk_edit, :move, :destroy] before_filter :find_project, :only => [:new, :update_form, :preview, :gantt, :calendar] - before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu] + before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu, :edit_gantt] before_filter :find_optional_project, :only => [:index, :changes] accept_key_auth :index, :changes @@ -154,6 +154,31 @@ # Attributes that can be updated on workflow transition (without :edit permission) # TODO: make it configurable (at least per role) UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION) + + def edit_gantt + date_from = Date.parse(params[:date_from]) + if params[:day] + #bar moved + day = params[:day].to_i + duration = @issue.due_date - @issue.start_date + @issue.start_date = date_from + day + @issue.due_date = @issue.start_date + duration.to_i + elsif params[:start_date] + #start date changed + start_date = Date.parse(params[:start_date]) + @issue.start_date = start_date + @issue.due_date = start_date if start_date > @issue.due_date + elsif params[:due_date] + #due date changed + due_date = Date.parse(params[:due_date]) + @issue.due_date = due_date + @issue.start_date = due_date if due_date < @issue.start_date + end + @issue.save! + + o = get_position(@issue, date_from, Date.parse(params[:date_to]), params[:zoom]) + render :text=>"#{format_date(@issue.start_date)},#{format_date(@issue.due_date)},#{o[0]},#{o[1]},#{o[2]},#{o[3]}" + end def edit @allowed_statuses = @issue.new_statuses_allowed_to(User.current) Index: app/helpers/issues_helper.rb =================================================================== --- app/helpers/issues_helper.rb (revision 1928) +++ app/helpers/issues_helper.rb (working copy) @@ -27,8 +27,8 @@ @cached_label_priority ||= l(:field_priority) link_to_issue(issue) + ": #{h(issue.subject)}

" + - "#{@cached_label_start_date}: #{format_date(issue.start_date)}
" + - "#{@cached_label_due_date}: #{format_date(issue.due_date)}
" + + "#{@cached_label_start_date}: #{format_date(issue.start_date)}
" + + "#{@cached_label_due_date}: #{format_date(issue.due_date)}
" + "#{@cached_label_assigned_to}: #{issue.assigned_to}
" + "#{@cached_label_priority}: #{issue.priority.name}" end @@ -185,4 +185,26 @@ export.rewind export end + + def get_position(event, date_from, date_to, zoom_str) + zoom = zoom_str.to_i + i_start_date = (event.start_date >= date_from ? event.start_date : date_from ) + i_end_date = (event.due_date <= date_to ? event.due_date : date_to ) + + i_done_date = event.start_date + ((event.due_date - event.start_date+1)*event.done_ratio/100).floor + i_done_date = (i_done_date <= date_from ? date_from : i_done_date ) + i_done_date = (i_done_date >= date_to ? date_to : i_done_date ) + + i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today + + i_left = ((i_start_date - date_from)*zoom).floor + i_left = 0 if i_left < 0 + i_width = ((i_end_date - i_start_date + 1)*zoom).floor - 2 # total width of the issue (- 2 for left and right borders) + i_width = 0 if i_width < 0 + d_width = ((i_done_date - i_start_date)*zoom).floor - 2 # done width + d_width = 0 if d_width < 0 + l_width = i_late_date ? ((i_late_date - i_start_date+1)*zoom).floor - 2 : 0 # delay width + l_width = 0 if l_width < 0 + return i_left, i_width, l_width, d_width + end end Index: app/views/issues/gantt.rhtml =================================================================== --- app/views/issues/gantt.rhtml (revision 1928) +++ app/views/issues/gantt.rhtml (working copy) @@ -49,7 +49,7 @@ <% zoom = 1 @gantt.zoom.times { zoom = zoom * 2 } -subject_width = 330 +subject_width = 280 header_heigth = 18 headers_height = header_heigth @@ -70,6 +70,55 @@ t_height = g_height + headers_height %> + + +
@@ -98,9 +147,44 @@ end %> +
+
+
+<% +top = headers_height + 8 +@gantt.events.each do |i| %> +
+ <%= format_date(i.start_date) %> + <%= calendar_for("#{i.id}_start_date") if i.is_a? Issue %> + <%= observe_field "#{i.id}_start_date", + :url => { :controller=>:issues, :action => :edit_gantt, :id=>i.id, + :date_from=>@gantt.date_from.strftime("%Y-%m-%d"), :date_to=>@gantt.date_to.strftime("%Y-%m-%d"), :zoom=>zoom }, + :frequency => 0.25, + :with => 'start_date', + :success=>"change_date('#{i.id}', request.responseText)", + :failure=>"alert('Error! See the log')" + %> + <% if i.is_a? Issue %> + <%= format_date(i.due_date) %> + <%= calendar_for("#{i.id}_due_date") %> + <%= observe_field "#{i.id}_due_date", + :url => { :controller=>:issues, :action => :edit_gantt, :id=>i.id, + :date_from=>@gantt.date_from.strftime("%Y-%m-%d"), :date_to=>@gantt.date_to.strftime("%Y-%m-%d"), :zoom=>zoom }, + :frequency => 0.25, + :with => 'due_date', + :success=>"change_date('#{i.id}', request.responseText)", + :failure=>"alert('Error! See the log')" + %> + <% end %> +
+<% top = top + 20 +end %> +
+
-
+
 
<% # @@ -160,15 +244,17 @@ left = 0 height = g_height + header_heigth - 1 wday = @gantt.date_from.cwday + dt = @gantt.date_from (@gantt.date_to - @gantt.date_from + 1).to_i.times do width = zoom - 1 %>
5 %>" class="gantt_hdr"> - <%= day_name(wday).first %> + <%= "#{dt.day}
"if @gantt.zoom == 4 %><%= day_name(wday).first %>
<% left = left + width+1 wday = wday + 1 + dt = dt + 1 wday = 1 if wday > 7 end end %> @@ -180,39 +266,35 @@ top = headers_height + 10 @gantt.events.each do |i| if i.is_a? Issue - i_start_date = (i.start_date >= @gantt.date_from ? i.start_date : @gantt.date_from ) - i_end_date = (i.due_before <= @gantt.date_to ? i.due_before : @gantt.date_to ) - - i_done_date = i.start_date + ((i.due_before - i.start_date+1)*i.done_ratio/100).floor - i_done_date = (i_done_date <= @gantt.date_from ? @gantt.date_from : i_done_date ) - i_done_date = (i_done_date >= @gantt.date_to ? @gantt.date_to : i_done_date ) - - i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today - - i_left = ((i_start_date - @gantt.date_from)*zoom).floor - i_width = ((i_end_date - i_start_date + 1)*zoom).floor - 2 # total width of the issue (- 2 for left and right borders) - d_width = ((i_done_date - i_start_date)*zoom).floor - 2 # done width - l_width = i_late_date ? ((i_late_date - i_start_date+1)*zoom).floor - 2 : 0 # delay width + i_left, i_width, l_width, d_width = get_position(i, @gantt.date_from, @gantt.date_to, zoom) %> -
 
- <% if l_width > 0 %> -
 
- <% end %> - <% if d_width > 0 %> -
 
- <% end %> -
- <%= i.status.name %> - <%= (i.done_ratio).to_i %>% -
-
- +
+
 
+ <% if l_width > 0 %> +
 
+ <% end %> + <% if d_width > 0 %> +
 
+ <% end %> +
+ <%= i.status.name %> + <%= (i.done_ratio).to_i %>% +
+
+ <% # === tooltip === %> +
+ <%= render_issue_tooltip i %>
+ <%= draggable_element("ev_#{i.id}", + :revert =>false, :scroll=>"'gantt-container'", :constraint => "'horizontal'", :snap=>zoom, + :onEnd=>"function( draggable, event ) {issue_moved(draggable.element);}" + ) %> + <% else i_left = ((i.start_date - @gantt.date_from)*zoom).floor %> -
 
+
 
<%= h("#{i.project} -") unless @project && @project == i.project %> <%=h i %>