diff --git a/.changeset/blue-ladybugs-raise.md b/.changeset/blue-ladybugs-raise.md deleted file mode 100644 index 44d7a06b4111..000000000000 --- a/.changeset/blue-ladybugs-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Translation files are requested multiple times diff --git a/.changeset/breezy-bugs-jam.md b/.changeset/breezy-bugs-jam.md deleted file mode 100644 index 7e7cc7b8283b..000000000000 --- a/.changeset/breezy-bugs-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: Managers allowed to make deactivated agent's available diff --git a/.changeset/bright-carpets-fly.md b/.changeset/bright-carpets-fly.md deleted file mode 100644 index 6a8ac2608569..000000000000 --- a/.changeset/bright-carpets-fly.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/core-typings': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -new: ring mobile users on direct conference calls diff --git a/.changeset/bright-snakes-vanish.md b/.changeset/bright-snakes-vanish.md deleted file mode 100644 index f198bfe93ae9..000000000000 --- a/.changeset/bright-snakes-vanish.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed an issue causing `queue time` to be calculated from current time when a room was closed without being served. -Now: -- For served rooms: queue time = servedBy time - queuedAt -- For not served, but open rooms = now - queuedAt -- For not served and closed rooms = closedAt - queuedAt diff --git a/.changeset/brown-clouds-add.md b/.changeset/brown-clouds-add.md deleted file mode 100644 index 6b69289177b5..000000000000 --- a/.changeset/brown-clouds-add.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: Performance issue on `Messages.countByType` aggregation caused by unindexed property on messages collection diff --git a/.changeset/brown-comics-cheat.md b/.changeset/brown-comics-cheat.md new file mode 100644 index 000000000000..a7907979881b --- /dev/null +++ b/.changeset/brown-comics-cheat.md @@ -0,0 +1,8 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/core-typings": patch +"@rocket.chat/model-typings": patch +--- + +chore: Calculate & Store MAC stats +Added new info to the stats: `omnichannelContactsBySource`, `uniqueContactsOfLastMonth`, `uniqueContactsOfLastWeek`, `uniqueContactsOfYesterday` diff --git a/.changeset/bump-patch-1694741499930.md b/.changeset/bump-patch-1694741499930.md deleted file mode 100644 index e1eaa7980afb..000000000000 --- a/.changeset/bump-patch-1694741499930.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1694827499043.md b/.changeset/bump-patch-1694827499043.md deleted file mode 100644 index e1eaa7980afb..000000000000 --- a/.changeset/bump-patch-1694827499043.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1695163548038.md b/.changeset/bump-patch-1695163548038.md deleted file mode 100644 index e1eaa7980afb..000000000000 --- a/.changeset/bump-patch-1695163548038.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1695165575069.md b/.changeset/bump-patch-1695165575069.md deleted file mode 100644 index e1eaa7980afb..000000000000 --- a/.changeset/bump-patch-1695165575069.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/chilled-flies-fold.md b/.changeset/chilled-flies-fold.md deleted file mode 100644 index 17a0f9eb6dc5..000000000000 --- a/.changeset/chilled-flies-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -feat: add sections to room header and user infos menus with menuV2 diff --git a/.changeset/chilled-phones-give.md b/.changeset/chilled-phones-give.md deleted file mode 100644 index cb0887db0883..000000000000 --- a/.changeset/chilled-phones-give.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-typings": patch -"@rocket.chat/rest-typings": patch ---- - -Fixed `overrideDestinationChannelEnabled` treated as a required param in `integrations.create` and `integration.update` endpoints diff --git a/.changeset/cool-students-tan.md b/.changeset/cool-students-tan.md deleted file mode 100644 index 07760541628a..000000000000 --- a/.changeset/cool-students-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -feat(apps): `ActionManagerBusyState` component for apps `ui.interaction` diff --git a/.changeset/cuddly-houses-tie.md b/.changeset/cuddly-houses-tie.md deleted file mode 100644 index 76d86a690388..000000000000 --- a/.changeset/cuddly-houses-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Hide Reset TOTP option if 2FA is disabled diff --git a/.changeset/cuddly-ties-bake.md b/.changeset/cuddly-ties-bake.md deleted file mode 100644 index d912d2969d75..000000000000 --- a/.changeset/cuddly-ties-bake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/fuselage-ui-kit": minor -"@rocket.chat/uikit-playground": minor ---- - -feat: Add missing variants to UIKit button diff --git a/.changeset/curly-shoes-burn.md b/.changeset/curly-shoes-burn.md deleted file mode 100644 index 67d453ab7245..000000000000 --- a/.changeset/curly-shoes-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Added ability to freeze or completely disable integration scripts through envvars diff --git a/.changeset/custom-emoji-fs.md b/.changeset/custom-emoji-fs.md deleted file mode 100644 index a9a797f35bc8..000000000000 --- a/.changeset/custom-emoji-fs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: custom emoji upload with FileSystem method diff --git a/.changeset/dropdown.md b/.changeset/dropdown.md deleted file mode 100644 index 935c12aebe85..000000000000 --- a/.changeset/dropdown.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -New filters to the Rooms Table at `Workspace > Rooms` diff --git a/.changeset/eighty-kids-jog.md b/.changeset/eighty-kids-jog.md deleted file mode 100644 index 6410813d80a6..000000000000 --- a/.changeset/eighty-kids-jog.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/livechat': minor -'@rocket.chat/meteor': minor ---- - -Added new Omnichannel's trigger condition "After starting a chat". diff --git a/.changeset/eleven-icons-tan.md b/.changeset/eleven-icons-tan.md deleted file mode 100644 index c51124c05dd2..000000000000 --- a/.changeset/eleven-icons-tan.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/core-typings": minor -"@rocket.chat/model-typings": minor -"@rocket.chat/rest-typings": minor ---- - -Introduce the ability to report an user diff --git a/.changeset/empty-ants-enjoy.md b/.changeset/empty-ants-enjoy.md deleted file mode 100644 index 4a55f82d0abf..000000000000 --- a/.changeset/empty-ants-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -fix: Wrong toast message while creating a new custom sound with an existing name diff --git a/.changeset/fair-cats-destroy.md b/.changeset/fair-cats-destroy.md deleted file mode 100644 index 7dfb74955a94..000000000000 --- a/.changeset/fair-cats-destroy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/model-typings": patch ---- - -When setting a room as read-only, do not allow previously unmuted users to send messages. diff --git a/.changeset/fast-pumpkins-smoke.md b/.changeset/fast-pumpkins-smoke.md deleted file mode 100644 index 2374776bf3b5..000000000000 --- a/.changeset/fast-pumpkins-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fix: finnish translation diff --git a/.changeset/fast-yaks-collect.md b/.changeset/fast-yaks-collect.md deleted file mode 100644 index 60dd92030163..000000000000 --- a/.changeset/fast-yaks-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fixed an issue where 2fa was not working after an OAuth redirect diff --git a/.changeset/fifty-cars-divide.md b/.changeset/fifty-cars-divide.md deleted file mode 100644 index 6c09cf6869c8..000000000000 --- a/.changeset/fifty-cars-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed issue with custom OAuth services' settings not being be fully removed diff --git a/.changeset/fluffy-beds-buy.md b/.changeset/fluffy-beds-buy.md deleted file mode 100644 index f90513b946c3..000000000000 --- a/.changeset/fluffy-beds-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -Added support for threaded conversation in Federated rooms. diff --git a/.changeset/fluffy-lions-rage.md b/.changeset/fluffy-lions-rage.md deleted file mode 100644 index 09437a2cb88e..000000000000 --- a/.changeset/fluffy-lions-rage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/livechat": patch ---- - -chore: (Livechat) Replace all `dangerouslySetInnerHTML` with `gazzodown` diff --git a/.changeset/forty-hotels-pretend.md b/.changeset/forty-hotels-pretend.md deleted file mode 100644 index b23825d5a02a..000000000000 --- a/.changeset/forty-hotels-pretend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: Prevent `RoomProvider.useEffect` from subscribing to room-data stream multiple times diff --git a/.changeset/four-parents-cheer.md b/.changeset/four-parents-cheer.md deleted file mode 100644 index 2fbb8e2b279f..000000000000 --- a/.changeset/four-parents-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -load sounds right before playing them diff --git a/.changeset/friendly-glasses-mate.md b/.changeset/friendly-glasses-mate.md deleted file mode 100644 index 6a7a7b4f8546..000000000000 --- a/.changeset/friendly-glasses-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -fix: Time format of Retention Policy diff --git a/.changeset/fuzzy-glasses-divide.md b/.changeset/fuzzy-glasses-divide.md deleted file mode 100644 index cf77bbde5507..000000000000 --- a/.changeset/fuzzy-glasses-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Added a new Roles bridge to RC Apps-Engine for reading and retrieving role details. diff --git a/.changeset/fuzzy-schools-brake.md b/.changeset/fuzzy-schools-brake.md deleted file mode 100644 index c6af54a2ef57..000000000000 --- a/.changeset/fuzzy-schools-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix users being created without the `roles` field diff --git a/.changeset/gold-horses-pretend.md b/.changeset/gold-horses-pretend.md deleted file mode 100644 index a8908b68a23e..000000000000 --- a/.changeset/gold-horses-pretend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed CAS login after popup closes diff --git a/.changeset/gold-moose-press.md b/.changeset/gold-moose-press.md deleted file mode 100644 index 605fb7c649ea..000000000000 --- a/.changeset/gold-moose-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix moment timestamps language change diff --git a/.changeset/good-elephants-live.md b/.changeset/good-elephants-live.md deleted file mode 100644 index 8cb3e9d87fc4..000000000000 --- a/.changeset/good-elephants-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed message fetching method in LivechatBridge for Apps diff --git a/.changeset/green-adults-peel.md b/.changeset/green-adults-peel.md deleted file mode 100644 index b07f5ea3e6bf..000000000000 --- a/.changeset/green-adults-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix pruning messages in a room results in an incorrect message counter diff --git a/.changeset/grumpy-candles-rule.md b/.changeset/grumpy-candles-rule.md deleted file mode 100644 index 28673ce91a73..000000000000 --- a/.changeset/grumpy-candles-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fix: rejected conference calls continue to ring diff --git a/.changeset/heavy-baboons-laugh.md b/.changeset/heavy-baboons-laugh.md deleted file mode 100644 index 5c32965dcf62..000000000000 --- a/.changeset/heavy-baboons-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -User information crashing for some locales diff --git a/.changeset/heavy-cougars-marry.md b/.changeset/heavy-cougars-marry.md deleted file mode 100644 index 893f53352114..000000000000 --- a/.changeset/heavy-cougars-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix performance issue on Engagement Dashboard aggregation diff --git a/.changeset/heavy-zebras-wonder.md b/.changeset/heavy-zebras-wonder.md deleted file mode 100644 index a1904a81c514..000000000000 --- a/.changeset/heavy-zebras-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Show correct date for last day time diff --git a/.changeset/hip-hounds-ring.md b/.changeset/hip-hounds-ring.md deleted file mode 100644 index 79dfba6dd031..000000000000 --- a/.changeset/hip-hounds-ring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Added ability to disable private app installation via envvar (DISABLE_PRIVATE_APP_INSTALLATION) diff --git a/.changeset/hip-mugs-promise.md b/.changeset/hip-mugs-promise.md deleted file mode 100644 index 7100fec026e3..000000000000 --- a/.changeset/hip-mugs-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -improve: System messages for omni-visitor abandonment feature diff --git a/.changeset/honest-glasses-roll.md b/.changeset/honest-glasses-roll.md deleted file mode 100644 index 679f46fb8420..000000000000 --- a/.changeset/honest-glasses-roll.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -chore: Add danger variant to apps action button menus diff --git a/.changeset/honest-mirrors-sit.md b/.changeset/honest-mirrors-sit.md deleted file mode 100644 index 4e4298cb8110..000000000000 --- a/.changeset/honest-mirrors-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Disabled call to tags enterprise endpoint when on community license diff --git a/.changeset/honest-numbers-compete.md b/.changeset/honest-numbers-compete.md deleted file mode 100644 index 1fd017e7fc16..000000000000 --- a/.changeset/honest-numbers-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes SAML full name updates not being mirrored to DM rooms. diff --git a/.changeset/importer-progress-bar.md b/.changeset/importer-progress-bar.md deleted file mode 100644 index 49c04289ddcb..000000000000 --- a/.changeset/importer-progress-bar.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed Importer Progress Bar progress indicator - diff --git a/.changeset/khaki-feet-dance.md b/.changeset/khaki-feet-dance.md new file mode 100644 index 000000000000..a419afa34143 --- /dev/null +++ b/.changeset/khaki-feet-dance.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +feat: Save visitor's activity on agent's interaction diff --git a/.changeset/kind-students-worry.md b/.changeset/kind-students-worry.md deleted file mode 100644 index 554c1c1204ea..000000000000 --- a/.changeset/kind-students-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Make user default role setting public diff --git a/.changeset/lazy-ghosts-design.md b/.changeset/lazy-ghosts-design.md deleted file mode 100644 index 080e9986cebb..000000000000 --- a/.changeset/lazy-ghosts-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed misleading of 'total' in team members list inside Channel diff --git a/.changeset/loud-sheep-try.md b/.changeset/loud-sheep-try.md deleted file mode 100644 index f82d0d069554..000000000000 --- a/.changeset/loud-sheep-try.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/fuselage-ui-kit": minor -"@rocket.chat/uikit-playground": minor ---- - -feat: Adding new UIKit components: Callout, Checkbox, Radio Button, Time Picker, Toast Bar, Toggle Switch, Tab Navigation diff --git a/.changeset/lovely-snails-drop.md b/.changeset/lovely-snails-drop.md deleted file mode 100644 index 4e28c6a43c20..000000000000 --- a/.changeset/lovely-snails-drop.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/model-typings": patch ---- - -Fix spotlight search does not find rooms with special or non-latin characters diff --git a/.changeset/lucky-balloons-divide.md b/.changeset/lucky-balloons-divide.md deleted file mode 100644 index beb4cbfe3b57..000000000000 --- a/.changeset/lucky-balloons-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix engagement dashboard not showing data diff --git a/.changeset/lucky-hounds-sing.md b/.changeset/lucky-hounds-sing.md deleted file mode 100644 index 20b09afaf545..000000000000 --- a/.changeset/lucky-hounds-sing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fixed wrong user status displayed during mentioning a user in a channel diff --git a/.changeset/many-icons-provide.md b/.changeset/many-icons-provide.md deleted file mode 100644 index bf82407980ad..000000000000 --- a/.changeset/many-icons-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Don't allow to report self messages diff --git a/.changeset/mighty-walls-smash.md b/.changeset/mighty-walls-smash.md deleted file mode 100644 index 54b2846901de..000000000000 --- a/.changeset/mighty-walls-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fixed scrollbar over content in Federated Room List diff --git a/.changeset/moody-comics-cheat.md b/.changeset/moody-comics-cheat.md deleted file mode 100644 index b8b372306d0e..000000000000 --- a/.changeset/moody-comics-cheat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/release-action': minor ---- - -Add back "Engine Versions" to the release notes diff --git a/.changeset/moody-pans-act.md b/.changeset/moody-pans-act.md deleted file mode 100644 index 6c307604eaa9..000000000000 --- a/.changeset/moody-pans-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix seat counter including bots users diff --git a/.changeset/nice-chairs-add.md b/.changeset/nice-chairs-add.md new file mode 100644 index 000000000000..dfc9d763e1c0 --- /dev/null +++ b/.changeset/nice-chairs-add.md @@ -0,0 +1,13 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/core-typings": minor +--- + +Added `push` statistic, containing three bits. Each bit represents a boolean: +``` +1 1 1 +| | | +| | +- push enabled = 0b1 = 1 +| +--- push gateway enabled = 0b10 = 2 ++----- push gateway changed = 0b100 = 4 +``` diff --git a/.changeset/nine-bottles-press.md b/.changeset/nine-bottles-press.md deleted file mode 100644 index f9a57fa676ad..000000000000 --- a/.changeset/nine-bottles-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -feat: Add flag to disable teams mention via troubleshoot page diff --git a/.changeset/nine-carrots-listen.md b/.changeset/nine-carrots-listen.md deleted file mode 100644 index bf5dc72e6cc0..000000000000 --- a/.changeset/nine-carrots-listen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fixed layout changing from embedded view when navigating diff --git a/.changeset/odd-elephants-promise.md b/.changeset/odd-elephants-promise.md deleted file mode 100644 index a12817ed175b..000000000000 --- a/.changeset/odd-elephants-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix LinkedIn OAuth broken diff --git a/.changeset/old-federation-card.md b/.changeset/old-federation-card.md deleted file mode 100644 index fa9879d84426..000000000000 --- a/.changeset/old-federation-card.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removed old/deprecated Rocket.Chat Federation card from Info page diff --git a/.changeset/perfect-adults-travel.md b/.changeset/perfect-adults-travel.md deleted file mode 100644 index 61ae4ab6dad5..000000000000 --- a/.changeset/perfect-adults-travel.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/fuselage-ui-kit": patch -"@rocket.chat/uikit-playground": patch ---- - -feat(fuselage-ui-kit): Introduce `TabsNavigationBlock` diff --git a/.changeset/pink-zoos-join.md b/.changeset/pink-zoos-join.md deleted file mode 100644 index dcc1088de0b5..000000000000 --- a/.changeset/pink-zoos-join.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix the code that was setting email URL to an invalid value when SMTP was not set diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 3bc535a4b50f..000000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "mode": "pre", - "tag": "rc", - "initialVersions": { - "@rocket.chat/meteor": "6.4.0-develop", - "rocketchat-services": "1.1.4", - "@rocket.chat/account-service": "0.2.4", - "@rocket.chat/authorization-service": "0.2.4", - "@rocket.chat/ddp-streamer": "0.1.4", - "@rocket.chat/omnichannel-transcript": "0.2.4", - "@rocket.chat/presence-service": "0.2.4", - "@rocket.chat/queue-worker": "0.2.4", - "@rocket.chat/stream-hub-service": "0.2.4", - "@rocket.chat/api-client": "0.1.4", - "@rocket.chat/ddp-client": "0.1.4", - "@rocket.chat/omnichannel-services": "0.0.10", - "@rocket.chat/pdf-worker": "0.0.10", - "@rocket.chat/presence": "0.0.10", - "@rocket.chat/ui-theming": "0.0.1", - "@rocket.chat/account-utils": "0.0.1", - "@rocket.chat/agenda": "0.0.2", - "@rocket.chat/base64": "1.0.12", - "@rocket.chat/cas-validate": "0.0.1", - "@rocket.chat/core-services": "0.1.4", - "@rocket.chat/core-typings": "6.3.4", - "@rocket.chat/cron": "0.0.6", - "@rocket.chat/eslint-config": "0.5.2", - "@rocket.chat/favicon": "0.0.1", - "@rocket.chat/fuselage-ui-kit": "1.0.4", - "@rocket.chat/gazzodown": "1.0.4", - "@rocket.chat/i18n": "0.0.1", - "@rocket.chat/instance-status": "0.0.10", - "@rocket.chat/livechat": "1.13.4", - "@rocket.chat/log-format": "0.0.1", - "@rocket.chat/logger": "0.0.1", - "@rocket.chat/mock-providers": "0.0.1", - "@rocket.chat/model-typings": "0.0.10", - "@rocket.chat/models": "0.0.10", - "@rocket.chat/poplib": "0.0.1", - "@rocket.chat/random": "1.2.1", - "@rocket.chat/release-action": "2.1.0", - "@rocket.chat/rest-typings": "6.3.4", - "@rocket.chat/server-fetch": "0.0.1", - "@rocket.chat/sha256": "1.0.9", - "@rocket.chat/tools": "0.0.1", - "@rocket.chat/ui-client": "1.0.4", - "@rocket.chat/ui-composer": "0.0.1", - "@rocket.chat/ui-contexts": "1.0.4", - "@rocket.chat/ui-video-conf": "1.0.4", - "@rocket.chat/uikit-playground": "0.1.4", - "@rocket.chat/web-ui-registration": "1.0.4" - }, - "changesets": [ - "blue-ladybugs-raise", - "breezy-bugs-jam", - "bright-carpets-fly", - "bright-snakes-vanish", - "brown-clouds-add", - "bump-patch-1694741499930", - "bump-patch-1694827499043", - "bump-patch-1695163548038", - "bump-patch-1695165575069", - "chilled-flies-fold", - "chilled-phones-give", - "cool-students-tan", - "cuddly-houses-tie", - "cuddly-ties-bake", - "curly-shoes-burn", - "custom-emoji-fs", - "dropdown", - "eighty-kids-jog", - "eleven-icons-tan", - "empty-ants-enjoy", - "fair-cats-destroy", - "fast-pumpkins-smoke", - "fast-yaks-collect", - "fifty-cars-divide", - "fluffy-beds-buy", - "fluffy-lions-rage", - "forty-hotels-pretend", - "four-parents-cheer", - "friendly-glasses-mate", - "fuzzy-glasses-divide", - "fuzzy-schools-brake", - "gold-horses-pretend", - "gold-moose-press", - "good-elephants-live", - "green-adults-peel", - "grumpy-candles-rule", - "heavy-baboons-laugh", - "heavy-cougars-marry", - "heavy-zebras-wonder", - "hip-hounds-ring", - "hip-mugs-promise", - "honest-glasses-roll", - "honest-mirrors-sit", - "honest-numbers-compete", - "importer-progress-bar", - "kind-students-worry", - "lazy-ghosts-design", - "loud-sheep-try", - "lovely-snails-drop", - "lucky-balloons-divide", - "lucky-hounds-sing", - "many-icons-provide", - "mighty-walls-smash", - "moody-comics-cheat", - "moody-pans-act", - "nine-bottles-press", - "nine-carrots-listen", - "odd-elephants-promise", - "old-federation-card", - "perfect-adults-travel", - "pink-zoos-join", - "pretty-bees-give", - "quick-emus-march", - "quiet-phones-sell", - "rare-sheep-yawn", - "real-pets-visit", - "red-windows-admire", - "red-zebras-clap", - "rotten-turtles-agree", - "serious-garlics-clean", - "serious-geckos-drive", - "serious-shrimps-try", - "seven-jobs-tickle", - "shaggy-beans-poke", - "shiny-garlics-carry", - "shiny-tools-worry", - "short-cobras-tell", - "silly-actors-laugh", - "silver-mugs-unite", - "six-buckets-eat", - "slimy-cheetahs-heal", - "slimy-wasps-double", - "slow-lizards-breathe", - "small-rice-repair", - "smooth-planes-cough", - "soft-yaks-matter", - "sour-cows-refuse", - "sour-parrots-nail", - "stale-roses-knock", - "strong-laws-pump", - "swift-birds-build", - "swift-walls-protect", - "tall-pumpkins-cross", - "tame-pens-occur", - "three-ants-give", - "three-birds-tickle", - "tidy-bears-camp", - "tiny-turkeys-burn", - "tough-candles-heal", - "tricky-years-swim", - "unlucky-turtles-search", - "user-mention", - "violet-frogs-cheer", - "warm-hornets-ring", - "wet-frogs-kiss", - "wet-walls-lie", - "wild-spiders-smell", - "wise-onions-trade", - "wise-walls-tan", - "wise-ways-fetch", - "witty-feet-warn", - "yellow-buttons-agree", - "yellow-schools-tell", - "young-trains-glow" - ] -} diff --git a/.changeset/pretty-bees-give.md b/.changeset/pretty-bees-give.md deleted file mode 100644 index 8891420308c5..000000000000 --- a/.changeset/pretty-bees-give.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add option to select what URL previews should be generated for each message. diff --git a/.changeset/quick-emus-march.md b/.changeset/quick-emus-march.md deleted file mode 100644 index 7a6d7b444654..000000000000 --- a/.changeset/quick-emus-march.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/ddp-client': minor -'@rocket.chat/core-services': minor -'@rocket.chat/meteor': minor ---- - -Add new event to notify users directly about new banners diff --git a/.changeset/quiet-phones-reply.md b/.changeset/quiet-phones-reply.md new file mode 100644 index 000000000000..f2735e615491 --- /dev/null +++ b/.changeset/quiet-phones-reply.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Search users using full name too on share message modal diff --git a/.changeset/quiet-phones-sell.md b/.changeset/quiet-phones-sell.md deleted file mode 100644 index a6222cba16c9..000000000000 --- a/.changeset/quiet-phones-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fixed an issue where oauth login was not working with some providers diff --git a/.changeset/rare-sheep-yawn.md b/.changeset/rare-sheep-yawn.md deleted file mode 100644 index 86c2d7283223..000000000000 --- a/.changeset/rare-sheep-yawn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/livechat": patch ---- - -fix: Issue caused by spaces in the `config.url` setting diff --git a/.changeset/real-pets-visit.md b/.changeset/real-pets-visit.md deleted file mode 100644 index d6531285597c..000000000000 --- a/.changeset/real-pets-visit.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-typings": patch ---- - -Fixed `default` field not being returned from the `setDefault` endpoints when setting to false diff --git a/.changeset/red-windows-admire.md b/.changeset/red-windows-admire.md deleted file mode 100644 index 48a82b5902cb..000000000000 --- a/.changeset/red-windows-admire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed an issue where timeout for http requests in Apps-Engine bridges was too short diff --git a/.changeset/red-zebras-clap.md b/.changeset/red-zebras-clap.md deleted file mode 100644 index cd8f832b1835..000000000000 --- a/.changeset/red-zebras-clap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix importer filters not working diff --git a/.changeset/rotten-turtles-agree.md b/.changeset/rotten-turtles-agree.md deleted file mode 100644 index f915aa38f758..000000000000 --- a/.changeset/rotten-turtles-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: stop blinking "Room not found" before dm creation diff --git a/.changeset/selfish-hounds-pay.md b/.changeset/selfish-hounds-pay.md new file mode 100644 index 000000000000..3ca321bd392f --- /dev/null +++ b/.changeset/selfish-hounds-pay.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +fix: Monitors now able to forward a chat without taking it first diff --git a/.changeset/serious-garlics-clean.md b/.changeset/serious-garlics-clean.md deleted file mode 100644 index ccdc3c94dda4..000000000000 --- a/.changeset/serious-garlics-clean.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/core-services': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -New AddUser workflow for Federated Rooms diff --git a/.changeset/serious-geckos-drive.md b/.changeset/serious-geckos-drive.md deleted file mode 100644 index 454337399772..000000000000 --- a/.changeset/serious-geckos-drive.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@rocket.chat/core-typings': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/ui-client': minor -'@rocket.chat/meteor': minor ---- - -Added Reports Metrics Dashboard to Omnichannel diff --git a/.changeset/serious-shrimps-try.md b/.changeset/serious-shrimps-try.md deleted file mode 100644 index 114293aa104e..000000000000 --- a/.changeset/serious-shrimps-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fixed an issue with the positioning of the message menu diff --git a/.changeset/seven-jobs-tickle.md b/.changeset/seven-jobs-tickle.md deleted file mode 100644 index 870bafbb7d9d..000000000000 --- a/.changeset/seven-jobs-tickle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/model-typings": patch ---- - -fix: agent role being removed upon user deactivation diff --git a/.changeset/shaggy-beans-poke.md b/.changeset/shaggy-beans-poke.md deleted file mode 100644 index 31a480638952..000000000000 --- a/.changeset/shaggy-beans-poke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fix `mention-here` and `mention-all` permissions not being honored diff --git a/.changeset/shiny-garlics-carry.md b/.changeset/shiny-garlics-carry.md deleted file mode 100644 index 117063d93f6f..000000000000 --- a/.changeset/shiny-garlics-carry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix CORS headers not being set for assets diff --git a/.changeset/shiny-tools-worry.md b/.changeset/shiny-tools-worry.md deleted file mode 100644 index f024eca38d04..000000000000 --- a/.changeset/shiny-tools-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -feat: remove enforce password fallback dependency diff --git a/.changeset/short-cobras-tell.md b/.changeset/short-cobras-tell.md deleted file mode 100644 index 1c28ce7bad11..000000000000 --- a/.changeset/short-cobras-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -Reorganized the message menu diff --git a/.changeset/silly-actors-laugh.md b/.changeset/silly-actors-laugh.md deleted file mode 100644 index aab23e14e5f1..000000000000 --- a/.changeset/silly-actors-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed Slackbridge was not handling correctly received events from Slack anymore. Events: (Send, edit, delete, react meassages) diff --git a/.changeset/silver-mugs-unite.md b/.changeset/silver-mugs-unite.md deleted file mode 100644 index be74b1bef215..000000000000 --- a/.changeset/silver-mugs-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: show requested filters only on requested apps view diff --git a/.changeset/six-buckets-eat.md b/.changeset/six-buckets-eat.md deleted file mode 100644 index f99bcfb71c30..000000000000 --- a/.changeset/six-buckets-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix users not able to login after block time perdiod has passed diff --git a/.changeset/slimy-cheetahs-heal.md b/.changeset/slimy-cheetahs-heal.md deleted file mode 100644 index 44233bc87766..000000000000 --- a/.changeset/slimy-cheetahs-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed selected departments not being displayed due to pagination diff --git a/.changeset/slimy-wasps-double.md b/.changeset/slimy-wasps-double.md deleted file mode 100644 index b28de342b274..000000000000 --- a/.changeset/slimy-wasps-double.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/meteor': minor -'@rocket.chat/ui-contexts': minor ---- - -UX improvement for the Moderation Console Context bar for viewing the reported messages. The Report reason is now displayed in the reported messages context bar. -The Moderation Action Modal confirmation description is updated to be more clear and concise. diff --git a/.changeset/slow-lizards-breathe.md b/.changeset/slow-lizards-breathe.md deleted file mode 100644 index fd773b17f5c8..000000000000 --- a/.changeset/slow-lizards-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed Apps-Engine event `IPostUserCreated` execution diff --git a/.changeset/small-rice-repair.md b/.changeset/small-rice-repair.md deleted file mode 100644 index 67fdff5ca758..000000000000 --- a/.changeset/small-rice-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix validation in app status call that allowed Enterprise apps to be enabled in invalid environments diff --git a/.changeset/smooth-planes-cough.md b/.changeset/smooth-planes-cough.md deleted file mode 100644 index 9ad4239f0342..000000000000 --- a/.changeset/smooth-planes-cough.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/ui-theming': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -feat: high-contrast theme diff --git a/.changeset/soft-cows-juggle.md b/.changeset/soft-cows-juggle.md new file mode 100644 index 000000000000..6fcb20506483 --- /dev/null +++ b/.changeset/soft-cows-juggle.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +download translation files through CDN diff --git a/.changeset/soft-yaks-matter.md b/.changeset/soft-yaks-matter.md deleted file mode 100644 index c326eb7dca70..000000000000 --- a/.changeset/soft-yaks-matter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -feat: return all broken password policies at once diff --git a/.changeset/sour-cows-refuse.md b/.changeset/sour-cows-refuse.md deleted file mode 100644 index d907c063f568..000000000000 --- a/.changeset/sour-cows-refuse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed inviter not informed when inviting member to room via `/invite` slashcommand diff --git a/.changeset/sour-parrots-nail.md b/.changeset/sour-parrots-nail.md deleted file mode 100644 index 1c1eaa3173a8..000000000000 --- a/.changeset/sour-parrots-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed "teams" icon not being displayed on spotlight sidebar search diff --git a/.changeset/stale-roses-knock.md b/.changeset/stale-roses-knock.md deleted file mode 100644 index 25e93fa8c346..000000000000 --- a/.changeset/stale-roses-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: User timezone not being respected on Current Chat's filter diff --git a/.changeset/strong-laws-pump.md b/.changeset/strong-laws-pump.md deleted file mode 100644 index a4afefd65316..000000000000 --- a/.changeset/strong-laws-pump.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@rocket.chat/model-typings': patch -'@rocket.chat/meteor': patch ---- - -Change SAU aggregation to consider only sessions from few days ago instead of the whole past. - -This is particularly important for large workspaces in case the cron job did not run for some time, in that case the amount of sessions would accumulate and the aggregation would take a long time to run. diff --git a/.changeset/sweet-chefs-exist.md b/.changeset/sweet-chefs-exist.md new file mode 100644 index 000000000000..6ceee63dd762 --- /dev/null +++ b/.changeset/sweet-chefs-exist.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Check for room scoped permissions for starting discussions diff --git a/.changeset/swift-birds-build.md b/.changeset/swift-birds-build.md deleted file mode 100644 index 4af3bddd875b..000000000000 --- a/.changeset/swift-birds-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed unable to create admin user using ADMIN\_\* environment variables diff --git a/.changeset/swift-walls-protect.md b/.changeset/swift-walls-protect.md deleted file mode 100644 index 6e3057775c32..000000000000 --- a/.changeset/swift-walls-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed failing user data exports diff --git a/.changeset/tall-pumpkins-cross.md b/.changeset/tall-pumpkins-cross.md deleted file mode 100644 index e6cfd8a309b9..000000000000 --- a/.changeset/tall-pumpkins-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/presence": patch ---- - -Fixed presence broadcast being disabled on server restart diff --git a/.changeset/tame-pens-occur.md b/.changeset/tame-pens-occur.md deleted file mode 100644 index 8cb729531fae..000000000000 --- a/.changeset/tame-pens-occur.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/model-typings": minor ---- - -Fixed read receipts not getting deleted after corresponding message is deleted \ No newline at end of file diff --git a/.changeset/three-ants-give.md b/.changeset/three-ants-give.md deleted file mode 100644 index 4d33fad05f39..000000000000 --- a/.changeset/three-ants-give.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@rocket.chat/cron": patch -"@rocket.chat/meteor": patch ---- - -Increase cron job check delay to 1 min from 5s. - -This reduces MongoDB requests introduced on 6.3. diff --git a/.changeset/three-birds-tickle.md b/.changeset/three-birds-tickle.md deleted file mode 100644 index 0ce911d9f6fa..000000000000 --- a/.changeset/three-birds-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -chore: Increase cache time from 5s to 10s on `getUnits` helpers. This should reduce the number of DB calls made by this method to fetch the unit limitations for a user. diff --git a/.changeset/tidy-bears-applaud.md b/.changeset/tidy-bears-applaud.md new file mode 100644 index 000000000000..cff12f3dc7d3 --- /dev/null +++ b/.changeset/tidy-bears-applaud.md @@ -0,0 +1,10 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/core-typings": minor +"@rocket.chat/model-typings": minor +"@rocket.chat/rest-typings": minor +--- + +Create a deployment fingerprint to identify possible deployment changes caused by database cloning. A question to the admin will confirm if it's a regular deployment change or an intent of a new deployment and correct identification values as needed. +The fingerprint is composed by `${siteUrl}${dbConnectionString}` and hashed via `sha256` in `base64`. +An environment variable named `AUTO_ACCEPT_FINGERPRINT`, when set to `true`, can be used to auto-accept an expected fingerprint change as a regular deployment update. diff --git a/.changeset/tidy-bears-camp.md b/.changeset/tidy-bears-camp.md deleted file mode 100644 index 3c2013f79023..000000000000 --- a/.changeset/tidy-bears-camp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -Introduced upsells for the engagement dashboard and device management admin sidebar items in CE workspaces. Additionally, restructured the admin sidebar items to enhance organization. diff --git a/.changeset/tiny-turkeys-burn.md b/.changeset/tiny-turkeys-burn.md deleted file mode 100644 index a146bd6a0eae..000000000000 --- a/.changeset/tiny-turkeys-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -fixed an issue on oauth login that caused missing emails to be detected as changed data diff --git a/.changeset/tiny-wolves-deliver.md b/.changeset/tiny-wolves-deliver.md new file mode 100644 index 000000000000..f89564a9b53c --- /dev/null +++ b/.changeset/tiny-wolves-deliver.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/ui-theming': patch +--- + +fix: light-theme font-disabled color diff --git a/.changeset/tough-candles-heal.md b/.changeset/tough-candles-heal.md deleted file mode 100644 index 59ad9c1fb3a1..000000000000 --- a/.changeset/tough-candles-heal.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-typings": patch -"@rocket.chat/model-typings": patch ---- - -Fixes a problem where the calculated time for considering the visitor abandonment was the first message from the visitor and not the visitor's reply to the agent. diff --git a/.changeset/tough-carrots-walk.md b/.changeset/tough-carrots-walk.md new file mode 100644 index 000000000000..2851e697b85e --- /dev/null +++ b/.changeset/tough-carrots-walk.md @@ -0,0 +1,7 @@ +--- +'@rocket.chat/rest-typings': minor +'@rocket.chat/license': patch +'@rocket.chat/meteor': patch +--- + +feat: added `licenses.info` endpoint diff --git a/.changeset/tricky-years-swim.md b/.changeset/tricky-years-swim.md deleted file mode 100644 index 2ab1254525b2..000000000000 --- a/.changeset/tricky-years-swim.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Deprecate `livechat:getOverviewData` and `livechat:getAgentOverviewData` methods and create API endpoints `livechat/analytics/overview` and `livechat/analytics/agent-overview` to fetch analytics data diff --git a/.changeset/unlucky-turtles-search.md b/.changeset/unlucky-turtles-search.md deleted file mode 100644 index fffa51020e30..000000000000 --- a/.changeset/unlucky-turtles-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixed Accounts profile form name change was not working diff --git a/.changeset/user-mention.md b/.changeset/user-mention.md deleted file mode 100644 index a896a7c12ee4..000000000000 --- a/.changeset/user-mention.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed user mentioning when prepending the username with `>` diff --git a/.changeset/violet-frogs-cheer.md b/.changeset/violet-frogs-cheer.md deleted file mode 100644 index db48243c40ed..000000000000 --- a/.changeset/violet-frogs-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/fuselage-ui-kit': patch ---- - -Handle invalid context on `VideoConferenceBlock` component diff --git a/.changeset/warm-hornets-ring.md b/.changeset/warm-hornets-ring.md deleted file mode 100644 index f81cf1efbe92..000000000000 --- a/.changeset/warm-hornets-ring.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-typings": patch ---- - -Use group filter when set to LDAP sync process diff --git a/.changeset/warm-melons-type.md b/.changeset/warm-melons-type.md new file mode 100644 index 000000000000..5b187b8a7f11 --- /dev/null +++ b/.changeset/warm-melons-type.md @@ -0,0 +1,7 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/core-typings": patch +"@rocket.chat/omnichannel-services": patch +--- + +feat: Disable and annonimize visitors instead of removing diff --git a/.changeset/wet-frogs-kiss.md b/.changeset/wet-frogs-kiss.md deleted file mode 100644 index 24395a78f85d..000000000000 --- a/.changeset/wet-frogs-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fix: Missing padding on Omnichannel contacts Contextualbar loading state diff --git a/.changeset/wet-walls-lie.md b/.changeset/wet-walls-lie.md deleted file mode 100644 index 6b18eb497686..000000000000 --- a/.changeset/wet-walls-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes a problem that allowed users to send empty spaces as comment to bypass the "comment required" setting diff --git a/.changeset/wild-spiders-smell.md b/.changeset/wild-spiders-smell.md deleted file mode 100644 index 9694d6259d3a..000000000000 --- a/.changeset/wild-spiders-smell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixed an issue where a mailer error was being sent to customers using offline message's form on Omnichannel instead of the translated one diff --git a/.changeset/wise-onions-trade.md b/.changeset/wise-onions-trade.md deleted file mode 100644 index cb5c731fb6fb..000000000000 --- a/.changeset/wise-onions-trade.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/i18n": patch -"@rocket.chat/livechat": patch -"@rocket.chat/mock-providers": patch -"@rocket.chat/ui-client": patch -"@rocket.chat/ui-contexts": patch -"@rocket.chat/web-ui-registration": patch ---- - -Fixed the login page language switcher, now the component has a new look, is reactive and the language selection becomes concrete upon login in. Also changed the default language of the login page to be the browser language. diff --git a/.changeset/wise-walls-tan.md b/.changeset/wise-walls-tan.md deleted file mode 100644 index f558de82ec4c..000000000000 --- a/.changeset/wise-walls-tan.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -fix: missing params on updateOwnBasicInfo endpoint diff --git a/.changeset/wise-ways-fetch.md b/.changeset/wise-ways-fetch.md deleted file mode 100644 index a81063813c35..000000000000 --- a/.changeset/wise-ways-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fixed the unread messages mark not showing diff --git a/.changeset/witty-feet-warn.md b/.changeset/witty-feet-warn.md deleted file mode 100644 index faaa5d44c134..000000000000 --- a/.changeset/witty-feet-warn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -fixed the video recorder window not closing after permission is denied. diff --git a/.changeset/yellow-buttons-agree.md b/.changeset/yellow-buttons-agree.md deleted file mode 100644 index a86d172a4544..000000000000 --- a/.changeset/yellow-buttons-agree.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/ui-client': minor -'@rocket.chat/meteor': minor ---- - -feat: add ChangePassword field to Account/Security diff --git a/.changeset/yellow-schools-tell.md b/.changeset/yellow-schools-tell.md deleted file mode 100644 index c1040fa0856a..000000000000 --- a/.changeset/yellow-schools-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/eslint-config': minor ---- - -Unpublished changes in ESLint config diff --git a/.changeset/young-trains-glow.md b/.changeset/young-trains-glow.md deleted file mode 100644 index 77f50812143f..000000000000 --- a/.changeset/young-trains-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Fixed the issue of apps icon uneven alignment in case of missing icons inside message composer toolbar & message toolbar menu. diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml index 808b8acdcbe3..284a0985b78e 100644 --- a/.github/actions/build-docker/action.yml +++ b/.github/actions/build-docker/action.yml @@ -19,6 +19,7 @@ runs: steps: - name: Login to GitHub Container Registry + if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') uses: docker/login-action@v2 with: registry: ghcr.io @@ -62,6 +63,7 @@ runs: docker compose -f docker-compose-ci.yml build "${args[@]}" - name: Publish Docker images to GitHub Container Registry + if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') shell: bash run: | args=(rocketchat) diff --git a/.github/workflows/ci-test-e2e.yml b/.github/workflows/ci-test-e2e.yml index e14857a97a09..d77966f186b3 100644 --- a/.github/workflows/ci-test-e2e.yml +++ b/.github/workflows/ci-test-e2e.yml @@ -97,6 +97,14 @@ jobs: cache-modules: true install: true + # if we are testing a PR from a fork, we need to build the docker image at this point + - uses: ./.github/actions/build-docker + if: github.event.pull_request.head.repo.full_name != github.repository + with: + CR_USER: ${{ secrets.CR_USER }} + CR_PAT: ${{ secrets.CR_PAT }} + node-version: ${{ inputs.node-version }} + - uses: dtinth/setup-github-actions-caching-for-turbo@v1 - name: Start httpbin container and wait for it to be ready diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31c2c42718b6..ec8e905cd803 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -172,7 +172,6 @@ jobs: build-gh-docker-coverage: name: 🚢 Build Docker Images for Testing needs: [build, release-versions] - if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') runs-on: ubuntu-20.04 env: @@ -189,7 +188,10 @@ jobs: steps: - uses: actions/checkout@v3 + + # we only build and publish the actual docker images if not a PR from a fork - uses: ./.github/actions/build-docker + if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') with: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index 18e6e45e8f48..9c2e0b63e240 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,216 @@ # @rocket.chat/meteor +## 6.4.0 + +### Minor Changes + +- 239a34e877: new: ring mobile users on direct conference calls +- 04fe492555: Added new Omnichannel's trigger condition "After starting a chat". +- 4186eecf05: Introduce the ability to report an user +- 92b690d206: fix: Wrong toast message while creating a new custom sound with an existing name +- f83ea5d6e8: Added support for threaded conversation in Federated rooms. +- 682d0bc05a: fix: Time format of Retention Policy +- 1b42dfc6c1: Added a new Roles bridge to RC Apps-Engine for reading and retrieving role details. +- 2db32f0d4a: Add option to select what URL previews should be generated for each message. +- 982ef6f459: Add new event to notify users directly about new banners +- 19aec23cda: New AddUser workflow for Federated Rooms +- ebab8c4dd8: Added Reports Metrics Dashboard to Omnichannel +- 85a936220c: feat: remove enforce password fallback dependency +- 5832be2e1b: Reorganized the message menu +- 074db3b419: UX improvement for the Moderation Console Context bar for viewing the reported messages. The Report reason is now displayed in the reported messages context bar. + The Moderation Action Modal confirmation description is updated to be more clear and concise. +- 357a3a50fa: feat: high-contrast theme +- 7070f00b05: feat: return all broken password policies at once +- ead7c7bef2: Fixed read receipts not getting deleted after corresponding message is deleted +- 1041d4d361: Added option to select between two script engine options for the integrations +- ad08c26b46: Introduced upsells for the engagement dashboard and device management admin sidebar items in CE workspaces. Additionally, restructured the admin sidebar items to enhance organization. +- 93d4912e17: fix: missing params on updateOwnBasicInfo endpoint +- ee3815fce4: feat: add ChangePassword field to Account/Security +- 1000b9b317: Fixed the issue of apps icon uneven alignment in case of missing icons inside message composer toolbar & message toolbar menu. + +### Patch Changes + +- 6d453f71ac: Translation files are requested multiple times +- cada29b6ce: fix: Managers allowed to make deactivated agent's available +- 470c29d7e9: Fixed an issue causing `queue time` to be calculated from current time when a room was closed without being served. + Now: + - For served rooms: queue time = servedBy time - queuedAt + - For not served, but open rooms = now - queuedAt + - For not served and closed rooms = closedAt - queuedAt +- ea8998602b: fix: Performance issue on `Messages.countByType` aggregation caused by unindexed property on messages collection +- f634601d90: Bump @rocket.chat/meteor version. +- f46c1f7b70: Bump @rocket.chat/meteor version. +- 6963cc2d00: Bump @rocket.chat/meteor version. +- 7cc15ac814: Bump @rocket.chat/meteor version. +- 40c5277197: Bump @rocket.chat/meteor version. +- Bump @rocket.chat/meteor version. +- a08006c9f0: feat: add sections to room header and user infos menus with menuV2 +- 203304782f: Fixed `overrideDestinationChannelEnabled` treated as a required param in `integrations.create` and `integration.update` endpoints +- 9edca67b9b: feat(apps): `ActionManagerBusyState` component for apps `ui.interaction` +- ec60dbe8f5: Fixed custom translations not being displayed +- 6fa30ddcd1: Hide Reset TOTP option if 2FA is disabled +- ff7e181464: Added ability to freeze or completely disable integration scripts through envvars +- 4ce8ea89a8: fix: custom emoji upload with FileSystem method +- 87570d0fb7: New filters to the Rooms Table at `Workspace > Rooms` +- 8a59855fcf: When setting a room as read-only, do not allow previously unmuted users to send messages. +- c73f5373b8: fix: finnish translation +- f5a886a144: fixed an issue where 2fa was not working after an OAuth redirect +- 459c8574ed: Fixed issue with custom OAuth services' settings not being be fully removed +- 42644a6e44: fix: Prevent `RoomProvider.useEffect` from subscribing to room-data stream multiple times +- 9bdbc9b086: load sounds right before playing them +- 6154979119: Fix users being created without the `roles` field +- 6bcdd88531: Fixed CAS login after popup closes +- 839789c988: Fix moment timestamps language change +- f0025d4d92: Fixed message fetching method in LivechatBridge for Apps +- 9c957b9d9a: Fix pruning messages in a room results in an incorrect message counter +- 583a3149fe: fix: rejected conference calls continue to ring +- b59fd5d7fb: User information crashing for some locales +- 4349443629: Fix performance issue on Engagement Dashboard aggregation +- 614a9b8fc8: Show correct date for last day time +- 69447e1864: Added ability to disable private app installation via envvar (DISABLE_PRIVATE_APP_INSTALLATION) +- 52a1aa94eb: improve: System messages for omni-visitor abandonment feature +- 7dffec2e2f: chore: Add danger variant to apps action button menus +- f0c8867bb9: Disabled call to tags enterprise endpoint when on community license +- 5e89694bfa: Fixes SAML full name updates not being mirrored to DM rooms. +- d6f0c6afe2: Fixed Importer Progress Bar progress indicator +- 177506ea91: Make user default role setting public +- 3fb2124166: Fixed misleading of 'total' in team members list inside Channel +- 5cee21468e: Fix spotlight search does not find rooms with special or non-latin characters +- cf59c8abe3: Fix engagement dashboard not showing data +- dfb9a075b3: fixed wrong user status displayed during mentioning a user in a channel +- 1fbbb6241a: Don't allow to report self messages +- 53e0c346e2: fixed scrollbar over content in Federated Room List +- 5321e87363: Fix seat counter including bots users +- 7137a193a7: feat: Add flag to disable teams mention via troubleshoot page +- 59e6fe3d2a: fixed layout changing from embedded view when navigating +- 3245a0a318: Fix LinkedIn OAuth broken +- 45a8943ed4: Removed old/deprecated Rocket.Chat Federation card from Info page +- 6eea189ec8: Fix the code that was setting email URL to an invalid value when SMTP was not set +- f5a886a144: fixed an issue where oauth login was not working with some providers +- ba24f3c21f: Fixed `default` field not being returned from the `setDefault` endpoints when setting to false +- a79f61461d: Fixed an issue where timeout for http requests in Apps-Engine bridges was too short +- 51b988b3df: Fix importer filters not working +- 5d857f462c: fix: stop blinking "Room not found" before dm creation +- db26f8a8ee: fixed an issue with the positioning of the message menu +- aaefe865a7: fix: agent role being removed upon user deactivation +- 306a5830c3: Fix `mention-here` and `mention-all` permissions not being honored +- 761cad4382: Fix CORS headers not being set for assets +- 9e5718002a: Fixed Slackbridge was not handling correctly received events from Slack anymore. Events: (Send, edit, delete, react meassages) +- 54ef89c9a7: fix: show requested filters only on requested apps view +- 1589279b79: Fix users not able to login after block time perdiod has passed +- 880ab5689c: Fixed selected departments not being displayed due to pagination +- a81bad24e0: Fixed Apps-Engine event `IPostUserCreated` execution +- 7a4fdf41f8: Fix validation in app status call that allowed Enterprise apps to be enabled in invalid environments +- e28f8d95f0: Fixed inviter not informed when inviting member to room via `/invite` slashcommand +- d47d2021ac: Fixed "teams" icon not being displayed on spotlight sidebar search +- 93d5a5ceb8: fix: User timezone not being respected on Current Chat's filter +- f556518fa1: Change SAU aggregation to consider only sessions from few days ago instead of the whole past. + + This is particularly important for large workspaces in case the cron job did not run for some time, in that case the amount of sessions would accumulate and the aggregation would take a long time to run. + +- b747f3d3bc: Fixed unable to create admin user using ADMIN\_\* environment variables +- 2cf2643399: Fixed failing user data exports +- 61a106fbf2: Increase cron job check delay to 1 min from 5s. + + This reduces MongoDB requests introduced on 6.3. + +- ace35997a6: chore: Increase cache time from 5s to 10s on `getUnits` helpers. This should reduce the number of DB calls made by this method to fetch the unit limitations for a user. +- f5a886a144: fixed an issue on oauth login that caused missing emails to be detected as changed data +- 61128364d6: Fixes a problem where the calculated time for considering the visitor abandonment was the first message from the visitor and not the visitor's reply to the agent. +- 9496f1eb97: Deprecate `livechat:getOverviewData` and `livechat:getAgentOverviewData` methods and create API endpoints `livechat/analytics/overview` and `livechat/analytics/agent-overview` to fetch analytics data +- 01dec055a0: Fixed Accounts profile form name change was not working +- e4837a15ed: Fixed user mentioning when prepending the username with `>` +- d45365436e: Use group filter when set to LDAP sync process +- c536a4a237: fix: Missing padding on Omnichannel contacts Contextualbar loading state +- 87e4a4aa56: Fixes a problem that allowed users to send empty spaces as comment to bypass the "comment required" setting +- 69a5213afc: Fixed an issue where a mailer error was being sent to customers using offline message's form on Omnichannel instead of the translated one +- b8f3d5014f: Fixed the login page language switcher, now the component has a new look, is reactive and the language selection becomes concrete upon login in. Also changed the default language of the login page to be the browser language. +- 22cf158c43: fixed the unread messages mark not showing +- 72a34a02f7: fixed the video recorder window not closing after permission is denied. +- Updated dependencies [239a34e877] +- Updated dependencies [203304782f] +- Updated dependencies [1246a21648] +- Updated dependencies [4186eecf05] +- Updated dependencies [8a59855fcf] +- Updated dependencies [f9a748526d] +- Updated dependencies [5cee21468e] +- Updated dependencies [dc1d8ce92e] +- Updated dependencies [2db32f0d4a] +- Updated dependencies [982ef6f459] +- Updated dependencies [ba24f3c21f] +- Updated dependencies [19aec23cda] +- Updated dependencies [ebab8c4dd8] +- Updated dependencies [aaefe865a7] +- Updated dependencies [074db3b419] +- Updated dependencies [357a3a50fa] +- Updated dependencies [f556518fa1] +- Updated dependencies [d9a150000d] +- Updated dependencies [ead7c7bef2] +- Updated dependencies [1041d4d361] +- Updated dependencies [61a106fbf2] +- Updated dependencies [61128364d6] +- Updated dependencies [9496f1eb97] +- Updated dependencies [dce4a829fa] +- Updated dependencies [d45365436e] +- Updated dependencies [b8f3d5014f] +- Updated dependencies [93d4912e17] +- Updated dependencies [ee3815fce4] + - @rocket.chat/core-typings@6.4.0 + - @rocket.chat/rest-typings@6.4.0 + - @rocket.chat/fuselage-ui-kit@2.0.0 + - @rocket.chat/model-typings@0.1.0 + - @rocket.chat/core-services@0.2.0 + - @rocket.chat/ui-client@2.0.0 + - @rocket.chat/ui-contexts@2.0.0 + - @rocket.chat/ui-theming@0.1.0 + - @rocket.chat/presence@0.0.15 + - @rocket.chat/tools@0.1.0 + - @rocket.chat/cron@0.0.11 + - @rocket.chat/i18n@0.0.2 + - @rocket.chat/web-ui-registration@2.0.0 + - @rocket.chat/api-client@0.1.9 + - @rocket.chat/omnichannel-services@0.0.15 + - @rocket.chat/pdf-worker@0.0.15 + - @rocket.chat/gazzodown@2.0.0 + - @rocket.chat/models@0.0.15 + - @rocket.chat/ui-video-conf@2.0.0 + - @rocket.chat/base64@1.0.12 + - @rocket.chat/instance-status@0.0.15 + - @rocket.chat/random@1.2.1 + - @rocket.chat/sha256@1.0.9 + - @rocket.chat/ui-composer@0.0.1 + +## 6.4.0-rc.5 + +### Minor Changes + +- 1041d4d361: Added option to select between two script engine options for the integrations + +### Patch Changes + +- Bump @rocket.chat/meteor version. +- ec60dbe8f5: Fixed custom translations not being displayed +- Updated dependencies [1041d4d361] + - @rocket.chat/core-typings@6.4.0-rc.5 + - @rocket.chat/rest-typings@6.4.0-rc.5 + - @rocket.chat/tools@0.1.0-rc.0 + - @rocket.chat/api-client@0.1.9-rc.5 + - @rocket.chat/omnichannel-services@0.0.15-rc.5 + - @rocket.chat/pdf-worker@0.0.15-rc.5 + - @rocket.chat/presence@0.0.15-rc.5 + - @rocket.chat/core-services@0.2.0-rc.5 + - @rocket.chat/cron@0.0.11-rc.5 + - @rocket.chat/gazzodown@2.0.0-rc.5 + - @rocket.chat/model-typings@0.1.0-rc.5 + - @rocket.chat/ui-contexts@2.0.0-rc.5 + - @rocket.chat/fuselage-ui-kit@2.0.0-rc.5 + - @rocket.chat/models@0.0.15-rc.5 + - @rocket.chat/ui-theming@0.1.0-rc.0 + - @rocket.chat/ui-client@2.0.0-rc.5 + - @rocket.chat/ui-video-conf@2.0.0-rc.5 + - @rocket.chat/web-ui-registration@2.0.0-rc.5 + - @rocket.chat/instance-status@0.0.15-rc.5 + ## 6.4.0-rc.4 ### Patch Changes @@ -266,6 +477,31 @@ - @rocket.chat/sha256@1.0.9 - @rocket.chat/ui-composer@0.0.1 +## 6.3.8 + +### Patch Changes + +- ff8e9d9f54: Bump @rocket.chat/meteor version. +- Bump @rocket.chat/meteor version. + - @rocket.chat/core-typings@6.3.8 + - @rocket.chat/rest-typings@6.3.8 + - @rocket.chat/api-client@0.1.8 + - @rocket.chat/omnichannel-services@0.0.14 + - @rocket.chat/pdf-worker@0.0.14 + - @rocket.chat/presence@0.0.14 + - @rocket.chat/core-services@0.1.8 + - @rocket.chat/cron@0.0.10 + - @rocket.chat/gazzodown@1.0.8 + - @rocket.chat/model-typings@0.0.14 + - @rocket.chat/ui-contexts@1.0.8 + - @rocket.chat/fuselage-ui-kit@1.0.8 + - @rocket.chat/models@0.0.14 + - @rocket.chat/ui-theming@0.0.1 + - @rocket.chat/ui-client@1.0.8 + - @rocket.chat/ui-video-conf@1.0.8 + - @rocket.chat/web-ui-registration@1.0.8 + - @rocket.chat/instance-status@0.0.14 + ## 6.3.7 ### Patch Changes diff --git a/apps/meteor/app/api/server/v1/channels.ts b/apps/meteor/app/api/server/v1/channels.ts index 4a7aec073442..8e0541b8040b 100644 --- a/apps/meteor/app/api/server/v1/channels.ts +++ b/apps/meteor/app/api/server/v1/channels.ts @@ -670,7 +670,14 @@ async function createChannelValidator(params: { async function createChannel( userId: string, - params: { name?: string; members?: string[]; customFields?: Record; extraData?: Record; readOnly?: boolean }, + params: { + name?: string; + members?: string[]; + customFields?: Record; + extraData?: Record; + readOnly?: boolean; + excludeSelf?: boolean; + }, ): Promise<{ channel: IRoom }> { const readOnly = typeof params.readOnly !== 'undefined' ? params.readOnly : false; const id = await createChannelMethod( @@ -680,6 +687,7 @@ async function createChannel( readOnly, params.customFields, params.extraData, + params.excludeSelf, ); return { diff --git a/apps/meteor/app/api/server/v1/groups.ts b/apps/meteor/app/api/server/v1/groups.ts index df54b683fda4..ef18d4256348 100644 --- a/apps/meteor/app/api/server/v1/groups.ts +++ b/apps/meteor/app/api/server/v1/groups.ts @@ -1,4 +1,4 @@ -import { Team } from '@rocket.chat/core-services'; +import { Team, isMeteorError } from '@rocket.chat/core-services'; import type { IIntegration, IUser, IRoom, RoomType } from '@rocket.chat/core-typings'; import { Integrations, Messages, Rooms, Subscriptions, Uploads, Users } from '@rocket.chat/models'; import { check, Match } from 'meteor/check'; @@ -302,10 +302,6 @@ API.v1.addRoute( { authRequired: true }, { async post() { - if (!(await hasPermissionAsync(this.userId, 'create-p'))) { - return API.v1.unauthorized(); - } - if (!this.bodyParams.name) { return API.v1.failure('Body param "name" is required'); } @@ -323,24 +319,32 @@ API.v1.addRoute( const readOnly = typeof this.bodyParams.readOnly !== 'undefined' ? this.bodyParams.readOnly : false; - const result = await createPrivateGroupMethod( - this.userId, - this.bodyParams.name, - this.bodyParams.members ? this.bodyParams.members : [], - readOnly, - this.bodyParams.customFields, - this.bodyParams.extraData, - ); - - const room = await Rooms.findOneById(result.rid, { projection: API.v1.defaultFieldsToExclude }); + try { + const result = await createPrivateGroupMethod( + this.user, + this.bodyParams.name, + this.bodyParams.members ? this.bodyParams.members : [], + readOnly, + this.bodyParams.customFields, + this.bodyParams.extraData, + this.bodyParams.excludeSelf ?? false, + ); + + const room = await Rooms.findOneById(result.rid, { projection: API.v1.defaultFieldsToExclude }); + if (!room) { + throw new Meteor.Error('error-room-not-found', 'The required "roomId" or "roomName" param provided does not match any group'); + } - if (!room) { - throw new Meteor.Error('error-room-not-found', 'The required "roomId" or "roomName" param provided does not match any group'); + return API.v1.success({ + group: await composeRoomWithLastMessage(room, this.userId), + }); + } catch (error: unknown) { + if (isMeteorError(error) && error.reason === 'error-not-allowed') { + return API.v1.unauthorized(); + } } - return API.v1.success({ - group: await composeRoomWithLastMessage(room, this.userId), - }); + return API.v1.internalError(); }, }, ); diff --git a/apps/meteor/app/api/server/v1/misc.ts b/apps/meteor/app/api/server/v1/misc.ts index dec4da6bf87b..ae5a79719cce 100644 --- a/apps/meteor/app/api/server/v1/misc.ts +++ b/apps/meteor/app/api/server/v1/misc.ts @@ -1,13 +1,14 @@ import crypto from 'crypto'; import type { IUser } from '@rocket.chat/core-typings'; -import { Users } from '@rocket.chat/models'; +import { Settings, Users } from '@rocket.chat/models'; import { isShieldSvgProps, isSpotlightProps, isDirectoryProps, isMethodCallProps, isMethodCallAnonProps, + isFingerprintProps, isMeteorCall, validateParamsPwGetPolicyRest, } from '@rocket.chat/rest-typings'; @@ -16,6 +17,7 @@ import EJSON from 'ejson'; import { check } from 'meteor/check'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Meteor } from 'meteor/meteor'; +import { v4 as uuidv4 } from 'uuid'; import { i18n } from '../../../../server/lib/i18n'; import { SystemLogger } from '../../../../server/lib/logger/system'; @@ -643,3 +645,75 @@ API.v1.addRoute( }, }, ); + +/** + * @openapi + * /api/v1/fingerprint: + * post: + * description: Update Fingerprint definition as a new workspace or update of configuration + * security: + * $ref: '#/security/authenticated' + * requestBody: + * content: + * application/json: + * schema: + * type: object + * properties: + * setDeploymentAs: + * type: string + * example: | + * { + * "setDeploymentAs": "new-workspace" + * } + * responses: + * 200: + * description: Workspace successfully configured + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ApiSuccessV1' + * default: + * description: Unexpected error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ApiFailureV1' + */ +API.v1.addRoute( + 'fingerprint', + { + authRequired: true, + validateParams: isFingerprintProps, + }, + { + async post() { + check(this.bodyParams, { + setDeploymentAs: String, + }); + + if (this.bodyParams.setDeploymentAs === 'new-workspace') { + await Promise.all([ + Settings.resetValueById('uniqueID', process.env.DEPLOYMENT_ID || uuidv4()), + // Settings.resetValueById('Cloud_Url'), + Settings.resetValueById('Cloud_Service_Agree_PrivacyTerms'), + Settings.resetValueById('Cloud_Workspace_Id'), + Settings.resetValueById('Cloud_Workspace_Name'), + Settings.resetValueById('Cloud_Workspace_Client_Id'), + Settings.resetValueById('Cloud_Workspace_Client_Secret'), + Settings.resetValueById('Cloud_Workspace_Client_Secret_Expires_At'), + Settings.resetValueById('Cloud_Workspace_Registration_Client_Uri'), + Settings.resetValueById('Cloud_Workspace_PublicKey'), + Settings.resetValueById('Cloud_Workspace_License'), + Settings.resetValueById('Cloud_Workspace_Had_Trial'), + Settings.resetValueById('Cloud_Workspace_Access_Token'), + Settings.resetValueById('Cloud_Workspace_Access_Token_Expires_At', new Date(0)), + Settings.resetValueById('Cloud_Workspace_Registration_State'), + ]); + } + + await Settings.updateValueById('Deployment_FingerPrint_Verified', true); + + return API.v1.success({}); + }, + }, +); diff --git a/apps/meteor/app/apps/server/bridges/livechat.ts b/apps/meteor/app/apps/server/bridges/livechat.ts index 71f7387e1aa5..76a0545c8801 100644 --- a/apps/meteor/app/apps/server/bridges/livechat.ts +++ b/apps/meteor/app/apps/server/bridges/livechat.ts @@ -223,7 +223,7 @@ export class AppLivechatBridge extends LivechatBridge { } return Promise.all( - (await LivechatVisitors.find(query).toArray()).map( + (await LivechatVisitors.findEnabled(query).toArray()).map( async (visitor) => visitor && this.orch.getConverters()?.get('visitors').convertVisitor(visitor), ), ); diff --git a/apps/meteor/app/apps/server/bridges/rooms.ts b/apps/meteor/app/apps/server/bridges/rooms.ts index 481292d61790..91b0049513f0 100644 --- a/apps/meteor/app/apps/server/bridges/rooms.ts +++ b/apps/meteor/app/apps/server/bridges/rooms.ts @@ -55,7 +55,11 @@ export class AppRoomBridge extends RoomBridge { } private async createPrivateGroup(userId: string, room: ICoreRoom, members: string[]): Promise { - return (await createPrivateGroupMethod(userId, room.name || '', members, room.ro, room.customFields, this.prepareExtraData(room))).rid; + const user = await Users.findOneById(userId); + if (!user) { + throw new Error('Invalid user'); + } + return (await createPrivateGroupMethod(user, room.name || '', members, room.ro, room.customFields, this.prepareExtraData(room))).rid; } protected async getById(roomId: string, appId: string): Promise { diff --git a/apps/meteor/app/apps/server/converters/rooms.js b/apps/meteor/app/apps/server/converters/rooms.js index ae38feff5eff..905534212836 100644 --- a/apps/meteor/app/apps/server/converters/rooms.js +++ b/apps/meteor/app/apps/server/converters/rooms.js @@ -37,7 +37,7 @@ export class AppRoomsConverter { let v; if (room.visitor) { - const visitor = await LivechatVisitors.findOneById(room.visitor.id); + const visitor = await LivechatVisitors.findOneEnabledById(room.visitor.id); const { lastMessageTs, phone } = room.visitorChannelInfo; diff --git a/apps/meteor/app/apps/server/converters/visitors.js b/apps/meteor/app/apps/server/converters/visitors.js index ba288c96d7b8..a9f5d450efad 100644 --- a/apps/meteor/app/apps/server/converters/visitors.js +++ b/apps/meteor/app/apps/server/converters/visitors.js @@ -9,7 +9,7 @@ export class AppVisitorsConverter { } async convertById(id) { - const visitor = await LivechatVisitors.findOneById(id); + const visitor = await LivechatVisitors.findOneEnabledById(id); return this.convertVisitor(visitor); } diff --git a/apps/meteor/app/cloud/server/functions/buildRegistrationData.ts b/apps/meteor/app/cloud/server/functions/buildRegistrationData.ts index 10e0d7f7f7ee..f887c9e6395c 100644 --- a/apps/meteor/app/cloud/server/functions/buildRegistrationData.ts +++ b/apps/meteor/app/cloud/server/functions/buildRegistrationData.ts @@ -1,50 +1,59 @@ -import type { SettingValue } from '@rocket.chat/core-typings'; import { Statistics, Users } from '@rocket.chat/models'; import { settings } from '../../../settings/server'; import { statistics } from '../../../statistics/server'; +import { Info } from '../../../utils/rocketchat.info'; import { LICENSE_VERSION } from '../license'; export type WorkspaceRegistrationData = { uniqueId: string; - workspaceId: SettingValue; - address: SettingValue; + deploymentFingerprintHash: string; + deploymentFingerprintVerified: boolean; + workspaceId: string; + address: string; contactName: string; contactEmail: T; seats: number; - allowMarketing: SettingValue; - accountName: SettingValue; + organizationType: string; industry: string; orgSize: string; country: string; language: string; - agreePrivacyTerms: SettingValue; - website: SettingValue; - siteName: SettingValue; + allowMarketing: string; + accountName: string; + agreePrivacyTerms: string; + website: string; + siteName: string; workspaceType: unknown; deploymentMethod: string; deploymentPlatform: string; - version: unknown; + version: string; licenseVersion: number; enterpriseReady: boolean; setupComplete: boolean; connectionDisable: boolean; - npsEnabled: SettingValue; + npsEnabled: string; + // TODO: Evaluate naming + MAC: number; + // activeContactsBillingMonth: number; + // activeContactsYesterday: number; }; export async function buildWorkspaceRegistrationData(contactEmail: T): Promise> { const stats = (await Statistics.findLast()) || (await statistics.get()); - const address = settings.get('Site_Url'); - const siteName = settings.get('Site_Name'); - const workspaceId = settings.get('Cloud_Workspace_Id'); - const allowMarketing = settings.get('Allow_Marketing_Emails'); - const accountName = settings.get('Organization_Name'); - const website = settings.get('Website'); - const npsEnabled = settings.get('NPS_survey_enabled'); - const agreePrivacyTerms = settings.get('Cloud_Service_Agree_PrivacyTerms'); - const setupWizardState = settings.get('Show_Setup_Wizard'); + const address = settings.get('Site_Url'); + const siteName = settings.get('Site_Name'); + const workspaceId = settings.get('Cloud_Workspace_Id'); + const allowMarketing = settings.get('Allow_Marketing_Emails'); + const accountName = settings.get('Organization_Name'); + const website = settings.get('Website'); + const npsEnabled = settings.get('NPS_survey_enabled'); + const agreePrivacyTerms = settings.get('Cloud_Service_Agree_PrivacyTerms'); + const setupWizardState = settings.get('Show_Setup_Wizard'); + const deploymentFingerprintHash = settings.get('Deployment_FingerPrint_Hash'); + const deploymentFingerprintVerified = settings.get('Deployment_FingerPrint_Verified'); const firstUser = await Users.getOldest({ projection: { name: 1, emails: 1 } }); const contactName = firstUser?.name || ''; @@ -54,6 +63,8 @@ export async function buildWorkspaceRegistrationData { const currentLicense = await Settings.findOne('Cloud_Workspace_License'); + // it should never happen, since even if the license is not found, it will return an empty settings + if (!currentLicense?._updatedAt) { + throw new CloudWorkspaceLicenseError('Failed to retrieve current license'); + } const fromCurrentLicense = async () => { const license = currentLicense?.value as string | undefined; @@ -67,10 +71,6 @@ export async function getWorkspaceLicense(): Promise<{ updated: boolean; license return fromCurrentLicense(); } - if (!currentLicense?._updatedAt) { - throw new CloudWorkspaceLicenseError('Failed to retrieve current license'); - } - const payload = await fetchCloudWorkspaceLicensePayload({ token }); if (Date.parse(payload.updatedAt) <= currentLicense._updatedAt.getTime()) { diff --git a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts index 3d79ed436e51..577abd4383d0 100644 --- a/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts +++ b/apps/meteor/app/cloud/server/functions/supportedVersionsToken/supportedVersionsToken.ts @@ -1,7 +1,7 @@ import type { SettingValue } from '@rocket.chat/core-typings'; import { License } from '@rocket.chat/license'; import { Settings } from '@rocket.chat/models'; -import type { SupportedVersions } from '@rocket.chat/server-cloud-communication'; +import type { SignedSupportedVersions, SupportedVersions } from '@rocket.chat/server-cloud-communication'; import type { Response } from '@rocket.chat/server-fetch'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; @@ -10,6 +10,12 @@ import { settings } from '../../../../settings/server'; import { generateWorkspaceBearerHttpHeader } from '../getWorkspaceAccessToken'; import { supportedVersionsChooseLatest } from './supportedVersionsChooseLatest'; +declare module '@rocket.chat/license' { + interface ILicenseV3 { + supportedVersions?: SignedSupportedVersions; + } +} + /** HELPERS */ export const wrapPromise = ( @@ -115,9 +121,10 @@ const getSupportedVersionsToken = async () => { * return the token */ - const [versionsFromLicense, response] = await Promise.all([License.supportedVersions(), getSupportedVersionsFromCloud()]); + const [versionsFromLicense, response] = await Promise.all([License.getLicense(), getSupportedVersionsFromCloud()]); - return (await supportedVersionsChooseLatest(versionsFromLicense, (response.success && response.result) || undefined))?.signed; + return (await supportedVersionsChooseLatest(versionsFromLicense?.supportedVersions, (response.success && response.result) || undefined)) + ?.signed; }; export const getCachedSupportedVersionsToken = cacheValueInSettings('Cloud_Workspace_Supported_Versions_Token', getSupportedVersionsToken); diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/announcementSync.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/announcementSync.ts new file mode 100644 index 000000000000..26d98b4a7574 --- /dev/null +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/announcementSync.ts @@ -0,0 +1,116 @@ +import { type Cloud, type Serialized } from '@rocket.chat/core-typings'; +import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { v, compile } from 'suretype'; + +import { CloudWorkspaceAccessError } from '../../../../../lib/errors/CloudWorkspaceAccessError'; +import { CloudWorkspaceConnectionError } from '../../../../../lib/errors/CloudWorkspaceConnectionError'; +import { CloudWorkspaceRegistrationError } from '../../../../../lib/errors/CloudWorkspaceRegistrationError'; +import { SystemLogger } from '../../../../../server/lib/logger/system'; +import { settings } from '../../../../settings/server'; +import { buildWorkspaceRegistrationData } from '../buildRegistrationData'; +import { getWorkspaceAccessToken } from '../getWorkspaceAccessToken'; +import { retrieveRegistrationStatus } from '../retrieveRegistrationStatus'; +import { handleAnnouncementsOnWorkspaceSync, handleNpsOnWorkspaceSync } from './handleCommsSync'; +import { legacySyncWorkspace } from './legacySyncWorkspace'; + +const workspaceCommPayloadSchema = v.object({ + workspaceId: v.string().required(), + publicKey: v.string(), + nps: v.object({ + id: v.string().required(), + startAt: v.string().format('date-time').required(), + expireAt: v.string().format('date-time').required(), + }), + announcements: v.object({ + create: v.array( + v.object({ + _id: v.string().required(), + _updatedAt: v.string().format('date-time').required(), + selector: v.object({ + roles: v.array(v.string()), + }), + platform: v.array(v.string().enum('web', 'mobile')).required(), + expireAt: v.string().format('date-time').required(), + startAt: v.string().format('date-time').required(), + createdBy: v.string().enum('cloud', 'system').required(), + createdAt: v.string().format('date-time').required(), + dictionary: v.object({}).additional(v.object({}).additional(v.string())), + view: v.any(), + surface: v.string().enum('banner', 'modal').required(), + }), + ), + delete: v.array(v.string()), + }), +}); + +const assertWorkspaceCommPayload = compile(workspaceCommPayloadSchema); + +const fetchCloudAnnouncementsSync = async ({ + token, + data, +}: { + token: string; + data: Cloud.WorkspaceSyncRequestPayload; +}): Promise> => { + const cloudUrl = settings.get('Cloud_Url'); + const response = await fetch(`${cloudUrl}/api/v3/comms/workspace`, { + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + }, + body: data, + }); + + if (!response.ok) { + try { + const { error } = await response.json(); + throw new CloudWorkspaceConnectionError(`Failed to connect to Rocket.Chat Cloud: ${error}`); + } catch (error) { + throw new CloudWorkspaceConnectionError(`Failed to connect to Rocket.Chat Cloud: ${response.statusText}`); + } + } + + const payload = await response.json(); + + assertWorkspaceCommPayload(payload); + return payload; +}; + +export async function announcementSync() { + try { + const { workspaceRegistered } = await retrieveRegistrationStatus(); + if (!workspaceRegistered) { + throw new CloudWorkspaceRegistrationError('Workspace is not registered'); + } + + const token = await getWorkspaceAccessToken(true); + if (!token) { + throw new CloudWorkspaceAccessError('Workspace does not have a valid access token'); + } + + const workspaceRegistrationData = await buildWorkspaceRegistrationData(undefined); + + const { nps, announcements } = await fetchCloudAnnouncementsSync({ + token, + data: workspaceRegistrationData, + }); + + if (nps) { + await handleNpsOnWorkspaceSync(nps); + } + + if (announcements) { + await handleAnnouncementsOnWorkspaceSync(announcements); + } + + return true; + } catch (err) { + SystemLogger.error({ + msg: 'Failed to sync with Rocket.Chat Cloud', + url: '/sync', + err, + }); + } + + await legacySyncWorkspace(); +} diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts new file mode 100644 index 000000000000..c8b07f8826cf --- /dev/null +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts @@ -0,0 +1,65 @@ +import { NPS, Banner } from '@rocket.chat/core-services'; +import { type Cloud, type Serialized } from '@rocket.chat/core-typings'; +import { CloudAnnouncements } from '@rocket.chat/models'; + +import { getAndCreateNpsSurvey } from '../../../../../server/services/nps/getAndCreateNpsSurvey'; + +export const handleNpsOnWorkspaceSync = async (nps: Exclude['nps'], undefined>) => { + const { id: npsId, expireAt } = nps; + + const startAt = new Date(nps.startAt); + + await NPS.create({ + npsId, + startAt, + expireAt: new Date(expireAt), + createdBy: { + _id: 'rocket.cat', + username: 'rocket.cat', + }, + }); + + const now = new Date(); + + if (startAt.getFullYear() === now.getFullYear() && startAt.getMonth() === now.getMonth() && startAt.getDate() === now.getDate()) { + await getAndCreateNpsSurvey(npsId); + } +}; + +export const handleBannerOnWorkspaceSync = async (banners: Exclude['banners'], undefined>) => { + for await (const banner of banners) { + const { createdAt, expireAt, startAt, inactivedAt, _updatedAt, ...rest } = banner; + + await Banner.create({ + ...rest, + createdAt: new Date(createdAt), + expireAt: new Date(expireAt), + startAt: new Date(startAt), + ...(inactivedAt && { inactivedAt: new Date(inactivedAt) }), + }); + } +}; + +const deserializeAnnouncement = (announcement: Serialized): Cloud.Announcement => ({ + ...announcement, + _updatedAt: new Date(announcement._updatedAt), + expireAt: new Date(announcement.expireAt), + startAt: new Date(announcement.startAt), + createdAt: new Date(announcement.createdAt), +}); + +export const handleAnnouncementsOnWorkspaceSync = async ( + announcements: Exclude['announcements'], undefined>, +) => { + const { create, delete: deleteIds } = announcements; + + if (deleteIds) { + await CloudAnnouncements.deleteMany({ _id: { $in: deleteIds } }); + } + + for await (const announcement of create.map(deserializeAnnouncement)) { + const { _id, ...rest } = announcement; + + await CloudAnnouncements.updateOne({ _id }, { $set: rest }, { upsert: true }); + } +}; diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts index 48d5afa9dbc5..3173e652afe5 100644 --- a/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts @@ -1,12 +1,12 @@ import { CloudWorkspaceAccessTokenError } from '../getWorkspaceAccessToken'; -import { getWorkspaceLicense } from '../getWorkspaceLicense'; import { getCachedSupportedVersionsToken } from '../supportedVersionsToken/supportedVersionsToken'; +import { announcementSync } from './announcementSync'; import { syncCloudData } from './syncCloudData'; export async function syncWorkspace() { try { await syncCloudData(); - await getWorkspaceLicense(); + await announcementSync(); } catch (error) { if (error instanceof CloudWorkspaceAccessTokenError) { // TODO: Remove License if there is no access token diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/legacySyncWorkspace.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/legacySyncWorkspace.ts new file mode 100644 index 000000000000..d5f86fad8409 --- /dev/null +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/legacySyncWorkspace.ts @@ -0,0 +1,182 @@ +import { type Cloud, type Serialized } from '@rocket.chat/core-typings'; +import { Settings } from '@rocket.chat/models'; +import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { v, compile } from 'suretype'; + +import { CloudWorkspaceAccessError } from '../../../../../lib/errors/CloudWorkspaceAccessError'; +import { CloudWorkspaceConnectionError } from '../../../../../lib/errors/CloudWorkspaceConnectionError'; +import { CloudWorkspaceRegistrationError } from '../../../../../lib/errors/CloudWorkspaceRegistrationError'; +import { SystemLogger } from '../../../../../server/lib/logger/system'; +import { settings } from '../../../../settings/server'; +import type { WorkspaceRegistrationData } from '../buildRegistrationData'; +import { buildWorkspaceRegistrationData } from '../buildRegistrationData'; +import { getWorkspaceAccessToken } from '../getWorkspaceAccessToken'; +import { getWorkspaceLicense } from '../getWorkspaceLicense'; +import { retrieveRegistrationStatus } from '../retrieveRegistrationStatus'; +import { handleBannerOnWorkspaceSync, handleNpsOnWorkspaceSync } from './handleCommsSync'; + +const workspaceClientPayloadSchema = v.object({ + workspaceId: v.string().required(), + publicKey: v.string(), + trial: v.object({ + trialing: v.boolean().required(), + trialID: v.string().required(), + endDate: v.string().format('date-time').required(), + marketing: v + .object({ + utmContent: v.string().required(), + utmMedium: v.string().required(), + utmSource: v.string().required(), + utmCampaign: v.string().required(), + }) + .required(), + DowngradesToPlan: v + .object({ + id: v.string().required(), + }) + .required(), + trialRequested: v.boolean().required(), + }), + nps: v.object({ + id: v.string().required(), + startAt: v.string().format('date-time').required(), + expireAt: v.string().format('date-time').required(), + }), + banners: v.array( + v.object({ + _id: v.string().required(), + _updatedAt: v.string().format('date-time').required(), + platform: v.array(v.string()).required(), + expireAt: v.string().format('date-time').required(), + startAt: v.string().format('date-time').required(), + roles: v.array(v.string()), + createdBy: v.object({ + _id: v.string().required(), + username: v.string(), + }), + createdAt: v.string().format('date-time').required(), + view: v.any(), + active: v.boolean(), + inactivedAt: v.string().format('date-time'), + snapshot: v.string(), + }), + ), + announcements: v.object({ + create: v.array( + v.object({ + _id: v.string().required(), + _updatedAt: v.string().format('date-time').required(), + selector: v.object({ + roles: v.array(v.string()), + }), + platform: v.array(v.string().enum('web', 'mobile')).required(), + expireAt: v.string().format('date-time').required(), + startAt: v.string().format('date-time').required(), + createdBy: v.string().enum('cloud', 'system').required(), + createdAt: v.string().format('date-time').required(), + dictionary: v.object({}).additional(v.object({}).additional(v.string())), + view: v.any(), + surface: v.string().enum('banner', 'modal').required(), + }), + ), + delete: v.array(v.string()), + }), +}); + +const assertWorkspaceClientPayload = compile(workspaceClientPayloadSchema); + +/** @deprecated */ +const fetchWorkspaceClientPayload = async ({ + token, + workspaceRegistrationData, +}: { + token: string; + workspaceRegistrationData: WorkspaceRegistrationData; +}): Promise | undefined> => { + const workspaceRegistrationClientUri = settings.get('Cloud_Workspace_Registration_Client_Uri'); + const response = await fetch(`${workspaceRegistrationClientUri}/client`, { + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + }, + body: workspaceRegistrationData, + }); + + if (!response.ok) { + try { + const { error } = await response.json(); + throw new CloudWorkspaceConnectionError(`Failed to connect to Rocket.Chat Cloud: ${error}`); + } catch (error) { + throw new CloudWorkspaceConnectionError(`Failed to connect to Rocket.Chat Cloud: ${response.statusText}`); + } + } + + const payload = await response.json(); + + if (!payload) { + return undefined; + } + + if (!assertWorkspaceClientPayload(payload)) { + throw new CloudWorkspaceConnectionError('Invalid response from Rocket.Chat Cloud'); + } + + return payload; +}; + +/** @deprecated */ +const consumeWorkspaceSyncPayload = async (result: Serialized) => { + if (result.publicKey) { + await Settings.updateValueById('Cloud_Workspace_PublicKey', result.publicKey); + } + + if (result.trial?.trialID) { + await Settings.updateValueById('Cloud_Workspace_Had_Trial', true); + } + + // add banners + if (result.banners) { + await handleBannerOnWorkspaceSync(result.banners); + } + + if (result.nps) { + await handleNpsOnWorkspaceSync(result.nps); + } +}; + +/** @deprecated */ +export async function legacySyncWorkspace() { + try { + const { workspaceRegistered } = await retrieveRegistrationStatus(); + if (!workspaceRegistered) { + throw new CloudWorkspaceRegistrationError('Workspace is not registered'); + } + + const token = await getWorkspaceAccessToken(true); + if (!token) { + throw new CloudWorkspaceAccessError('Workspace does not have a valid access token'); + } + + const workspaceRegistrationData = await buildWorkspaceRegistrationData(undefined); + + const payload = await fetchWorkspaceClientPayload({ token, workspaceRegistrationData }); + + if (!payload) { + return true; + } + + await consumeWorkspaceSyncPayload(payload); + + return true; + } catch (err) { + SystemLogger.error({ + msg: 'Failed to sync with Rocket.Chat Cloud', + url: '/client', + err, + }); + + return false; + } finally { + await getWorkspaceLicense(); + } +} diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/syncCloudData.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/syncCloudData.ts index df63dda6d563..5f529a4892ec 100644 --- a/apps/meteor/app/cloud/server/functions/syncWorkspace/syncCloudData.ts +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/syncCloudData.ts @@ -1,105 +1,40 @@ -import { NPS, Banner } from '@rocket.chat/core-services'; -import { type Cloud, type Serialized } from '@rocket.chat/core-typings'; -import { CloudAnnouncements, Settings } from '@rocket.chat/models'; +import type { Cloud, Serialized } from '@rocket.chat/core-typings'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import { v, compile } from 'suretype'; +import { callbacks } from '../../../../../lib/callbacks'; import { CloudWorkspaceAccessError } from '../../../../../lib/errors/CloudWorkspaceAccessError'; import { CloudWorkspaceConnectionError } from '../../../../../lib/errors/CloudWorkspaceConnectionError'; import { CloudWorkspaceRegistrationError } from '../../../../../lib/errors/CloudWorkspaceRegistrationError'; import { SystemLogger } from '../../../../../server/lib/logger/system'; -import { getAndCreateNpsSurvey } from '../../../../../server/services/nps/getAndCreateNpsSurvey'; import { settings } from '../../../../settings/server'; -import type { WorkspaceRegistrationData } from '../buildRegistrationData'; import { buildWorkspaceRegistrationData } from '../buildRegistrationData'; import { getWorkspaceAccessToken } from '../getWorkspaceAccessToken'; -import { getWorkspaceLicense } from '../getWorkspaceLicense'; import { retrieveRegistrationStatus } from '../retrieveRegistrationStatus'; +import { legacySyncWorkspace } from './legacySyncWorkspace'; const workspaceSyncPayloadSchema = v.object({ workspaceId: v.string().required(), publicKey: v.string(), - trial: v.object({ - trialing: v.boolean().required(), - trialID: v.string().required(), - endDate: v.string().format('date-time').required(), - marketing: v - .object({ - utmContent: v.string().required(), - utmMedium: v.string().required(), - utmSource: v.string().required(), - utmCampaign: v.string().required(), - }) - .required(), - DowngradesToPlan: v - .object({ - id: v.string().required(), - }) - .required(), - trialRequested: v.boolean().required(), - }), - nps: v.object({ - id: v.string().required(), - startAt: v.string().format('date-time').required(), - expireAt: v.string().format('date-time').required(), - }), - banners: v.array( - v.object({ - _id: v.string().required(), - _updatedAt: v.string().format('date-time').required(), - platform: v.array(v.string()).required(), - expireAt: v.string().format('date-time').required(), - startAt: v.string().format('date-time').required(), - roles: v.array(v.string()), - createdBy: v.object({ - _id: v.string().required(), - username: v.string(), - }), - createdAt: v.string().format('date-time').required(), - view: v.any(), - active: v.boolean(), - inactivedAt: v.string().format('date-time'), - snapshot: v.string(), - }), - ), - announcements: v.object({ - create: v.array( - v.object({ - _id: v.string().required(), - _updatedAt: v.string().format('date-time').required(), - selector: v.object({ - roles: v.array(v.string()), - }), - platform: v.array(v.string().enum('web', 'mobile')).required(), - expireAt: v.string().format('date-time').required(), - startAt: v.string().format('date-time').required(), - createdBy: v.string().enum('cloud', 'system').required(), - createdAt: v.string().format('date-time').required(), - dictionary: v.object({}).additional(v.object({}).additional(v.string())), - view: v.any(), - surface: v.string().enum('banner', 'modal').required(), - }), - ), - delete: v.array(v.string()), - }), + license: v.string().required(), }); const assertWorkspaceSyncPayload = compile(workspaceSyncPayloadSchema); const fetchWorkspaceSyncPayload = async ({ token, - workspaceRegistrationData, + data, }: { token: string; - workspaceRegistrationData: WorkspaceRegistrationData; -}): Promise | undefined> => { + data: Cloud.WorkspaceSyncRequestPayload; +}): Promise> => { const workspaceRegistrationClientUri = settings.get('Cloud_Workspace_Registration_Client_Uri'); - const response = await fetch(`${workspaceRegistrationClientUri}/client`, { + const response = await fetch(`${workspaceRegistrationClientUri}/sync`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, }, - body: workspaceRegistrationData, + body: data, }); if (!response.ok) { @@ -113,98 +48,11 @@ const fetchWorkspaceSyncPayload = async ({ const payload = await response.json(); - if (!payload) { - return undefined; - } - assertWorkspaceSyncPayload(payload); return payload; }; -const handleNpsOnWorkspaceSync = async (nps: Exclude['nps'], undefined>) => { - const { id: npsId, expireAt } = nps; - - const startAt = new Date(nps.startAt); - - await NPS.create({ - npsId, - startAt, - expireAt: new Date(expireAt), - createdBy: { - _id: 'rocket.cat', - username: 'rocket.cat', - }, - }); - - const now = new Date(); - - if (startAt.getFullYear() === now.getFullYear() && startAt.getMonth() === now.getMonth() && startAt.getDate() === now.getDate()) { - await getAndCreateNpsSurvey(npsId); - } -}; - -const handleBannerOnWorkspaceSync = async (banners: Exclude['banners'], undefined>) => { - for await (const banner of banners) { - const { createdAt, expireAt, startAt, inactivedAt, _updatedAt, ...rest } = banner; - - await Banner.create({ - ...rest, - createdAt: new Date(createdAt), - expireAt: new Date(expireAt), - startAt: new Date(startAt), - ...(inactivedAt && { inactivedAt: new Date(inactivedAt) }), - }); - } -}; - -const deserializeAnnouncement = (announcement: Serialized): Cloud.Announcement => ({ - ...announcement, - _updatedAt: new Date(announcement._updatedAt), - expireAt: new Date(announcement.expireAt), - startAt: new Date(announcement.startAt), - createdAt: new Date(announcement.createdAt), -}); - -const handleAnnouncementsOnWorkspaceSync = async ( - announcements: Exclude['announcements'], undefined>, -) => { - const { create, delete: deleteIds } = announcements; - - if (deleteIds) { - await CloudAnnouncements.deleteMany({ _id: { $in: deleteIds } }); - } - - for await (const announcement of create.map(deserializeAnnouncement)) { - const { _id, ...rest } = announcement; - - await CloudAnnouncements.updateOne({ _id }, { $set: rest }, { upsert: true }); - } -}; - -const consumeWorkspaceSyncPayload = async (result: Serialized) => { - if (result.publicKey) { - await Settings.updateValueById('Cloud_Workspace_PublicKey', result.publicKey); - } - - if (result.trial?.trialID) { - await Settings.updateValueById('Cloud_Workspace_Had_Trial', true); - } - - if (result.nps) { - await handleNpsOnWorkspaceSync(result.nps); - } - - // add banners - if (result.banners) { - await handleBannerOnWorkspaceSync(result.banners); - } - - if (result.announcements) { - await handleAnnouncementsOnWorkspaceSync(result.announcements); - } -}; - export async function syncCloudData() { try { const { workspaceRegistered } = await retrieveRegistrationStatus(); @@ -219,24 +67,21 @@ export async function syncCloudData() { const workspaceRegistrationData = await buildWorkspaceRegistrationData(undefined); - const payload = await fetchWorkspaceSyncPayload({ token, workspaceRegistrationData }); - - if (!payload) { - return true; - } + const { license } = await fetchWorkspaceSyncPayload({ + token, + data: workspaceRegistrationData, + }); - await consumeWorkspaceSyncPayload(payload); + await callbacks.run('workspaceLicenseChanged', license); return true; } catch (err) { SystemLogger.error({ msg: 'Failed to sync with Rocket.Chat Cloud', - url: '/client', + url: '/sync', err, }); - - return false; - } finally { - await getWorkspaceLicense(); } + + await legacySyncWorkspace(); } diff --git a/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts b/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts index 5eb2ef38e5b7..3ad61c4c42f0 100644 --- a/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts +++ b/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts @@ -59,7 +59,7 @@ Meteor.startup(() => { return false; } - return uid !== user._id ? hasPermission('start-discussion-other-user') : hasPermission('start-discussion'); + return uid !== user._id ? hasPermission('start-discussion-other-user', room._id) : hasPermission('start-discussion', room._id); }, order: 1, group: 'menu', diff --git a/apps/meteor/app/discussion/server/methods/createDiscussion.ts b/apps/meteor/app/discussion/server/methods/createDiscussion.ts index ce5c09947a60..c3869f8ff963 100644 --- a/apps/meteor/app/discussion/server/methods/createDiscussion.ts +++ b/apps/meteor/app/discussion/server/methods/createDiscussion.ts @@ -156,7 +156,7 @@ const create = async ({ const discussion = await createRoom( type, name, - user.username as string, + user, [...new Set(invitedUsers)].filter(Boolean), false, false, @@ -221,7 +221,7 @@ export const createDiscussion = async ( }); } - if (!(await hasAtLeastOnePermissionAsync(userId, ['start-discussion', 'start-discussion-other-user']))) { + if (!(await hasAtLeastOnePermissionAsync(userId, ['start-discussion', 'start-discussion-other-user'], prid))) { throw new Meteor.Error('error-action-not-allowed', 'You are not allowed to create a discussion', { method: 'createDiscussion' }); } const user = await Users.findOneById(userId); diff --git a/apps/meteor/app/importer/server/classes/ImportDataConverter.ts b/apps/meteor/app/importer/server/classes/ImportDataConverter.ts index f241879cdc67..1b596d625d9b 100644 --- a/apps/meteor/app/importer/server/classes/ImportDataConverter.ts +++ b/apps/meteor/app/importer/server/classes/ImportDataConverter.ts @@ -1034,7 +1034,11 @@ export class ImportDataConverter { return; } if (roomData.t === 'p') { - roomInfo = await createPrivateGroupMethod(startedByUserId, roomData.name, members, false, {}, {}, true); + const user = await Users.findOneById(startedByUserId); + if (!user) { + throw new Error('importer-channel-invalid-creator'); + } + roomInfo = await createPrivateGroupMethod(user, roomData.name, members, false, {}, {}, true); } else { roomInfo = await createChannelMethod(startedByUserId, roomData.name, members, false, {}, {}, true); } diff --git a/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts b/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts index ad632a3b7dfc..835f59419ad5 100644 --- a/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts +++ b/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts @@ -12,7 +12,7 @@ export const addUserToDefaultChannels = async function (user: IUser, silenced?: }).toArray(); for await (const room of defaultRooms) { if (!(await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { projection: { _id: 1 } }))) { - const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(user); + const autoTranslateConfig = getSubscriptionAutotranslateDefaultConfig(user); // Add a subscription to this user await Subscriptions.createWithRoomAndUser(room, user, { ts: new Date(), diff --git a/apps/meteor/app/lib/server/functions/addUserToRoom.ts b/apps/meteor/app/lib/server/functions/addUserToRoom.ts index 41000cda2038..4e29576cf3bb 100644 --- a/apps/meteor/app/lib/server/functions/addUserToRoom.ts +++ b/apps/meteor/app/lib/server/functions/addUserToRoom.ts @@ -71,7 +71,7 @@ export const addUserToRoom = async function ( await callbacks.run('beforeJoinRoom', userToBeAdded, room); } - const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(userToBeAdded); + const autoTranslateConfig = getSubscriptionAutotranslateDefaultConfig(userToBeAdded); await Subscriptions.createWithRoomAndUser(room, userToBeAdded as IUser, { ts: now, diff --git a/apps/meteor/app/lib/server/functions/createRoom.ts b/apps/meteor/app/lib/server/functions/createRoom.ts index 30cf2a593700..312451f54845 100644 --- a/apps/meteor/app/lib/server/functions/createRoom.ts +++ b/apps/meteor/app/lib/server/functions/createRoom.ts @@ -10,7 +10,6 @@ import { Apps } from '../../../../ee/server/apps/orchestrator'; import { callbacks } from '../../../../lib/callbacks'; import { beforeCreateRoomCallback } from '../../../../lib/callbacks/beforeCreateRoomCallback'; import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig'; -import { addUserRolesAsync } from '../../../../server/lib/roles/addUserRoles'; import { getValidRoomName } from '../../../utils/server/lib/getValidRoomName'; import { createDirectRoom } from './createDirectRoom'; @@ -21,10 +20,90 @@ const isValidName = (name: unknown): name is string => { const onlyUsernames = (members: unknown): members is string[] => Array.isArray(members) && members.every((member) => typeof member === 'string'); +async function createUsersSubscriptions({ + room, + shouldBeHandledByFederation, + members, + now, + owner, + options, +}: { + room: IRoom; + shouldBeHandledByFederation: boolean; + members: string[]; + now: Date; + owner: IUser; + options?: ICreateRoomParams['options']; +}) { + if (shouldBeHandledByFederation) { + const extra: Partial = options?.subscriptionExtra || {}; + extra.open = true; + extra.ls = now; + + if (room.prid) { + extra.prid = room.prid; + } + + await Subscriptions.createWithRoomAndUser(room, owner, extra); + + return; + } + + const subs = []; + + const memberIds = []; + + const membersCursor = Users.findUsersByUsernames>(members, { + projection: { 'username': 1, 'settings.preferences': 1, 'federated': 1, 'roles': 1 }, + }); + + for await (const member of membersCursor) { + try { + await callbacks.run('federation.beforeAddUserToARoom', { user: member, inviter: owner }, room); + await callbacks.run('beforeAddedToRoom', { user: member, inviter: owner }); + } catch (error) { + continue; + } + + memberIds.push(member._id); + + const extra: Partial = options?.subscriptionExtra || {}; + + extra.open = true; + + if (room.prid) { + extra.prid = room.prid; + } + + if (member.username === owner.username) { + extra.ls = now; + extra.roles = ['owner']; + } + + const autoTranslateConfig = getSubscriptionAutotranslateDefaultConfig(member); + + subs.push({ + user: member, + extraData: { + ...extra, + ...autoTranslateConfig, + }, + }); + } + + if (!['d', 'l'].includes(room.t)) { + await Users.addRoomByUserIds(memberIds, room._id); + } + + await Subscriptions.createWithRoomAndManyUsers(room, subs); + + await Rooms.incUsersCountById(room._id, subs.length); +} + export const createRoom = async ( type: T, name: T extends 'd' ? undefined : string, - ownerUsername: string | undefined, + owner: T extends 'd' ? IUser | undefined : IUser, members: T extends 'd' ? IUser[] : string[] = [], excludeSelf?: boolean, readOnly?: boolean, @@ -47,7 +126,7 @@ export const createRoom = async ( // options, }); if (type === 'd') { - return createDirectRoom(members as IUser[], extraData, { ...options, creator: options?.creator || ownerUsername }); + return createDirectRoom(members as IUser[], extraData, { ...options, creator: options?.creator || owner?.username }); } if (!onlyUsernames(members)) { @@ -63,15 +142,13 @@ export const createRoom = async ( }); } - if (!ownerUsername) { + if (!owner) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'RocketChat.createRoom', }); } - const owner = await Users.findOneByUsernameIgnoringCase(ownerUsername, { projection: { username: 1, name: 1 } }); - - if (!ownerUsername || !owner) { + if (!owner?.username) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'RocketChat.createRoom', }); @@ -140,53 +217,12 @@ export const createRoom = async ( if (type === 'c') { await callbacks.run('beforeCreateChannel', owner, roomProps); } - const room = await Rooms.createWithFullRoomData(roomProps); - const shouldBeHandledByFederation = room.federated === true || ownerUsername.includes(':'); - if (shouldBeHandledByFederation) { - const extra: Partial = options?.subscriptionExtra || {}; - extra.open = true; - extra.ls = now; - if (room.prid) { - extra.prid = room.prid; - } - - await Subscriptions.createWithRoomAndUser(room, owner, extra); - } else { - for await (const username of [...new Set(members)]) { - const member = await Users.findOneByUsername(username, { - projection: { 'username': 1, 'settings.preferences': 1, 'federated': 1, 'roles': 1 }, - }); - if (!member) { - continue; - } - - try { - await callbacks.run('federation.beforeAddUserToARoom', { user: member, inviter: owner }, room); - await callbacks.run('beforeAddedToRoom', { user: member, inviter: owner }); - } catch (error) { - continue; - } - - const extra: Partial = options?.subscriptionExtra || {}; - - extra.open = true; - - if (room.prid) { - extra.prid = room.prid; - } - - if (username === owner.username) { - extra.ls = now; - } - - const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(member); + const room = await Rooms.createWithFullRoomData(roomProps); - await Subscriptions.createWithRoomAndUser(room, member, { ...extra, ...autoTranslateConfig }); - } - } + const shouldBeHandledByFederation = room.federated === true || owner.username.includes(':'); - await addUserRolesAsync(owner._id, ['owner'], room._id); + await createUsersSubscriptions({ room, members, now, owner, options, shouldBeHandledByFederation }); if (type === 'c') { if (room.teamId) { @@ -195,7 +231,7 @@ export const createRoom = async ( await Message.saveSystemMessage('user-added-room-to-team', team.roomId, room.name || '', owner); } } - await callbacks.run('afterCreateChannel', owner, room); + callbacks.runAsync('afterCreateChannel', owner, room); } else if (type === 'p') { callbacks.runAsync('afterCreatePrivateGroup', owner, room); } diff --git a/apps/meteor/app/lib/server/methods/createChannel.ts b/apps/meteor/app/lib/server/methods/createChannel.ts index ff8182cec8c9..98cea517bed4 100644 --- a/apps/meteor/app/lib/server/methods/createChannel.ts +++ b/apps/meteor/app/lib/server/methods/createChannel.ts @@ -35,8 +35,7 @@ export const createChannelMethod = async ( throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'createChannel' }); } - const user = await Users.findOneById(userId, { projection: { username: 1 } }); - + const user = await Users.findOneById(userId); if (!user?.username) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'createChannel' }); } @@ -44,7 +43,7 @@ export const createChannelMethod = async ( if (!(await hasPermissionAsync(userId, 'create-c'))) { throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createChannel' }); } - return createRoom('c', name, user.username, members, excludeSelf, readOnly, { + return createRoom('c', name, user, members, excludeSelf, readOnly, { customFields, ...extraData, }); diff --git a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts index 65298949a345..75097b5c89b8 100644 --- a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts +++ b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts @@ -1,4 +1,4 @@ -import type { ICreatedRoom } from '@rocket.chat/core-typings'; +import type { ICreatedRoom, IUser } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; @@ -21,7 +21,7 @@ declare module '@rocket.chat/ui-contexts' { } export const createPrivateGroupMethod = async ( - userId: string, + user: IUser, name: string, members: string[], readOnly = false, @@ -35,23 +35,12 @@ export const createPrivateGroupMethod = async ( > => { check(name, String); check(members, Match.Optional([String])); - if (!userId) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'createPrivateGroup', - }); - } - const user = await Users.findOneById(userId, { projection: { username: 1 } }); - if (!user) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'createPrivateGroup', - }); - } - if (!(await hasPermissionAsync(userId, 'create-p'))) { + if (!(await hasPermissionAsync(user._id, 'create-p'))) { throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createPrivateGroup' }); } - return createRoom('p', name, user.username, members, excludeSelf, readOnly, { + return createRoom('p', name, user, members, excludeSelf, readOnly, { customFields, ...extraData, }); @@ -67,6 +56,13 @@ Meteor.methods({ }); } - return createPrivateGroupMethod(uid, name, members, readOnly, customFields, extraData); + const user = await Users.findOneById(uid); + if (!user) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'createPrivateGroup', + }); + } + + return createPrivateGroupMethod(user, name, members, readOnly, customFields, extraData); }, }); diff --git a/apps/meteor/app/livechat/imports/server/rest/sms.js b/apps/meteor/app/livechat/imports/server/rest/sms.js index 6521c0f662dd..7ecb3b3fc100 100644 --- a/apps/meteor/app/livechat/imports/server/rest/sms.js +++ b/apps/meteor/app/livechat/imports/server/rest/sms.js @@ -56,7 +56,7 @@ const defineVisitor = async (smsNumber, targetDepartment) => { } const id = await LivechatTyped.registerGuest(data); - return LivechatVisitors.findOneById(id); + return LivechatVisitors.findOneEnabledById(id); }; const normalizeLocationSharing = (payload) => { diff --git a/apps/meteor/app/livechat/server/api/lib/visitors.ts b/apps/meteor/app/livechat/server/api/lib/visitors.ts index e559aecc892e..0abed5197d78 100644 --- a/apps/meteor/app/livechat/server/api/lib/visitors.ts +++ b/apps/meteor/app/livechat/server/api/lib/visitors.ts @@ -6,7 +6,7 @@ import { callbacks } from '../../../../../lib/callbacks'; import { canAccessRoomAsync } from '../../../../authorization/server/functions/canAccessRoom'; export async function findVisitorInfo({ visitorId }: { visitorId: IVisitor['_id'] }) { - const visitor = await LivechatVisitors.findOneById(visitorId); + const visitor = await LivechatVisitors.findOneEnabledById(visitorId); if (!visitor) { throw new Error('visitor-not-found'); } diff --git a/apps/meteor/app/livechat/server/api/v1/contact.ts b/apps/meteor/app/livechat/server/api/v1/contact.ts index 517acf33f137..57c1d117f1b0 100644 --- a/apps/meteor/app/livechat/server/api/v1/contact.ts +++ b/apps/meteor/app/livechat/server/api/v1/contact.ts @@ -33,7 +33,7 @@ API.v1.addRoute( contactId: String, }); - const contact = await LivechatVisitors.findOneById(this.queryParams.contactId); + const contact = await LivechatVisitors.findOneEnabledById(this.queryParams.contactId); return API.v1.success({ contact }); }, diff --git a/apps/meteor/app/livechat/server/api/v1/message.ts b/apps/meteor/app/livechat/server/api/v1/message.ts index 2b6f4c00af53..104e2ece94d5 100644 --- a/apps/meteor/app/livechat/server/api/v1/message.ts +++ b/apps/meteor/app/livechat/server/api/v1/message.ts @@ -269,7 +269,7 @@ API.v1.addRoute( guest.connectionData = normalizeHttpHeaderData(this.request.headers); const visitorId = await LivechatTyped.registerGuest(guest); - visitor = await LivechatVisitors.findOneById(visitorId); + visitor = await LivechatVisitors.findOneEnabledById(visitorId); } const sentMessages = await Promise.all( diff --git a/apps/meteor/app/livechat/server/api/v1/room.ts b/apps/meteor/app/livechat/server/api/v1/room.ts index 0fe60248bfba..86629e636bf8 100644 --- a/apps/meteor/app/livechat/server/api/v1/room.ts +++ b/apps/meteor/app/livechat/server/api/v1/room.ts @@ -326,7 +326,7 @@ API.v1.addRoute( throw new Error('This_conversation_is_already_closed'); } - const guest = await LivechatVisitors.findOneById(room.v?._id); + const guest = await LivechatVisitors.findOneEnabledById(room.v?._id); const transferedBy = this.user satisfies TransferByData; transferData.transferredBy = normalizeTransferredByData(transferedBy, room); if (transferData.userId) { diff --git a/apps/meteor/app/livechat/server/api/v1/visitor.ts b/apps/meteor/app/livechat/server/api/v1/visitor.ts index 012b412639ea..ae9d1ea4fd83 100644 --- a/apps/meteor/app/livechat/server/api/v1/visitor.ts +++ b/apps/meteor/app/livechat/server/api/v1/visitor.ts @@ -45,7 +45,7 @@ API.v1.addRoute('livechat/visitor', { const visitorId = await LivechatTyped.registerGuest(guest); - let visitor = await VisitorsRaw.findOneById(visitorId, {}); + let visitor = await VisitorsRaw.findOneEnabledById(visitorId, {}); if (visitor) { const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}); // If it's updating an existing visitor, it must also update the roomInfo @@ -65,7 +65,7 @@ API.v1.addRoute('livechat/visitor', { } } - visitor = await VisitorsRaw.findOneById(visitorId, {}); + visitor = await VisitorsRaw.findOneEnabledById(visitorId, {}); } if (!visitor) { @@ -122,7 +122,7 @@ API.v1.addRoute('livechat/visitor/:token', { const { _id } = visitor; const result = await Livechat.removeGuest(_id); - if (!result) { + if (!result.modifiedCount) { throw new Meteor.Error('error-removing-visitor', 'An error ocurred while deleting visitor'); } diff --git a/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts b/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts index 5ebf924e7334..ad68fcf5ce5c 100644 --- a/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts +++ b/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts @@ -1,6 +1,7 @@ import type { IOmnichannelRoom } from '@rocket.chat/core-typings'; import { isOmnichannelRoom, isEditedMessage } from '@rocket.chat/core-typings'; -import { LivechatRooms } from '@rocket.chat/models'; +import { LivechatRooms, LivechatVisitors } from '@rocket.chat/models'; +import moment from 'moment'; import { callbacks } from '../../../../lib/callbacks'; @@ -26,6 +27,19 @@ callbacks.add( return message; } + // Return YYYY-MM from moment + const monthYear = moment().format('YYYY-MM'); + const isVisitorActive = await LivechatVisitors.isVisitorActiveOnPeriod(room.v._id, monthYear); + if (!isVisitorActive) { + await LivechatVisitors.markVisitorActiveForPeriod(room.v._id, monthYear); + } + + await LivechatRooms.markVisitorActiveForPeriod(room._id, monthYear); + + if (room.responseBy) { + await LivechatRooms.setAgentLastMessageTs(room._id); + } + // check if room is yet awaiting for response from visitor if (!room.waitingResponse) { // case where agent sends second message or any subsequent message in a room before visitor responds to the first message diff --git a/apps/meteor/app/livechat/server/lib/Livechat.js b/apps/meteor/app/livechat/server/lib/Livechat.js index 52138740e295..ffd3a29b229f 100644 --- a/apps/meteor/app/livechat/server/lib/Livechat.js +++ b/apps/meteor/app/livechat/server/lib/Livechat.js @@ -298,7 +298,7 @@ export const Livechat = { async forwardOpenChats(userId) { Livechat.logger.debug(`Transferring open chats for user ${userId}`); for await (const room of LivechatRooms.findOpenByAgent(userId)) { - const guest = await LivechatVisitors.findOneById(room.v._id); + const guest = await LivechatVisitors.findOneEnabledById(room.v._id); const user = await Users.findOneById(userId); const { _id, username, name } = user; const transferredBy = normalizeTransferredByData({ _id, username, name }, room); @@ -462,7 +462,7 @@ export const Livechat = { }, async getLivechatRoomGuestInfo(room) { - const visitor = await LivechatVisitors.findOneById(room.v._id); + const visitor = await LivechatVisitors.findOneEnabledById(room.v._id); const agent = await Users.findOneById(room.servedBy && room.servedBy._id); const ua = new UAParser(); @@ -604,16 +604,15 @@ export const Livechat = { }, async removeGuest(_id) { - check(_id, String); - const guest = await LivechatVisitors.findOneById(_id, { projection: { _id: 1 } }); + const guest = await LivechatVisitors.findOneEnabledById(_id, { projection: { _id: 1, token: 1 } }); if (!guest) { throw new Meteor.Error('error-invalid-guest', 'Invalid guest', { method: 'livechat:removeGuest', }); } - await this.cleanGuestHistory(_id); - return LivechatVisitors.removeById(_id); + await this.cleanGuestHistory(guest); + return LivechatVisitors.disableById(_id); }, async setUserStatusLivechat(userId, status) { @@ -628,16 +627,13 @@ export const Livechat = { return user; }, - async cleanGuestHistory(_id) { - const guest = await LivechatVisitors.findOneById(_id); - if (!guest) { - throw new Meteor.Error('error-invalid-guest', 'Invalid guest', { - method: 'livechat:cleanGuestHistory', - }); - } - + async cleanGuestHistory(guest) { const { token } = guest; - check(token, String); + + // This shouldn't be possible, but just in case + if (!token) { + throw new Error('error-invalid-guest'); + } const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}); const cursor = LivechatRooms.findByVisitorToken(token, extraQuery); diff --git a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts index 1c60a257d319..c443bc7873c7 100644 --- a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts +++ b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts @@ -305,7 +305,7 @@ class LivechatClass { !(await LivechatDepartment.findOneById>(guest.department, { projection: { _id: 1 } })) ) { await LivechatVisitors.removeDepartmentById(guest._id); - const tmpGuest = await LivechatVisitors.findOneById(guest._id); + const tmpGuest = await LivechatVisitors.findOneEnabledById(guest._id); if (tmpGuest) { guest = tmpGuest; } diff --git a/apps/meteor/app/livechat/server/methods/transfer.ts b/apps/meteor/app/livechat/server/methods/transfer.ts index 2dc796fc6c94..3817b10bf42b 100644 --- a/apps/meteor/app/livechat/server/methods/transfer.ts +++ b/apps/meteor/app/livechat/server/methods/transfer.ts @@ -58,7 +58,7 @@ Meteor.methods({ }); } - const guest = await LivechatVisitors.findOneById(room.v?._id); + const guest = await LivechatVisitors.findOneEnabledById(room.v?._id); const user = await Meteor.userAsync(); diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts index 06c3014a8a56..f62ab71f2302 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts @@ -480,7 +480,6 @@ export class SAML { continue; } - const room = await Rooms.findOneByNameAndType(roomName, 'c', {}); const privRoom = await Rooms.findOneByNameAndType(roomName, 'p', {}); if (privRoom && includePrivateChannelsInUpdate === true) { @@ -488,6 +487,7 @@ export class SAML { continue; } + const room = await Rooms.findOneByNameAndType(roomName, 'c', {}); if (room) { await addUserToRoom(room._id, user); continue; @@ -496,7 +496,7 @@ export class SAML { if (!room && !privRoom) { // If the user doesn't have an username yet, we can't create new rooms for them if (user.username) { - await createRoom('c', roomName, user.username); + await createRoom('c', roomName, user); } } } diff --git a/apps/meteor/app/slashcommands-create/server/server.ts b/apps/meteor/app/slashcommands-create/server/server.ts index a3c70f012fa1..104d50c56926 100644 --- a/apps/meteor/app/slashcommands-create/server/server.ts +++ b/apps/meteor/app/slashcommands-create/server/server.ts @@ -1,6 +1,6 @@ import { api } from '@rocket.chat/core-services'; import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings'; -import { Rooms } from '@rocket.chat/models'; +import { Rooms, Users } from '@rocket.chat/models'; import { i18n } from '../../../server/lib/i18n'; import { createChannelMethod } from '../../lib/server/methods/createChannel'; @@ -50,7 +50,11 @@ slashCommands.add({ } if (getParams(params).indexOf('private') > -1) { - await createPrivateGroupMethod(userId, channelStr, []); + const user = await Users.findOneById(userId); + if (!user) { + return; + } + await createPrivateGroupMethod(user, channelStr, []); return; } diff --git a/apps/meteor/app/slashcommands-inviteall/server/server.ts b/apps/meteor/app/slashcommands-inviteall/server/server.ts index 9917775aca06..5376bd6ae64b 100644 --- a/apps/meteor/app/slashcommands-inviteall/server/server.ts +++ b/apps/meteor/app/slashcommands-inviteall/server/server.ts @@ -37,6 +37,9 @@ function inviteAll(type: T): SlashCommand['callback'] { } const user = await Users.findOneById(userId); + if (!user) { + return; + } const lng = user?.language || settings.get('Language') || 'en'; const baseChannel = type === 'to' ? await Rooms.findOneById(message.rid) : await Rooms.findOneByName(channel); @@ -69,7 +72,7 @@ function inviteAll(type: T): SlashCommand['callback'] { const users = (await cursor.toArray()).map((s: ISubscription) => s.u.username).filter(isTruthy); if (!targetChannel && ['c', 'p'].indexOf(baseChannel.t) > -1) { - baseChannel.t === 'c' ? await createChannelMethod(userId, channel, users) : await createPrivateGroupMethod(userId, channel, users); + baseChannel.t === 'c' ? await createChannelMethod(userId, channel, users) : await createPrivateGroupMethod(user, channel, users); void api.broadcast('notify.ephemeralMessage', userId, message.rid, { msg: i18n.t('Channel_created', { postProcess: 'sprintf', diff --git a/apps/meteor/app/statistics/server/lib/statistics.ts b/apps/meteor/app/statistics/server/lib/statistics.ts index b6b983d92fce..64543deb88a1 100644 --- a/apps/meteor/app/statistics/server/lib/statistics.ts +++ b/apps/meteor/app/statistics/server/lib/statistics.ts @@ -24,8 +24,10 @@ import { LivechatCustomField, Subscriptions, Users, + LivechatRooms, } from '@rocket.chat/models'; import { MongoInternals } from 'meteor/mongo'; +import moment from 'moment'; import { getStatistics as getEnterpriseStatistics } from '../../../../ee/app/license/server/getStatistics'; import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred'; @@ -99,6 +101,9 @@ export const statistics = { statistics.installedAt = uniqueID.createdAt.toISOString(); } + statistics.deploymentFingerprintHash = settings.get('Deployment_FingerPrint_Hash'); + statistics.deploymentFingerprintVerified = settings.get('Deployment_FingerPrint_Verified'); + if (Info) { statistics.version = Info.version; statistics.tag = Info.tag; @@ -269,6 +274,36 @@ export const statistics = { }), ); + const defaultValue = { contactsCount: 0, conversationsCount: 0, sources: [] }; + const billablePeriod = moment.utc().format('YYYY-MM'); + statsPms.push( + LivechatRooms.getMACStatisticsForPeriod(billablePeriod).then(([result]) => { + statistics.omnichannelContactsBySource = result || defaultValue; + }), + ); + + const monthAgo = moment.utc().subtract(30, 'days').toDate(); + const today = moment.utc().toDate(); + statsPms.push( + LivechatRooms.getMACStatisticsBetweenDates(monthAgo, today).then(([result]) => { + statistics.uniqueContactsOfLastMonth = result || defaultValue; + }), + ); + + const weekAgo = moment.utc().subtract(7, 'days').toDate(); + statsPms.push( + LivechatRooms.getMACStatisticsBetweenDates(weekAgo, today).then(([result]) => { + statistics.uniqueContactsOfLastWeek = result || defaultValue; + }), + ); + + const yesterday = moment.utc().subtract(1, 'days').toDate(); + statsPms.push( + LivechatRooms.getMACStatisticsBetweenDates(yesterday, today).then(([result]) => { + statistics.uniqueContactsOfYesterday = result || defaultValue; + }), + ); + // Message statistics statistics.totalChannelMessages = (await Rooms.findByType('c', { projection: { msgs: 1 } }).toArray()).reduce( function _countChannelMessages(num: number, room: IRoom) { @@ -517,6 +552,15 @@ export const statistics = { statistics.totalWebRTCCalls = settings.get('WebRTC_Calls_Count'); statistics.uncaughtExceptionsCount = settings.get('Uncaught_Exceptions_Count'); + const defaultGateway = (await Settings.findOneById('Push_gateway', { projection: { packageValue: 1 } }))?.packageValue; + + // one bit for each of the following: + const pushEnabled = settings.get('Push_enable') ? 1 : 0; + const pushGatewayEnabled = settings.get('Push_enable_gateway') ? 2 : 0; + const pushGatewayChanged = settings.get('Push_gateway') !== defaultGateway ? 4 : 0; + + statistics.push = pushEnabled | pushGatewayEnabled | pushGatewayChanged; + const defaultHomeTitle = (await Settings.findOneById('Layout_Home_Title'))?.packageValue; statistics.homeTitleChanged = settings.get('Layout_Home_Title') !== defaultHomeTitle; diff --git a/apps/meteor/app/theme/client/imports/general/base.css b/apps/meteor/app/theme/client/imports/general/base.css index 311327fb6f73..d1f4b8d11fb6 100644 --- a/apps/meteor/app/theme/client/imports/general/base.css +++ b/apps/meteor/app/theme/client/imports/general/base.css @@ -52,12 +52,6 @@ body { a { cursor: pointer; - text-decoration: none; - - &:hover, - &:active { - text-decoration: none; - } } button { diff --git a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts index 4609797e6bd2..a926f8540d27 100644 --- a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts +++ b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts @@ -48,13 +48,15 @@ export const createComposerAPI = (input: HTMLTextAreaElement, storageID: string) text: string, { selection, + skipFocus, }: { selection?: | { readonly start?: number; readonly end?: number } | ((previous: { readonly start: number; readonly end: number }) => { readonly start?: number; readonly end?: number }); + skipFocus?: boolean; } = {}, ): void => { - focus(); + !skipFocus && focus(); const { selectionStart, selectionEnd } = input; const textAreaTxt = input.value; @@ -66,7 +68,7 @@ export const createComposerAPI = (input: HTMLTextAreaElement, storageID: string) if (selection) { if (!document.execCommand?.('insertText', false, text)) { input.value = textAreaTxt.substring(0, selectionStart) + text + textAreaTxt.substring(selectionStart); - focus(); + !skipFocus && focus(); } input.setSelectionRange(selection.start ?? 0, selection.end ?? text.length); } @@ -78,7 +80,7 @@ export const createComposerAPI = (input: HTMLTextAreaElement, storageID: string) triggerEvent(input, 'input'); triggerEvent(input, 'change'); - focus(); + !skipFocus && focus(); }; const insertText = (text: string): void => { @@ -260,7 +262,9 @@ export const createComposerAPI = (input: HTMLTextAreaElement, storageID: string) const insertNewLine = (): void => insertText('\n'); - setText(Meteor._localStorage.getItem(storageID) ?? ''); + setText(Meteor._localStorage.getItem(storageID) ?? '', { + skipFocus: true, + }); // Gets the text that is connected to the cursor and replaces it with the given text const replaceText = (text: string, selection: { readonly start: number; readonly end: number }): void => { diff --git a/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts b/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts index 5618442ee6da..5807673188e5 100644 --- a/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts +++ b/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts @@ -29,7 +29,7 @@ Meteor.startup(async () => { id: 'reply-directly', icon: 'reply-directly', label: 'Reply_in_direct_message', - context: ['message', 'message-mobile', 'threads', 'federated', 'videoconf', 'videoconf-threads'], + context: ['message', 'message-mobile', 'threads', 'federated'], role: 'link', type: 'communication', action(_, props) { @@ -122,7 +122,7 @@ Meteor.startup(async () => { icon: 'permalink', label: 'Copy_link', // classes: 'clipboard', - context: ['message', 'message-mobile', 'threads', 'federated'], + context: ['message', 'message-mobile', 'threads', 'federated', 'videoconf', 'videoconf-threads'], type: 'duplication', async action(_, props) { try { @@ -208,7 +208,7 @@ Meteor.startup(async () => { id: 'delete-message', icon: 'trash', label: 'Delete', - context: ['message', 'message-mobile', 'threads', 'federated'], + context: ['message', 'message-mobile', 'threads', 'federated', 'videoconf', 'videoconf-threads'], color: 'alert', type: 'management', async action(this: unknown, _, { message = messageArgs(this).msg, chat }) { @@ -236,7 +236,7 @@ Meteor.startup(async () => { id: 'report-message', icon: 'report', label: 'Report', - context: ['message', 'message-mobile', 'threads', 'federated'], + context: ['message', 'message-mobile', 'threads', 'federated', 'videoconf', 'videoconf-threads'], color: 'alert', type: 'management', action(this: unknown, _, { message = messageArgs(this).msg }) { @@ -264,7 +264,7 @@ Meteor.startup(async () => { id: 'reaction-list', icon: 'emoji', label: 'Reactions', - context: ['message', 'message-mobile', 'threads'], + context: ['message', 'message-mobile', 'threads', 'videoconf', 'videoconf-threads'], type: 'interaction', action(this: unknown, _, { message: { reactions = {} } = messageArgs(this).msg }) { imperativeModal.open({ diff --git a/apps/meteor/app/utils/lib/getDefaultSubscriptionPref.ts b/apps/meteor/app/utils/lib/getDefaultSubscriptionPref.ts index a388548c18a8..adb4c2ab1ae9 100644 --- a/apps/meteor/app/utils/lib/getDefaultSubscriptionPref.ts +++ b/apps/meteor/app/utils/lib/getDefaultSubscriptionPref.ts @@ -1,4 +1,4 @@ -import type { ISubscription, IUser } from '@rocket.chat/core-typings'; +import type { AtLeast, ISubscription, IUser } from '@rocket.chat/core-typings'; /** * @type {(userPref: Pick) => { @@ -7,7 +7,7 @@ import type { ISubscription, IUser } from '@rocket.chat/core-typings'; * emailPrefOrigin: 'user'; * }} */ -export const getDefaultSubscriptionPref = (userPref: IUser) => { +export const getDefaultSubscriptionPref = (userPref: AtLeast) => { const subscription: Partial = {}; const { desktopNotifications, pushNotifications, emailNotificationMode, highlights } = userPref.settings?.preferences || {}; diff --git a/apps/meteor/client/components/AutoCompleteDepartmentMultiple.tsx b/apps/meteor/client/components/AutoCompleteDepartmentMultiple.tsx index 50d53da351bc..38aadf0a840b 100644 --- a/apps/meteor/client/components/AutoCompleteDepartmentMultiple.tsx +++ b/apps/meteor/client/components/AutoCompleteDepartmentMultiple.tsx @@ -17,7 +17,7 @@ type AutoCompleteDepartmentMultipleProps = { }; const AutoCompleteDepartmentMultiple = ({ - value, + value = [], onlyMyDepartments = false, showArchived = false, enabled = false, @@ -37,6 +37,11 @@ const AutoCompleteDepartmentMultiple = ({ const { phase: departmentsPhase, items: departmentsItems, itemCount: departmentsTotal } = useRecordList(departmentsList); + const departmentOptions = useMemo(() => { + const pending = value.filter(({ value }) => !departmentsItems.find((dep) => dep.value === value)) || []; + return [...departmentsItems, ...pending]; + }, [departmentsItems, value]); + return ( - {t('Discussion_description')} + {t('Discussion_description')} - {t('Discussion_target_channel')} - + {t('Discussion_target_channel')} + {defaultParentRoom && ( )} - - {errors.parentRoom && {errors.parentRoom.message}} + + {errors.parentRoom && {errors.parentRoom.message}} - {t('Encrypted')} + {t('Encrypted')} - {t('Discussion_name')} - + {t('Discussion_name')} + } /> - - {errors.name && {errors.name.message}} + + {errors.name && {errors.name.message}} - {t('Invite_Users')} - + {t('Invite_Users')} + )} /> - + - {t('Discussion_first_message_title')} - + {t('Discussion_first_message_title')} + - - {encrypted && {t('Discussion_first_message_disabled_due_to_e2e')}} + + {encrypted && {t('Discussion_first_message_disabled_due_to_e2e')}} diff --git a/apps/meteor/client/components/FingerprintChangeModal.tsx b/apps/meteor/client/components/FingerprintChangeModal.tsx new file mode 100644 index 000000000000..db4c33654a92 --- /dev/null +++ b/apps/meteor/client/components/FingerprintChangeModal.tsx @@ -0,0 +1,44 @@ +import { Box } from '@rocket.chat/fuselage'; +import { useTranslation } from '@rocket.chat/ui-contexts'; +import type { ReactElement } from 'react'; +import React from 'react'; + +import GenericModal from './GenericModal'; + +type FingerprintChangeModalProps = { + onConfirm: () => void; + onCancel: () => void; + onClose: () => void; +}; + +const FingerprintChangeModal = ({ onConfirm, onCancel, onClose }: FingerprintChangeModalProps): ReactElement => { + const t = useTranslation(); + return ( + + + + + ); +}; + +export default FingerprintChangeModal; diff --git a/apps/meteor/client/components/FingerprintChangeModalConfirmation.tsx b/apps/meteor/client/components/FingerprintChangeModalConfirmation.tsx new file mode 100644 index 000000000000..77718de0f441 --- /dev/null +++ b/apps/meteor/client/components/FingerprintChangeModalConfirmation.tsx @@ -0,0 +1,47 @@ +import { Box } from '@rocket.chat/fuselage'; +import { useTranslation } from '@rocket.chat/ui-contexts'; +import type { ReactElement } from 'react'; +import React from 'react'; + +import GenericModal from './GenericModal'; + +type FingerprintChangeModalConfirmationProps = { + onConfirm: () => void; + onCancel: () => void; + newWorkspace: boolean; +}; + +const FingerprintChangeModalConfirmation = ({ + onConfirm, + onCancel, + newWorkspace, +}: FingerprintChangeModalConfirmationProps): ReactElement => { + const t = useTranslation(); + return ( + + + + + ); +}; + +export default FingerprintChangeModalConfirmation; diff --git a/apps/meteor/client/components/Omnichannel/Tags.tsx b/apps/meteor/client/components/Omnichannel/Tags.tsx index 39564ca7f89f..88f5f1a5c6e7 100644 --- a/apps/meteor/client/components/Omnichannel/Tags.tsx +++ b/apps/meteor/client/components/Omnichannel/Tags.tsx @@ -1,4 +1,4 @@ -import { Field, TextInput, Chip, Button } from '@rocket.chat/fuselage'; +import { TextInput, Chip, Button, FieldLabel, FieldRow } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ChangeEvent, ReactElement } from 'react'; @@ -71,12 +71,12 @@ const Tags = ({ tags = [], handler, error, tagRequired, department }: TagsProps) return ( <> - + {t('Tags')} - + {EETagsComponent && tagsResult?.tags && tagsResult?.tags.length ? ( - + { @@ -85,10 +85,10 @@ const Tags = ({ tags = [], handler, error, tagRequired, department }: TagsProps) department={department} viewAll={!department} /> - + ) : ( <> - + {t('Add')} - + )} {customTags.length > 0 && ( - + {customTags?.map((tag, i) => ( removeTag(tag)} mie={8}> {tag} ))} - + )} ); diff --git a/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx b/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx index 17cbc094160b..67d650186680 100644 --- a/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx +++ b/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx @@ -1,5 +1,18 @@ import type { ILivechatDepartment } from '@rocket.chat/core-typings'; -import { Field, FieldGroup, Button, TextInput, Modal, Box, CheckBox, Divider, EmailInput } from '@rocket.chat/fuselage'; +import { + Field, + FieldGroup, + Button, + TextInput, + Modal, + Box, + CheckBox, + Divider, + EmailInput, + FieldLabel, + FieldRow, + FieldError, +} from '@rocket.chat/fuselage'; import { usePermission, useSetting, useTranslation, useUserPreference } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { useCallback, useState, useEffect, useMemo } from 'react'; @@ -134,8 +147,8 @@ const CloseChatModal = ({ {t('Close_room_description')} - {t('Comment')} - + {t('Comment')} + - - {errors.comment?.message} + + {errors.comment?.message} - {errors.tags?.message} + {errors.tags?.message} {canSendTranscript && ( <> - {t('Chat_transcript')} + {t('Chat_transcript')} {canSendTranscriptPDF && ( - + - + {t('Omnichannel_transcript_pdf')} - - + + )} {canSendTranscriptEmail && ( <> - + - + {t('Omnichannel_transcript_email')} - - + + {transcriptEmail && ( <> - {t('Contact_email')} - + {t('Contact_email')} + - + - {t('Subject')} - + {t('Subject')} + - - {errors.subject?.message} + + {errors.subject?.message} )} )} - + {canSendTranscriptPDF && canSendTranscriptEmail ? t('These_options_affect_this_conversation_only_To_set_default_selections_go_to_My_Account_Omnichannel') : t('This_option_affect_this_conversation_only_To_set_default_selection_go_to_My_Account_Omnichannel')} - + )} diff --git a/apps/meteor/client/components/Omnichannel/modals/ForwardChatModal.tsx b/apps/meteor/client/components/Omnichannel/modals/ForwardChatModal.tsx index 82c92d39cc8f..bdbde6b05acd 100644 --- a/apps/meteor/client/components/Omnichannel/modals/ForwardChatModal.tsx +++ b/apps/meteor/client/components/Omnichannel/modals/ForwardChatModal.tsx @@ -1,5 +1,16 @@ import type { IOmnichannelRoom } from '@rocket.chat/core-typings'; -import { Field, FieldGroup, Button, TextAreaInput, Modal, Box, PaginatedSelectFiltered, Divider } from '@rocket.chat/fuselage'; +import { + Field, + FieldGroup, + Button, + TextAreaInput, + Modal, + Box, + PaginatedSelectFiltered, + Divider, + FieldLabel, + FieldRow, +} from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { useEndpoint, useSetting, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -66,7 +77,7 @@ const ForwardChatModal = ({ const endReached = useCallback( (start) => { - if (departmentsPhase === AsyncStatePhase.LOADING) { + if (departmentsPhase !== AsyncStatePhase.LOADING) { loadMoreDepartments(start, Math.min(50, departmentsTotal)); } }, @@ -102,8 +113,8 @@ const ForwardChatModal = ({ - {t('Forward_to_department')} - + {t('Forward_to_department')} + - + - {t('Forward_to_user')} - + {t('Forward_to_user')} + - + - + {t('Leave_a_comment')}{' '} ({t('Optional')}) - - + + - + diff --git a/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx index e879caf38032..2757b5d9a88b 100644 --- a/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx +++ b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx @@ -1,5 +1,5 @@ import type { IOmnichannelRoom } from '@rocket.chat/core-typings'; -import { Field, Button, TextInput, Modal, Box, FieldGroup } from '@rocket.chat/fuselage'; +import { Field, Button, TextInput, Modal, Box, FieldGroup, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FC } from 'react'; import React, { useCallback, useEffect } from 'react'; @@ -78,28 +78,28 @@ const TranscriptModal: FC = ({ {!!transcriptRequest &&

{t('Livechat_transcript_already_requested_warning')}

} - {t('Email')}* - + {t('Email')}* + - - {errors.email?.message} + + {errors.email?.message} - {t('Subject')}* - + {t('Subject')}* + - - {errors.subject?.message} + + {errors.subject?.message} diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx index 1b7936cafd3e..19074f7f6b34 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx @@ -1,4 +1,4 @@ -import { Box, FieldGroup, TextInput, Field } from '@rocket.chat/fuselage'; +import { Box, FieldGroup, TextInput, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useAutoFocus, useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, ChangeEvent, SyntheticEvent } from 'react'; @@ -59,13 +59,13 @@ const TwoFactorEmailModal = ({ onConfirm, onClose, emailOrUsername, invalidAttem > - + {t('Verify_your_email_with_the_code_we_sent')} - - + + - - {invalidAttempt && {t('Invalid_password')}} + + {invalidAttempt && {t('Invalid_password')}} diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx index 3d604fc5004b..4c91e274de68 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx @@ -1,4 +1,4 @@ -import { Box, PasswordInput, FieldGroup, Field } from '@rocket.chat/fuselage'; +import { Box, PasswordInput, FieldGroup, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useAutoFocus, useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, ChangeEvent, Ref, SyntheticEvent } from 'react'; @@ -43,10 +43,10 @@ const TwoFactorPasswordModal = ({ onConfirm, onClose, invalidAttempt }: TwoFacto > - + {t('For_your_security_you_must_enter_your_current_password_to_continue')} - - + + } @@ -54,8 +54,8 @@ const TwoFactorPasswordModal = ({ onConfirm, onClose, invalidAttempt }: TwoFacto onChange={onChange} placeholder={t('Password')} > - - {invalidAttempt && {t('Invalid_password')}} + + {invalidAttempt && {t('Invalid_password')}} diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx index 266e92586944..04aa7a4f94f0 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx @@ -1,4 +1,4 @@ -import { Box, TextInput, Field, FieldGroup } from '@rocket.chat/fuselage'; +import { Box, TextInput, Field, FieldGroup, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useAutoFocus, useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, ChangeEvent, SyntheticEvent } from 'react'; @@ -42,13 +42,13 @@ const TwoFactorTotpModal = ({ onConfirm, onClose, invalidAttempt }: TwoFactorTot > - + {t('Open_your_authentication_app_and_enter_the_code')} - - + + - - {invalidAttempt && {t('Invalid_password')}} + + {invalidAttempt && {t('Invalid_password')}} diff --git a/apps/meteor/client/components/UserAndRoomAutoCompleteMultiple/UserAndRoomAutoCompleteMultiple.tsx b/apps/meteor/client/components/UserAndRoomAutoCompleteMultiple/UserAndRoomAutoCompleteMultiple.tsx index 96d11cf44cb7..f96c198865cc 100644 --- a/apps/meteor/client/components/UserAndRoomAutoCompleteMultiple/UserAndRoomAutoCompleteMultiple.tsx +++ b/apps/meteor/client/components/UserAndRoomAutoCompleteMultiple/UserAndRoomAutoCompleteMultiple.tsx @@ -18,7 +18,16 @@ const UserAndRoomAutoCompleteMultiple = ({ value, onChange, ...props }: UserAndR const debouncedFilter = useDebouncedValue(filter, 1000); const rooms = useUserSubscriptions( - useMemo(() => ({ open: { $ne: false }, lowerCaseName: new RegExp(escapeRegExp(debouncedFilter), 'i') }), [debouncedFilter]), + useMemo( + () => ({ + open: { $ne: false }, + $or: [ + { lowerCaseFName: new RegExp(escapeRegExp(debouncedFilter), 'i') }, + { lowerCaseName: new RegExp(escapeRegExp(debouncedFilter), 'i') }, + ], + }), + [debouncedFilter], + ), ).filter((room) => { if (!user) { return; diff --git a/apps/meteor/client/providers/TranslationProvider.tsx b/apps/meteor/client/providers/TranslationProvider.tsx index fdddb9ec5349..2cf47066c4e4 100644 --- a/apps/meteor/client/providers/TranslationProvider.tsx +++ b/apps/meteor/client/providers/TranslationProvider.tsx @@ -2,7 +2,7 @@ import { useLocalStorage, useMutableCallback } from '@rocket.chat/fuselage-hooks import languages from '@rocket.chat/i18n/dist/languages'; import en from '@rocket.chat/i18n/src/locales/en.i18n.json'; import type { TranslationKey, TranslationContextValue } from '@rocket.chat/ui-contexts'; -import { useMethod, useSetting, TranslationContext, useAbsoluteUrl } from '@rocket.chat/ui-contexts'; +import { useMethod, useSetting, TranslationContext } from '@rocket.chat/ui-contexts'; import type i18next from 'i18next'; import I18NextHttpBackend from 'i18next-http-backend'; import sprintf from 'i18next-sprintf-postprocessor'; @@ -12,6 +12,7 @@ import React, { useEffect, useMemo } from 'react'; import { I18nextProvider, initReactI18next, useTranslation } from 'react-i18next'; import { CachedCollectionManager } from '../../app/ui-cached-collection/client'; +import { getURL } from '../../app/utils/client'; import { i18n, addSprinfToI18n } from '../../app/utils/lib/i18n'; import { AppClientOrchestratorInstance } from '../../ee/client/apps/orchestrator'; import { applyCustomTranslations } from '../lib/utils/applyCustomTranslations'; @@ -39,8 +40,6 @@ const parseToJSON = (customTranslations: string): Record>(); const useI18next = (lng: string): typeof i18next => { - const basePath = useAbsoluteUrl()('/i18n'); - const customTranslations = useSetting('Custom_Translations'); const parsedCustomTranslations = useMemo(() => { @@ -79,6 +78,11 @@ const useI18next = (lng: string): typeof i18next => { if (prefix) { result[key.slice(prefix.length + 1)] = value; + continue; + } + + if (Array.isArray(namespaces) ? namespaces.includes('core') : namespaces === 'core') { + result[key] = value; } } } @@ -100,17 +104,18 @@ const useI18next = (lng: string): typeof i18next => { partialBundledLanguages: true, defaultNS: 'core', backend: { - loadPath: `${basePath}/{{lng}}.json`, + loadPath: 'i18n/{{lng}}.json', parse: (data: string, lngs?: string | string[], namespaces: string | string[] = []) => extractKeys(JSON.parse(data), lngs, namespaces), request: (_options, url, _payload, callback) => { const params = url.split('/'); + const lng = params[params.length - 1]; let promise = localeCache.get(lng); if (!promise) { - promise = fetch(url).then((res) => res.text()); + promise = fetch(getURL(url)).then((res) => res.text()); localeCache.set(lng, promise); } diff --git a/apps/meteor/client/sidebar/Sidebar.tsx b/apps/meteor/client/sidebar/Sidebar.tsx index 9c7634872ed4..84c63eac01be 100644 --- a/apps/meteor/client/sidebar/Sidebar.tsx +++ b/apps/meteor/client/sidebar/Sidebar.tsx @@ -22,6 +22,9 @@ const Sidebar = () => { const sideBarBackground = css` background-color: ${Palette.surface['surface-tint']}; + a { + text-decoration: none; + } `; return ( diff --git a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx index 57ebffdbcf39..3f001b158d72 100644 --- a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx +++ b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx @@ -1,4 +1,18 @@ -import { Box, Modal, Button, TextInput, Icon, Field, ToggleSwitch, FieldGroup } from '@rocket.chat/fuselage'; +import { + Box, + Modal, + Button, + TextInput, + Icon, + Field, + ToggleSwitch, + FieldGroup, + FieldLabel, + FieldRow, + FieldError, + FieldHint, + FieldDescription, +} from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { @@ -194,10 +208,10 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): - + {t('Channel_name')} - - + + - + {errors.name && ( - + {errors.name.message} - + )} - {t('Topic')} - + {t('Topic')} + - - {t('Channel_what_is_this_channel_about')} + + {t('Channel_what_is_this_channel_about')} - {t('Private')} - + {t('Private')} + {isPrivate ? t('Only_invited_users_can_acess_this_channel') : t('Everyone_can_access_this_channel')} - + - {t('Federation_Matrix_Federated')} - {t(getFederationHintKey(federatedModule, federationEnabled))} + {t('Federation_Matrix_Federated')} + {t(getFederationHintKey(federatedModule, federationEnabled))} - {t('Read_only')} - + {t('Read_only')} + {readOnly ? t('Only_authorized_users_can_write_new_messages') : t('All_users_in_the_channel_can_write_new_messages')} - + - {t('Encrypted')} - + {t('Encrypted')} + {isPrivate ? t('Encrypted_channel_Description') : t('Encrypted_not_available')} - + - {t('Broadcast')} - {t('Broadcast_channel_Description')} + {t('Broadcast')} + {t('Broadcast_channel_Description')} - {t('Add_members')} + {t('Add_members')} void }): ReactElement => - + {t('Teams_New_Name_Label')} - - + + void }): ReactElement => aria-describedby={`${nameId}-error`} aria-required='true' /> - + {errors?.name && ( - + {errors.name.message} - + )} - + {t('Teams_New_Description_Label')}{' '} ({t('optional')}) - - + + - + - {t('Teams_New_Private_Label')} - + {t('Teams_New_Private_Label')} + {isPrivate ? t('Teams_New_Private_Description_Enabled') : t('Teams_New_Private_Description_Disabled')} - + void }): ReactElement => - {t('Teams_New_Read_only_Label')} - + {t('Teams_New_Read_only_Label')} + {readOnly ? t('Only_authorized_users_can_write_new_messages') : t('Teams_New_Read_only_Description')} - + void }): ReactElement => - {t('Teams_New_Encrypted_Label')} - + {t('Teams_New_Encrypted_Label')} + {isPrivate ? t('Teams_New_Encrypted_Description_Enabled') : t('Teams_New_Encrypted_Description_Disabled')} - + void }): ReactElement => - {t('Teams_New_Broadcast_Label')} - {t('Teams_New_Broadcast_Description')} + {t('Teams_New_Broadcast_Label')} + {t('Teams_New_Broadcast_Description')} void }): ReactElement => - + {t('Teams_New_Add_members_Label')}{' '} ({t('optional')}) - + - {t('StatusMessage')} - + {t('StatusMessage')} + } /> - - {!allowUserStatusMessageChange && {t('StatusMessage_Change_Disabled')}} - {statusTextError} + + {!allowUserStatusMessageChange && {t('StatusMessage_Change_Disabled')}} + {statusTextError} diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx index a0f90a7d2f2f..6ea69ce6c037 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx @@ -1,4 +1,16 @@ -import { Divider, Modal, ButtonGroup, Button, Field, TextInput, Throbber } from '@rocket.chat/fuselage'; +import { + Divider, + Modal, + ButtonGroup, + Button, + Field, + TextInput, + Throbber, + FieldLabel, + FieldRow, + FieldError, + FieldHint, +} from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useSetModal, useTranslation, useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import { useMutation, useQueryClient } from '@tanstack/react-query'; @@ -63,8 +75,8 @@ const MatrixFederationAddServerModal: VFC = - {t('Server_name')} - + {t('Server_name')} + = {!isLoading && t('Add')} {isLoading && } - - {isError && errorKey && {t(errorKey)}} - {t('Federation_Example_matrix_server')} + + {isError && errorKey && {t(errorKey)}} + {t('Federation_Example_matrix_server')} {!isLoadingServerList && data?.servers && } diff --git a/apps/meteor/client/startup/rootUrlChange.ts b/apps/meteor/client/startup/rootUrlChange.ts index 45f98634a373..4e42874eba4a 100644 --- a/apps/meteor/client/startup/rootUrlChange.ts +++ b/apps/meteor/client/startup/rootUrlChange.ts @@ -6,6 +6,8 @@ import { Roles } from '../../app/models/client'; import { settings } from '../../app/settings/client'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { t } from '../../app/utils/lib/i18n'; +import FingerprintChangeModal from '../components/FingerprintChangeModal'; +import FingerprintChangeModalConfirmation from '../components/FingerprintChangeModalConfirmation'; import UrlChangeModal from '../components/UrlChangeModal'; import { imperativeModal } from '../lib/imperativeModal'; import { dispatchToastMessage } from '../lib/toast'; @@ -58,3 +60,72 @@ Meteor.startup(() => { return c.stop(); }); }); + +Meteor.startup(() => { + Tracker.autorun((c) => { + const userId = Meteor.userId(); + if (!userId) { + return; + } + + if (!Roles.ready.get() || !isSyncReady.get()) { + return; + } + + if (hasRole(userId, 'admin') === false) { + return c.stop(); + } + + const deploymentFingerPrintVerified = settings.get('Deployment_FingerPrint_Verified'); + if (deploymentFingerPrintVerified == null || deploymentFingerPrintVerified === true) { + return; + } + + const updateWorkspace = (): void => { + imperativeModal.close(); + void sdk.rest.post('/v1/fingerprint', { setDeploymentAs: 'updated-configuration' }).then(() => { + dispatchToastMessage({ type: 'success', message: t('Configuration_update_confirmed') }); + }); + }; + + const setNewWorkspace = (): void => { + imperativeModal.close(); + void sdk.rest.post('/v1/fingerprint', { setDeploymentAs: 'new-workspace' }).then(() => { + dispatchToastMessage({ type: 'success', message: t('New_workspace_confirmed') }); + }); + }; + + const openModal = (): void => { + imperativeModal.open({ + component: FingerprintChangeModal, + props: { + onConfirm: () => { + imperativeModal.open({ + component: FingerprintChangeModalConfirmation, + props: { + onConfirm: setNewWorkspace, + onCancel: openModal, + newWorkspace: true, + }, + }); + }, + onCancel: () => { + imperativeModal.open({ + component: FingerprintChangeModalConfirmation, + props: { + onConfirm: updateWorkspace, + onCancel: openModal, + newWorkspace: false, + }, + }); + }, + onClose: imperativeModal.close, + }, + }); + }; + + openModal(); + + return c.stop(); + }); +}); diff --git a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx index ceb904613533..657548d5a1b9 100644 --- a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx +++ b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx @@ -38,8 +38,9 @@ const AccessibilityPage = () => { const t = useTranslation(); const setModal = useSetModal(); const dispatchToastMessage = useToastMessageDispatch(); - const { data: license } = useIsEnterprise(); const preferencesValues = useAccessiblityPreferencesValues(); + const { data: license } = useIsEnterprise(); + const isEnterprise = license?.isEnterprise; const { themeAppearence } = preferencesValues; const [, setPrevTheme] = useLocalStorage('prevTheme', themeAppearence); @@ -102,14 +103,14 @@ const AccessibilityPage = () => { {themes.map(({ id, title, description, ...item }, index) => { - const communityDisabled = 'isEEOnly' in item && item.isEEOnly && !license?.isEnterprise; + const showCommunityUpsellTriggers = 'isEEOnly' in item && item.isEEOnly && !isEnterprise; return ( {t.has(title) ? t(title) : title} - {communityDisabled && ( + {showCommunityUpsellTriggers && ( @@ -123,7 +124,7 @@ const AccessibilityPage = () => { control={control} name='themeAppearence' render={({ field: { onChange, value, ref } }) => { - if (communityDisabled) { + if (showCommunityUpsellTriggers) { return ( { {t('Mentions_with_@_symbol')} - - - - {t('Enterprise')} - - + {!isEnterprise && ( + + + + {t('Enterprise')} + + + )} - {license?.isEnterprise ? ( + {isEnterprise ? ( void }) => if (!isAdmin) { return ( ); } return ( { - {t(feature.i18n)} - + {t(feature.i18n)} + - + - {feature.description && {t(feature.description)}} + {feature.description && {t(feature.description)}} {feature.imageUrl && } diff --git a/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx b/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx index 71d025d792cd..54806d879aa1 100644 --- a/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx +++ b/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx @@ -1,6 +1,6 @@ import type { IWebdavAccountIntegration } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; -import { SelectLegacy, Box, Field, Button } from '@rocket.chat/fuselage'; +import { SelectLegacy, Box, Button, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useEndpoint, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -38,8 +38,8 @@ const AccountIntegrationsPage = (): ReactElement => { - {t('WebDAV_Accounts')} - + {t('WebDAV_Accounts')} + { - + diff --git a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx index fb1903806fec..9fccaef4593e 100644 --- a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx +++ b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx @@ -1,4 +1,4 @@ -import { Accordion, Box, Field, FieldGroup, Tag, ToggleSwitch } from '@rocket.chat/fuselage'; +import { Accordion, Box, Field, FieldGroup, FieldLabel, FieldRow, FieldHint, Tag, ToggleSwitch } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation, usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; @@ -24,7 +24,7 @@ const PreferencesConversationTranscript = () => { - + {t('Omnichannel_transcript_pdf')} @@ -32,16 +32,16 @@ const PreferencesConversationTranscript = () => { {!canSendTranscriptPDF && hasLicense && {t('No_permission')}} - - + + - + - {t('Accounts_Default_User_Preferences_omnichannelTranscriptPDF_Description')} + {t('Accounts_Default_User_Preferences_omnichannelTranscriptPDF_Description')} - + {t('Omnichannel_transcript_email')} {!canSendTranscriptEmail && ( @@ -50,16 +50,16 @@ const PreferencesConversationTranscript = () => { )} - - + + - + - {t('Accounts_Default_User_Preferences_omnichannelTranscriptEmail_Description')} + {t('Accounts_Default_User_Preferences_omnichannelTranscriptEmail_Description')} diff --git a/apps/meteor/client/views/account/preferences/PreferencesGlobalSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesGlobalSection.tsx index 4e616072d185..d09492fdc5a6 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesGlobalSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesGlobalSection.tsx @@ -1,5 +1,5 @@ import type { SelectOption } from '@rocket.chat/fuselage'; -import { Accordion, Field, FieldGroup, MultiSelect } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldGroup, FieldLabel, FieldRow, MultiSelect } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useUserPreference, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; @@ -18,8 +18,8 @@ const PreferencesGlobalSection = () => { - {t('Dont_ask_me_again_list')} - + {t('Dont_ask_me_again_list')} + { )} /> - + diff --git a/apps/meteor/client/views/account/preferences/PreferencesHighlightsSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesHighlightsSection.tsx index 8c05a92bad47..85bfc9072b12 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesHighlightsSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesHighlightsSection.tsx @@ -1,4 +1,4 @@ -import { Accordion, Field, FieldGroup, TextAreaInput } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldGroup, FieldLabel, FieldRow, FieldHint, TextAreaInput } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; @@ -14,11 +14,11 @@ const PreferencesHighlightsSection = () => { - {t('Highlights_List')} - + {t('Highlights_List')} + - - {t('Highlights_How_To')} + + {t('Highlights_How_To')} diff --git a/apps/meteor/client/views/account/preferences/PreferencesLocalizationSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesLocalizationSection.tsx index 2faaa9da89c2..0dc6e25f1ac3 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesLocalizationSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesLocalizationSection.tsx @@ -1,5 +1,5 @@ import type { SelectOption } from '@rocket.chat/fuselage'; -import { Accordion, Field, Select, FieldGroup } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldGroup, FieldLabel, FieldRow, Select } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useLanguages, useTranslation } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; @@ -23,8 +23,8 @@ const PreferencesLocalizationSection = () => { - {t('Language')} - + {t('Language')} + { )} /> - - {t('Enter_Behaviour_Description')} + + {t('Enter_Behaviour_Description')} diff --git a/apps/meteor/client/views/account/preferences/PreferencesMyDataSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesMyDataSection.tsx index 0775b07cec3e..0b82d7441323 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesMyDataSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesMyDataSection.tsx @@ -1,4 +1,4 @@ -import { Accordion, Field, FieldGroup, ButtonGroup, Button, Box } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldGroup, FieldRow, ButtonGroup, Button, Box } from '@rocket.chat/fuselage'; import { useSetModal, useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; @@ -77,7 +77,7 @@ const PreferencesMyDataSection = () => { - + - + diff --git a/apps/meteor/client/views/account/preferences/PreferencesNotificationsSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesNotificationsSection.tsx index e0a6017e7efe..2643eab0ebc7 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesNotificationsSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesNotificationsSection.tsx @@ -1,5 +1,5 @@ import type { SelectOption } from '@rocket.chat/fuselage'; -import { Accordion, Field, Select, FieldGroup, ToggleSwitch, Button, Box } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldLabel, FieldRow, FieldHint, Select, FieldGroup, ToggleSwitch, Button, Box } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useUserPreference, useSetting, useTranslation } from '@rocket.chat/ui-contexts'; @@ -92,8 +92,8 @@ const PreferencesNotificationsSection = () => { - {t('Desktop_Notifications')} - + {t('Desktop_Notifications')} + {notificationsPermission === 'denied' && t('Desktop_Notifications_Disabled')} {notificationsPermission === 'granted' && ( <> @@ -109,12 +109,12 @@ const PreferencesNotificationsSection = () => { )} - + - {t('Notification_RequireInteraction')} - + {t('Notification_RequireInteraction')} + { /> )} /> - + - {t('Only_works_with_chrome_version_greater_50')} + {t('Only_works_with_chrome_version_greater_50')} - {t('Notification_Desktop_Default_For')} - + {t('Notification_Desktop_Default_For')} + { )} /> - + - {t('Email_Notification_Mode')} - + {t('Email_Notification_Mode')} + { /> )} /> - - + + {canChangeEmailNotification && t('You_need_to_verifiy_your_email_address_to_get_notications')} {!canChangeEmailNotification && t('Email_Notifications_Change_Disabled')} - + {showNewLoginEmailPreference && ( - {t('Receive_Login_Detection_Emails')} - + {t('Receive_Login_Detection_Emails')} + { /> )} /> - + - {t('Receive_Login_Detection_Emails_Description')} + {t('Receive_Login_Detection_Emails_Description')} )} {showCalendarPreference && ( - {t('Notify_Calendar_Events')} - + {t('Notify_Calendar_Events')} + { )} /> - + )} {showMobileRinging && ( - {t('VideoConf_Mobile_Ringing')} - + {t('VideoConf_Mobile_Ringing')} + { )} /> - + )} diff --git a/apps/meteor/client/views/account/preferences/PreferencesSoundSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesSoundSection.tsx index 7b5f051fc017..223d67fd7f95 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesSoundSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesSoundSection.tsx @@ -1,5 +1,5 @@ import type { SelectOption } from '@rocket.chat/fuselage'; -import { Accordion, Field, Select, FieldGroup, ToggleSwitch, Tooltip, Box } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldLabel, FieldRow, Select, FieldGroup, ToggleSwitch, Tooltip, Box } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useCustomSound } from '@rocket.chat/ui-contexts'; import type { ChangeEvent } from 'react'; @@ -23,8 +23,8 @@ const PreferencesSoundSection = () => { - {t('New_Room_Notification')} - + {t('New_Room_Notification')} + { /> )} /> - + - {t('New_Message_Notification')} - + {t('New_Message_Notification')} + { /> )} /> - + - {t('Mute_Focused_Conversations')} - + {t('Mute_Focused_Conversations')} + { )} /> - + - {t('Notifications_Sound_Volume')} - + {t('Notifications_Sound_Volume')} + { {notificationsSoundVolume} - + diff --git a/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx index 3a075c50f7d7..89575e36aa6b 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx @@ -1,4 +1,4 @@ -import { Accordion, Field, NumberInput, FieldGroup, ToggleSwitch, Box } from '@rocket.chat/fuselage'; +import { Accordion, Field, FieldLabel, FieldRow, NumberInput, FieldGroup, ToggleSwitch, Box } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; @@ -16,8 +16,8 @@ const PreferencesUserPresenceSection = () => { - {t('Enable_Auto_Away')} - + {t('Enable_Auto_Away')} + { )} /> - + - {t('Idle_Time_Limit')} - + {t('Idle_Time_Limit')} + - + diff --git a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx index 1a326db4544d..ed97b95caae8 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx @@ -1,5 +1,17 @@ import type { IUser } from '@rocket.chat/core-typings'; -import { Field, FieldGroup, TextInput, TextAreaInput, Box, Icon, Button } from '@rocket.chat/fuselage'; +import { + Field, + FieldGroup, + FieldLabel, + FieldRow, + FieldError, + FieldHint, + TextInput, + TextAreaInput, + Box, + Icon, + Button, +} from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { @@ -139,10 +151,10 @@ const AccountProfileForm = (props: AllHTMLAttributes): ReactEle - + {t('Name')} - - + + ): ReactEle /> )} /> - + {errors.name && ( - + {errors.name.message} - + )} - {!allowRealNameChange && {t('RealName_Change_Disabled')}} + {!allowRealNameChange && {t('RealName_Change_Disabled')}} - + {t('Username')} - - + + ): ReactEle /> )} /> - + {errors?.username && ( - + {errors.username.message} - + )} - {!canChangeUsername && {t('Username_Change_Disabled')}} + {!canChangeUsername && {t('Username_Change_Disabled')}} - {t('StatusMessage')} - + {t('StatusMessage')} + ): ReactEle /> )} /> - + {errors?.statusText && ( - + {errors?.statusText.message} - + )} - {!allowUserStatusMessageChange && {t('StatusMessage_Change_Disabled')}} + {!allowUserStatusMessageChange && {t('StatusMessage_Change_Disabled')}} - {t('Nickname')} - + {t('Nickname')} + ): ReactEle } /> )} /> - + - {t('Bio')} - + {t('Bio')} + ): ReactEle /> )} /> - + {errors?.bio && ( - + {errors.bio.message} - + )} - + {t('Email')} - - + + ): ReactEle {t('Resend_verification_email')} )} - + {errors.email && ( - + {errors?.email?.message} - + )} - {!allowEmailChange && {t('Email_Change_Disabled')}} + {!allowEmailChange && {t('Email_Change_Disabled')}} {customFieldsMetadata && }
diff --git a/apps/meteor/client/views/account/profile/ActionConfirmModal.tsx b/apps/meteor/client/views/account/profile/ActionConfirmModal.tsx index 4d73f04c2973..286bd564dd18 100644 --- a/apps/meteor/client/views/account/profile/ActionConfirmModal.tsx +++ b/apps/meteor/client/views/account/profile/ActionConfirmModal.tsx @@ -1,4 +1,4 @@ -import { Box, PasswordInput, TextInput, FieldGroup, Field } from '@rocket.chat/fuselage'; +import { Box, PasswordInput, TextInput, FieldGroup, Field, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FC } from 'react'; import React, { useState, useCallback } from 'react'; @@ -50,11 +50,11 @@ const ActionConfirmModal: FC = ({ isPassword, onConfirm {isPassword ? t('Enter_your_password_to_delete_your_account') : t('Enter_your_username_to_delete_your_account')} - + {isPassword && } {!isPassword && } - - {inputError} + + {inputError} diff --git a/apps/meteor/client/views/account/security/EndToEnd.tsx b/apps/meteor/client/views/account/security/EndToEnd.tsx index 78410e519e2c..72213f3202ba 100644 --- a/apps/meteor/client/views/account/security/EndToEnd.tsx +++ b/apps/meteor/client/views/account/security/EndToEnd.tsx @@ -1,4 +1,4 @@ -import { Box, Margins, PasswordInput, Field, FieldGroup, Button } from '@rocket.chat/fuselage'; +import { Box, Margins, PasswordInput, Field, FieldGroup, FieldLabel, FieldRow, FieldError, FieldHint, Button } from '@rocket.chat/fuselage'; import { useToastMessageDispatch, useMethod, useTranslation, useLogout } from '@rocket.chat/ui-contexts'; import type { ComponentProps, ReactElement } from 'react'; import React, { useCallback, useEffect } from 'react'; @@ -71,20 +71,20 @@ const EndToEnd = (props: ComponentProps): ReactElement => { - {t('New_encryption_password')} - + {t('New_encryption_password')} + - - {!keysExist && {t('EncryptionKey_Change_Disabled')}} + + {!keysExist && {t('EncryptionKey_Change_Disabled')}} {hasTypedPassword && ( - {t('Confirm_new_encryption_password')} + {t('Confirm_new_encryption_password')} ): ReactElement => { placeholder={t('Confirm_New_Password_Placeholder')} aria-labelledby='Confirm_new_encryption_password' /> - {errors.passwordConfirm && {errors.passwordConfirm.message}} + {errors.passwordConfirm && {errors.passwordConfirm.message}} )} diff --git a/apps/meteor/client/views/account/tokens/AccountTokensTable/AddToken.tsx b/apps/meteor/client/views/account/tokens/AccountTokensTable/AddToken.tsx index 4d38d2e68fc6..97d2a8163cab 100644 --- a/apps/meteor/client/views/account/tokens/AccountTokensTable/AddToken.tsx +++ b/apps/meteor/client/views/account/tokens/AccountTokensTable/AddToken.tsx @@ -1,4 +1,4 @@ -import { Box, TextInput, Button, Field, FieldGroup, Margins, CheckBox } from '@rocket.chat/fuselage'; +import { Box, TextInput, Button, Field, FieldGroup, FieldLabel, FieldRow, Margins, CheckBox } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useToastMessageDispatch, useUserId, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -56,18 +56,18 @@ const AddToken = ({ reload, ...props }: { reload: () => void }): ReactElement => return ( - + - - + + - {t('Ignore_Two_Factor_Authentication')} - + {t('Ignore_Two_Factor_Authentication')} + ); diff --git a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepOneModal.tsx b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepOneModal.tsx index 09548b3349a9..41e8f300d898 100644 --- a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepOneModal.tsx +++ b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepOneModal.tsx @@ -1,4 +1,4 @@ -import { Modal, Box, Field, TextInput, CheckBox, ButtonGroup, Button } from '@rocket.chat/fuselage'; +import { Modal, Box, Field, FieldLabel, FieldRow, TextInput, CheckBox, ButtonGroup, Button } from '@rocket.chat/fuselage'; import { ExternalLink } from '@rocket.chat/ui-client'; import { useEndpoint, useSetModal, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; @@ -66,14 +66,14 @@ const RegisterWorkspaceSetupStepOneModal = ({ {t('RegisterWorkspace_Setup_Subtitle')} - {t('RegisterWorkspace_Setup_Label')} - + {t('RegisterWorkspace_Setup_Label')} + { setEmail((e.target as HTMLInputElement).value); }} /> - + diff --git a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepTwoModal.tsx b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepTwoModal.tsx index fa1640bc8dfb..734f07442f11 100644 --- a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepTwoModal.tsx +++ b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepTwoModal.tsx @@ -1,4 +1,4 @@ -import { Modal, Box, Field, TextInput } from '@rocket.chat/fuselage'; +import { Modal, Box, Field, FieldLabel, FieldRow, TextInput } from '@rocket.chat/fuselage'; import { useEndpoint, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import React, { useCallback, useEffect } from 'react'; import { Trans } from 'react-i18next'; @@ -81,10 +81,10 @@ const RegisterWorkspaceSetupStepTwoModal = ({ email, step, setStep, onClose, int {t('RegisterWorkspace_Setup_Email_Verification')} - {t('Security_code')} - + {t('Security_code')} + - + diff --git a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceTokenModal.tsx b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceTokenModal.tsx index 12ba3798c97e..89728457226b 100644 --- a/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceTokenModal.tsx +++ b/apps/meteor/client/views/admin/cloud/modals/RegisterWorkspaceTokenModal.tsx @@ -1,4 +1,4 @@ -import { Box, Button, ButtonGroup, Field, Modal, TextInput } from '@rocket.chat/fuselage'; +import { Box, Button, ButtonGroup, Field, FieldLabel, FieldRow, FieldError, Modal, TextInput } from '@rocket.chat/fuselage'; import { useMethod, useSetModal, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ChangeEvent } from 'react'; import React, { useState } from 'react'; @@ -79,11 +79,11 @@ const RegisterWorkspaceTokenModal = ({ onClose, onStatusChange, ...props }: Regi {`2. ${t('RegisterWorkspace_Token_Step_Two')}`} - {t('Registration_Token')} - + {t('Registration_Token')} + - - {error && {t('Token_Not_Recognized')}} + + {error && {t('Token_Not_Recognized')}} diff --git a/apps/meteor/client/views/admin/customEmoji/AddCustomEmoji.tsx b/apps/meteor/client/views/admin/customEmoji/AddCustomEmoji.tsx index eaeaccd3e395..8fae8501327a 100644 --- a/apps/meteor/client/views/admin/customEmoji/AddCustomEmoji.tsx +++ b/apps/meteor/client/views/admin/customEmoji/AddCustomEmoji.tsx @@ -1,4 +1,4 @@ -import { Box, Button, ButtonGroup, Margins, TextInput, Field, Icon } from '@rocket.chat/fuselage'; +import { Box, Button, ButtonGroup, Margins, TextInput, Field, FieldLabel, FieldRow, FieldError, Icon } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, ChangeEvent } from 'react'; import React, { useCallback, useState } from 'react'; @@ -78,28 +78,28 @@ const AddCustomEmoji = ({ close, onChange, ...props }: AddCustomEmojiProps): Rea <> - {t('Name')} - + {t('Name')} + - - {errors.name && {t('error-the-field-is-required', { field: t('Name') })}} + + {errors.name && {t('error-the-field-is-required', { field: t('Name') })}} - {t('Aliases')} - + {t('Aliases')} + - - {errors.aliases && {t('Custom_Emoji_Error_Same_Name_And_Alias')}} + + {errors.aliases && {t('Custom_Emoji_Error_Same_Name_And_Alias')}} - + {t('Custom_Emoji')} {/* FIXME: replace to IconButton */} - - {errors.emoji && {t('error-the-field-is-required', { field: t('Custom_Emoji') })}} + + {errors.emoji && {t('error-the-field-is-required', { field: t('Custom_Emoji') })}} {newEmojiPreview && ( diff --git a/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx b/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx index e11b5722fe0a..f561001a20be 100644 --- a/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx +++ b/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx @@ -1,4 +1,16 @@ -import { Box, Button, ButtonGroup, Margins, TextInput, Field, FieldGroup, IconButton } from '@rocket.chat/fuselage'; +import { + Box, + Button, + ButtonGroup, + Margins, + TextInput, + Field, + FieldGroup, + FieldLabel, + FieldRow, + FieldError, + IconButton, +} from '@rocket.chat/fuselage'; import { useSetModal, useToastMessageDispatch, useAbsoluteUrl, useTranslation } from '@rocket.chat/ui-contexts'; import type { FC, ChangeEvent } from 'react'; import React, { useCallback, useState, useMemo, useEffect } from 'react'; @@ -134,24 +146,24 @@ const EditCustomEmoji: FC = ({ close, onChange, data, ...p - {t('Name')} - + {t('Name')} + - - {errors.name && {t('error-the-field-is-required', { field: t('Name') })}} + + {errors.name && {t('error-the-field-is-required', { field: t('Name') })}} - {t('Aliases')} - + {t('Aliases')} + - - {errors.aliases && {t('Custom_Emoji_Error_Same_Name_And_Alias')}} + + {errors.aliases && {t('Custom_Emoji_Error_Same_Name_And_Alias')}} - + {t('Custom_Emoji')} - + {newEmojiPreview && ( diff --git a/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx b/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx index bf391e8feae1..434cb1769db6 100644 --- a/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx @@ -1,4 +1,4 @@ -import { Field, TextInput, Box, Icon, Margins, Button, ButtonGroup } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, TextInput, Box, Icon, Margins, Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, FormEvent } from 'react'; import React, { useState, useCallback } from 'react'; @@ -86,17 +86,17 @@ const AddCustomSound = ({ goToNew, close, onChange, ...props }: AddCustomSoundPr <> - {t('Name')} - + {t('Name')} + ): void => setName(e.currentTarget.value)} placeholder={t('Name')} /> - + - {t('Sound_File_mp3')} + {t('Sound_File_mp3')} {/* FIXME: replace to IconButton */} diff --git a/apps/meteor/client/views/admin/customSounds/EditSound.tsx b/apps/meteor/client/views/admin/customSounds/EditSound.tsx index d1d214d15e20..44b728821c4c 100644 --- a/apps/meteor/client/views/admin/customSounds/EditSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/EditSound.tsx @@ -1,4 +1,4 @@ -import { Box, Button, ButtonGroup, Margins, TextInput, Field, IconButton } from '@rocket.chat/fuselage'; +import { Box, Button, ButtonGroup, Margins, TextInput, Field, FieldLabel, FieldRow, IconButton } from '@rocket.chat/fuselage'; import { useSetModal, useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, SyntheticEvent } from 'react'; import React, { useCallback, useState, useMemo, useEffect } from 'react'; @@ -120,17 +120,17 @@ function EditSound({ close, onChange, data, ...props }: EditSoundProps): ReactEl <> - {t('Name')} - + {t('Name')} + ): void => setName(e.currentTarget.value)} placeholder={t('Name')} /> - + - {t('Sound_File_mp3')} + {t('Sound_File_mp3')} diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusForm.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusForm.tsx index 2c832e8299ec..9796438fde7e 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusForm.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusForm.tsx @@ -1,6 +1,6 @@ import type { IUserStatus } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; -import { FieldGroup, Button, ButtonGroup, TextInput, Field, Select } from '@rocket.chat/fuselage'; +import { FieldGroup, Button, ButtonGroup, TextInput, Field, FieldLabel, FieldRow, FieldError, Select } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useRoute, useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -92,23 +92,23 @@ const CustomUserStatusForm = ({ onClose, onReload, status }: CustomUserStatusFor - {t('Name')} - + {t('Name')} + - - {errors?.name && {t('error-the-field-is-required', { field: t('Name') })}} + + {errors?.name && {t('error-the-field-is-required', { field: t('Name') })}} - {t('Presence')} - + {t('Presence')} + [extension, extension]) || []} @@ -61,7 +61,7 @@ const AssignAgentModal: FC = ({ existingExtension, close placeholder={t('Select_an_option')} onChange={(value) => setExtension(String(value))} /> - + diff --git a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx index bd9de953eb30..b674e589d446 100644 --- a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx @@ -1,4 +1,4 @@ -import { Button, Field } from '@rocket.chat/fuselage'; +import { Button, FieldRow, FieldHint } from '@rocket.chat/fuselage'; import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts'; import { useMethod, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -29,12 +29,12 @@ function ActionSettingInput({ _id, actionText, value, disabled, sectionChanged } return ( <> - + - - {sectionChanged && {t('Save_to_enable_this_action')}} + + {sectionChanged && {t('Save_to_enable_this_action')}} ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/AssetSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/AssetSettingInput.tsx index 5871296cee6a..f3122a23295b 100644 --- a/apps/meteor/client/views/admin/settings/inputs/AssetSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/AssetSettingInput.tsx @@ -1,4 +1,4 @@ -import { Button, Field, Icon } from '@rocket.chat/fuselage'; +import { Button, FieldLabel, FieldRow, Icon } from '@rocket.chat/fuselage'; import { Random } from '@rocket.chat/random'; import { useToastMessageDispatch, useEndpoint, useTranslation, useUpload } from '@rocket.chat/ui-contexts'; import type { ChangeEventHandler, DragEvent, ReactElement, SyntheticEvent } from 'react'; @@ -58,10 +58,10 @@ function AssetSettingInput({ _id, label, value, asset, fileConstraints }: AssetS return ( <> - + {label} - - + +
{value?.url ? (
- + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/BooleanSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/BooleanSettingInput.tsx index acac16b5b7e8..308e781e8e46 100644 --- a/apps/meteor/client/views/admin/settings/inputs/BooleanSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/BooleanSettingInput.tsx @@ -1,4 +1,4 @@ -import { Field, ToggleSwitch } from '@rocket.chat/fuselage'; +import { FieldLabel, FieldRow, ToggleSwitch } from '@rocket.chat/fuselage'; import type { ReactElement, SyntheticEvent } from 'react'; import React from 'react'; @@ -30,7 +30,7 @@ function BooleanSettingInput({ }; return ( - + - + {label} - + {hasResetButton && } - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/CodeSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/CodeSettingInput.tsx index 2b615a63b8d5..85698b66e2b7 100644 --- a/apps/meteor/client/views/admin/settings/inputs/CodeSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/CodeSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldHint, Flex } from '@rocket.chat/fuselage'; import type { ReactElement } from 'react'; import React from 'react'; @@ -43,12 +43,12 @@ function CodeSettingInput({ <> - + {label} - + {hasResetButton && } - {hint && {hint}} + {hint && {hint}} - + {label} - + {hasResetButton && } - + {editor === 'color' && ( @@ -104,9 +104,9 @@ function ColorSettingInput({ options={allowedTypes.map((type) => [type, t(type)])} /> - + - Variable name: {_id.replace(/theme-color-/, '@')} + Variable name: {_id.replace(/theme-color-/, '@')} ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/FontSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/FontSettingInput.tsx index 2d7a93b9c96f..35b255b4e756 100644 --- a/apps/meteor/client/views/admin/settings/inputs/FontSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/FontSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, TextInput } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, TextInput } from '@rocket.chat/fuselage'; import type { FormEventHandler, ReactElement } from 'react'; import React from 'react'; @@ -36,13 +36,13 @@ function FontSettingInput({ <> - + {label} - + {hasResetButton && } - + - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/GenericSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/GenericSettingInput.tsx index 46ffc61a8f3b..32425a57c698 100644 --- a/apps/meteor/client/views/admin/settings/inputs/GenericSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/GenericSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, TextInput } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, TextInput } from '@rocket.chat/fuselage'; import type { FormEventHandler, ReactElement } from 'react'; import React from 'react'; @@ -36,13 +36,13 @@ function GenericSettingInput({ <> - + {label} - + {hasResetButton && } - + - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/IntSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/IntSettingInput.tsx index 03f837117223..cd5abd54f481 100644 --- a/apps/meteor/client/views/admin/settings/inputs/IntSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/IntSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, InputBox } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, InputBox } from '@rocket.chat/fuselage'; import type { FormEventHandler, ReactElement } from 'react'; import React from 'react'; @@ -37,13 +37,13 @@ function IntSettingInput({ <> - + {label} - + {hasResetButton && } - + - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/LanguageSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/LanguageSettingInput.tsx index 770edd5c12a6..8bfe977aaf39 100644 --- a/apps/meteor/client/views/admin/settings/inputs/LanguageSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/LanguageSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, Select } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, Select } from '@rocket.chat/fuselage'; import { useLanguages } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; @@ -40,13 +40,13 @@ function LanguageSettingInput({ <> - + {label} - + {hasResetButton && } - + handleChange(String(value))} options={values.map(({ key, label }) => [key, label])} /> - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/MultiSelectSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/MultiSelectSettingInput.tsx index 114503c959ed..bc8d8062d8a2 100644 --- a/apps/meteor/client/views/admin/settings/inputs/MultiSelectSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/MultiSelectSettingInput.tsx @@ -1,4 +1,4 @@ -import { Field, Flex, Box, MultiSelectFiltered, MultiSelect } from '@rocket.chat/fuselage'; +import { FieldLabel, Flex, Box, MultiSelectFiltered, MultiSelect } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -45,9 +45,9 @@ function MultiSelectSettingInput({ <> - + {label} - + {hasResetButton && } diff --git a/apps/meteor/client/views/admin/settings/inputs/PasswordSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/PasswordSettingInput.tsx index 087d83b98a0d..b7d2c1d48d47 100644 --- a/apps/meteor/client/views/admin/settings/inputs/PasswordSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/PasswordSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, PasswordInput } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, PasswordInput } from '@rocket.chat/fuselage'; import type { EventHandler, ReactElement, SyntheticEvent } from 'react'; import React from 'react'; @@ -37,13 +37,13 @@ function PasswordSettingInput({ <> - + {label} - + {hasResetButton && } - + - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/RelativeUrlSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/RelativeUrlSettingInput.tsx index 0541ea81eb36..b94581706757 100644 --- a/apps/meteor/client/views/admin/settings/inputs/RelativeUrlSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/RelativeUrlSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, UrlInput } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, Flex, UrlInput } from '@rocket.chat/fuselage'; import { useAbsoluteUrl } from '@rocket.chat/ui-contexts'; import type { EventHandler, ReactElement, SyntheticEvent } from 'react'; import React from 'react'; @@ -40,9 +40,9 @@ function RelativeUrlSettingInput({ <> - + {label} - + {hasResetButton && } diff --git a/apps/meteor/client/views/admin/settings/inputs/RoomPickSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/RoomPickSettingInput.tsx index d44235afbde9..15423742ff91 100644 --- a/apps/meteor/client/views/admin/settings/inputs/RoomPickSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/RoomPickSettingInput.tsx @@ -1,5 +1,5 @@ import type { SettingValueRoomPick } from '@rocket.chat/core-typings'; -import { Box, Field, Flex } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex } from '@rocket.chat/fuselage'; import type { ReactElement } from 'react'; import React from 'react'; @@ -42,13 +42,13 @@ function RoomPickSettingInput({ <> - + {label} - + {hasResetButton && } - + - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/SelectSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/SelectSettingInput.tsx index 28014d65d375..a6fa88f7ffe7 100644 --- a/apps/meteor/client/views/admin/settings/inputs/SelectSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/SelectSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, Select } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, Select } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -43,13 +43,13 @@ function SelectSettingInput({ <> - + {label} - + {hasResetButton && } - + handleChange(String(value))} options={moment.tz.names().map((key) => [key, key])} /> - + ); } diff --git a/apps/meteor/client/views/admin/settings/inputs/StringSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/StringSettingInput.tsx index 30b79e01683f..3d0ba78a127a 100644 --- a/apps/meteor/client/views/admin/settings/inputs/StringSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/StringSettingInput.tsx @@ -1,4 +1,4 @@ -import { Box, Field, Flex, TextAreaInput, TextInput } from '@rocket.chat/fuselage'; +import { Box, FieldLabel, FieldRow, Flex, TextAreaInput, TextInput } from '@rocket.chat/fuselage'; import type { EventHandler, ReactElement, SyntheticEvent } from 'react'; import React from 'react'; @@ -43,13 +43,13 @@ function StringSettingInput({ <> - + {label} - + {hasResetButton && } - + {multiline ? ( )} - + ); } diff --git a/apps/meteor/client/views/admin/users/AdminUserForm.tsx b/apps/meteor/client/views/admin/users/AdminUserForm.tsx index 334aca68b8f8..1912150b4a48 100644 --- a/apps/meteor/client/views/admin/users/AdminUserForm.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserForm.tsx @@ -1,6 +1,10 @@ import type { AvatarObject, IUser, Serialized } from '@rocket.chat/core-typings'; import { Field, + FieldLabel, + FieldRow, + FieldError, + FieldHint, TextInput, TextAreaInput, PasswordInput, @@ -179,8 +183,8 @@ const UserForm = ({ userData, onReload, ...props }: AdminUserFormProps) => { )} - {t('Name')} - + {t('Name')} + { /> )} /> - + {errors?.name && ( - + {errors.name.message} - + )} - {t('Username')} - + {t('Username')} + { /> )} /> - + {errors?.username && ( - + {errors.username.message} - + )} - {t('Email')} - + {t('Email')} + { /> )} /> - + {errors?.email && ( - + {errors.email.message} - + )} - {t('Verified')} - + {t('Verified')} + } /> - + - {t('StatusMessage')} - + {t('StatusMessage')} + { /> )} /> - + {errors?.statusText && ( - + {errors.statusText.message} - + )} - {t('Bio')} - + {t('Bio')} + { /> )} /> - + {errors?.bio && ( - + {errors.bio.message} - + )} - {t('Nickname')} - + {t('Nickname')} + { } /> )} /> - + {!setRandomPassword && ( - {t('Password')} - + {t('Password')} + { /> )} /> - + {errors?.password && ( - + {errors.password.message} - + )} )} - {t('Require_password_change')} - + {t('Require_password_change')} + { /> )} /> - + - {t('Set_random_password_and_send_by_email')} - + {t('Set_random_password_and_send_by_email')} + { /> )} /> - + {!isSmtpEnabled && ( - )} - {t('Roles')} - + {t('Roles')} + {roleError && {roleError}} {!roleError && ( { )} /> )} - - {errors?.roles && {errors.roles.message}} + + {errors?.roles && {errors.roles.message}} - {t('Join_default_channels')} - + {t('Join_default_channels')} + { )} /> - + - {t('Send_welcome_email')} - + {t('Send_welcome_email')} + { /> )} /> - + {!isSmtpEnabled && ( - diff --git a/apps/meteor/client/views/e2e/EnterE2EPasswordModal.tsx b/apps/meteor/client/views/e2e/EnterE2EPasswordModal.tsx index 76d5f3b61e28..249ae6df5efa 100644 --- a/apps/meteor/client/views/e2e/EnterE2EPasswordModal.tsx +++ b/apps/meteor/client/views/e2e/EnterE2EPasswordModal.tsx @@ -1,4 +1,4 @@ -import { Box, PasswordInput, Field, FieldGroup } from '@rocket.chat/fuselage'; +import { Box, PasswordInput, Field, FieldGroup, FieldRow, FieldError } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -50,7 +50,7 @@ const EnterE2EPasswordModal = ({ - + - - {passwordError} + + {passwordError} diff --git a/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx b/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx index b6b536925ba1..aa5a917405b4 100644 --- a/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx +++ b/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx @@ -1,5 +1,17 @@ import type { ILivechatAgent, ILivechatDepartment, ILivechatDepartmentAgents } from '@rocket.chat/core-typings'; -import { Field, TextInput, Button, Box, MultiSelect, Icon, Select, ContextualbarFooter, ButtonGroup } from '@rocket.chat/fuselage'; +import { + Field, + FieldLabel, + FieldRow, + TextInput, + Button, + Box, + MultiSelect, + Icon, + Select, + ContextualbarFooter, + ButtonGroup, +} from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useRoute, useSetting, useMethod, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import type { FC, ReactElement } from 'react'; @@ -121,26 +133,26 @@ const AgentEdit: FC = ({ data, userDepartments, availableDepartm )} - {t('Name')} - + {t('Name')} + - + - {t('Username')} - + {t('Username')} + } /> - + - {t('Email')} - + {t('Email')} + } /> - + - {t('Departments')} - + {t('Departments')} + = ({ data, userDepartments, availableDepartm placeholder={t('Select_an_option')} onChange={handleDepartments} /> - + - {t('Status')} - + {t('Status')} + setChartName(String(value))} /> - + diff --git a/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx b/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx index b84996f168d4..40644b1f1b04 100644 --- a/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx +++ b/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx @@ -1,4 +1,4 @@ -import { Box, InputBox, Menu, Field } from '@rocket.chat/fuselage'; +import { Box, InputBox, Menu, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { Moment } from 'moment'; @@ -112,21 +112,21 @@ const DateRangePicker = ({ onChange = () => undefined, ...props }: DateRangePick - {t('Start')} - + {t('Start')} + - + - {t('End')} - + {t('End')} + - + diff --git a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx index 9d5e176301a8..4983c5ca8837 100644 --- a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx +++ b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx @@ -1,4 +1,16 @@ -import { Box, Field, TextInput, ToggleSwitch, Accordion, FieldGroup, InputBox, TextAreaInput, NumberInput } from '@rocket.chat/fuselage'; +import { + Box, + Field, + FieldLabel, + FieldRow, + TextInput, + ToggleSwitch, + Accordion, + FieldGroup, + InputBox, + TextAreaInput, + NumberInput, +} from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FC, FormEvent } from 'react'; @@ -105,46 +117,46 @@ const AppearanceForm: FC = ({ values = {}, handlers = {} }) - {t('Title')} - + {t('Title')} + - + - {t('Title_bar_color')} - + {t('Title_bar_color')} + - + - {t('Message_Characther_Limit')} - + {t('Message_Characther_Limit')} + - + - + - + - {t('Show_agent_info')} - + {t('Show_agent_info')} + - + - {t('Show_agent_email')} - + {t('Show_agent_email')} + - + @@ -154,66 +166,66 @@ const AppearanceForm: FC = ({ values = {}, handlers = {} }) - {t('Display_offline_form')} - + {t('Display_offline_form')} + - + - {t('Offline_form_unavailable_message')} - + {t('Offline_form_unavailable_message')} + - + - {t('Offline_message')} - + {t('Offline_message')} + - + - {t('Title_offline')} - + {t('Title_offline')} + - + - {t('Title_bar_color_offline')} - + {t('Title_bar_color_offline')} + - + - {t('Email_address_to_send_offline_messages')} - + {t('Email_address_to_send_offline_messages')} + - + - {t('Offline_success_message')} - + {t('Offline_success_message')} + - + @@ -222,64 +234,64 @@ const AppearanceForm: FC = ({ values = {}, handlers = {} }) - {t('Enabled')} - + {t('Enabled')} + - + - {t('Show_name_field')} - + {t('Show_name_field')} + - + - {t('Show_email_field')} - + {t('Show_email_field')} + - + - {t('Livechat_registration_form_message')} - + {t('Livechat_registration_form_message')} + - + - {t('Conversation_finished_message')} - + {t('Conversation_finished_message')} + - + - {t('Conversation_finished_text')} - + {t('Conversation_finished_text')} + - + diff --git a/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx b/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx index e0b8a77381b4..803b74b9522d 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx @@ -1,5 +1,5 @@ import type { ILivechatCustomField } from '@rocket.chat/core-typings'; -import { Field, TextInput, Select } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, TextInput, Select } from '@rocket.chat/fuselage'; import { useTranslation, useRoute } from '@rocket.chat/ui-contexts'; import type { ReactElement, Dispatch, SetStateAction } from 'react'; import React, { useEffect } from 'react'; @@ -39,8 +39,8 @@ const CustomFieldsList = ({ setCustomFields, allCustomFields }: CustomFieldsList if (customField.type === 'select') { return ( - {customField.label} - + {customField.label} + [item, item])} /> )} /> - + ); } return ( - {customField.label} - + {customField.label} + - + ); })} diff --git a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx index ce7780181ddc..f9872c710a5e 100644 --- a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx +++ b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx @@ -43,7 +43,9 @@ const CustomFieldsTable = ({ reload }: { reload: MutableRefObject<() => void> }) ); const getCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - const { data, isSuccess, isLoading, refetch } = useQuery(['livechat-customFields', query], async () => getCustomFields(query)); + const { data, isSuccess, isLoading, refetch } = useQuery(['livechat-customFields', query, debouncedFilter], async () => + getCustomFields(query), + ); const [defaultQuery] = useState(hashQueryKey([query])); const queryHasChanged = defaultQuery !== hashQueryKey([query]); @@ -105,7 +107,7 @@ const CustomFieldsTable = ({ reload }: { reload: MutableRefObject<() => void> }) {isSuccess && data.customFields.length > 0 && ( <> - + {headers} {data.customFields.map(({ label, _id, scope, visibility }) => ( diff --git a/apps/meteor/client/views/omnichannel/departments/DepartmentTags/index.tsx b/apps/meteor/client/views/omnichannel/departments/DepartmentTags/index.tsx index b1542f857316..cead6a0fb15f 100644 --- a/apps/meteor/client/views/omnichannel/departments/DepartmentTags/index.tsx +++ b/apps/meteor/client/views/omnichannel/departments/DepartmentTags/index.tsx @@ -1,4 +1,4 @@ -import { Button, Chip, Field, TextInput } from '@rocket.chat/fuselage'; +import { Button, Chip, FieldRow, FieldHint, TextInput } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FormEvent } from 'react'; import React, { useCallback, useState } from 'react'; @@ -28,7 +28,7 @@ export const DepartmentTags = ({ error, value: tags, onChange }: DepartmentTagsP return ( <> - + {t('Add')} - + - {t('Conversation_closing_tags_description')} + {t('Conversation_closing_tags_description')} {tags?.length > 0 && ( - + {tags.map((tag, i) => ( {tag} ))} - + )} ); diff --git a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx index 3a408bfa7507..46919307b052 100644 --- a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx +++ b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx @@ -2,6 +2,9 @@ import type { ILivechatDepartment, ILivechatDepartmentAgents, Serialized } from import { FieldGroup, Field, + FieldLabel, + FieldRow, + FieldError, TextInput, Box, Icon, @@ -240,16 +243,16 @@ function EditDepartment({ data, id, title, allowedToForwardData }: EditDepartmen > - {t('Enabled')} - + {t('Enabled')} + - + - {t('Name')}* - + {t('Name')}* + - - {errors.name && {errors.name?.message}} + + {errors.name && {errors.name?.message}} - {t('Description')} - + {t('Description')} + - + - {t('Show_on_registration_page')} - + {t('Show_on_registration_page')} + - + - {t('Email')}* - + {t('Email')}* + validateEmail(email) || t('error-invalid-email-address'), })} /> - - {errors.email && {errors.email?.message}} + + {errors.email && {errors.email?.message}} - {t('Show_on_offline_page')} - + {t('Show_on_offline_page')} + - + - {t('Livechat_DepartmentOfflineMessageToChannel')} - + {t('Livechat_DepartmentOfflineMessageToChannel')} + )} /> - + {MaxChats && ( @@ -421,7 +424,7 @@ function EditDepartment({ data, id, title, allowedToForwardData }: EditDepartmen {AutoCompleteDepartment && ( - {t('Fallback_forward_department')} + {t('Fallback_forward_department')} - {t('Request_tag_before_closing_chat')} - + {t('Request_tag_before_closing_chat')} + - + {requestTagBeforeClosingChat && ( - {t('Conversation_closing_tags')}* + {t('Conversation_closing_tags')}* )} /> - {errors.chatClosingTags && {errors.chatClosingTags?.message}} + {errors.chatClosingTags && {errors.chatClosingTags?.message}} )} @@ -475,7 +478,7 @@ function EditDepartment({ data, id, title, allowedToForwardData }: EditDepartmen - {t('Agents')}: + {t('Agents')}: diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx index 433af2135068..89b7b4582fa5 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx @@ -1,5 +1,5 @@ import type { ILivechatVisitor, IOmnichannelRoom, Serialized } from '@rocket.chat/core-typings'; -import { Field, TextInput, ButtonGroup, Button } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, TextInput, ButtonGroup, Button } from '@rocket.chat/fuselage'; import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; @@ -127,10 +127,10 @@ function RoomEdit({ room, visitor, reload, reloadInfo, onClose }: RoomEditProps) )} - {t('Topic')} - + {t('Topic')} + - + diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx b/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx index afb609e5f801..a41c155c4f9d 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx +++ b/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx @@ -1,5 +1,5 @@ import type { ILivechatVisitor, Serialized } from '@rocket.chat/core-typings'; -import { Field, TextInput, ButtonGroup, Button, ContextualbarContent } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, FieldError, TextInput, ButtonGroup, Button, ContextualbarContent } from '@rocket.chat/fuselage'; import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; @@ -189,25 +189,25 @@ const ContactNewEdit = ({ id, data, close }: ContactNewEditProps): ReactElement <> - {t('Name')}* - + {t('Name')}* + - - {errors.name?.message} + + {errors.name?.message} - {t('Email')} - + {t('Email')} + - - {errors.email?.message} + + {errors.email?.message} - {t('Phone')} - + {t('Phone')} + - - {errors.phone?.message} + + {errors.phone?.message} {canViewCustomFields() && } {ContactManager && } diff --git a/apps/meteor/client/views/omnichannel/managers/AddManager.tsx b/apps/meteor/client/views/omnichannel/managers/AddManager.tsx index d6668d7f35d7..b4f56f78b62b 100644 --- a/apps/meteor/client/views/omnichannel/managers/AddManager.tsx +++ b/apps/meteor/client/views/omnichannel/managers/AddManager.tsx @@ -1,4 +1,4 @@ -import { Button, Box, Field } from '@rocket.chat/fuselage'; +import { Button, Box, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -34,13 +34,13 @@ const AddManager = ({ reload }: { reload: () => void }): ReactElement => { return ( - {t('Username')} - + {t('Username')} + - + ); diff --git a/apps/meteor/client/views/omnichannel/sidebarItems.ts b/apps/meteor/client/views/omnichannel/sidebarItems.ts index 048bcb4ef88e..7942764a8b89 100644 --- a/apps/meteor/client/views/omnichannel/sidebarItems.ts +++ b/apps/meteor/client/views/omnichannel/sidebarItems.ts @@ -13,12 +13,6 @@ export const { i18nLabel: 'Current_Chats', permissionGranted: (): boolean => hasPermission('view-livechat-current-chats'), }, - { - href: '/omnichannel/reports', - icon: 'file', - i18nLabel: 'Reports', - permissionGranted: (): boolean => hasPermission('view-livechat-reports'), - }, { href: '/omnichannel/analytics', icon: 'dashboard', diff --git a/apps/meteor/client/views/omnichannel/triggers/TriggersForm.tsx b/apps/meteor/client/views/omnichannel/triggers/TriggersForm.tsx index 72c8d30d973e..7c9476059411 100644 --- a/apps/meteor/client/views/omnichannel/triggers/TriggersForm.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/TriggersForm.tsx @@ -1,5 +1,5 @@ import type { SelectOption } from '@rocket.chat/fuselage'; -import { Box, Field, TextInput, ToggleSwitch, Select, TextAreaInput } from '@rocket.chat/fuselage'; +import { Box, Field, FieldLabel, FieldRow, FieldError, TextInput, ToggleSwitch, Select, TextAreaInput } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ComponentProps, FC, FormEvent } from 'react'; @@ -138,55 +138,55 @@ const TriggersForm: FC = ({ values, handlers, className }) => <> - {t('Enabled')} - + {t('Enabled')} + - + - {t('Run_only_once_for_each_visitor')} - + {t('Run_only_once_for_each_visitor')} + - + - {t('Name')}* - + {t('Name')}* + - - {nameError} + + {nameError} - {t('Description')} - + {t('Description')} + - + - {t('Condition')} - + {t('Condition')} + = ({ values, handlers, className }) => onChange={handleActionSender} placeholder={t('Select_an_option')} /> - + {actionSender === 'custom' && ( - + - + )} - + - - {msgError} + + {msgError} ); diff --git a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx index 7f376341992d..54ce71bd80ec 100644 --- a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx +++ b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx @@ -300,8 +300,9 @@ export const useQuickActions = (): { const manualOnHoldAllowed = useSetting('Livechat_allow_manual_on_hold'); const hasManagerRole = useRole('livechat-manager'); + const hasMonitorRole = useRole('livechat-monitor'); - const roomOpen = room?.open && (room.u?._id === uid || hasManagerRole) && room?.lastMessage?.t !== 'livechat-close'; + const roomOpen = room?.open && (room.u?._id === uid || hasManagerRole || hasMonitorRole) && room?.lastMessage?.t !== 'livechat-close'; const canMoveQueue = !!omnichannelRouteConfig?.returnQueue && room?.u !== undefined; const canForwardGuest = usePermission('transfer-livechat-guest'); const canSendTranscriptEmail = usePermission('send-omnichannel-chat-transcript'); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index de9a96dc43b4..da598c00be11 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -141,7 +141,7 @@ const MessageBox = ({ [chat, storageID], ); - const autofocusRef = useMessageBoxAutoFocus(); + const autofocusRef = useMessageBoxAutoFocus(!isMobile); const useEmojis = useUserPreference('useEmojis'); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/actions/CreateDiscussionAction.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/actions/CreateDiscussionAction.tsx index 3a1f1eef6dcc..419c6c2cfdda 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/actions/CreateDiscussionAction.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/actions/CreateDiscussionAction.tsx @@ -14,8 +14,8 @@ const CreateDiscussionAction = ({ room }: { room: IRoom }) => { setModal( setModal(null)} defaultParentRoom={room?.prid || room?._id} />); const discussionEnabled = useSetting('Discussion_enabled') as boolean; - const canStartDiscussion = usePermission('start-discussion'); - const canSstartDiscussionOtherUser = usePermission('start-discussion-other-user'); + const canStartDiscussion = usePermission('start-discussion', room._id); + const canSstartDiscussionOtherUser = usePermission('start-discussion-other-user', room._id); const allowDiscussion = room && discussionEnabled && !isRoomFederated(room) && (canStartDiscussion || canSstartDiscussionOtherUser); diff --git a/apps/meteor/client/views/room/composer/messageBox/hooks/useMessageBoxAutoFocus.ts b/apps/meteor/client/views/room/composer/messageBox/hooks/useMessageBoxAutoFocus.ts index 5ea6db79a869..b8efd9391f87 100644 --- a/apps/meteor/client/views/room/composer/messageBox/hooks/useMessageBoxAutoFocus.ts +++ b/apps/meteor/client/views/room/composer/messageBox/hooks/useMessageBoxAutoFocus.ts @@ -1,13 +1,13 @@ import type { Ref } from 'react'; -import { useEffect, useRef } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; /** * if the user is types outside the message box and its not actually typing in any input field * then the message box should be focused * @returns callbackRef to bind the logic to the message box */ -export const useMessageBoxAutoFocus = (): Ref => { - const ref = useRef(null); +export const useMessageBoxAutoFocus = (enabled: boolean): Ref => { + const ref = useRef(); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { @@ -43,5 +43,22 @@ export const useMessageBoxAutoFocus = (): Ref => { }; }, []); - return ref; + return useCallback( + (node: HTMLElement | null) => { + if (!node) { + return; + } + + ref.current = node; + + if (!enabled) { + return; + } + + if (ref.current) { + ref.current.focus(); + } + }, + [enabled, ref], + ); }; diff --git a/apps/meteor/client/views/room/contextualBar/AutoTranslate/AutoTranslate.tsx b/apps/meteor/client/views/room/contextualBar/AutoTranslate/AutoTranslate.tsx index a15edebf8c16..6952b5b1dafe 100644 --- a/apps/meteor/client/views/room/contextualBar/AutoTranslate/AutoTranslate.tsx +++ b/apps/meteor/client/views/room/contextualBar/AutoTranslate/AutoTranslate.tsx @@ -1,4 +1,4 @@ -import { FieldGroup, Field, ToggleSwitch, Select } from '@rocket.chat/fuselage'; +import { FieldGroup, Field, FieldLabel, FieldRow, ToggleSwitch, Select } from '@rocket.chat/fuselage'; import type { SelectOption } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement, ChangeEvent } from 'react'; @@ -41,14 +41,14 @@ const AutoTranslate = ({ - + - {t('Automatic_Translation')} - + {t('Automatic_Translation')} + - {t('Language')} - + {t('Language')} + setType(String(value))} placeholder={t('Type')} options={exportOptions} /> - + {type && type === 'file' && } diff --git a/apps/meteor/client/views/room/contextualBar/ExportMessages/FileExport.tsx b/apps/meteor/client/views/room/contextualBar/ExportMessages/FileExport.tsx index efbf60b69606..2085e11ea11d 100644 --- a/apps/meteor/client/views/room/contextualBar/ExportMessages/FileExport.tsx +++ b/apps/meteor/client/views/room/contextualBar/ExportMessages/FileExport.tsx @@ -1,6 +1,6 @@ import type { IRoom } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; -import { Field, Select, ButtonGroup, Button, FieldGroup, InputBox } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, Select, ButtonGroup, Button, FieldGroup, InputBox } from '@rocket.chat/fuselage'; import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import type { FC, MouseEventHandler } from 'react'; import React, { useMemo } from 'react'; @@ -65,22 +65,22 @@ const FileExport: FC = ({ onCancel, rid }) => { return ( - {t('Date_From')} - + {t('Date_From')} + - + - {t('Date_to')} - + {t('Date_to')} + - + - {t('Output_format')} - + {t('Output_format')} + {children} - + ); diff --git a/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessages.tsx b/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessages.tsx index 9f64bbc6504b..709699ebd697 100644 --- a/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessages.tsx +++ b/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessages.tsx @@ -1,4 +1,4 @@ -import { Field, ButtonGroup, Button, CheckBox, Callout } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, FieldRow, ButtonGroup, Button, CheckBox, Callout } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -45,7 +45,7 @@ const PruneMessages = ({ callOutText, validateText, onClickClose, onClickPrune } - {t('Only_from_users')} + {t('Only_from_users')} - + - {t('Inclusive')} - + {t('Inclusive')} + - + - {t('RetentionPolicy_DoNotPrunePinned')} - + {t('RetentionPolicy_DoNotPrunePinned')} + - + - {t('RetentionPolicy_DoNotPruneDiscussion')} - + {t('RetentionPolicy_DoNotPruneDiscussion')} + - + - {t('RetentionPolicy_DoNotPruneThreads')} - + {t('RetentionPolicy_DoNotPruneThreads')} + - + - {t('Files_only')} - + {t('Files_only')} + {callOutText && !validateText && {callOutText}} {validateText && {validateText}} diff --git a/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessagesDateTimeRow.tsx b/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessagesDateTimeRow.tsx index e774311e5564..38bf1c233f5a 100644 --- a/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessagesDateTimeRow.tsx +++ b/apps/meteor/client/views/room/contextualBar/PruneMessages/PruneMessagesDateTimeRow.tsx @@ -1,4 +1,4 @@ -import { Field, InputBox, Box, Margins } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, InputBox, Box, Margins } from '@rocket.chat/fuselage'; import type { ReactElement } from 'react'; import React from 'react'; import { useFormContext } from 'react-hook-form'; @@ -13,7 +13,7 @@ const PruneMessagesDateTimeRow = ({ label, field }: PruneMessagesDateTimeRowProp return ( - {label} + {label} diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx index 7a8f0d1e699a..09eaca08cbc9 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx @@ -1,6 +1,6 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { isRoomFederated } from '@rocket.chat/core-typings'; -import { Field, Button, ButtonGroup, FieldGroup } from '@rocket.chat/fuselage'; +import { Field, FieldLabel, Button, ButtonGroup, FieldGroup } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; @@ -65,7 +65,7 @@ const AddUsers = ({ rid, onClickBack, reload }: AddUsersProps): ReactElement => - {t('Choose_users')} + {t('Choose_users')} {isRoomFederated(room) ? ( - {t('Expiration_(Days)')} - + {t('Expiration_(Days)')} + )} /> - + - {t('Max_number_of_uses')} - + {t('Max_number_of_uses')} + )} /> - +