Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
fa1ac47e
Commit
fa1ac47e
authored
Sep 08, 2016
by
Clement Ho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace jQuery.timeago with timeago.js
parent
6be0c160
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
320 additions
and
289 deletions
+320
-289
app/assets/javascripts/activities.js
app/assets/javascripts/activities.js
+2
-2
app/assets/javascripts/application.js
app/assets/javascripts/application.js
+0
-4
app/assets/javascripts/build.js
app/assets/javascripts/build.js
+1
-1
app/assets/javascripts/compare.js
app/assets/javascripts/compare.js
+2
-1
app/assets/javascripts/lib/utils/common_utils.js
app/assets/javascripts/lib/utils/common_utils.js
+0
-19
app/assets/javascripts/lib/utils/datetime_utility.js
app/assets/javascripts/lib/utils/datetime_utility.js
+54
-41
app/assets/javascripts/lib/utils/timeago.js
app/assets/javascripts/lib/utils/timeago.js
+237
-0
app/assets/javascripts/merge_request_widget.js.es6
app/assets/javascripts/merge_request_widget.js.es6
+1
-1
app/assets/javascripts/milestone_select.js
app/assets/javascripts/milestone_select.js
+1
-1
app/helpers/application_helper.rb
app/helpers/application_helper.rb
+7
-11
app/views/events/_event.html.haml
app/views/events/_event.html.haml
+1
-1
app/views/projects/_last_commit.html.haml
app/views/projects/_last_commit.html.haml
+1
-1
app/views/projects/blame/show.html.haml
app/views/projects/blame/show.html.haml
+1
-1
app/views/projects/ci/pipelines/_pipeline.html.haml
app/views/projects/ci/pipelines/_pipeline.html.haml
+1
-1
app/views/projects/refs/logs_tree.js.haml
app/views/projects/refs/logs_tree.js.haml
+3
-0
changelogs/unreleased/upgrade-timeago.yml
changelogs/unreleased/upgrade-timeago.yml
+4
-0
spec/helpers/application_helper_spec.rb
spec/helpers/application_helper_spec.rb
+3
-21
spec/javascripts/merge_request_widget_spec.js
spec/javascripts/merge_request_widget_spec.js
+1
-1
vendor/assets/javascripts/jquery.timeago.js
vendor/assets/javascripts/jquery.timeago.js
+0
-182
No files found.
app/assets/javascripts/activities.js
View file @
fa1ac47e
...
...
@@ -13,12 +13,12 @@
}
Activities
.
prototype
.
updateTooltips
=
function
()
{
return
gl
.
utils
.
localTimeAgo
(
$
(
'
.js-timeago
'
,
'
.content_list
'
));
gl
.
utils
.
localTimeAgo
(
$
(
'
.js-timeago
'
,
'
.content_list
'
));
};
Activities
.
prototype
.
reloadActivities
=
function
()
{
$
(
"
.content_list
"
).
html
(
''
);
return
Pager
.
init
(
20
,
true
);
Pager
.
init
(
20
,
true
,
false
,
this
.
updateTooltips
);
};
Activities
.
prototype
.
toggleFilter
=
function
(
sender
)
{
...
...
app/assets/javascripts/application.js
View file @
fa1ac47e
...
...
@@ -13,7 +13,6 @@
/*= require jquery-ui/sortable */
/*= require jquery_ujs */
/*= require jquery.endless-scroll */
/*= require jquery.timeago */
/*= require jquery.highlight */
/*= require jquery.waitforimages */
/*= require jquery.atwho */
...
...
@@ -238,8 +237,5 @@
// bind sidebar events
new
gl
.
Sidebar
();
// Custom time ago
gl
.
utils
.
shortTimeAgo
(
$
(
'
.js-short-timeago
'
));
});
}).
call
(
this
);
app/assets/javascripts/build.js
View file @
fa1ac47e
...
...
@@ -169,7 +169,7 @@
$date
=
$
(
'
.js-artifacts-remove
'
);
if
(
$date
.
length
)
{
date
=
$date
.
text
();
return
$date
.
text
(
$
.
timefor
(
new
Date
(
date
.
replace
(
/
([
0-9
]
+
)
-
([
0-9
]
+
)
-
([
0-9
]
+
)
/g
,
'
$1/$2/$3
'
)),
'
'
));
return
$date
.
text
(
gl
.
utils
.
timefor
(
new
Date
(
date
.
replace
(
/
([
0-9
]
+
)
-
([
0-9
]
+
)
-
([
0-9
]
+
)
/g
,
'
$1/$2/$3
'
)),
'
'
));
}
};
...
...
app/assets/javascripts/compare.js
View file @
fa1ac47e
...
...
@@ -80,7 +80,8 @@
success
:
function
(
html
)
{
loading
.
hide
();
$target
.
html
(
html
);
return
$
(
'
.js-timeago
'
,
$target
).
timeago
();
var
className
=
'
.
'
+
$target
[
0
].
className
.
replace
(
'
'
,
'
.
'
);
gl
.
utils
.
localTimeAgo
(
$
(
'
.js-timeago
'
,
className
));
}
});
};
...
...
app/assets/javascripts/lib/utils/common_utils.js
View file @
fa1ac47e
...
...
@@ -119,31 +119,12 @@
parser
.
href
=
url
;
return
parser
;
};
gl
.
utils
.
cleanupBeforeFetch
=
function
()
{
// Unbind scroll events
$
(
document
).
off
(
'
scroll
'
);
// Close any open tooltips
$
(
'
.has-tooltip, [data-toggle="tooltip"]
'
).
tooltip
(
'
destroy
'
);
};
return
jQuery
.
timefor
=
function
(
time
,
suffix
,
expiredLabel
)
{
var
suffixFromNow
,
timefor
;
if
(
!
time
)
{
return
''
;
}
suffix
||
(
suffix
=
'
remaining
'
);
expiredLabel
||
(
expiredLabel
=
'
Past due
'
);
jQuery
.
timeago
.
settings
.
allowFuture
=
true
;
suffixFromNow
=
jQuery
.
timeago
.
settings
.
strings
.
suffixFromNow
;
jQuery
.
timeago
.
settings
.
strings
.
suffixFromNow
=
suffix
;
timefor
=
$
.
timeago
(
time
);
if
(
timefor
.
indexOf
(
'
ago
'
)
>
-
1
)
{
timefor
=
expiredLabel
;
}
jQuery
.
timeago
.
settings
.
strings
.
suffixFromNow
=
suffixFromNow
;
return
timefor
;
};
})(
window
);
}).
call
(
this
);
app/assets/javascripts/lib/utils/datetime_utility.js
View file @
fa1ac47e
...
...
@@ -22,51 +22,64 @@
if
(
setTimeago
==
null
)
{
setTimeago
=
true
;
}
$timeagoEls
.
each
(
function
()
{
var
$el
;
$el
=
$
(
this
);
return
$el
.
attr
(
'
title
'
,
gl
.
utils
.
formatDate
(
$el
.
attr
(
'
datetime
'
)));
var
$el
=
$
(
this
);
$el
.
attr
(
'
title
'
,
gl
.
utils
.
formatDate
(
$el
.
attr
(
'
datetime
'
)));
if
(
setTimeago
)
{
// Recreate with custom template
$el
.
tooltip
({
template
:
'
<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>
'
});
}
gl
.
utils
.
renderTimeago
(
$el
);
});
if
(
setTimeago
)
{
$timeagoEls
.
timeago
();
$timeagoEls
.
tooltip
(
'
destroy
'
);
// Recreate with custom template
return
$timeagoEls
.
tooltip
({
template
:
'
<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>
'
});
}
};
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
:
[]
w
.
gl
.
utils
.
getTimeago
=
function
()
{
var
locale
=
function
(
number
,
index
)
{
return
[
[
'
less than a minute ago
'
,
'
a while
'
],
[
'
less than a minute ago
'
,
'
in %s seconds
'
],
[
'
about a minute ago
'
,
'
in 1 minute
'
],
[
'
%s minutes ago
'
,
'
in %s minutes
'
],
[
'
about an hour ago
'
,
'
in 1 hour
'
],
[
'
about %s hours ago
'
,
'
in %s hours
'
],
[
'
a day ago
'
,
'
in 1 day
'
],
[
'
%s days ago
'
,
'
in %s days
'
],
[
'
a week ago
'
,
'
in 1 week
'
],
[
'
%s weeks ago
'
,
'
in %s weeks
'
],
[
'
a month ago
'
,
'
in 1 month
'
],
[
'
%s months ago
'
,
'
in %s months
'
],
[
'
a year ago
'
,
'
in 1 year
'
],
[
'
%s years ago
'
,
'
in %s years
'
]
][
index
];
};
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
;
timeago
.
register
(
'
gl_en
'
,
locale
);
return
timeago
();
};
w
.
gl
.
utils
.
timeFor
=
function
(
time
,
suffix
,
expiredLabel
)
{
var
timefor
;
if
(
!
time
)
{
return
''
;
}
suffix
||
(
suffix
=
'
remaining
'
);
expiredLabel
||
(
expiredLabel
=
'
Past due
'
);
timefor
=
gl
.
utils
.
getTimeago
().
format
(
time
).
replace
(
'
in
'
,
''
);
if
(
timefor
.
indexOf
(
'
ago
'
)
>
-
1
)
{
timefor
=
expiredLabel
;
}
else
{
timefor
=
timefor
.
trim
()
+
'
'
+
suffix
;
}
return
timefor
;
};
w
.
gl
.
utils
.
renderTimeago
=
function
(
$element
)
{
var
timeagoInstance
=
gl
.
utils
.
getTimeago
();
timeagoInstance
.
render
(
$element
,
'
gl_en
'
);
};
w
.
gl
.
utils
.
getDayDifference
=
function
(
a
,
b
)
{
...
...
@@ -75,7 +88,7 @@
var
date2
=
Date
.
UTC
(
b
.
getFullYear
(),
b
.
getMonth
(),
b
.
getDate
());
return
Math
.
floor
((
date2
-
date1
)
/
millisecondsPerDay
);
}
}
;
})(
window
);
...
...
app/assets/javascripts/lib/utils/timeago.js
0 → 100644
View file @
fa1ac47e
/**
* Copyright (c) 2016 hustcc
* License: MIT
* Version: v2.0.2
* https://github.com/hustcc/timeago.js
* This is a forked from (https://gitlab.com/ClemMakesApps/timeago.js)
**/
/* eslint-disable */
/* jshint expr: true */
!
function
(
root
,
factory
)
{
if
(
typeof
module
===
'
object
'
&&
module
.
exports
)
module
.
exports
=
factory
(
root
);
else
root
.
timeago
=
factory
(
root
);
}(
typeof
window
!==
'
undefined
'
?
window
:
this
,
function
()
{
var
cnt
=
0
,
// the timer counter, for timer key
indexMapEn
=
'
second_minute_hour_day_week_month_year
'
.
split
(
'
_
'
),
// build-in locales: en & zh_CN
locales
=
{
'
en
'
:
function
(
number
,
index
)
{
if
(
index
===
0
)
return
[
'
just now
'
,
'
right now
'
];
var
unit
=
indexMapEn
[
parseInt
(
index
/
2
)];
if
(
number
>
1
)
unit
+=
'
s
'
;
return
[
number
+
'
'
+
unit
+
'
ago
'
,
'
in
'
+
number
+
'
'
+
unit
];
},
},
// second, minute, hour, day, week, month, year(365 days)
SEC_ARRAY
=
[
60
,
60
,
24
,
7
,
365
/
7
/
12
,
12
],
SEC_ARRAY_LEN
=
6
,
ATTR_DATETIME
=
'
datetime
'
;
// format Date / string / timestamp to Date instance.
function
toDate
(
input
)
{
if
(
input
instanceof
Date
)
return
input
;
if
(
!
isNaN
(
input
))
return
new
Date
(
toInt
(
input
));
if
(
/^
\d
+$/
.
test
(
input
))
return
new
Date
(
toInt
(
input
,
10
));
input
=
(
input
||
''
).
trim
().
replace
(
/
\.\d
+/
,
''
)
// remove milliseconds
.
replace
(
/-/
,
'
/
'
).
replace
(
/-/
,
'
/
'
)
.
replace
(
/T/
,
'
'
).
replace
(
/Z/
,
'
UTC
'
)
.
replace
(
/
([\+\-]\d\d)\:?(\d\d)
/
,
'
$1$2
'
);
// -04:00 -> -0400
return
new
Date
(
input
);
}
// change f into int, remove Decimal. just for code compression
function
toInt
(
f
)
{
return
parseInt
(
f
);
}
// format the diff second to *** time ago, with setting locale
function
formatDiff
(
diff
,
locale
,
defaultLocale
)
{
// if locale is not exist, use defaultLocale.
// if defaultLocale is not exist, use build-in `en`.
// be sure of no error when locale is not exist.
locale
=
locales
[
locale
]
?
locale
:
(
locales
[
defaultLocale
]
?
defaultLocale
:
'
en
'
);
// if (! locales[locale]) locale = defaultLocale;
var
i
=
0
;
agoin
=
diff
<
0
?
1
:
0
;
// timein or timeago
diff
=
Math
.
abs
(
diff
);
for
(;
diff
>=
SEC_ARRAY
[
i
]
&&
i
<
SEC_ARRAY_LEN
;
i
++
)
{
diff
/=
SEC_ARRAY
[
i
];
}
diff
=
toInt
(
diff
);
i
*=
2
;
if
(
diff
>
(
i
===
0
?
9
:
1
))
i
+=
1
;
return
locales
[
locale
](
diff
,
i
)[
agoin
].
replace
(
'
%s
'
,
diff
);
}
// calculate the diff second between date to be formated an now date.
function
diffSec
(
date
,
nowDate
)
{
nowDate
=
nowDate
?
toDate
(
nowDate
)
:
new
Date
();
return
(
nowDate
-
toDate
(
date
))
/
1000
;
}
/**
* nextInterval: calculate the next interval time.
* - diff: the diff sec between now and date to be formated.
*
* What's the meaning?
* diff = 61 then return 59
* diff = 3601 (an hour + 1 second), then return 3599
* make the interval with high performace.
**/
function
nextInterval
(
diff
)
{
var
rst
=
1
,
i
=
0
,
d
=
Math
.
abs
(
diff
);
for
(;
diff
>=
SEC_ARRAY
[
i
]
&&
i
<
SEC_ARRAY_LEN
;
i
++
)
{
diff
/=
SEC_ARRAY
[
i
];
rst
*=
SEC_ARRAY
[
i
];
}
// return leftSec(d, rst);
d
=
d
%
rst
;
d
=
d
?
rst
-
d
:
rst
;
return
Math
.
ceil
(
d
);
}
// get the datetime attribute, jQuery and DOM
function
getDateAttr
(
node
)
{
if
(
node
.
getAttribute
)
return
node
.
getAttribute
(
ATTR_DATETIME
);
if
(
node
.
attr
)
return
node
.
attr
(
ATTR_DATETIME
);
}
/**
* timeago: the function to get `timeago` instance.
* - nowDate: the relative date, default is new Date().
* - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you.
*
* How to use it?
* var timeagoLib = require('timeago.js');
* var timeago = timeagoLib(); // all use default.
* var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
* var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`.
* var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前.
**/
function
Timeago
(
nowDate
,
defaultLocale
)
{
var
timers
=
{};
// real-time render timers
// if do not set the defaultLocale, set it with `en`
if
(
!
defaultLocale
)
defaultLocale
=
'
en
'
;
// use default build-in locale
// what the timer will do
function
doRender
(
node
,
date
,
locale
,
cnt
)
{
var
diff
=
diffSec
(
date
,
nowDate
);
node
.
innerHTML
=
formatDiff
(
diff
,
locale
,
defaultLocale
);
// waiting %s seconds, do the next render
timers
[
'
k
'
+
cnt
]
=
setTimeout
(
function
()
{
doRender
(
node
,
date
,
locale
,
cnt
);
},
nextInterval
(
diff
)
*
1000
);
}
/**
* nextInterval: calculate the next interval time.
* - diff: the diff sec between now and date to be formated.
*
* What's the meaning?
* diff = 61 then return 59
* diff = 3601 (an hour + 1 second), then return 3599
* make the interval with high performace.
**/
// this.nextInterval = function(diff) { // for dev test
// var rst = 1, i = 0, d = Math.abs(diff);
// for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
// diff /= SEC_ARRAY[i];
// rst *= SEC_ARRAY[i];
// }
// // return leftSec(d, rst);
// d = d % rst;
// d = d ? rst - d : rst;
// return Math.ceil(d);
// }; // for dev test
/**
* format: format the date to *** time ago, with setting or default locale
* - date: the date / string / timestamp to be formated
* - locale: the formated string's locale name, e.g. en / zh_CN
*
* How to use it?
* var timeago = require('timeago.js')();
* timeago.format(new Date(), 'pl'); // Date instance
* timeago.format('2016-09-10', 'fr'); // formated date string
* timeago.format(1473473400269); // timestamp with ms
**/
this
.
format
=
function
(
date
,
locale
)
{
return
formatDiff
(
diffSec
(
date
,
nowDate
),
locale
,
defaultLocale
);
};
/**
* render: render the DOM real-time.
* - nodes: which nodes will be rendered.
* - locale: the locale name used to format date.
*
* How to use it?
* var timeago = new require('timeago.js')();
* // 1. javascript selector
* timeago.render(document.querySelectorAll('.need_to_be_rendered'));
* // 2. use jQuery selector
* timeago.render($('.need_to_be_rendered'), 'pl');
*
* Notice: please be sure the dom has attribute `datetime`.
**/
this
.
render
=
function
(
nodes
,
locale
)
{
if
(
nodes
.
length
===
undefined
)
nodes
=
[
nodes
];
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
doRender
(
nodes
[
i
],
getDateAttr
(
nodes
[
i
]),
locale
,
++
cnt
);
// render item
}
};
/**
* cancel: cancel all the timers which are doing real-time render.
*
* How to use it?
* var timeago = new require('timeago.js')();
* timeago.render(document.querySelectorAll('.need_to_be_rendered'));
* timeago.cancel(); // will stop all the timer, stop render in real time.
**/
this
.
cancel
=
function
()
{
for
(
var
key
in
timers
)
{
clearTimeout
(
timers
[
key
]);
}
timers
=
{};
};
/**
* setLocale: set the default locale name.
*
* How to use it?
* var timeago = require('timeago.js');
* timeago = new timeago();
* timeago.setLocale('fr');
**/
this
.
setLocale
=
function
(
locale
)
{
defaultLocale
=
locale
;
};
return
this
;
}
/**
* timeago: the function to get `timeago` instance.
* - nowDate: the relative date, default is new Date().
* - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you.
*
* How to use it?
* var timeagoLib = require('timeago.js');
* var timeago = timeagoLib(); // all use default.
* var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
* var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`.
* var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前.
**/
function
timeagoFactory
(
nowDate
,
defaultLocale
)
{
return
new
Timeago
(
nowDate
,
defaultLocale
);
}
/**
* register: register a new language locale
* - locale: locale name, e.g. en / zh_CN, notice the standard.
* - localeFunc: the locale process function
*
* How to use it?
* var timeagoLib = require('timeago.js');
*
* timeagoLib.register('the locale name', the_locale_func);
* // or
* timeagoLib.register('pl', require('timeago.js/locales/pl'));
**/
timeagoFactory
.
register
=
function
(
locale
,
localeFunc
)
{
locales
[
locale
]
=
localeFunc
;
};
return
timeagoFactory
;
});
\ No newline at end of file
app/assets/javascripts/merge_request_widget.js.es6
View file @
fa1ac47e
...
...
@@ -218,7 +218,7 @@
}
if (environment.deployed_at && environment.deployed_at_formatted) {
environment.deployed_at =
$.t
imeago(environment.deployed_at) + '.';
environment.deployed_at =
gl.utils.getT
imeago(environment.deployed_at) + '.';
} else {
$('.js-environment-timeago', $template).remove();
environment.name += '.';
...
...
app/assets/javascripts/milestone_select.js
View file @
fa1ac47e
...
...
@@ -162,7 +162,7 @@
if
(
data
.
milestone
!=
null
)
{
data
.
milestone
.
namespace
=
_this
.
currentProject
.
namespace
;
data
.
milestone
.
path
=
_this
.
currentProject
.
path
;
data
.
milestone
.
remaining
=
$
.
timef
or
(
data
.
milestone
.
due_date
);
data
.
milestone
.
remaining
=
gl
.
utils
.
timeF
or
(
data
.
milestone
.
due_date
);
$value
.
html
(
milestoneLinkTemplate
(
data
.
milestone
));
return
$sidebarCollapsedValue
.
find
(
'
span
'
).
html
(
collapsedSidebarLabelTemplate
(
data
.
milestone
));
}
else
{
...
...
app/helpers/application_helper.rb
View file @
fa1ac47e
...
...
@@ -151,7 +151,6 @@ module ApplicationHelper
# 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
...
...
@@ -163,22 +162,19 @@ module ApplicationHelper
# `html_class` argument is provided.
#
# Returns an HTML-safe String
def
time_ago_with_tooltip
(
time
,
placement:
'top'
,
html_class:
''
,
s
kip_js:
false
,
s
hort_format:
false
)
def
time_ago_with_tooltip
(
time
,
placement:
'top'
,
html_class:
''
,
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:
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'
}
unless
skip_js
element
<<
javascript_tag
(
"$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()"
)
end
datetime:
time
.
to_time
.
getutc
.
iso8601
,
data:
{
toggle:
'tooltip'
,
placement:
placement
,
container:
'body'
}
element
end
...
...
app/views/events/_event.html.haml
View file @
fa1ac47e
-
if
event
.
visible_to_user?
(
current_user
)
.event-item
{
class:
event_row_class
(
event
)
}
.event-item-timestamp
#{
time_ago_with_tooltip
(
event
.
created_at
,
skip_js:
true
)
}
#{
time_ago_with_tooltip
(
event
.
created_at
)
}
=
cache
[
event
,
current_application_settings
,
"v2.2"
]
do
=
author_avatar
(
event
,
size:
40
)
...
...
app/views/projects/_last_commit.html.haml
View file @
fa1ac47e
...
...
@@ -8,5 +8,5 @@
=
link_to
commit
.
short_id
,
namespace_project_commit_path
(
project
.
namespace
,
project
,
commit
),
class:
"commit_short_id"
=
link_to_gfm
commit
.
title
,
namespace_project_commit_path
(
project
.
namespace
,
project
,
commit
),
class:
"commit-row-message"
·
#{
time_ago_with_tooltip
(
commit
.
committed_date
,
skip_js:
true
)
}
by
#{
time_ago_with_tooltip
(
commit
.
committed_date
)
}
by
=
commit_author_link
(
commit
,
avatar:
true
,
size:
24
)
app/views/projects/blame/show.html.haml
View file @
fa1ac47e
...
...
@@ -32,7 +32,7 @@
.light
=
commit_author_link
(
commit
,
avatar:
false
)
authored
#{
time_ago_with_tooltip
(
commit
.
committed_date
,
skip_js:
true
)
}
#{
time_ago_with_tooltip
(
commit
.
committed_date
)
}
%td
.line-numbers
-
line_count
=
blame_group
[
:lines
].
count
-
(
current_line
...
(
current_line
+
line_count
)).
each
do
|
i
|
...
...
app/views/projects/ci/pipelines/_pipeline.html.haml
View file @
fa1ac47e
...
...
@@ -59,7 +59,7 @@
-
if
pipeline
.
finished_at
%p
.finished-at
=
icon
(
"calendar"
)
#{
time_ago_with_tooltip
(
pipeline
.
finished_at
,
short_format:
false
,
skip_js:
true
)
}
#{
time_ago_with_tooltip
(
pipeline
.
finished_at
,
short_format:
false
)
}
%td
.pipeline-actions.hidden-xs
.controls.pull-right
...
...
app/views/projects/refs/logs_tree.js.haml
View file @
fa1ac47e
...
...
@@ -16,3 +16,6 @@
var url = "
#{
escape_javascript
(
@more_log_url
)
}
";
ajaxGet(url);
}
:plain
gl.utils.localTimeAgo($('.js-timeago', 'table.table_
#{
@hex_path
}
tbody'));
\ No newline at end of file
changelogs/unreleased/upgrade-timeago.yml
0 → 100644
View file @
fa1ac47e
---
title
:
Replace jQuery.timeago with timeago.js
merge_request
:
6274
author
:
ClemMakesApps
spec/helpers/application_helper_spec.rb
View file @
fa1ac47e
...
...
@@ -218,42 +218,24 @@ describe ApplicationHelper do
end
it
'includes a default js-timeago class'
do
expect
(
element
.
attr
(
'class'
)).
to
eq
'js-timeago
js-timeago-pending
'
expect
(
element
.
attr
(
'class'
)).
to
eq
'js-timeago'
end
it
'accepts a custom html_class'
do
expect
(
element
(
html_class:
'custom_class'
).
attr
(
'class'
)).
to
eq
'js-timeago custom_class
js-timeago-pending
'
to
eq
'js-timeago custom_class'
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-pending').removeClass('js-timeago-pending').timeago()"
end
it
'allows the script tag to be excluded'
do
expect
(
element
(
skip_js:
true
)).
not_to
include
'script'
end
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
it
'add class for the short format'
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
...
...
spec/javascripts/merge_request_widget_spec.js
View file @
fa1ac47e
/* eslint-disable */
/*= require merge_request_widget */
/*= require
jquery.
timeago.js */
/*= require
lib/utils/
timeago.js */
(
function
()
{
describe
(
'
MergeRequestWidget
'
,
function
()
{
...
...
vendor/assets/javascripts/jquery.timeago.js
deleted
100644 → 0
View file @
6be0c160
/* eslint-disable */
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 1.1.0
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(
function
(
factory
)
{
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
// AMD. Register as an anonymous module.
define
([
'
jquery
'
],
factory
);
}
else
{
// Browser globals
factory
(
jQuery
);
}
}(
function
(
$
)
{
$
.
timeago
=
function
(
timestamp
)
{
if
(
timestamp
instanceof
Date
)
{
return
inWords
(
timestamp
);
}
else
if
(
typeof
timestamp
===
"
string
"
)
{
return
inWords
(
$
.
timeago
.
parse
(
timestamp
));
}
else
if
(
typeof
timestamp
===
"
number
"
)
{
return
inWords
(
new
Date
(
timestamp
));
}
else
{
return
inWords
(
$
.
timeago
.
datetime
(
timestamp
));
}
};
var
$t
=
$
.
timeago
;
$
.
extend
(
$
.
timeago
,
{
settings
:
{
refreshMillis
:
60000
,
allowFuture
:
false
,
strings
:
{
prefixAgo
:
null
,
prefixFromNow
:
null
,
suffixAgo
:
"
ago
"
,
suffixFromNow
:
"
from now
"
,
seconds
:
"
less than a minute
"
,
minute
:
"
about a minute
"
,
minutes
:
"
%d minutes
"
,
hour
:
"
about an hour
"
,
hours
:
"
about %d hours
"
,
day
:
"
a day
"
,
days
:
"
%d days
"
,
month
:
"
about a month
"
,
months
:
"
%d months
"
,
year
:
"
about a year
"
,
years
:
"
%d years
"
,
wordSeparator
:
"
"
,
numbers
:
[]
}
},
inWords
:
function
(
distanceMillis
)
{
var
$l
=
this
.
settings
.
strings
;
var
prefix
=
$l
.
prefixAgo
;
var
suffix
=
$l
.
suffixAgo
;
if
(
this
.
settings
.
allowFuture
)
{
if
(
distanceMillis
<
0
)
{
prefix
=
$l
.
prefixFromNow
;
suffix
=
$l
.
suffixFromNow
;
}
}
var
seconds
=
Math
.
abs
(
distanceMillis
)
/
1000
;
var
minutes
=
seconds
/
60
;
var
hours
=
minutes
/
60
;
var
days
=
hours
/
24
;
var
years
=
days
/
365
;
function
substitute
(
stringOrFunction
,
number
)
{
var
string
=
$
.
isFunction
(
stringOrFunction
)
?
stringOrFunction
(
number
,
distanceMillis
)
:
stringOrFunction
;
var
value
=
(
$l
.
numbers
&&
$l
.
numbers
[
number
])
||
number
;
return
string
.
replace
(
/%d/i
,
value
);
}
var
words
=
seconds
<
45
&&
substitute
(
$l
.
seconds
,
Math
.
round
(
seconds
))
||
seconds
<
90
&&
substitute
(
$l
.
minute
,
1
)
||
minutes
<
45
&&
substitute
(
$l
.
minutes
,
Math
.
round
(
minutes
))
||
minutes
<
90
&&
substitute
(
$l
.
hour
,
1
)
||
hours
<
24
&&
substitute
(
$l
.
hours
,
Math
.
round
(
hours
))
||
hours
<
42
&&
substitute
(
$l
.
day
,
1
)
||
days
<
30
&&
substitute
(
$l
.
days
,
Math
.
round
(
days
))
||
days
<
45
&&
substitute
(
$l
.
month
,
1
)
||
days
<
365
&&
substitute
(
$l
.
months
,
Math
.
round
(
days
/
30
))
||
years
<
1.5
&&
substitute
(
$l
.
year
,
1
)
||
substitute
(
$l
.
years
,
Math
.
round
(
years
));
var
separator
=
$l
.
wordSeparator
||
""
;
if
(
$l
.
wordSeparator
===
undefined
)
{
separator
=
"
"
;
}
return
$
.
trim
([
prefix
,
words
,
suffix
].
join
(
separator
));
},
parse
:
function
(
iso8601
)
{
var
s
=
$
.
trim
(
iso8601
);
s
=
s
.
replace
(
/
\.\d
+/
,
""
);
// remove milliseconds
s
=
s
.
replace
(
/-/
,
"
/
"
).
replace
(
/-/
,
"
/
"
);
s
=
s
.
replace
(
/T/
,
"
"
).
replace
(
/Z/
,
"
UTC
"
);
s
=
s
.
replace
(
/
([\+\-]\d\d)\:?(\d\d)
/
,
"
$1$2
"
);
// -04:00 -> -0400
return
new
Date
(
s
);
},
datetime
:
function
(
elem
)
{
var
iso8601
=
$t
.
isTime
(
elem
)
?
$
(
elem
).
attr
(
"
datetime
"
)
:
$
(
elem
).
attr
(
"
title
"
);
return
$t
.
parse
(
iso8601
);
},
isTime
:
function
(
elem
)
{
// jQuery's `is()` doesn't play well with HTML5 in IE
return
$
(
elem
).
get
(
0
).
tagName
.
toLowerCase
()
===
"
time
"
;
// $(elem).is("time");
}
});
// functions that can be called via $(el).timeago('action')
// init is default when no action is given
// functions are called with context of a single element
var
functions
=
{
init
:
function
(){
var
refresh_el
=
$
.
proxy
(
refresh
,
this
);
refresh_el
();
var
$s
=
$t
.
settings
;
if
(
$s
.
refreshMillis
>
0
)
{
setInterval
(
refresh_el
,
$s
.
refreshMillis
);
}
},
update
:
function
(
time
){
$
(
this
).
data
(
'
timeago
'
,
{
datetime
:
$t
.
parse
(
time
)
});
refresh
.
apply
(
this
);
}
};
$
.
fn
.
timeago
=
function
(
action
,
options
)
{
var
fn
=
action
?
functions
[
action
]
:
functions
.
init
;
if
(
!
fn
){
throw
new
Error
(
"
Unknown function name '
"
+
action
+
"
' for timeago
"
);
}
// each over objects here and call the requested function
this
.
each
(
function
(){
fn
.
call
(
this
,
options
);
});
return
this
;
};
function
refresh
()
{
var
data
=
prepareData
(
this
);
if
(
!
isNaN
(
data
.
datetime
))
{
$
(
this
).
text
(
inWords
(
data
.
datetime
));
}
return
this
;
}
function
prepareData
(
element
)
{
element
=
$
(
element
);
if
(
!
element
.
data
(
"
timeago
"
))
{
element
.
data
(
"
timeago
"
,
{
datetime
:
$t
.
datetime
(
element
)
});
var
text
=
$
.
trim
(
element
.
text
());
if
(
text
.
length
>
0
&&
!
(
$t
.
isTime
(
element
)
&&
element
.
attr
(
"
title
"
)))
{
element
.
attr
(
"
title
"
,
text
);
}
}
return
element
.
data
(
"
timeago
"
);
}
function
inWords
(
date
)
{
return
$t
.
inWords
(
distance
(
date
));
}
function
distance
(
date
)
{
return
(
new
Date
().
getTime
()
-
date
.
getTime
());
}
// fix for IE6 suckage
document
.
createElement
(
"
abbr
"
);
document
.
createElement
(
"
time
"
);
}));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment