Update time_ago_with_tooltip helper

Minor refactoring, add specs, changes arguments to use keywords.
This commit is contained in:
Robert Speicher 2015-06-17 14:04:14 -04:00
parent e12b643192
commit 8c8cd8be43
10 changed files with 87 additions and 20 deletions

View file

@ -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 }
# 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 }
haml_tag :script, "$('." + html_class + "').timeago().tooltip()"
end.html_safe
element += javascript_tag "$('.js-timeago').timeago()" unless skip_js
element
end
def render_markup(file_name, file_content)

View file

@ -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 '&middot;'
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

View file

@ -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 '&middot;'
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

View file

@ -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

View file

@ -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')}

View file

@ -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')}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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' }