Feature #5458 » 5458-use_time_in_issue_start_and_due_date_2.3_stable.diff
| 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  |