From 262e29a7e9c690e3ec0a42e9b4e8cbd2991d257d Mon Sep 17 00:00:00 2001 From: Chris Blanchard Date: Fri, 12 Feb 2016 16:14:30 +0000 Subject: [PATCH] Simplify message timestamps --- app/javascripts/components/message.js | 29 +--- app/stylesheets/app.css | 7 + brunch-config.js | 2 +- package.json | 1 + vendor/timeago.jquery.js | 221 -------------------------- 5 files changed, 12 insertions(+), 248 deletions(-) delete mode 100644 vendor/timeago.jquery.js diff --git a/app/javascripts/components/message.js b/app/javascripts/components/message.js index a722240..7474eca 100644 --- a/app/javascripts/components/message.js +++ b/app/javascripts/components/message.js @@ -1,4 +1,5 @@ const React = require("react"); +const moment = require("moment"); const ReactDOM = require("react-dom"); const Ps = require("perfect-scrollbar"); const ReactEmoji = require("react-emoji"); @@ -307,27 +308,6 @@ const ChatMessage = React.createClass({ } }, - updateCreatedAt() { - let self = this; - if (this.props.message.createdAt) { - self.setState({ - createdAt: $.timeago(self.props.message.createdAt) - }) - } - }, - - componentWillMount() { - this.updateCreatedAt(); - }, - - componentDidMount() { - this.interval = setInterval(this.updateCreatedAt, 60000); - }, - - componentWillUnmount: function () { - clearInterval(this.interval); - }, - messageContent: function () { let self = this; let message = self.props.message.content @@ -366,9 +346,7 @@ const ChatMessage = React.createClass({ User Avatar + className="chat-avatar" />
@@ -378,8 +356,7 @@ const ChatMessage = React.createClass({ {deleteButton} - - {this.state.createdAt} + {moment(this.props.message.createdAt).format("hh:mm DD/MM")} 
diff --git a/app/stylesheets/app.css b/app/stylesheets/app.css index 7d7baa1..b9fd0cf 100644 --- a/app/stylesheets/app.css +++ b/app/stylesheets/app.css @@ -16,6 +16,13 @@ html, body { word-wrap: break-word; /* IE */ } +.chat-avatar { + border-radius: 50%; + max-height: 20px; + max-width: 20px; + margin-right: 5px; +} + .chat-container { padding: 10px; } diff --git a/brunch-config.js b/brunch-config.js index a5dfc4e..923c0ad 100644 --- a/brunch-config.js +++ b/brunch-config.js @@ -54,7 +54,7 @@ exports.config = { }, whitelist: ["react", "react-dom", "jquery", "lodash", "react-autolink", "react-dom", "react-emoji", "howler", - "bootstrap", "perfect-scrollbar"], + "bootstrap", "perfect-scrollbar", "moment"], globals: { "_": "lodash", "jQuery": "jquery", diff --git a/package.json b/package.json index 2915c81..0ebb8ef 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "javascript-state-machine": "~2.3.5", "jquery": "~2.2.0", "lodash": "~4.0.0", + "moment": "^2.11.2", "mongoose": "~4.1.1", "morgan": "~1.6.1", "newrelic": "~1.22.1", diff --git a/vendor/timeago.jquery.js b/vendor/timeago.jquery.js deleted file mode 100644 index 4b4362c..0000000 --- a/vendor/timeago.jquery.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * 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.4.1 - * @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-2015, 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, - allowPast: true, - allowFuture: false, - localeTitle: false, - cutoff: 0, - strings: { - prefixAgo: null, - prefixFromNow: null, - suffixAgo: "ago", - suffixFromNow: "from now", - inPast: 'any moment 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) { - if(!this.settings.allowPast && ! this.settings.allowFuture) { - throw 'timeago allowPast and allowFuture settings can not both be set to false.'; - } - - 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; - } - } - - if(!this.settings.allowPast && distanceMillis >= 0) { - return this.settings.strings.inPast; - } - - 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 - s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 - 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) { - this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); - } - }, - update: function(time){ - var parsedTime = $t.parse(time); - $(this).data('timeago', { datetime: parsedTime }); - if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString()); - refresh.apply(this); - }, - updateFromDOM: function(){ - $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); - refresh.apply(this); - }, - dispose: function () { - if (this._timeagoInterval) { - window.clearInterval(this._timeagoInterval); - this._timeagoInterval = null; - } - } - }; - - $.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() { - //check if it's still visible - if(!$.contains(document.documentElement,this)){ - //stop if it has been removed - $(this).timeago("dispose"); - return this; - } - - var data = prepareData(this); - var $s = $t.settings; - - if (!isNaN(data.datetime)) { - if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { - $(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 ($t.settings.localeTitle) { - element.attr("title", element.data('timeago').datetime.toLocaleString()); - } else 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"); -})); \ No newline at end of file