From abccdb09f16f73bc66ac15f39f359dd47baffc32 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Cunha <42151808+mariaeduardacunha@users.noreply.github.com> Date: Thu, 30 Jan 2020 13:12:39 -0300 Subject: [PATCH] [BREAK] Hide system messages (#16243) --- .../server/functions/loadMessageHistory.js | 30 ++------- app/lib/server/methods/saveSettings.js | 3 + app/lib/server/startup/settings.js | 64 +++++++++++++------ app/ui/client/views/app/room.js | 27 ++------ client/components/admin/settings/Setting.js | 2 + .../inputs/MultiSelectSettingInput.js | 58 +++++++++++++++++ .../inputs/MultiSelectSettingInput.stories.js | 57 +++++++++++++++++ package-lock.json | 17 ++++- packages/rocketchat-i18n/i18n/en.i18n.json | 9 +++ server/methods/loadHistory.js | 21 ++---- server/startup/migrations/index.js | 1 + server/startup/migrations/v172.js | 17 +++++ 12 files changed, 223 insertions(+), 83 deletions(-) create mode 100644 client/components/admin/settings/inputs/MultiSelectSettingInput.js create mode 100644 client/components/admin/settings/inputs/MultiSelectSettingInput.stories.js create mode 100644 server/startup/migrations/v172.js diff --git a/app/lib/server/functions/loadMessageHistory.js b/app/lib/server/functions/loadMessageHistory.js index 66251284400..eb214fcddcb 100644 --- a/app/lib/server/functions/loadMessageHistory.js +++ b/app/lib/server/functions/loadMessageHistory.js @@ -2,23 +2,12 @@ import { settings } from '../../../settings'; import { Messages } from '../../../models'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; -const hideMessagesOfType = []; +const hideMessagesOfType = new Set(); -settings.get(/Message_HideType_.+/, function(key, value) { - const type = key.replace('Message_HideType_', ''); - const types = type === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [type]; - - return types.forEach((type) => { - const index = hideMessagesOfType.indexOf(type); - - if (value === true && index === -1) { - return hideMessagesOfType.push(type); - } - - if (index > -1) { - return hideMessagesOfType.splice(index, 1); - } - }); +settings.get('Hide_System_Messages', function(key, values) { + const hiddenTypes = values.reduce((array, value) => [...array, ...value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value]], []); + hideMessagesOfType.clear(); + hiddenTypes.forEach((item) => hideMessagesOfType.add(item)); }); export const loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls }) { @@ -35,12 +24,7 @@ export const loadMessageHistory = function loadMessageHistory({ userId, rid, end }; } - let records; - if (end != null) { - records = Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, hideMessagesOfType, options).fetch(); - } else { - records = Messages.findVisibleByRoomIdNotContainingTypes(rid, hideMessagesOfType, options).fetch(); - } + const records = end != null ? Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, Array.from(hideMessagesOfType.values()), options).fetch() : Messages.findVisibleByRoomIdNotContainingTypes(rid, Array.from(hideMessagesOfType.values()), options).fetch(); const messages = normalizeMessagesForUser(records, userId); let unreadNotLoaded = 0; let firstUnread; @@ -51,7 +35,7 @@ export const loadMessageHistory = function loadMessageHistory({ userId, rid, end if ((firstMessage != null ? firstMessage.ts : undefined) > ls) { delete options.limit; - const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, hideMessagesOfType, { + const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, Array.from(hideMessagesOfType.values()), { limit: 1, sort: { ts: 1, diff --git a/app/lib/server/methods/saveSettings.js b/app/lib/server/methods/saveSettings.js index d7cf7bd02ad..97c12bd85ca 100644 --- a/app/lib/server/methods/saveSettings.js +++ b/app/lib/server/methods/saveSettings.js @@ -37,6 +37,9 @@ Meteor.methods({ case 'int': check(value, Number); break; + case 'multiSelect': + check(value, Array); + break; default: check(value, String); break; diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js index a269ec0edad..0014786f813 100644 --- a/app/lib/server/startup/settings.js +++ b/app/lib/server/startup/settings.js @@ -1093,28 +1093,56 @@ settings.addGroup('Message', function() { type: 'int', public: true, }); - this.add('Message_HideType_uj', false, { - type: 'boolean', - public: true, - }); - this.add('Message_HideType_ul', false, { - type: 'boolean', - public: true, - }); - this.add('Message_HideType_ru', false, { - type: 'boolean', - public: true, - }); - this.add('Message_HideType_au', false, { - type: 'boolean', - public: true, - }); - this.add('Message_HideType_mute_unmute', false, { - type: 'boolean', + + this.add('Hide_System_Messages', [], { + type: 'multiSelect', public: true, + values: [ + { + key: 'uj', + i18nLabel: 'Message_HideType_uj', + }, { + key: 'ul', + i18nLabel: 'Message_HideType_ul', + }, { + key: 'ru', + i18nLabel: 'Message_HideType_ru', + }, { + key: 'au', + i18nLabel: 'Message_HideType_au', + }, { + key: 'mute_unmute', + i18nLabel: 'Message_HideType_mute_unmute', + }, { + key: 'r', + i18nLabel: 'Message_HideType_r', + }, { + key: 'ut', + i18nLabel: 'Message_HideType_ut', + }, { + key: 'wm', + i18nLabel: 'Message_HideType_wm', + }, { + key: 'rm', + i18nLabel: 'Message_HideType_rm', + }, { + key: 'subscription_role_added', + i18nLabel: 'Message_HideType_subscription_role_added', + }, { + key: 'subscription_role_removed', + i18nLabel: 'Message_HideType_subscription_role_removed', + }, { + key: 'room_archived', + i18nLabel: 'Message_HideType_room_archived', + }, { + key: 'room_unarchived', + i18nLabel: 'Message_HideType_room_unarchived', + }, + ], }); + this.add('Message_ErasureType', 'Delete', { type: 'select', public: true, diff --git a/app/ui/client/views/app/room.js b/app/ui/client/views/app/room.js index 0fcce54af26..2fae57a4bd0 100644 --- a/app/ui/client/views/app/room.js +++ b/app/ui/client/views/app/room.js @@ -296,27 +296,8 @@ Template.room.helpers({ messagesHistory() { const { rid } = Template.instance(); - const hideMessagesOfType = []; - settings.collection.find({ _id: /Message_HideType_.+/ }).forEach(function(record) { - let types; - const type = record._id.replace('Message_HideType_', ''); - switch (type) { - case 'mute_unmute': - types = ['user-muted', 'user-unmuted']; - break; - default: - types = [type]; - } - return types.forEach(function(type) { - const index = hideMessagesOfType.indexOf(type); - - if ((record.value === true) && (index === -1)) { - hideMessagesOfType.push(type); - } else if (index > -1) { - hideMessagesOfType.splice(index, 1); - } - }); - }); + const { value: settingValues = [] } = settings.collection.findOne('Hide_System_Messages') || {}; + const hideMessagesOfType = new Set(settingValues.reduce((array, value) => [...array, ...value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value]], [])); const modes = ['', 'cozy', 'compact']; const viewMode = getUserPreference(Meteor.userId(), 'messageViewMode'); @@ -326,8 +307,8 @@ Template.room.helpers({ ...(ignoreReplies || modes[viewMode] === 'compact') && { tmid: { $exists: 0 } }, }; - if (hideMessagesOfType.length > 0) { - query.t = { $nin: hideMessagesOfType }; + if (hideMessagesOfType.size) { + query.t = { $nin: Array.from(hideMessagesOfType.values()) }; } const options = { diff --git a/client/components/admin/settings/Setting.js b/client/components/admin/settings/Setting.js index dba5266ceea..e8d171e5816 100644 --- a/client/components/admin/settings/Setting.js +++ b/client/components/admin/settings/Setting.js @@ -11,6 +11,7 @@ import { RelativeUrlSettingInput } from './inputs/RelativeUrlSettingInput'; import { PasswordSettingInput } from './inputs/PasswordSettingInput'; import { IntSettingInput } from './inputs/IntSettingInput'; import { SelectSettingInput } from './inputs/SelectSettingInput'; +import { MultiSelectSettingInput } from './inputs/MultiSelectSettingInput'; import { LanguageSettingInput } from './inputs/LanguageSettingInput'; import { ColorSettingInput } from './inputs/ColorSettingInput'; import { FontSettingInput } from './inputs/FontSettingInput'; @@ -37,6 +38,7 @@ export const MemoizedSetting = memo(function MemoizedSetting({ password: PasswordSettingInput, int: IntSettingInput, select: SelectSettingInput, + multiSelect: MultiSelectSettingInput, language: LanguageSettingInput, color: ColorSettingInput, font: FontSettingInput, diff --git a/client/components/admin/settings/inputs/MultiSelectSettingInput.js b/client/components/admin/settings/inputs/MultiSelectSettingInput.js new file mode 100644 index 00000000000..538b4a74c4c --- /dev/null +++ b/client/components/admin/settings/inputs/MultiSelectSettingInput.js @@ -0,0 +1,58 @@ +import { Field, Flex, Box, MultiSelectFiltered, MultiSelect } from '@rocket.chat/fuselage'; +import React from 'react'; + +import { useTranslation } from '../../../../contexts/TranslationContext'; +import { ResetSettingButton } from '../ResetSettingButton'; + +export function MultiSelectSettingInput({ + _id, + label, + value = [], + placeholder, + readonly, + disabled, + values = [], + hasResetButton, + onChangeValue, + onResetButtonClick, + autocomplete, +}) { + const t = useTranslation(); + + const handleChange = (value) => { + onChangeValue && onChangeValue(value); + // onChangeValue && onChangeValue([...event.currentTarget.querySelectorAll('option')].filter((e) => e.selected).map((el) => el.value)); + }; + const Component = autocomplete ? MultiSelectFiltered : MultiSelect; + return ( + <> + + + + {label} + + {hasResetButton && ( + + )} + + + [ + key, + t(i18nLabel), + ])} + /> + + ); +} diff --git a/client/components/admin/settings/inputs/MultiSelectSettingInput.stories.js b/client/components/admin/settings/inputs/MultiSelectSettingInput.stories.js new file mode 100644 index 00000000000..78e223f7325 --- /dev/null +++ b/client/components/admin/settings/inputs/MultiSelectSettingInput.stories.js @@ -0,0 +1,57 @@ +import { Field } from '@rocket.chat/fuselage'; +import { action } from '@storybook/addon-actions'; +import React from 'react'; + +import { MultiSelectSettingInput } from './MultiSelectSettingInput'; + +export default { + title: 'admin/settings/inputs/MultiSelectSettingInput', + component: MultiSelectSettingInput, + decorators: [ + (storyFn) => {storyFn()}, + ], +}; +const options = [ + { key: '1', i18nLabel: '1' }, + { key: '2', i18nLabel: '2' }, + { key: '3', i18nLabel: '3' }, +]; + +export const _default = () => + ; + +export const disabled = () => + ; + +export const withValue = () => + ; + +export const withResetButton = () => + ; diff --git a/package-lock.json b/package-lock.json index cbc6455214c..0812d1cec6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26800,9 +26800,9 @@ "dev": true }, "prismjs": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", - "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.18.0.tgz", + "integrity": "sha512-N0r3i/Cto516V8+GKKamhsPVZSFcO0TMUBtIDW6uq6BVqoC3FNtZVZ+cmH16N2XtGQlgRN+sFUTjOdCsEP51qw==", "dev": true, "requires": { "clipboard": "^2.0.0" @@ -28145,6 +28145,17 @@ "hastscript": "^5.0.0", "parse-entities": "^1.1.2", "prismjs": "~1.17.0" + }, + "dependencies": { + "prismjs": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", + "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "dev": true, + "requires": { + "clipboard": "^2.0.0" + } + } } }, "regenerate": { diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 269cdef8187..8e920297ab6 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2215,6 +2215,15 @@ "Message_HideType_ru": "Hide \"User Removed\" messages", "Message_HideType_uj": "Hide \"User Join\" messages", "Message_HideType_ul": "Hide \"User Leave\" messages", + "Message_HideType_r": "Hide \"Room Name Changed\" messages", + "Message_HideType_ut": "Hide \"User Joined Conversation\" messages", + "Message_HideType_wm": "Hide \"Welcome\" messages", + "Message_HideType_rm": "Hide \"Message Removed\" messages", + "Message_HideType_subscription_role_added": "Hide \"Was Set Role\" messages", + "Message_HideType_subscription_role_removed": "Hide \"Role No Longer Defined\" messages", + "Message_HideType_room_archived": "Hide \"Room Archived\" messages", + "Message_HideType_room_unarchived": "Hide \"Room Unarchived\" messages", + "Hide_System_Messages": "Hide System Messages", "Message_Id": "Message Id", "Message_Ignored": "This message was ignored", "Message_info": "Message info", diff --git a/server/methods/loadHistory.js b/server/methods/loadHistory.js index e1354c4925f..4f03fdea51e 100644 --- a/server/methods/loadHistory.js +++ b/server/methods/loadHistory.js @@ -6,23 +6,12 @@ import { hasPermission } from '../../app/authorization'; import { settings } from '../../app/settings'; import { loadMessageHistory } from '../../app/lib'; -const hideMessagesOfType = []; +const hideMessagesOfType = new Set(); -settings.get(/Message_HideType_.+/, function(key, value) { - const type = key.replace('Message_HideType_', ''); - const types = type === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [type]; - - return types.forEach((type) => { - const index = hideMessagesOfType.indexOf(type); - - if (value === true && index === -1) { - return hideMessagesOfType.push(type); - } - - if (index > -1) { - return hideMessagesOfType.splice(index, 1); - } - }); +settings.get('Hide_System_Messages', function(key, values) { + const hiddenTypes = values.reduce((array, value) => [...array, ...value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value]], []); + hideMessagesOfType.clear(); + hiddenTypes.forEach((item) => hideMessagesOfType.add(item)); }); Meteor.methods({ diff --git a/server/startup/migrations/index.js b/server/startup/migrations/index.js index 752cba43548..cb70c0a5c35 100644 --- a/server/startup/migrations/index.js +++ b/server/startup/migrations/index.js @@ -169,4 +169,5 @@ import './v168'; import './v169'; import './v170'; import './v171'; +import './v172'; import './xrun'; diff --git a/server/startup/migrations/v172.js b/server/startup/migrations/v172.js new file mode 100644 index 00000000000..3eb3ec0bfba --- /dev/null +++ b/server/startup/migrations/v172.js @@ -0,0 +1,17 @@ +import { + Migrations, +} from '../../../app/migrations'; +import { + Settings, +} from '../../../app/models'; + + +Migrations.add({ + version: 172, + up() { + const settings = Settings.find({ _id: /Message_HideType_.*/i }).fetch(); + + Settings.update({ _id: 'Hide_System_Messages' }, { $set: { value: settings.filter((setting) => setting.value).map((setting) => setting._id.replace('Message_HideType_')) } }); + Settings.remove({ _id: /Message_HideType_.*/i }, { multi: true }); + }, +});