Commit 9daeccfb authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '38869-datetime' into 'master'

Export date utility functions as ES6 modules

See merge request gitlab-org/gitlab-ce!15782
parents 54c2d7bd 114f93cc
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Pager */ /* global Pager */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { localTimeAgo } from './lib/utils/datetime_utility';
class Activities { class Activities {
constructor() { constructor() {
...@@ -15,7 +16,7 @@ class Activities { ...@@ -15,7 +16,7 @@ class Activities {
} }
updateTooltips() { updateTooltips() {
gl.utils.localTimeAgo($('.js-timeago', '.content_list')); localTimeAgo($('.js-timeago', '.content_list'));
} }
reloadActivities() { reloadActivities() {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
/* global Pager */ /* global Pager */
import { pluralize } from './lib/utils/text_utility'; import { pluralize } from './lib/utils/text_utility';
import { localTimeAgo } from './lib/utils/datetime_utility';
export default (function () { export default (function () {
const CommitsList = {}; const CommitsList = {};
...@@ -91,7 +92,7 @@ export default (function () { ...@@ -91,7 +92,7 @@ export default (function () {
$commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`); $commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
} }
gl.utils.localTimeAgo($processedData.find('.js-timeago')); localTimeAgo($processedData.find('.js-timeago'));
return processedData; return processedData;
}; };
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, no-var, object-shorthand, consistent-return, no-unused-vars, comma-dangle, vars-on-top, prefer-template, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, no-var, object-shorthand, consistent-return, no-unused-vars, comma-dangle, vars-on-top, prefer-template, max-len */
import { localTimeAgo } from './lib/utils/datetime_utility';
export default class Compare { export default class Compare {
constructor(opts) { constructor(opts) {
...@@ -81,7 +82,7 @@ export default class Compare { ...@@ -81,7 +82,7 @@ export default class Compare {
loading.hide(); loading.hide();
$target.html(html); $target.html(html);
var className = '.' + $target[0].className.replace(' ', '.'); var className = '.' + $target[0].className.replace(' ', '.');
gl.utils.localTimeAgo($('.js-timeago', className)); localTimeAgo($('.js-timeago', className));
} }
}); });
} }
......
<script> <script>
import actionBtn from './action_btn.vue'; import actionBtn from './action_btn.vue';
import { getTimeago } from '../../lib/utils/datetime_utility';
export default { export default {
props: { props: {
...@@ -21,7 +22,7 @@ ...@@ -21,7 +22,7 @@
}, },
computed: { computed: {
timeagoDate() { timeagoDate() {
return gl.utils.getTimeago().format(this.deployKey.created_at); return getTimeago().format(this.deployKey.created_at);
}, },
editDeployKeyPath() { editDeployKeyPath() {
return `${this.endpoint}/${this.deployKey.id}/edit`; return `${this.endpoint}/${this.deployKey.id}/edit`;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global NoteModel */ /* global NoteModel */
import Vue from 'vue'; import Vue from 'vue';
import { localTimeAgo } from '../../lib/utils/datetime_utility';
class DiscussionModel { class DiscussionModel {
constructor (discussionId) { constructor (discussionId) {
...@@ -71,7 +72,7 @@ class DiscussionModel { ...@@ -71,7 +72,7 @@ class DiscussionModel {
$(`${discussionSelector} .discussion-header`).append(data.discussion_headline_html); $(`${discussionSelector} .discussion-header`).append(data.discussion_headline_html);
} }
gl.utils.localTimeAgo($('.js-timeago', `${discussionSelector}`)); localTimeAgo($('.js-timeago', `${discussionSelector}`));
} else { } else {
$discussionHeadline.remove(); $discussionHeadline.remove();
} }
......
...@@ -3,6 +3,7 @@ import { visitUrl } from './lib/utils/url_utility'; ...@@ -3,6 +3,7 @@ import { visitUrl } from './lib/utils/url_utility';
import bp from './breakpoints'; import bp from './breakpoints';
import { bytesToKiB } from './lib/utils/number_utils'; import { bytesToKiB } from './lib/utils/number_utils';
import { setCiStatusFavicon } from './lib/utils/common_utils'; import { setCiStatusFavicon } from './lib/utils/common_utils';
import { timeFor } from './lib/utils/datetime_utility';
export default class Job { export default class Job {
constructor(options) { constructor(options) {
...@@ -261,7 +262,7 @@ export default class Job { ...@@ -261,7 +262,7 @@ export default class Job {
if ($date.length) { if ($date.length) {
const date = $date.text(); const date = $date.text();
return $date.text( return $date.text(
gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '), timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3'))),
); );
} }
} }
......
class Cache { export default class Cache {
constructor() { constructor() {
this.internalStorage = { }; this.internalStorage = { };
} }
...@@ -15,5 +15,3 @@ class Cache { ...@@ -15,5 +15,3 @@ class Cache {
delete this.internalStorage[key]; delete this.internalStorage[key];
} }
} }
export default Cache;
/* eslint-disable import/prefer-default-export */
export const BYTES_IN_KIB = 1024; export const BYTES_IN_KIB = 1024;
export const HIDDEN_CLASS = 'hidden'; export const HIDDEN_CLASS = 'hidden';
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, comma-dangle, no-unused-expressions, prefer-template, max-len */
import timeago from 'timeago.js'; import timeago from 'timeago.js';
import dateFormat from 'vendor/date.format'; import dateFormat from 'vendor/date.format';
import { pluralize } from './text_utility'; import { pluralize } from './text_utility';
import { import {
lang, lang,
s__, s__,
...@@ -12,121 +9,125 @@ import { ...@@ -12,121 +9,125 @@ import {
window.timeago = timeago; window.timeago = timeago;
window.dateFormat = dateFormat; window.dateFormat = dateFormat;
(function() { /**
(function(w) { * Given a date object returns the day of the week in English
var base; * @param {date} date
var timeagoInstance; * @returns {String}
*/
export const getDayName = date => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()];
if (w.gl == null) { /**
w.gl = {}; * @example
} * dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am GMT+0000"
if ((base = w.gl).utils == null) { * @param {date} datetime
base.utils = {}; * @returns {String}
} */
w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; export const formatDate = datetime => dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
w.gl.utils.formatDate = function(datetime) { let timeagoInstance;
return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z'); /**
* Sets a timeago Instance
*/
export function getTimeago() {
if (!timeagoInstance) {
const localeRemaining = function getLocaleRemaining(number, index) {
return [
[s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
[s__('Timeago|less than a minute ago'), s__('Timeago|%s seconds remaining')],
[s__('Timeago|about a minute ago'), s__('Timeago|1 minute remaining')],
[s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
[s__('Timeago|about an hour ago'), s__('Timeago|1 hour remaining')],
[s__('Timeago|about %s hours ago'), s__('Timeago|%s hours remaining')],
[s__('Timeago|a day ago'), s__('Timeago|1 day remaining')],
[s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
[s__('Timeago|a week ago'), s__('Timeago|1 week remaining')],
[s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
[s__('Timeago|a month ago'), s__('Timeago|1 month remaining')],
[s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
[s__('Timeago|a year ago'), s__('Timeago|1 year remaining')],
[s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
][index];
}; };
const locale = function getLocale(number, index) {
w.gl.utils.getDayName = function(date) { return [
return this.days[date.getDay()]; [s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
[s__('Timeago|less than a minute ago'), s__('Timeago|in %s seconds')],
[s__('Timeago|about a minute ago'), s__('Timeago|in 1 minute')],
[s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
[s__('Timeago|about an hour ago'), s__('Timeago|in 1 hour')],
[s__('Timeago|about %s hours ago'), s__('Timeago|in %s hours')],
[s__('Timeago|a day ago'), s__('Timeago|in 1 day')],
[s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
[s__('Timeago|a week ago'), s__('Timeago|in 1 week')],
[s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
[s__('Timeago|a month ago'), s__('Timeago|in 1 month')],
[s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
[s__('Timeago|a year ago'), s__('Timeago|in 1 year')],
[s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
][index];
}; };
w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago = true) { timeago.register(lang, locale);
$timeagoEls.each((i, el) => { timeago.register(`${lang}-remaining`, localeRemaining);
if (setTimeago) { timeagoInstance = timeago();
// 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>'
});
}
el.classList.add('js-timeago-render'); return timeagoInstance;
}); }
gl.utils.renderTimeago($timeagoEls); /**
}; * For the given element, renders a timeago instance.
* @param {jQuery} $els
*/
export const renderTimeago = ($els) => {
const timeagoEls = $els || document.querySelectorAll('.js-timeago-render');
w.gl.utils.getTimeago = function() { // timeago.js sets timeouts internally for each timeago value to be updated in real time
var locale; getTimeago().render(timeagoEls, lang);
};
if (!timeagoInstance) {
const localeRemaining = function(number, index) {
return [
[s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
[s__('Timeago|less than a minute ago'), s__('Timeago|%s seconds remaining')],
[s__('Timeago|about a minute ago'), s__('Timeago|1 minute remaining')],
[s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
[s__('Timeago|about an hour ago'), s__('Timeago|1 hour remaining')],
[s__('Timeago|about %s hours ago'), s__('Timeago|%s hours remaining')],
[s__('Timeago|a day ago'), s__('Timeago|1 day remaining')],
[s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
[s__('Timeago|a week ago'), s__('Timeago|1 week remaining')],
[s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
[s__('Timeago|a month ago'), s__('Timeago|1 month remaining')],
[s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
[s__('Timeago|a year ago'), s__('Timeago|1 year remaining')],
[s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')]
][index];
};
locale = function(number, index) {
return [
[s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
[s__('Timeago|less than a minute ago'), s__('Timeago|in %s seconds')],
[s__('Timeago|about a minute ago'), s__('Timeago|in 1 minute')],
[s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
[s__('Timeago|about an hour ago'), s__('Timeago|in 1 hour')],
[s__('Timeago|about %s hours ago'), s__('Timeago|in %s hours')],
[s__('Timeago|a day ago'), s__('Timeago|in 1 day')],
[s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
[s__('Timeago|a week ago'), s__('Timeago|in 1 week')],
[s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
[s__('Timeago|a month ago'), s__('Timeago|in 1 month')],
[s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
[s__('Timeago|a year ago'), s__('Timeago|in 1 year')],
[s__('Timeago|%s years ago'), s__('Timeago|in %s years')]
][index];
};
timeago.register(lang, locale);
timeago.register(`${lang}-remaining`, localeRemaining);
timeagoInstance = timeago();
}
return timeagoInstance;
};
w.gl.utils.timeFor = function(time, suffix, expiredLabel) { /**
var timefor; * For the given elements, sets a tooltip with a formatted date.
if (!time) { * @param {jQuery}
return ''; * @param {Boolean} setTimeago
} */
if (new Date(time) < new Date()) { export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
expiredLabel || (expiredLabel = s__('Timeago|Past due')); $timeagoEls.each((i, el) => {
timefor = expiredLabel; if (setTimeago) {
} else { // Recreate with custom template
timefor = gl.utils.getTimeago().format(time, `${lang}-remaining`).trim(); $(el).tooltip({
} template: '<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
return timefor; });
}; }
w.gl.utils.renderTimeago = function($els) { el.classList.add('js-timeago-render');
const timeagoEls = $els || document.querySelectorAll('.js-timeago-render'); });
// timeago.js sets timeouts internally for each timeago value to be updated in real time renderTimeago($timeagoEls);
gl.utils.getTimeago().render(timeagoEls, lang); };
};
w.gl.utils.getDayDifference = function(a, b) { /**
var millisecondsPerDay = 1000 * 60 * 60 * 24; * Returns remaining or passed time over the given time.
var date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate()); * @param {*} time
var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()); * @param {*} expiredLabel
*/
export const timeFor = (time, expiredLabel) => {
if (!time) {
return '';
}
if (new Date(time) < new Date()) {
return expiredLabel || s__('Timeago|Past due');
}
return getTimeago().format(time, `${lang}-remaining`).trim();
};
return Math.floor((date2 - date1) / millisecondsPerDay); export const getDayDifference = (a, b) => {
}; const millisecondsPerDay = 1000 * 60 * 60 * 24;
})(window); const date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
}).call(window); const date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((date2 - date1) / millisecondsPerDay);
};
/** /**
* Port of ruby helper time_interval_in_words. * Port of ruby helper time_interval_in_words.
...@@ -162,3 +163,10 @@ export function dateInWords(date, abbreviated = false) { ...@@ -162,3 +163,10 @@ export function dateInWords(date, abbreviated = false) {
return `${monthName} ${date.getDate()}, ${year}`; return `${monthName} ${date.getDate()}, ${year}`;
} }
window.gl = window.gl || {};
window.gl.utils = {
...(window.gl.utils || {}),
getTimeago,
localTimeAgo,
};
...@@ -28,7 +28,7 @@ import './commit/image_file'; ...@@ -28,7 +28,7 @@ import './commit/image_file';
// lib/utils // lib/utils
import { handleLocationHash } from './lib/utils/common_utils'; import { handleLocationHash } from './lib/utils/common_utils';
import './lib/utils/datetime_utility'; import { localTimeAgo, renderTimeago } from './lib/utils/datetime_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility'; import { getLocationHash, visitUrl } from './lib/utils/url_utility';
// behaviors // behaviors
...@@ -186,7 +186,7 @@ $(function () { ...@@ -186,7 +186,7 @@ $(function () {
return $(this).parents('form').submit(); return $(this).parents('form').submit();
// Form submitter // Form submitter
}); });
gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true); localTimeAgo($('abbr.timeago, .js-timeago'), true);
// Disable form buttons while a form is submitting // Disable form buttons while a form is submitting
$body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) { $body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) {
var buttons; var buttons;
...@@ -275,7 +275,7 @@ $(function () { ...@@ -275,7 +275,7 @@ $(function () {
loadAwardsHandler(); loadAwardsHandler();
new Aside(); new Aside();
gl.utils.renderTimeago(); renderTimeago();
$(document).trigger('init.scrolling-tabs'); $(document).trigger('init.scrolling-tabs');
......
...@@ -14,6 +14,7 @@ import { ...@@ -14,6 +14,7 @@ import {
import { getLocationHash } from './lib/utils/url_utility'; import { getLocationHash } from './lib/utils/url_utility';
import initDiscussionTab from './image_diff/init_discussion_tab'; import initDiscussionTab from './image_diff/init_discussion_tab';
import Diff from './diff'; import Diff from './diff';
import { localTimeAgo } from './lib/utils/datetime_utility';
import syntaxHighlight from './syntax_highlight'; import syntaxHighlight from './syntax_highlight';
/* eslint-disable max-len */ /* eslint-disable max-len */
...@@ -248,7 +249,7 @@ import syntaxHighlight from './syntax_highlight'; ...@@ -248,7 +249,7 @@ import syntaxHighlight from './syntax_highlight';
url: `${source}.json`, url: `${source}.json`,
success: (data) => { success: (data) => {
document.querySelector('div#commits').innerHTML = data.html; document.querySelector('div#commits').innerHTML = data.html;
gl.utils.localTimeAgo($('.js-timeago', 'div#commits')); localTimeAgo($('.js-timeago', 'div#commits'));
this.commitsLoaded = true; this.commitsLoaded = true;
this.scrollToElement('#commits'); this.scrollToElement('#commits');
}, },
...@@ -295,7 +296,7 @@ import syntaxHighlight from './syntax_highlight'; ...@@ -295,7 +296,7 @@ import syntaxHighlight from './syntax_highlight';
gl.diffNotesCompileComponents(); gl.diffNotesCompileComponents();
} }
gl.utils.localTimeAgo($('.js-timeago', 'div#diffs')); localTimeAgo($('.js-timeago', 'div#diffs'));
syntaxHighlight($('#diffs .js-syntax-highlight')); syntaxHighlight($('#diffs .js-syntax-highlight'));
if (this.diffViewType() === 'parallel' && this.isDiffAction(this.currentAction)) { if (this.diffViewType() === 'parallel' && this.isDiffAction(this.currentAction)) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Issuable */ /* global Issuable */
/* global ListMilestone */ /* global ListMilestone */
import _ from 'underscore'; import _ from 'underscore';
import { timeFor } from './lib/utils/datetime_utility';
(function() { (function() {
this.MilestoneSelect = (function() { this.MilestoneSelect = (function() {
...@@ -216,7 +217,7 @@ import _ from 'underscore'; ...@@ -216,7 +217,7 @@ import _ from 'underscore';
$value.css('display', ''); $value.css('display', '');
if (data.milestone != null) { if (data.milestone != null) {
data.milestone.full_path = _this.currentProject.full_path; data.milestone.full_path = _this.currentProject.full_path;
data.milestone.remaining = gl.utils.timeFor(data.milestone.due_date); data.milestone.remaining = timeFor(data.milestone.due_date);
data.milestone.name = data.milestone.title; data.milestone.name = data.milestone.title;
$value.html(milestoneLinkTemplate(data.milestone)); $value.html(milestoneLinkTemplate(data.milestone));
return $sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone)); return $sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone));
......
...@@ -25,6 +25,7 @@ import Autosave from './autosave'; ...@@ -25,6 +25,7 @@ import Autosave from './autosave';
import TaskList from './task_list'; import TaskList from './task_list';
import { ajaxPost, isInViewport, getPagePath, scrollToElement, isMetaKey } from './lib/utils/common_utils'; import { ajaxPost, isInViewport, getPagePath, scrollToElement, isMetaKey } from './lib/utils/common_utils';
import imageDiffHelper from './image_diff/helpers/index'; import imageDiffHelper from './image_diff/helpers/index';
import { localTimeAgo } from './lib/utils/datetime_utility';
window.autosize = Autosize; window.autosize = Autosize;
...@@ -311,7 +312,7 @@ export default class Notes { ...@@ -311,7 +312,7 @@ export default class Notes {
setupNewNote($note) { setupNewNote($note) {
// Update datetime format on the recent note // Update datetime format on the recent note
gl.utils.localTimeAgo($note.find('.js-timeago'), false); localTimeAgo($note.find('.js-timeago'), false);
this.collapseLongCommitList(); this.collapseLongCommitList();
this.taskList.init(); this.taskList.init();
...@@ -463,7 +464,7 @@ export default class Notes { ...@@ -463,7 +464,7 @@ export default class Notes {
this.renderDiscussionAvatar(diffAvatarContainer, noteEntity); this.renderDiscussionAvatar(diffAvatarContainer, noteEntity);
} }
gl.utils.localTimeAgo($('.js-timeago'), false); localTimeAgo($('.js-timeago'), false);
Notes.checkMergeRequestStatus(); Notes.checkMergeRequestStatus();
return this.updateNotesCount(1); return this.updateNotesCount(1);
} }
......
import _ from 'underscore'; import _ from 'underscore';
import d3 from 'd3'; import d3 from 'd3';
import { getDayName, getDayDifference } from '../lib/utils/datetime_utility';
const LOADING_HTML = ` const LOADING_HTML = `
<div class="text-center"> <div class="text-center">
...@@ -17,7 +18,7 @@ function getSystemDate(systemUtcOffsetSeconds) { ...@@ -17,7 +18,7 @@ function getSystemDate(systemUtcOffsetSeconds) {
function formatTooltipText({ date, count }) { function formatTooltipText({ date, count }) {
const dateObject = new Date(date); const dateObject = new Date(date);
const dateDayName = gl.utils.getDayName(dateObject); const dateDayName = getDayName(dateObject);
const dateText = dateObject.format('mmm d, yyyy'); const dateText = dateObject.format('mmm d, yyyy');
let contribText = 'No contributions'; let contribText = 'No contributions';
...@@ -51,7 +52,7 @@ export default class ActivityCalendar { ...@@ -51,7 +52,7 @@ export default class ActivityCalendar {
const oneYearAgo = new Date(today); const oneYearAgo = new Date(today);
oneYearAgo.setFullYear(today.getFullYear() - 1); oneYearAgo.setFullYear(today.getFullYear() - 1);
const days = gl.utils.getDayDifference(oneYearAgo, today); const days = getDayDifference(oneYearAgo, today);
for (let i = 0; i <= days; i += 1) { for (let i = 0; i <= days; i += 1) {
const date = new Date(oneYearAgo); const date = new Date(oneYearAgo);
......
import ActivityCalendar from './activity_calendar'; import ActivityCalendar from './activity_calendar';
import { localTimeAgo } from '../lib/utils/datetime_utility';
/** /**
* UserTabs * UserTabs
...@@ -138,7 +139,7 @@ export default class UserTabs { ...@@ -138,7 +139,7 @@ export default class UserTabs {
const tabSelector = `div#${action}`; const tabSelector = `div#${action}`;
this.$parentEl.find(tabSelector).html(data.html); this.$parentEl.find(tabSelector).html(data.html);
this.loaded[action] = true; this.loaded[action] = true;
gl.utils.localTimeAgo($('.js-timeago', tabSelector)); localTimeAgo($('.js-timeago', tabSelector));
}, },
}); });
} }
......
import '~/lib/utils/datetime_utility'; import { getTimeago } from '~/lib/utils/datetime_utility';
import { visitUrl } from '../../lib/utils/url_utility'; import { visitUrl } from '../../lib/utils/url_utility';
import Flash from '../../flash'; import Flash from '../../flash';
import MemoryUsage from './mr_widget_memory_usage'; import MemoryUsage from './mr_widget_memory_usage';
...@@ -17,7 +17,7 @@ export default { ...@@ -17,7 +17,7 @@ export default {
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
return gl.utils.getTimeago().format(date); return getTimeago().format(date);
}, },
hasExternalUrls(deployment = {}) { hasExternalUrls(deployment = {}) {
return deployment.external_url && deployment.external_url_formatted; return deployment.external_url && deployment.external_url_formatted;
......
import Timeago from 'timeago.js'; import Timeago from 'timeago.js';
import { getStateKey } from '../dependencies'; import { getStateKey } from '../dependencies';
import { formatDate } from '../../lib/utils/datetime_utility';
export default class MergeRequestStore { export default class MergeRequestStore {
...@@ -122,7 +123,7 @@ export default class MergeRequestStore { ...@@ -122,7 +123,7 @@ export default class MergeRequestStore {
static getEventObject(event) { static getEventObject(event) {
return { return {
author: MergeRequestStore.getAuthorObject(event), author: MergeRequestStore.getAuthorObject(event),
updatedAt: gl.utils.formatDate(MergeRequestStore.getEventUpdatedAtDate(event)), updatedAt: formatDate(MergeRequestStore.getEventUpdatedAtDate(event)),
formattedUpdatedAt: MergeRequestStore.getEventDate(event), formattedUpdatedAt: MergeRequestStore.getEventDate(event),
}; };
} }
......
import { getTimeago } from '../../lib/utils/datetime_utility';
export default { export default {
name: 'MemoryGraph', name: 'MemoryGraph',
props: { props: {
...@@ -16,7 +18,7 @@ export default { ...@@ -16,7 +18,7 @@ export default {
}, },
computed: { computed: {
getFormattedMedian() { getFormattedMedian() {
const deployedSince = gl.utils.getTimeago().format(this.deploymentTime * 1000); const deployedSince = getTimeago().format(this.deploymentTime * 1000);
return `Deployed ${deployedSince}`; return `Deployed ${deployedSince}`;
}, },
}, },
......
import '../../lib/utils/datetime_utility'; import { formatDate, getTimeago } from '../../lib/utils/datetime_utility';
/** /**
* Mixin with time ago methods used in some vue components * Mixin with time ago methods used in some vue components
...@@ -6,13 +6,13 @@ import '../../lib/utils/datetime_utility'; ...@@ -6,13 +6,13 @@ import '../../lib/utils/datetime_utility';
export default { export default {
methods: { methods: {
timeFormated(time) { timeFormated(time) {
const timeago = gl.utils.getTimeago(); const timeago = getTimeago();
return timeago.format(time); return timeago.format(time);
}, },
tooltipTitle(time) { tooltipTitle(time) {
return gl.utils.formatDate(time); return formatDate(time);
}, },
}, },
}; };
import * as datetimeUtility from '~/lib/utils/datetime_utility'; import * as datetimeUtility from '~/lib/utils/datetime_utility';
(() => { describe('Date time utils', () => {
describe('Date time utils', () => { describe('timeFor', () => {
describe('timeFor', () => { it('returns `past due` when in past', () => {
it('returns `past due` when in past', () => { const date = new Date();
const date = new Date(); date.setFullYear(date.getFullYear() - 1);
date.setFullYear(date.getFullYear() - 1);
expect(
expect( datetimeUtility.timeFor(date),
gl.utils.timeFor(date), ).toBe('Past due');
).toBe('Past due');
});
it('returns remaining time when in the future', () => {
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
// Add a day to prevent a transient error. If date is even 1 second
// short of a full year, timeFor will return '11 months remaining'
date.setDate(date.getDate() + 1);
expect(
gl.utils.timeFor(date),
).toBe('1 year remaining');
});
}); });
describe('get day name', () => { it('returns remaining time when in the future', () => {
it('should return Sunday', () => { const date = new Date();
const day = gl.utils.getDayName(new Date('07/17/2016')); date.setFullYear(date.getFullYear() + 1);
expect(day).toBe('Sunday');
}); // Add a day to prevent a transient error. If date is even 1 second
// short of a full year, timeFor will return '11 months remaining'
it('should return Monday', () => { date.setDate(date.getDate() + 1);
const day = gl.utils.getDayName(new Date('07/18/2016'));
expect(day).toBe('Monday');
});
it('should return Tuesday', () => {
const day = gl.utils.getDayName(new Date('07/19/2016'));
expect(day).toBe('Tuesday');
});
it('should return Wednesday', () => {
const day = gl.utils.getDayName(new Date('07/20/2016'));
expect(day).toBe('Wednesday');
});
it('should return Thursday', () => {
const day = gl.utils.getDayName(new Date('07/21/2016'));
expect(day).toBe('Thursday');
});
it('should return Friday', () => {
const day = gl.utils.getDayName(new Date('07/22/2016'));
expect(day).toBe('Friday');
});
it('should return Saturday', () => {
const day = gl.utils.getDayName(new Date('07/23/2016'));
expect(day).toBe('Saturday');
});
});
describe('get day difference', () => { expect(
it('should return 7', () => { datetimeUtility.timeFor(date),
const firstDay = new Date('07/01/2016'); ).toBe('1 year remaining');
const secondDay = new Date('07/08/2016');
const difference = gl.utils.getDayDifference(firstDay, secondDay);
expect(difference).toBe(7);
});
it('should return 31', () => {
const firstDay = new Date('07/01/2016');
const secondDay = new Date('08/01/2016');
const difference = gl.utils.getDayDifference(firstDay, secondDay);
expect(difference).toBe(31);
});
it('should return 365', () => {
const firstDay = new Date('07/02/2015');
const secondDay = new Date('07/01/2016');
const difference = gl.utils.getDayDifference(firstDay, secondDay);
expect(difference).toBe(365);
});
}); });
}); });
describe('timeIntervalInWords', () => { describe('get day name', () => {
it('should return string with number of minutes and seconds', () => { it('should return Sunday', () => {
expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds'); const day = datetimeUtility.getDayName(new Date('07/17/2016'));
expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second'); expect(day).toBe('Sunday');
expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds'); });
expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
it('should return Monday', () => {
const day = datetimeUtility.getDayName(new Date('07/18/2016'));
expect(day).toBe('Monday');
});
it('should return Tuesday', () => {
const day = datetimeUtility.getDayName(new Date('07/19/2016'));
expect(day).toBe('Tuesday');
});
it('should return Wednesday', () => {
const day = datetimeUtility.getDayName(new Date('07/20/2016'));
expect(day).toBe('Wednesday');
});
it('should return Thursday', () => {
const day = datetimeUtility.getDayName(new Date('07/21/2016'));
expect(day).toBe('Thursday');
});
it('should return Friday', () => {
const day = datetimeUtility.getDayName(new Date('07/22/2016'));
expect(day).toBe('Friday');
});
it('should return Saturday', () => {
const day = datetimeUtility.getDayName(new Date('07/23/2016'));
expect(day).toBe('Saturday');
}); });
}); });
describe('dateInWords', () => { describe('get day difference', () => {
const date = new Date('07/01/2016'); it('should return 7', () => {
const firstDay = new Date('07/01/2016');
const secondDay = new Date('07/08/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(7);
});
it('should return date in words', () => { it('should return 31', () => {
expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016'); const firstDay = new Date('07/01/2016');
const secondDay = new Date('08/01/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(31);
}); });
it('should return abbreviated month name', () => { it('should return 365', () => {
expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016'); const firstDay = new Date('07/02/2015');
const secondDay = new Date('07/01/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(365);
}); });
}); });
})(); });
describe('timeIntervalInWords', () => {
it('should return string with number of minutes and seconds', () => {
expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds');
expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second');
expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds');
expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
});
});
describe('dateInWords', () => {
const date = new Date('07/01/2016');
it('should return date in words', () => {
expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016');
});
it('should return abbreviated month name', () => {
expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016');
});
});
import Vue from 'vue'; import Vue from 'vue';
import DeployKeysStore from '~/deploy_keys/store'; import DeployKeysStore from '~/deploy_keys/store';
import key from '~/deploy_keys/components/key.vue'; import key from '~/deploy_keys/components/key.vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Deploy keys key', () => { describe('Deploy keys key', () => {
let vm; let vm;
...@@ -37,7 +38,7 @@ describe('Deploy keys key', () => { ...@@ -37,7 +38,7 @@ describe('Deploy keys key', () => {
it('renders human friendly formatted created date', () => { it('renders human friendly formatted created date', () => {
expect( expect(
vm.$el.querySelector('.key-created-at').textContent.trim(), vm.$el.querySelector('.key-created-at').textContent.trim(),
).toBe(`created ${gl.utils.getTimeago().format(deployKey.created_at)}`); ).toBe(`created ${getTimeago().format(deployKey.created_at)}`);
}); });
it('shows edit button', () => { it('shows edit button', () => {
......
...@@ -222,7 +222,6 @@ import '~/notes'; ...@@ -222,7 +222,6 @@ import '~/notes';
notes.note_ids = []; notes.note_ids = [];
notes.updatedNotesTrackingMap = {}; notes.updatedNotesTrackingMap = {};
spyOn(gl.utils, 'localTimeAgo');
spyOn(Notes, 'isNewNote').and.callThrough(); spyOn(Notes, 'isNewNote').and.callThrough();
spyOn(Notes, 'isUpdatedNote').and.callThrough(); spyOn(Notes, 'isUpdatedNote').and.callThrough();
spyOn(Notes, 'animateAppendNote').and.callThrough(); spyOn(Notes, 'animateAppendNote').and.callThrough();
...@@ -349,7 +348,6 @@ import '~/notes'; ...@@ -349,7 +348,6 @@ import '~/notes';
]); ]);
notes.note_ids = []; notes.note_ids = [];
spyOn(gl.utils, 'localTimeAgo');
spyOn(Notes, 'isNewNote'); spyOn(Notes, 'isNewNote');
spyOn(Notes, 'animateAppendNote'); spyOn(Notes, 'animateAppendNote');
Notes.isNewNote.and.returnValue(true); Notes.isNewNote.and.returnValue(true);
......
...@@ -2,6 +2,7 @@ import Vue from 'vue'; ...@@ -2,6 +2,7 @@ import Vue from 'vue';
import * as urlUtils from '~/lib/utils/url_utility'; import * as urlUtils from '~/lib/utils/url_utility';
import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment'; import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service'; import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import { getTimeago } from '~/lib/utils/datetime_utility';
const deploymentMockData = [ const deploymentMockData = [
{ {
...@@ -49,7 +50,7 @@ describe('MRWidgetDeployment', () => { ...@@ -49,7 +50,7 @@ describe('MRWidgetDeployment', () => {
describe('formatDate', () => { describe('formatDate', () => {
it('should work', () => { it('should work', () => {
const readable = gl.utils.getTimeago().format(deployment.deployed_at); const readable = getTimeago().format(deployment.deployed_at);
expect(vm.formatDate(deployment.deployed_at)).toEqual(readable); expect(vm.formatDate(deployment.deployed_at)).toEqual(readable);
}); });
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import '~/lib/utils/datetime_utility'; import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
describe('Time ago with tooltip component', () => { describe('Time ago with tooltip component', () => {
let TimeagoTooltip; let TimeagoTooltip;
...@@ -24,10 +24,10 @@ describe('Time ago with tooltip component', () => { ...@@ -24,10 +24,10 @@ describe('Time ago with tooltip component', () => {
expect(vm.$el.tagName).toEqual('TIME'); expect(vm.$el.tagName).toEqual('TIME');
expect( expect(
vm.$el.getAttribute('data-original-title'), vm.$el.getAttribute('data-original-title'),
).toEqual(gl.utils.formatDate('2017-05-08T14:57:39.781Z')); ).toEqual(formatDate('2017-05-08T14:57:39.781Z'));
expect(vm.$el.getAttribute('data-placement')).toEqual('top'); expect(vm.$el.getAttribute('data-placement')).toEqual('top');
const timeago = gl.utils.getTimeago(); const timeago = getTimeago();
expect(vm.$el.textContent.trim()).toEqual(timeago.format('2017-05-08T14:57:39.781Z')); expect(vm.$el.textContent.trim()).toEqual(timeago.format('2017-05-08T14:57:39.781Z'));
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment