5458-use_time_in_issue_start_and_due_date_2.3_stable.diff

Patch to add time to start/due date in issues for redmine 2.3 - Evzen Sindelar, 2013-06-05 18:11

Download (12 KB)

View differences:

app/helpers/application_helper.rb Fri May 31 17:49:32 2013 +0200
298 298
    end
299 299
  end
300 300

  
301
  def time_select_tag( name, stime )
302
    out = ''
303
    time = stime.to_time(:utc)
304
    if time.nil?
305
      time = Date.today.to_time(:local)
306
    end
307
    time = time.in_time_zone(Time.zone.name)
308
    out << select_tag(
309
      "#{name}[hour]",
310
      options_for_select( (0..24).map{|i| [i,i] }, time.hour ),
311
      :style => 'min-width: 10px;max-width: 50px;'
312
    )
313
    out << ':'
314
    out << select_tag(
315
      "#{name}[minute]",
316
      options_for_select( (0..12).map{|i| [i*5,i*5] }, (time.min/5).round*5 ),
317
      :style => 'min-width: 10px;max-width: 50px;'
318
    )
319
    out << 'h'
320
    out
321
  end
322

  
301 323
  def project_tree_options_for_select(projects, options = {})
302 324
    s = ''
303 325
    project_tree(projects) do |project, level|
app/helpers/queries_helper.rb Fri May 31 17:49:32 2013 +0200
100 100
        h(value)
101 101
      end
102 102
    when 'Time'
103
      format_time(value)
103
      if ( column.name == :start_date or column.name == :due_date ) and
104
        ( !issue.project.use_datetime_for_issues or value.strftime('%H%M')=='0000' )
105
        format_date(value)
106
      else
107
        format_time(value)
108
      end
104 109
    when 'Date'
105 110
      format_date(value)
106 111
    when 'Fixnum'
app/models/issue.rb Fri May 31 17:49:32 2013 +0200
61 61
  DONE_RATIO_OPTIONS = %w(issue_field issue_status)
62 62

  
63 63
  attr_reader :current_journal
64
  attr_accessor :start_time
65
  attr_accessor :due_time
66

  
64 67
  delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true
65 68

  
66 69
  validates_presence_of :subject, :priority, :project, :tracker, :author, :status
......
68 71
  validates_length_of :subject, :maximum => 255
69 72
  validates_inclusion_of :done_ratio, :in => 0..100
70 73
  validates :estimated_hours, :numericality => {:greater_than_or_equal_to => 0, :allow_nil => true, :message => :invalid}
71
  validates :start_date, :date => true
72
  validates :due_date, :date => true
74
  #validates :start_date, :date => true
75
  #validates :due_date, :date => true
73 76
  validate :validate_issue, :validate_required_fields
74 77

  
75 78
  scope :visible, lambda {|*args|
......
90 93
    ids.any? ? where(:fixed_version_id => ids) : where('1=0')
91 94
  }
92 95

  
93
  before_create :default_assign
94
  before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on
96
  before_create :default_assign, :add_start_and_due_time
97
  before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on, :add_start_and_due_time
95 98
  after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?} 
96 99
  after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal
97 100
  # Should be after_create but would be called before previous after_save callbacks
......
361 364
    'subject',
362 365
    'description',
363 366
    'start_date',
367
    'start_time',
364 368
    'due_date',
369
    'due_time',    
365 370
    'done_ratio',
366 371
    'estimated_hours',
367 372
    'custom_field_values',
......
1302 1307
    end
1303 1308
  end
1304 1309

  
1310
  # Callback on start and due time
1311
  def add_start_and_due_time
1312
    if project.use_datetime_for_issues
1313
      if st=start_time and sd=start_date
1314
        if st['hour'].to_i > 0 or st['minute'].to_i > 0
1315
          self.start_date = Time.parse( "#{sd.year}.#{sd.month}.#{sd.day} #{st['hour']}:#{st['minute']}:00" )
1316
        end
1317
      end
1318
      if dt=due_time and dd=due_date
1319
        if dt['hour'].to_i > 0 or dt['minute'].to_i > 0
1320
          self.due_date = Time.parse( "#{dd.year}.#{dd.month}.#{dd.day} #{dt['hour']}:#{dt['minute']}:00" )
1321
        end
1322
      end
1323
    end
1324
  end
1325

  
1305 1326
  # Default assignment based on category
1306 1327
  def default_assign
1307 1328
    if assigned_to.nil? && category && category.assigned_to
app/models/project.rb Fri May 31 17:49:32 2013 +0200
650 650
    'description',
651 651
    'homepage',
652 652
    'is_public',
653
    'use_datetime_for_issues',
653 654
    'identifier',
654 655
    'custom_field_values',
655 656
    'custom_fields',
app/views/issues/_attributes.html.erb Fri May 31 17:49:32 2013 +0200
47 47
<% end %>
48 48

  
49 49
<% if @issue.safe_attribute? 'start_date' %>
50
<p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %></p>
50
<p>
51
  <%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %>
52
  <%= calendar_for('issue_start_date') if @issue.leaf? %> <br />
53
  <%== time_select_tag( "issue[start_time]", @issue.start_date.to_s ) if @project.use_datetime_for_issues %>
54
</p>
51 55
<% end %>
52 56

  
53 57
<% if @issue.safe_attribute? 'due_date' %>
54
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %></p>
58
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %>
59
   <%= calendar_for('issue_due_date') if @issue.leaf? %> <br />
60
   <%== time_select_tag( "issue[due_time]", @issue.due_date.to_s ) if @project.use_datetime_for_issues %>
61
</p>
55 62
<% end %>
56 63

  
57 64
<% if @issue.safe_attribute? 'estimated_hours' %>
app/views/issues/show.html.erb Fri May 31 17:49:32 2013 +0200
47 47
  end
48 48

  
49 49
  unless @issue.disabled_core_fields.include?('start_date')
50
    rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
50
    rows.right l(:field_start_date), (@project.use_datetime_for_issues ? format_time(@issue.start_date) : format_date(@issue.start_date)), :class => 'start-date'
51 51
  end
52 52
  unless @issue.disabled_core_fields.include?('due_date')
53
    rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
53
    rows.right l(:field_due_date), (@project.use_datetime_for_issues ? format_time(@issue.due_date) : format_date(@issue.due_date)), :class => 'due-date'
54 54
  end
55 55
  unless @issue.disabled_core_fields.include?('done_ratio')
56 56
    rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress'
app/views/projects/_form.html.erb Fri May 31 17:49:32 2013 +0200
11 11
<% end %></p>
12 12
<p><%= f.text_field :homepage, :size => 60 %></p>
13 13
<p><%= f.check_box :is_public %></p>
14
<p><%= f.check_box :use_datetime_for_issues %></p>
14 15

  
15 16
<% unless @project.allowed_parents.compact.empty? %>
16 17
    <p><%= label(:project, :parent_id, l(:field_parent)) %><%= parent_project_select_tag(@project) %></p>
config/locales/cs.yml Fri May 31 17:49:32 2013 +0200
311 311
  field_assigned_to_role: Role přiřaditele
312 312
  field_text: Textové pole
313 313
  field_visible: Viditelný
314

  
314
  field_use_datetime_for_issues: Použít u tiketů také čas
315 315
  setting_app_title: Název aplikace
316 316
  setting_app_subtitle: Podtitulek aplikace
317 317
  setting_welcome_text: Uvítací text
config/locales/en-GB.yml Fri May 31 17:49:32 2013 +0200
311 311
  field_assigned_to_role: "Assignee's role"
312 312
  field_text: Text field
313 313
  field_visible: Visible
314
  field_use_datetime_for_issues: Use time in tickets too
314 315
  field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
315 316

  
316 317
  setting_app_title: Application title
config/locales/en.yml Fri May 31 17:49:32 2013 +0200
314 314
  field_assigned_to_role: "Assignee's role"
315 315
  field_text: Text field
316 316
  field_visible: Visible
317
  field_use_datetime_for_issues: Use time in tickets too
317 318
  field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
318 319
  field_issues_visibility: Issues visibility
319 320
  field_is_private: Private
db/migrate/20130531174459_add_time_to_issue_start_date_and_issue_due_date.rb Fri May 31 17:49:32 2013 +0200
1
class AddTimeToIssueStartDateAndIssueDueDate < ActiveRecord::Migration
2
  def self.up
3
    change_column :issues, :start_date, :datetime
4
    change_column :issues, :due_date, :datetime
5
  end
6
  
7
  def self.down
8
    change_column :issues, :start_date, :date
9
    change_column :issues, :due_date, :date
10
  end
11
end
db/migrate/20130531174549_add_use_datetime_for_issues_to_projects.rb Fri May 31 17:49:32 2013 +0200
1
class AddUseDatetimeForIssuesToProjects < ActiveRecord::Migration
2

  
3
  def self.up
4
    add_column :projects, :use_datetime_for_issues, :boolean, :default => false
5
  end
6

  
7
  def self.down
8
    remove_column :projects, :use_datetime_for_issues
9
  end
10

  
11
end
lib/redmine/utils.rb Wed Jun 05 15:41:36 2013 +0200
60 60
          weeks = days / 7
61 61
          result = weeks * (7 - non_working_week_days.size)
62 62
          days_left = days - weeks * 7
63
          start_cwday = from.cwday
63
          start_cwday = from.to_date.cwday
64 64
          days_left.times do |i|
65 65
            unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)
66 66
              result += 1
......
78 78
          weeks = working_days / (7 - non_working_week_days.size)
79 79
          result = weeks * 7
80 80
          days_left = working_days - weeks * (7 - non_working_week_days.size)
81
          cwday = date.cwday
81
          cwday = date.to_date.cwday
82 82
          while days_left > 0
83 83
            cwday += 1
84 84
            unless non_working_week_days.include?(((cwday - 1) % 7) + 1)
......
94 94

  
95 95
      # Returns the date of the first day on or after the given date that is a working day
96 96
      def next_working_date(date)
97
        cwday = date.cwday
97
        cwday = date.to_date.cwday
98 98
        days = 0
99 99
        while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)
100 100
          days += 1