diff --git a/packages/chatpal-search/client/template/result.js b/packages/chatpal-search/client/template/result.js index 5446b9688f87..b188e21b8a94 100644 --- a/packages/chatpal-search/client/template/result.js +++ b/packages/chatpal-search/client/template/result.js @@ -1,4 +1,4 @@ -import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; Template.ChatpalSearchResultTemplate.onCreated(function() { this.badRequest = new ReactiveVar(false); @@ -100,10 +100,10 @@ Template.ChatpalSearchSingleMessage.helpers({ }, time() { - return moment(this.created).format(RocketChat.settings.get('Message_TimeFormat')); + return DateFormat.formatTime(this.created); }, date() { - return moment(this.created).format(RocketChat.settings.get('Message_DateFormat')); + return DateFormat.formatDate(this.created); }, }); diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 4da86d568f6a..c231830a6c2b 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -345,6 +345,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { data: Match.ObjectIncluding({ newRoomNotification: Match.Maybe(String), newMessageNotification: Match.Maybe(String), + clockMode: Match.Maybe(Number), useEmojis: Match.Maybe(Boolean), convertAsciiEmoji: Match.Maybe(Boolean), saveMobileBandwidth: Match.Maybe(Boolean), diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index e2b53727b24d..e59485d2bf50 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1,7 +1,9 @@ { "#channel": "#channel", "0_Errors_Only": "0 - Errors Only", + "12_Hour": "12-hour clock", "1_Errors_and_Information": "1 - Errors and Information", + "24_Hour": "24-hour clock", "2_Erros_Information_and_Debug": "2 - Errors, Information and Debug", "403": "Forbidden", "500": "Internal Server Error", diff --git a/packages/rocketchat-lib/client/lib/formatDate.js b/packages/rocketchat-lib/client/lib/formatDate.js new file mode 100644 index 000000000000..94f6afa4a62c --- /dev/null +++ b/packages/rocketchat-lib/client/lib/formatDate.js @@ -0,0 +1,24 @@ +import moment from 'moment'; +export const formatTime = (time) => { + switch (RocketChat.getUserPreference(Meteor.userId(), 'clockMode', false)) { + case 1: + return moment(time).format('h:mm A'); + case 2: + return moment(time).format('H:mm'); + default: + return moment(time).format(RocketChat.settings.get('Message_TimeFormat')); + } +}; + +export const formatDateAndTime = (time) => { + switch (RocketChat.getUserPreference(Meteor.userId(), 'clockMode', false)) { + case 1: + return moment(time).format('MMMM D, Y h:mm A'); + case 2: + return moment(time).format('MMMM D, Y H:mm'); + default: + return moment(time).format(RocketChat.settings.get('Message_TimeAndDateFormat')); + } +}; + +export const formatDate = (time) => moment(time).format(RocketChat.settings.get('Message_DateFormat')); diff --git a/packages/rocketchat-lib/client/lib/index.js b/packages/rocketchat-lib/client/lib/index.js index 1a77c5a97164..4684347c02a1 100644 --- a/packages/rocketchat-lib/client/lib/index.js +++ b/packages/rocketchat-lib/client/lib/index.js @@ -12,6 +12,7 @@ import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext } import { hide, leave, erase } from './ChannelActions'; import { call } from './callMethod'; import { LoginPresence } from './LoginPresence'; +import * as DateFormat from './formatDate'; export { call, @@ -25,4 +26,5 @@ export { UiTextContext, RocketChatAnnouncement, LoginPresence, + DateFormat, }; diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 5d31e45087bd..aec91942c376 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -465,6 +465,10 @@ class ModelUsers extends RocketChat.models._Base { const update = { $set: settings, }; + if (![1, 2].includes(parseInt(settings.preferences.clockMode))) { + delete update.$set['settings.preferences.clockMode']; + update.$unset = { 'settings.preferences.clockMode': 1 }; + } return this.update(_id, update); } diff --git a/packages/rocketchat-message-attachments/client/messageAttachment.js b/packages/rocketchat-message-attachments/client/messageAttachment.js index 2c24a3dc40d5..73438fdd78e2 100644 --- a/packages/rocketchat-message-attachments/client/messageAttachment.js +++ b/packages/rocketchat-message-attachments/client/messageAttachment.js @@ -1,4 +1,4 @@ -import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; import { fixCordova } from 'meteor/rocketchat:lazy-load'; const colors = { good: '#35AC19', @@ -58,10 +58,9 @@ Template.messageAttachment.helpers({ const messageDate = new Date(this.ts); const today = new Date(); if (messageDate.toDateString() === today.toDateString()) { - return moment(this.ts).format(RocketChat.settings.get('Message_TimeFormat')); - } else { - return moment(this.ts).format(RocketChat.settings.get('Message_TimeAndDateFormat')); + return DateFormat.formatTime(this.ts); } + return DateFormat.formatDateAndTime(this.ts); }, injectIndex(data, previousIndex, index) { data.index = `${ previousIndex }.attachments.${ index }`; diff --git a/packages/rocketchat-message-snippet/client/page/snippetPage.js b/packages/rocketchat-message-snippet/client/page/snippetPage.js index b14dd7057d4d..a5242ccb3f06 100644 --- a/packages/rocketchat-message-snippet/client/page/snippetPage.js +++ b/packages/rocketchat-message-snippet/client/page/snippetPage.js @@ -1,5 +1,5 @@ /* global SnippetedMessages */ -import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; Template.snippetPage.helpers({ snippet() { @@ -23,7 +23,7 @@ Template.snippetPage.helpers({ time() { const snippet = SnippetedMessages.findOne({ _id: FlowRouter.getParam('snippetId') }); if (snippet !== undefined) { - return moment(snippet.ts).format(RocketChat.settings.get('Message_TimeFormat')); + return DateFormat.formatTime(snippet.ts); } }, }); @@ -34,4 +34,3 @@ Template.snippetPage.onCreated(function() { Meteor.subscribe('snippetedMessage', snippetId); }); }); - diff --git a/packages/rocketchat-ui-account/client/accountPreferences.html b/packages/rocketchat-ui-account/client/accountPreferences.html index 22c4df61e54b..8d4b6a327890 100644 --- a/packages/rocketchat-ui-account/client/accountPreferences.html +++ b/packages/rocketchat-ui-account/client/accountPreferences.html @@ -144,6 +144,19 @@

{{_ "Messages"}}

+
+ +
+
+ + {{> icon block="rc-select__arrow" icon="arrow-down" }} +
+
+
diff --git a/packages/rocketchat-ui-account/client/accountPreferences.js b/packages/rocketchat-ui-account/client/accountPreferences.js index cf7a8cdddb80..c0c07c8c57ff 100644 --- a/packages/rocketchat-ui-account/client/accountPreferences.js +++ b/packages/rocketchat-ui-account/client/accountPreferences.js @@ -141,6 +141,7 @@ Template.accountPreferences.onCreated(function() { data.newRoomNotification = $('select[name=newRoomNotification]').val(); data.newMessageNotification = $('select[name=newMessageNotification]').val(); + data.clockMode = parseInt($('select[name=clockMode]').val()); data.useEmojis = JSON.parse($('input[name=useEmojis]:checked').val()); data.convertAsciiEmoji = JSON.parse($('input[name=convertAsciiEmoji]:checked').val()); data.saveMobileBandwidth = JSON.parse($('input[name=saveMobileBandwidth]:checked').val()); diff --git a/packages/rocketchat-ui-flextab/client/tabs/uploadedFilesList.js b/packages/rocketchat-ui-flextab/client/tabs/uploadedFilesList.js index 5f56fa99c82b..a32fc21b7d28 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/uploadedFilesList.js +++ b/packages/rocketchat-ui-flextab/client/tabs/uploadedFilesList.js @@ -1,5 +1,5 @@ import { fixCordova } from 'meteor/rocketchat:lazy-load'; -import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; import _ from 'underscore'; const roomFiles = new Mongo.Collection('room_files'); @@ -42,7 +42,9 @@ Template.uploadedFilesList.helpers({ return fixCordova(this.url); } }, - + format(timestamp) { + return DateFormat.formatDateAndTime(timestamp); + }, fileTypeIcon() { const [, extension] = this.name.match(/.*?\.(.*)$/); @@ -87,7 +89,7 @@ Template.uploadedFilesList.helpers({ }, formatTimestamp(timestamp) { - return moment(timestamp).format(RocketChat.settings.get('Message_TimeAndDateFormat') || 'LLL'); + return DateFormat.formatDateAndTime(timestamp); }, hasMore() { diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index a4dc8e5348c0..cfd4295d951e 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import s from 'underscore.string'; import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; import { getActions } from './userActions'; @@ -113,7 +114,7 @@ Template.userInfo.helpers({ userTime() { const user = Template.instance().user.get(); if (user && user.utcOffset != null) { - return Template.instance().now.get().utcOffset(user.utcOffset).format(RocketChat.settings.get('Message_TimeFormat')); + return DateFormat.formatTime(Template.instance().now.get().utcOffset(user.utcOffset)); } }, diff --git a/packages/rocketchat-ui-message/client/message.js b/packages/rocketchat-ui-message/client/message.js index 46c34c5c4759..d2b1201989ef 100644 --- a/packages/rocketchat-ui-message/client/message.js +++ b/packages/rocketchat-ui-message/client/message.js @@ -1,6 +1,7 @@ /* globals renderEmoji renderMessageBody */ import _ from 'underscore'; import moment from 'moment'; +import { DateFormat } from 'meteor/rocketchat:lib'; Template.message.helpers({ encodeURI(text) { @@ -98,10 +99,10 @@ Template.message.helpers({ } }, time() { - return moment(this.ts).format(RocketChat.settings.get('Message_TimeFormat')); + return DateFormat.formatTime(this.ts); }, date() { - return moment(this.ts).format(RocketChat.settings.get('Message_DateFormat')); + return DateFormat.formatDate(this.ts); }, isTemp() { if (this.temp === true) { @@ -139,7 +140,7 @@ Template.message.helpers({ }, editTime() { if (Template.instance().wasEdited) { - return moment(this.editedAt).format(`${ RocketChat.settings.get('Message_DateFormat') } ${ RocketChat.settings.get('Message_TimeFormat') }`); + return DateFormat.formatDateAndTime(this.editedAt); } }, editedBy() { diff --git a/server/methods/saveUserPreferences.js b/server/methods/saveUserPreferences.js index 7b3091bdbc07..be78b7436253 100644 --- a/server/methods/saveUserPreferences.js +++ b/server/methods/saveUserPreferences.js @@ -4,6 +4,7 @@ Meteor.methods({ language: Match.Optional(String), newRoomNotification: Match.Optional(String), newMessageNotification: Match.Optional(String), + clockMode: Match.Optional(Number), useEmojis: Match.Optional(Boolean), convertAsciiEmoji: Match.Optional(Boolean), saveMobileBandwidth: Match.Optional(Boolean), diff --git a/tests/data/user.js b/tests/data/user.js index 0e3baffbad2f..a43f4a4310d4 100644 --- a/tests/data/user.js +++ b/tests/data/user.js @@ -10,6 +10,7 @@ export const preferences = { newRoomNotification: 'door', newMessageNotification: 'chime', muteFocusedConversations: true, + clockMode: 0, useEmojis: true, convertAsciiEmoji: true, saveMobileBandwidth: true,