Feature #23996 » 0001-introduces-a-setting-to-have-durations-displayed-as-.patch
| app/helpers/application_helper.rb | ||
|---|---|---|
| 423 | 423 | 
    end  | 
| 424 | 424 | |
| 425 | 425 | 
    def html_hours(text)  | 
| 426 | 
        text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>').html_safe
   | 
|
| 426 | 
        text.gsub(%r{(\d+)([\.:])(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">\2\3</span>').html_safe
   | 
|
| 427 | 427 | 
    end  | 
| 428 | 428 | |
| 429 | 429 | 
      def authoring(created, author, options={})
   | 
| app/helpers/queries_helper.rb | ||
|---|---|---|
| 149 | 149 | |
| 150 | 150 | 
    def total_tag(column, value)  | 
| 151 | 151 | 
        label = content_tag('span', "#{column.caption}:")
   | 
| 152 | 
        value = content_tag('span', format_object(value), :class => 'value')
   | 
|
| 152 | 
    value = if [:hours, :spent_hours, :total_spent_hours, :estimated_hours].include? column.name  | 
|
| 153 | 
    format_hours(value)  | 
|
| 154 | 
    else  | 
|
| 155 | 
    format_object(value)  | 
|
| 156 | 
    end  | 
|
| 157 | 
        value = content_tag('span', value, :class => 'value')
   | 
|
| 153 | 158 | 
        content_tag('span', label + " " + value, :class => "total-for-#{column.name.to_s.dasherize}")
   | 
| 154 | 159 | 
    end  | 
| 155 | 160 | |
| ... | ... | |
| 184 | 189 | 
          content_tag('span',
   | 
| 185 | 190 | 
            value.to_s(issue) {|other| link_to_issue(other, :subject => false, :tracker => false)}.html_safe,
   | 
| 186 | 191 | 
    :class => value.css_classes_for(issue))  | 
| 192 | 
    when :hours, :spent_hours, :total_spent_hours, :estimated_hours  | 
|
| 193 | 
    format_hours(value)  | 
|
| 187 | 194 | 
    else  | 
| 188 | 195 | 
    format_object(value)  | 
| 189 | 196 | 
    end  | 
| app/views/issues/_attributes.html.erb | ||
|---|---|---|
| 65 | 65 | 
    <% end %>  | 
| 66 | 66 | |
| 67 | 67 | 
    <% if @issue.safe_attribute? 'estimated_hours' %>  | 
| 68 | 
    <p><%= f.text_field :estimated_hours, :size => 3, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %></p>
   | 
|
| 68 | 
    <p><%= f.text_field :estimated_hours, :size => 3, :required => @issue.required_attribute?('estimated_hours'), :value => format_hours(@issue.estimated_hours) %> <%= l(:field_hours) %></p>
   | 
|
| 69 | 69 | 
    <% end %>  | 
| 70 | 70 | |
| 71 | 71 | 
    <% if @issue.safe_attribute?('done_ratio') && Issue.use_field_for_done_ratio? %>
   | 
| app/views/issues/_edit.html.erb | ||
|---|---|---|
| 14 | 14 | 
    <%= labelled_fields_for :time_entry, @time_entry do |time_entry| %>  | 
| 15 | 15 | 
    <div class="splitcontent">  | 
| 16 | 16 | 
    <div class="splitcontentleft">  | 
| 17 | 
    <p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time %> <%= l(:field_hours) %></p>  | 
|
| 17 | 
            <p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time, :value => format_hours(@time_entry.hours) %> <%= l(:field_hours) %></p>
   | 
|
| 18 | 18 | 
    </div>  | 
| 19 | 19 | 
    <div class="splitcontentright">  | 
| 20 | 20 | 
    <p><%= time_entry.select :activity_id, activity_collection_for_select_options %></p>  | 
| app/views/my/blocks/_timelog.html.erb | ||
|---|---|---|
| 14 | 14 | 
    <% end %>  | 
| 15 | 15 | |
| 16 | 16 | 
    <div class="total-hours">  | 
| 17 | 
    <p><%= l(:label_total_time) %>: <%= html_hours("%.2f" % entries.sum(&:hours).to_f) %></p>
   | 
|
| 17 | 
    <p><%= l(:label_total_time) %>: <%= html_hours(l_hours_short(entries.sum(&:hours))) %></p>
   | 
|
| 18 | 18 | 
    </div>  | 
| 19 | 19 | |
| 20 | 20 | 
    <% if entries.any? %>  | 
| ... | ... | |
| 31 | 31 | 
    <tr class="odd">  | 
| 32 | 32 | 
    <td><strong><%= day == User.current.today ? l(:label_today).titleize : format_date(day) %></strong></td>  | 
| 33 | 33 | 
    <td colspan="2"></td>  | 
| 34 | 
        <td class="hours"><em><%= html_hours("%.2f" % entries_by_day[day].sum(&:hours).to_f) %></em></td>
   | 
|
| 34 | 
        <td class="hours"><em><%= html_hours(l_hours_short(entries_by_day[day].sum(&:hours))) %></em></td>
   | 
|
| 35 | 35 | 
    <td></td>  | 
| 36 | 36 | 
    </tr>  | 
| 37 | 37 | 
    <% entries_by_day[day].each do |entry| -%>  | 
| ... | ... | |
| 39 | 39 | 
    <td class="activity"><%= entry.activity %></td>  | 
| 40 | 40 | 
        <td class="subject"><%= entry.project %> <%= h(' - ') + link_to_issue(entry.issue, :truncate => 50) if entry.issue %></td>
   | 
| 41 | 41 | 
    <td class="comments"><%= entry.comments %></td>  | 
| 42 | 
        <td class="hours"><%= html_hours("%.2f" % entry.hours) %></td>
   | 
|
| 42 | 
        <td class="hours"><%= html_hours(l_hours_short(entry.hours)) %></td>
   | 
|
| 43 | 43 | 
    <td class="buttons">  | 
| 44 | 44 | 
    <% if entry.editable_by?(@user) -%>  | 
| 45 | 45 | 
            <%= link_to l(:button_edit), {:controller => 'timelog', :action => 'edit', :id => entry},
   | 
| app/views/settings/_display.html.erb | ||
|---|---|---|
| 15 | 15 | |
| 16 | 16 | 
    <p><%= setting_select :time_format, Setting::TIME_FORMATS.collect {|f| [::I18n.l(Time.now, :locale => locale, :format => f), f]}, :blank => :label_language_based %></p>
   | 
| 17 | 17 | |
| 18 | 
    <p><%= setting_select :timespan_format, [["%.2f" % 0.75, 'decimal'], ['0:45 h', 'minutes']], :blank => false %></p>  | 
|
| 19 | ||
| 18 | 20 | 
    <p><%= setting_select :user_format, @options[:user_format] %></p>  | 
| 19 | 21 | |
| 20 | 22 | 
    <p><%= setting_check_box :gravatar_enabled %></p>  | 
| app/views/timelog/_form.html.erb | ||
|---|---|---|
| 18 | 18 | 
    <% end %>  | 
| 19 | 19 | 
    </p>  | 
| 20 | 20 | 
      <p><%= f.date_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %></p>
   | 
| 21 | 
    <p><%= f.text_field :hours, :size => 6, :required => true %></p>  | 
|
| 21 | 
      <p><%= f.text_field :hours, :size => 6, :required => true, :value => format_hours(@time_entry.hours) %></p>
   | 
|
| 22 | 22 | 
    <p><%= f.text_field :comments, :size => 100, :maxlength => 1024 %></p>  | 
| 23 | 23 | 
    <p><%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %></p>  | 
| 24 | 24 | 
    <% @time_entry.custom_field_values.each do |value| %>  | 
| app/views/timelog/_report_criteria.html.erb | ||
|---|---|---|
| 8 | 8 | 
    <% total = 0 -%>  | 
| 9 | 9 | 
    <% @report.periods.each do |period| -%>  | 
| 10 | 10 | 
    <% sum = sum_hours(select_hours(hours_for_value, @report.columns, period.to_s)); total += sum -%>  | 
| 11 | 
        <td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
   | 
|
| 11 | 
        <td class="hours"><%= html_hours(l_hours_short(sum)) if sum > 0 %></td>
   | 
|
| 12 | 12 | 
    <% end -%>  | 
| 13 | 
      <td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
   | 
|
| 13 | 
      <td class="hours"><%= html_hours(l_hours_short(total)) if total > 0 %></td>
   | 
|
| 14 | 14 | 
    </tr>  | 
| 15 | 15 | 
    <% if criterias.length > level+1 -%>  | 
| 16 | 16 | 
      <%= render(:partial => 'report_criteria', :locals => {:criterias => criterias, :hours => hours_for_value, :level => (level + 1)}) %>
   | 
| app/views/timelog/report.html.erb | ||
|---|---|---|
| 52 | 52 | 
    <% total = 0 -%>  | 
| 53 | 53 | 
    <% @report.periods.each do |period| -%>  | 
| 54 | 54 | 
    <% sum = sum_hours(select_hours(@report.hours, @report.columns, period.to_s)); total += sum -%>  | 
| 55 | 
        <td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
   | 
|
| 55 | 
        <td class="hours"><%= html_hours(l_hours_short(sum)) if sum > 0 %></td>
   | 
|
| 56 | 56 | 
    <% end -%>  | 
| 57 | 
      <td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
   | 
|
| 57 | 
      <td class="hours"><%= html_hours(l_hours_short(total)) if total > 0 %></td>
   | 
|
| 58 | 58 | 
    </tr>  | 
| 59 | 59 | 
    </tbody>  | 
| 60 | 60 | 
    </table>  | 
| config/locales/de.yml | ||
|---|---|---|
| 1047 | 1047 | 
    setting_thumbnails_enabled: Vorschaubilder von Dateianhängen anzeigen  | 
| 1048 | 1048 | 
    setting_thumbnails_size: Größe der Vorschaubilder (in Pixel)  | 
| 1049 | 1049 | 
    setting_time_format: Zeitformat  | 
| 1050 | 
    setting_timespan_format: Format für Zeitspannen  | 
|
| 1050 | 1051 | 
    setting_unsubscribe: Erlaubt Benutzern das eigene Benutzerkonto zu löschen  | 
| 1051 | 1052 | 
    setting_user_format: Benutzer-Anzeigeformat  | 
| 1052 | 1053 | 
    setting_welcome_text: Willkommenstext  | 
| config/locales/en.yml | ||
|---|---|---|
| 389 | 389 | 
    setting_autologin: Autologin  | 
| 390 | 390 | 
    setting_date_format: Date format  | 
| 391 | 391 | 
    setting_time_format: Time format  | 
| 392 | 
    setting_timespan_format: Time span format  | 
|
| 392 | 393 | 
    setting_cross_project_issue_relations: Allow cross-project issue relations  | 
| 393 | 394 | 
    setting_cross_project_subtasks: Allow cross-project subtasks  | 
| 394 | 395 | 
    setting_issue_list_default_columns: Default columns displayed on the issue list  | 
| config/settings.yml | ||
|---|---|---|
| 153 | 153 | 
    default: ''  | 
| 154 | 154 | 
    time_format:  | 
| 155 | 155 | 
    default: ''  | 
| 156 | 
    timespan_format:  | 
|
| 157 | 
    default: 'decimal'  | 
|
| 156 | 158 | 
    user_format:  | 
| 157 | 159 | 
    default: :firstname_lastname  | 
| 158 | 160 | 
    format: symbol  | 
| lib/redmine/i18n.rb | ||
|---|---|---|
| 45 | 45 | |
| 46 | 46 | 
    def l_hours(hours)  | 
| 47 | 47 | 
    hours = hours.to_f  | 
| 48 | 
          l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
   | 
|
| 48 | 
          l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => format_hours(hours))
   | 
|
| 49 | 49 | 
    end  | 
| 50 | 50 | |
| 51 | 51 | 
    def l_hours_short(hours)  | 
| 52 | 
          l(:label_f_hour_short, :value => ("%.2f" % hours.to_f))
   | 
|
| 52 | 
          l(:label_f_hour_short, :value => format_hours(hours.to_f))
   | 
|
| 53 | 53 | 
    end  | 
| 54 | 54 | |
| 55 | 55 | 
    def ll(lang, str, arg=nil)  | 
| ... | ... | |
| 82 | 82 | 
          (include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
   | 
| 83 | 83 | 
    end  | 
| 84 | 84 | |
| 85 | 
    def format_hours(hours)  | 
|
| 86 | 
    return "" if hours.blank?  | 
|
| 87 | ||
| 88 | 
    if Setting.timespan_format == 'minutes'  | 
|
| 89 | 
    h = hours.floor  | 
|
| 90 | 
    m = ((hours - h) * 60).round  | 
|
| 91 | 
    "%d:%02d" % [ h, m ]  | 
|
| 92 | 
    else  | 
|
| 93 | 
    "%.2f" % hours.to_f  | 
|
| 94 | 
    end  | 
|
| 95 | 
    end  | 
|
| 96 | ||
| 85 | 97 | 
    def day_name(day)  | 
| 86 | 98 | 
          ::I18n.t('date.day_names')[day % 7]
   | 
| 87 | 99 | 
    end  | 
| test/unit/helpers/application_helper_test.rb | ||
|---|---|---|
| 1543 | 1543 | 
        stubs(:request).returns(stub(:env => {'HTTP_REFERER' => "/path?utf8=\u2713&foo=bar"}))
   | 
| 1544 | 1544 | 
    assert_equal "/path?foo=bar", back_url  | 
| 1545 | 1545 | 
    end  | 
| 1546 | ||
| 1547 | 
    def test_hours_formatting  | 
|
| 1548 | 
    with_settings :timespan_format => 'minutes' do  | 
|
| 1549 | 
    assert_equal '0:45', format_hours(0.75)  | 
|
| 1550 | 
    assert_equal '0:45 h', l_hours_short(0.75)  | 
|
| 1551 | 
    assert_equal '0:45 hour', l_hours(0.75)  | 
|
| 1552 | 
    end  | 
|
| 1553 | 
    with_settings :timespan_format => 'decimal' do  | 
|
| 1554 | 
    assert_equal '0.75', format_hours(0.75)  | 
|
| 1555 | 
    assert_equal '0.75 h', l_hours_short(0.75)  | 
|
| 1556 | 
    assert_equal '0.75 hour', l_hours(0.75)  | 
|
| 1557 | 
    end  | 
|
| 1558 | 
    end  | 
|
| 1559 | ||
| 1560 | 
    def test_html_hours  | 
|
| 1561 | 
        assert_equal '<span class="hours hours-int">0</span><span class="hours hours-dec">:45</span>', html_hours('0:45')
   | 
|
| 1562 | 
        assert_equal '<span class="hours hours-int">0</span><span class="hours hours-dec">.75</span>', html_hours('0.75')
   | 
|
| 1563 | 
    end  | 
|
| 1546 | 1564 | 
    end  |