[NEW] User preference for 24- or 12-hour clock (#11169)

Closes #2922
Closes #4706

This PR adds a personal preference for what timestamp format to use:
![2018-06-16_21-26-48](https://user-images.githubusercontent.com/39674991/41501824-ffb5f034-71ab-11e8-813e-8a2c724fc84b.png)

**Default** uses the timestamp formats (usually `LT` and `LLL`) defined in admin settings.
**12-hour** uses a 12-hour format (`6:30 PM` or `January 3, 2018 6:30 PM`)
**24-hour** uses a 24-hour format (`18:30` or `January 3, 2018 18:30`)
pull/11866/merge
フィンメーラ 7 years ago committed by Guilherme Gazzo
parent be7386f60a
commit 9a77976e40
  1. 6
      packages/chatpal-search/client/template/result.js
  2. 1
      packages/rocketchat-api/server/v1/users.js
  3. 2
      packages/rocketchat-i18n/i18n/en.i18n.json
  4. 24
      packages/rocketchat-lib/client/lib/formatDate.js
  5. 2
      packages/rocketchat-lib/client/lib/index.js
  6. 4
      packages/rocketchat-lib/server/models/Users.js
  7. 7
      packages/rocketchat-message-attachments/client/messageAttachment.js
  8. 5
      packages/rocketchat-message-snippet/client/page/snippetPage.js
  9. 13
      packages/rocketchat-ui-account/client/accountPreferences.html
  10. 1
      packages/rocketchat-ui-account/client/accountPreferences.js
  11. 8
      packages/rocketchat-ui-flextab/client/tabs/uploadedFilesList.js
  12. 3
      packages/rocketchat-ui-flextab/client/tabs/userInfo.js
  13. 7
      packages/rocketchat-ui-message/client/message.js
  14. 1
      server/methods/saveUserPreferences.js
  15. 1
      tests/data/user.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);
},
});

@ -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),

@ -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",

@ -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'));

@ -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,
};

@ -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);
}

@ -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 }`;

@ -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);
});
});

@ -144,6 +144,19 @@
<label><input type="radio" name="unreadAlert" value="false" checked="{{checked 'unreadAlert' false}}"/> {{_ "Off"}}</label>
</div>
</div>
<div class="input-line double-col" id="clockMode">
<label>{{_ "Message_TimeFormat"}}</label>
<div>
<div class="rc-select">
<select class="input-monitor rc-select__element" name="clockMode">
<option value="0" selected="{{selected 'clockMode' 0}}">{{_ "Default"}}</option>
<option value="1" selected="{{selected 'clockMode' 1}}">{{_ "12_Hour"}}</option>
<option value="2" selected="{{selected 'clockMode' 2}}">{{_ "24_Hour"}}</option>
</select>
{{> icon block="rc-select__arrow" icon="arrow-down" }}
</div>
</div>
</div>
<div class="input-line double-col">
<label>{{_ "Use_Emojis"}}</label>
<div>

@ -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());

@ -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() {

@ -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));
}
},

@ -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() {

@ -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),

@ -10,6 +10,7 @@ export const preferences = {
newRoomNotification: 'door',
newMessageNotification: 'chime',
muteFocusedConversations: true,
clockMode: 0,
useEmojis: true,
convertAsciiEmoji: true,
saveMobileBandwidth: true,

Loading…
Cancel
Save