Update time_ago_with_tooltip helper
Minor refactoring, add specs, changes arguments to use keywords.
This commit is contained in:
parent
e12b643192
commit
8c8cd8be43
10 changed files with 87 additions and 20 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')}
|
||||
|
|
|
@ -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')}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' }
|
||||
|
||||
|
|
Loading…
Reference in a new issue