diff options
-rw-r--r-- | app/helpers/application_helper.rb | 35 | ||||
-rw-r--r-- | app/helpers/issues_helper.rb | 4 | ||||
-rw-r--r-- | app/helpers/notes_helper.rb | 4 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 2 | ||||
-rw-r--r-- | app/views/projects/issues/_issue.html.haml | 4 | ||||
-rw-r--r-- | app/views/projects/merge_requests/_merge_request.html.haml | 4 | ||||
-rw-r--r-- | app/views/projects/notes/discussions/_active.html.haml | 4 | ||||
-rw-r--r-- | app/views/projects/notes/discussions/_commit.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/notes/discussions/_outdated.html.haml | 2 | ||||
-rw-r--r-- | spec/helpers/application_helper_spec.rb | 48 |
10 files changed, 88 insertions, 21 deletions
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 10d7aa11209..c1342331119 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -179,14 +179,33 @@ module ApplicationHelper BroadcastMessage.current end - def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago') - capture_haml do - haml_tag :time, date.to_s, - class: html_class, datetime: date.getutc.iso8601, title: date.in_time_zone.stamp('Aug 21, 2011 9:23pm'), - data: { toggle: 'tooltip', placement: placement } - - haml_tag :script, "$('." + html_class + "').timeago().tooltip()" - end.html_safe + # Render a `time` element with Javascript-based relative date and tooltip + # + # time - Time object + # placement - Tooltip placement String (default: "top") + # html_class - Custom class for `time` element (default: "time_ago") + # skip_js - When true, exclude the `script` tag (default: false) + # + # By default also includes a `script` element with Javascript necessary to + # initialize the `timeago` jQuery extension. If this method is called many + # times, for example rendering hundreds of commits, it's advisable to disable + # this behavior using the `skip_js` argument and re-initializing `timeago` + # manually once all of the elements have been rendered. + # + # A `js-timeago` class is always added to the element, even when a custom + # `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) + element = content_tag :time, time.to_s, + class: "#{html_class} js-timeago", + datetime: time.getutc.iso8601, + title: time.in_time_zone.stamp('Aug 21, 2011 9:23pm'), + data: { toggle: 'tooltip', placement: placement } + + element += javascript_tag "$('.js-timeago').timeago()" unless skip_js + + element end def render_markup(file_name, file_content) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 36d3f371c1b..d4c345fe431 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -45,13 +45,13 @@ module IssuesHelper def issue_timestamp(issue) # Shows the created at time and the updated at time if different - ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}" + ts = time_ago_with_tooltip(issue.created_at, placement: 'bottom', html_class: 'note_created_ago') if issue.updated_at != issue.created_at ts << capture_haml do haml_tag :span do haml_concat '·' haml_concat icon('edit', title: 'edited') - haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago') + haml_concat time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago') end end end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index a7c1fa0b071..dda9b17d61d 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -25,13 +25,13 @@ module NotesHelper def note_timestamp(note) # Shows the created at time and the updated at time if different - ts = "#{time_ago_with_tooltip(note.created_at, 'bottom', 'note_created_ago')}" + ts = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note_created_ago') if note.updated_at != note.created_at ts << capture_haml do haml_tag :span do haml_concat '·' haml_concat icon('edit', title: 'edited') - haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago') + haml_concat time_ago_with_tooltip(note.updated_at, placement: 'bottom', html_class: 'note_edited_ago') end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 94ce6646634..ec65e473919 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -211,7 +211,7 @@ module ProjectsHelper def project_last_activity(project) if project.last_activity_at - time_ago_with_tooltip(project.last_activity_at, 'bottom', 'last_activity_time_ago') + time_ago_with_tooltip(project.last_activity_at, placement: 'bottom', html_class: 'last_activity_time_ago') else "Never" end diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 64d62b45657..2c296cab977 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -28,7 +28,7 @@ = 0 .issue-info - = "##{issue.iid} opened #{time_ago_with_tooltip(issue.created_at, 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe + = "##{issue.iid} opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe - if issue.votes_count > 0 = render 'votes/votes_inline', votable: issue - if issue.milestone @@ -41,4 +41,4 @@ = issue.task_status .pull-right.issue-updated-at - %small updated #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_update_ago')} + %small updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')} diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index c16df27ee8f..d79c4548247 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -35,7 +35,7 @@ = 0 .merge-request-info - = "##{merge_request.iid} opened #{time_ago_with_tooltip(merge_request.created_at, 'bottom')} by #{link_to_member(@project, merge_request.author, avatar: false)}".html_safe + = "##{merge_request.iid} opened #{time_ago_with_tooltip(merge_request.created_at, placement: 'bottom')} by #{link_to_member(@project, merge_request.author, avatar: false)}".html_safe - if merge_request.votes_count > 0 = render 'votes/votes_inline', votable: merge_request - if merge_request.milestone_id? @@ -48,4 +48,4 @@ = merge_request.task_status .pull-right.hidden-xs - %small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')} + %small updated #{time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago')} diff --git a/app/views/projects/notes/discussions/_active.html.haml b/app/views/projects/notes/discussions/_active.html.haml index e7a3854701c..4f15a99d061 100644 --- a/app/views/projects/notes/discussions/_active.html.haml +++ b/app/views/projects/notes/discussions/_active.html.haml @@ -16,7 +16,7 @@ = link_to_member(@project, last_note.author, avatar: false) %span.discussion-last-update - #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} - + #{time_ago_with_tooltip(last_note.updated_at, placement: 'bottom', html_class: 'discussion_updated_ago')} + .discussion-body.js-toggle-content = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/notes/discussions/_commit.html.haml b/app/views/projects/notes/discussions/_commit.html.haml index 62609cfc1c8..6903fad4a0a 100644 --- a/app/views/projects/notes/discussions/_commit.html.haml +++ b/app/views/projects/notes/discussions/_commit.html.haml @@ -14,7 +14,7 @@ last updated by = link_to_member(@project, last_note.author, avatar: false) %span.discussion-last-update - #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} + #{time_ago_with_tooltip(last_note.updated_at, placement: 'bottom', html_class: 'discussion_updated_ago')} .discussion-body.js-toggle-content - if note.for_diff_line? = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/notes/discussions/_outdated.html.haml b/app/views/projects/notes/discussions/_outdated.html.haml index 52a1d342f55..218b0da3977 100644 --- a/app/views/projects/notes/discussions/_outdated.html.haml +++ b/app/views/projects/notes/discussions/_outdated.html.haml @@ -14,6 +14,6 @@ last updated by = link_to_member(@project, last_note.author, avatar: false) %span.discussion-last-update - #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} + #{time_ago_with_tooltip(last_note.updated_at, placement: 'bottom', html_class: 'discussion_updated_ago')} .discussion-body.js-toggle-content.hide = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 47e10197f5c..34fe08f5545 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -240,6 +240,54 @@ describe ApplicationHelper do end end + describe 'time_ago_with_tooltip' do + def element(*arguments) + time = Time.parse('2015-07-02 08:00') + element = time_ago_with_tooltip(time, *arguments) + + Nokogiri::HTML::DocumentFragment.parse(element).first_element_child + end + + it 'returns a time element' do + expect(element.name).to eq 'time' + end + + it 'includes the date string' do + expect(element.text).to match %r{2015-07-02 \d{2}:\d{2}:\d{2}} + end + + it 'has a datetime attribute' do + expect(element.attr('datetime')).to eq '2015-07-02T12:00:00Z' + end + + it 'has a formatted title attribute' do + expect(element.attr('title')).to eq 'Jul 02, 2015 12:00pm' + end + + it 'includes a default js-timeago class' do + expect(element.attr('class')).to eq 'time_ago js-timeago' + end + + it 'accepts a custom html_class' do + expect(element(html_class: 'custom_class').attr('class')).to eq 'custom_class js-timeago' + end + + it 'accepts a custom tooltip placement' do + expect(element(placement: 'bottom').attr('data-placement')).to eq 'bottom' + end + + it 're-initializes timeago Javascript' do + el = element.next_element + + expect(el.name).to eq 'script' + expect(el.text).to include "$('.js-timeago').timeago()" + end + + it 'allows the script tag to be excluded' do + expect(element(skip_js: true)).not_to include 'script' + end + end + describe 'render_markup' do let(:content) { 'Noël' } |