diff --git a/CHANGELOG b/CHANGELOG index 77bcea54cf9..9e5d00c01f8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 8.11.0 (unreleased) - Add "No one can push" as an option for protected branches. !5081 - Improve performance of AutolinkFilter#text_parse by using XPath - Environments have an url to link to + - Update `timeago` plugin to use multiple string/locale settings - Remove unused images (ClemMakesApps) - Limit git rev-list output count to one in forced push check - Clean up unused routes (Josef Strzibny) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 127e568adc9..f1aab067351 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -287,7 +287,7 @@ $('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned'); $('.navbar-fixed-top').removeClass('header-pinned-nav'); } - return $document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) { + $document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) { var $page, $pinBtn, $tooltip, $topNav, doPinNav, tooltipText; e.preventDefault(); $pinBtn = $(e.currentTarget); @@ -315,6 +315,8 @@ $tooltip.find('.tooltip-inner').text(tooltipText); return $pinBtn.attr('title', tooltipText).tooltip('fixTitle'); }); - }); + // Custom time ago + gl.utils.shortTimeAgo($('.js-short-timeago')); + }); }).call(this); diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index e817261f210..10afa7e4329 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -8,13 +8,16 @@ base.utils = {}; } w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + w.gl.utils.formatDate = function(datetime) { return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z'); }; + w.gl.utils.getDayName = function(date) { return this.days[date.getDay()]; }; - return w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) { + + w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) { if (setTimeago == null) { setTimeago = true; } @@ -31,6 +34,39 @@ }); } }; + + w.gl.utils.shortTimeAgo = function($el) { + var shortLocale, tmpLocale; + shortLocale = { + prefixAgo: null, + prefixFromNow: null, + suffixAgo: 'ago', + suffixFromNow: 'from now', + seconds: '1 min', + minute: '1 min', + minutes: '%d mins', + hour: '1 hr', + hours: '%d hrs', + day: '1 day', + days: '%d days', + month: '1 month', + months: '%d months', + year: '1 year', + years: '%d years', + wordSeparator: ' ', + numbers: [] + }; + tmpLocale = $.timeago.settings.strings; + $el.each(function(el) { + var $el1; + $el1 = $(this); + return $el1.attr('title', gl.utils.formatDate($el.attr('datetime'))); + }); + $.timeago.settings.strings = shortLocale; + $el.timeago(); + $.timeago.settings.strings = tmpLocale; + }; + })(window); }).call(this); diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 50de93d4bdf..c3613bc67dd 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -163,9 +163,13 @@ module ApplicationHelper # `html_class` argument is provided. # # Returns an HTML-safe String - def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false) + def time_ago_with_tooltip(time, placement: 'top', html_class: '', skip_js: false, short_format: false) + css_classes = short_format ? 'js-short-timeago' : 'js-timeago' + css_classes << " #{html_class}" unless html_class.blank? + css_classes << ' js-timeago-pending' unless skip_js + element = content_tag :time, time.to_s, - class: "#{html_class} js-timeago #{"js-timeago-pending" unless skip_js}", + class: css_classes, datetime: time.to_time.getutc.iso8601, title: time.to_time.in_time_zone.to_s(:medium), data: { toggle: 'tooltip', placement: placement, container: 'body' } diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 558c35553da..9a594877803 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -53,7 +53,7 @@ - if pipeline.finished_at %p.finished-at = icon("calendar") - #{time_ago_with_tooltip(pipeline.finished_at)} + #{time_ago_with_tooltip(pipeline.finished_at, short_format: true, skip_js: true)} %td.pipeline-actions .controls.hidden-xs.pull-right diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index bb28866f010..3e15a137e33 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -218,12 +218,12 @@ describe ApplicationHelper do end it 'includes a default js-timeago class' do - expect(element.attr('class')).to eq 'time_ago js-timeago js-timeago-pending' + expect(element.attr('class')).to eq 'js-timeago js-timeago-pending' end it 'accepts a custom html_class' do expect(element(html_class: 'custom_class').attr('class')). - to eq 'custom_class js-timeago js-timeago-pending' + to eq 'js-timeago custom_class js-timeago-pending' end it 'accepts a custom tooltip placement' do @@ -244,6 +244,19 @@ describe ApplicationHelper do it 'converts to Time' do expect { helper.time_ago_with_tooltip(Date.today) }.not_to raise_error end + + it 'add class for the short format and includes inline script' do + timeago_element = element(short_format: 'short') + expect(timeago_element.attr('class')).to eq 'js-short-timeago js-timeago-pending' + script_element = timeago_element.next_element + expect(script_element.name).to eq 'script' + end + + it 'add class for the short format and does not include inline script' do + timeago_element = element(short_format: 'short', skip_js: true) + expect(timeago_element.attr('class')).to eq 'js-short-timeago' + expect(timeago_element.next_element).to eq nil + end end describe 'render_markup' do