From ca8add4fce80c3633e552a004d1d8c5b251d7554 Mon Sep 17 00:00:00 2001 From: shivang-16 Date: Sat, 27 Jan 2024 03:33:55 +0530 Subject: [PATCH 1/8] added toggleFavorite method while updating roomInformation --- .../meteor/client/views/admin/rooms/EditRoom.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/meteor/client/views/admin/rooms/EditRoom.tsx b/apps/meteor/client/views/admin/rooms/EditRoom.tsx index f6c3a0db04f1..88e5fe0d6086 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoom.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoom.tsx @@ -14,7 +14,7 @@ import { FieldError, } from '@rocket.chat/fuselage'; import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks'; -import { useEndpoint, useRouter, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; +import { useEndpoint, useMethod, useRouter, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useForm, Controller } from 'react-hook-form'; @@ -95,6 +95,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { const saveAction = useEndpoint('POST', '/v1/rooms.saveRoomSettings'); const handleArchive = useArchiveRoom(room); + const toggleFavorite = useMethod('toggleFavorite'); const handleUpdateRoomData = useMutableCallback(async ({ isDefault, roomName, favorite, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); @@ -105,7 +106,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { rid: room._id, roomName: roomType === 'd' ? undefined : roomName, default: isDefault, - favorite: { defaultValue: isDefault, favorite }, + favorite: { favorite, defaultValue: isDefault }, ...data, }); @@ -117,9 +118,14 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { } }); - const handleSave = useMutableCallback(async (data) => { - await Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)); - }); + const handleSave = useMutableCallback(async (data) => { + const { favorite } = data; + + await Promise.all( + [isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive(), toggleFavorite(room._id, favorite)].filter(Boolean), + ); + }); + const formId = useUniqueId(); const roomNameField = useUniqueId(); From 6aa97f5d4dd0a877a2b7392f6a4c6c48d2ffc21f Mon Sep 17 00:00:00 2001 From: shivang-16 Date: Sat, 27 Jan 2024 04:22:47 +0530 Subject: [PATCH 2/8] code lint fix --- apps/meteor/client/views/admin/rooms/EditRoom.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/meteor/client/views/admin/rooms/EditRoom.tsx b/apps/meteor/client/views/admin/rooms/EditRoom.tsx index 88e5fe0d6086..48ce3ca5b8f3 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoom.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoom.tsx @@ -106,7 +106,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { rid: room._id, roomName: roomType === 'd' ? undefined : roomName, default: isDefault, - favorite: { favorite, defaultValue: isDefault }, + favorite: { defaultValue: isDefault, favorite }, ...data, }); @@ -118,14 +118,13 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { } }); - const handleSave = useMutableCallback(async (data) => { - const { favorite } = data; - - await Promise.all( - [isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive(), toggleFavorite(room._id, favorite)].filter(Boolean), - ); - }); + const handleSave = useMutableCallback(async (data) => { + const { favorite } = data; + await Promise.all( + [isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive(), toggleFavorite(room._id, favorite)].filter(Boolean), + ); + }); const formId = useUniqueId(); const roomNameField = useUniqueId(); From 05b9e8481940bf18d93b3bfd0b147b943a0329f4 Mon Sep 17 00:00:00 2001 From: rique223 Date: Mon, 29 Jan 2024 13:04:55 -0300 Subject: [PATCH 3/8] fix: :bug: Unwanted overide of favorite field in save room settings payload Fixed a bug where the favorite field in the save room settings payload was being overridden by the favorite field returned from the getDirtyFields function. Consequently, this resulted in always sending the favorite field as undefined to the back-end. Deleting the field before building the payload solved the issue. --- apps/meteor/client/views/admin/rooms/EditRoom.tsx | 14 +++++--------- .../Info/EditRoomInfo/EditRoomInfo.tsx | 7 ++++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/meteor/client/views/admin/rooms/EditRoom.tsx b/apps/meteor/client/views/admin/rooms/EditRoom.tsx index 48ce3ca5b8f3..1fcb8187733f 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoom.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoom.tsx @@ -14,7 +14,7 @@ import { FieldError, } from '@rocket.chat/fuselage'; import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks'; -import { useEndpoint, useMethod, useRouter, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; +import { useEndpoint, useRouter, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useForm, Controller } from 'react-hook-form'; @@ -95,11 +95,11 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { const saveAction = useEndpoint('POST', '/v1/rooms.saveRoomSettings'); const handleArchive = useArchiveRoom(room); - const toggleFavorite = useMethod('toggleFavorite'); const handleUpdateRoomData = useMutableCallback(async ({ isDefault, roomName, favorite, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); delete data.archived; + delete data.favorite; try { await saveAction({ @@ -118,13 +118,9 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { } }); - const handleSave = useMutableCallback(async (data) => { - const { favorite } = data; - - await Promise.all( - [isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive(), toggleFavorite(room._id, favorite)].filter(Boolean), - ); - }); + const handleSave = useMutableCallback(async (data) => + Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)), + ); const formId = useUniqueId(); const roomNameField = useUniqueId(); diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index 09268dc6a43a..2778098040ac 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -101,6 +101,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => const handleUpdateRoomData = useMutableCallback(async ({ hideSysMes, joinCodeRequired, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); delete data.archived; + delete data.favorite; try { await saveAction({ @@ -119,9 +120,9 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => } }); - const handleSave = useMutableCallback(async (data) => { - await Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)); - }); + const handleSave = useMutableCallback(async (data) => + Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)), + ); const formId = useUniqueId(); const roomNameField = useUniqueId(); From efa7cc6fecee725ad7b384638a99876f88a2c705 Mon Sep 17 00:00:00 2001 From: rique223 Date: Mon, 29 Jan 2024 13:24:21 -0300 Subject: [PATCH 4/8] Remove unnecessary delete --- .../views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index 2778098040ac..2eaad0226c09 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -101,7 +101,6 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => const handleUpdateRoomData = useMutableCallback(async ({ hideSysMes, joinCodeRequired, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); delete data.archived; - delete data.favorite; try { await saveAction({ From eaed0b8958f3028027a8e9316f7146e1152fe5bc Mon Sep 17 00:00:00 2001 From: rique223 Date: Mon, 29 Jan 2024 15:43:36 -0300 Subject: [PATCH 5/8] test: :white_check_mark: Favorite by default e2e test --- apps/meteor/tests/e2e/administration.spec.ts | 12 ++++++++++++ apps/meteor/tests/e2e/page-objects/admin.ts | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/apps/meteor/tests/e2e/administration.spec.ts b/apps/meteor/tests/e2e/administration.spec.ts index 6df7e425c396..fb657f4a8c8b 100644 --- a/apps/meteor/tests/e2e/administration.spec.ts +++ b/apps/meteor/tests/e2e/administration.spec.ts @@ -87,6 +87,18 @@ test.describe.parallel('administration', () => { await poAdmin.getRoomRow(targetChannel).click(); await expect(poAdmin.archivedInput).toBeChecked(); }); + + test('should mark target default channel as "favorite by default"', async () => { + await poAdmin.inputSearchRooms.type(targetChannel); + await poAdmin.getRoomRow(targetChannel).click(); + await poAdmin.defaultLabel.click(); + await poAdmin.favoriteLabel.click(); + await poAdmin.btnSave.click(); + + await poAdmin.getRoomRow(targetChannel).click(); + await expect(poAdmin.favoriteInput).toBeChecked(); + await expect(poAdmin.defaultInput).toBeChecked(); + }); }); test.describe('Permissions', () => { diff --git a/apps/meteor/tests/e2e/page-objects/admin.ts b/apps/meteor/tests/e2e/page-objects/admin.ts index 17e5185becaf..022fd609077f 100644 --- a/apps/meteor/tests/e2e/page-objects/admin.ts +++ b/apps/meteor/tests/e2e/page-objects/admin.ts @@ -36,6 +36,22 @@ export class Admin { return this.page.locator('input[name="archived"]'); } + get favoriteLabel(): Locator { + return this.page.locator('label >> text=Favorite'); + } + + get favoriteInput(): Locator { + return this.page.locator('input[name="favorite"]'); + } + + get defaultLabel(): Locator { + return this.page.locator('label >> text=Default'); + } + + get defaultInput(): Locator { + return this.page.locator('input[name="isDefault"]'); + } + get inputSearchUsers(): Locator { return this.page.locator('input[placeholder="Search Users"]'); } From 8db614d56969b33b467bcd5cd8ef8870be929e3c Mon Sep 17 00:00:00 2001 From: rique223 Date: Mon, 29 Jan 2024 17:57:15 -0300 Subject: [PATCH 6/8] test: :white_check_mark: Improve default and favorite room e2e test --- apps/meteor/tests/e2e/administration.spec.ts | 33 ++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/apps/meteor/tests/e2e/administration.spec.ts b/apps/meteor/tests/e2e/administration.spec.ts index fb657f4a8c8b..d62577b90c2f 100644 --- a/apps/meteor/tests/e2e/administration.spec.ts +++ b/apps/meteor/tests/e2e/administration.spec.ts @@ -88,16 +88,31 @@ test.describe.parallel('administration', () => { await expect(poAdmin.archivedInput).toBeChecked(); }); - test('should mark target default channel as "favorite by default"', async () => { - await poAdmin.inputSearchRooms.type(targetChannel); - await poAdmin.getRoomRow(targetChannel).click(); - await poAdmin.defaultLabel.click(); - await poAdmin.favoriteLabel.click(); - await poAdmin.btnSave.click(); + test.describe.serial('Default rooms', () => { + test('expect target channell to be default', async () => { + await poAdmin.inputSearchRooms.type(targetChannel); + await poAdmin.getRoomRow(targetChannel).click(); + await poAdmin.defaultLabel.click(); + await poAdmin.btnSave.click(); + + // The contextual bar closes after the save, because of that it has to be opened again + // Also, this flow assumes the data is not stale which can cause false positives + // TODO: If this feature is not removed in the future, Use api to check if the room is default for test optimization + await poAdmin.getRoomRow(targetChannel).click(); + await expect(poAdmin.defaultInput).toBeChecked(); + }); - await poAdmin.getRoomRow(targetChannel).click(); - await expect(poAdmin.favoriteInput).toBeChecked(); - await expect(poAdmin.defaultInput).toBeChecked(); + test('should mark target default channel as "favorite by default"', async () => { + await poAdmin.inputSearchRooms.type(targetChannel); + await poAdmin.getRoomRow(targetChannel).click(); + await poAdmin.favoriteLabel.click(); + await poAdmin.btnSave.click(); + + // Same as the previous test + // TODO: If this feature is not removed in the future, Use api to check if the room is default for test optimization + await poAdmin.getRoomRow(targetChannel).click(); + await expect(poAdmin.favoriteInput).toBeChecked(); + }); }); }); From c93f456ddc0ee0a3800f0657636592c7055675c8 Mon Sep 17 00:00:00 2001 From: rique223 Date: Tue, 30 Jan 2024 14:52:46 -0300 Subject: [PATCH 7/8] Reviews --- apps/meteor/client/views/admin/rooms/EditRoom.tsx | 6 +++--- .../room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx | 6 +++--- apps/meteor/tests/e2e/administration.spec.ts | 7 +------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/apps/meteor/client/views/admin/rooms/EditRoom.tsx b/apps/meteor/client/views/admin/rooms/EditRoom.tsx index 1fcb8187733f..bc9899bd438d 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoom.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoom.tsx @@ -13,7 +13,7 @@ import { TextAreaInput, FieldError, } from '@rocket.chat/fuselage'; -import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks'; +import { useEffectEvent, useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useEndpoint, useRouter, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useForm, Controller } from 'react-hook-form'; @@ -96,7 +96,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { const handleArchive = useArchiveRoom(room); - const handleUpdateRoomData = useMutableCallback(async ({ isDefault, roomName, favorite, ...formData }) => { + const handleUpdateRoomData = useEffectEvent(async ({ isDefault, roomName, favorite, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); delete data.archived; delete data.favorite; @@ -118,7 +118,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps) => { } }); - const handleSave = useMutableCallback(async (data) => + const handleSave = useEffectEvent((data) => Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)), ); diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index 2eaad0226c09..2a9397364757 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -20,7 +20,7 @@ import { Box, TextAreaInput, } from '@rocket.chat/fuselage'; -import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks'; +import { useEffectEvent, useUniqueId } from '@rocket.chat/fuselage-hooks'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useSetting, useTranslation, useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; @@ -98,7 +98,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => const handleArchive = useArchiveRoom(room); - const handleUpdateRoomData = useMutableCallback(async ({ hideSysMes, joinCodeRequired, ...formData }) => { + const handleUpdateRoomData = useEffectEvent(async ({ hideSysMes, joinCodeRequired, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); delete data.archived; @@ -119,7 +119,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => } }); - const handleSave = useMutableCallback(async (data) => + const handleSave = useEffectEvent((data) => Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)), ); diff --git a/apps/meteor/tests/e2e/administration.spec.ts b/apps/meteor/tests/e2e/administration.spec.ts index d62577b90c2f..8c3bd5c23f6b 100644 --- a/apps/meteor/tests/e2e/administration.spec.ts +++ b/apps/meteor/tests/e2e/administration.spec.ts @@ -95,9 +95,6 @@ test.describe.parallel('administration', () => { await poAdmin.defaultLabel.click(); await poAdmin.btnSave.click(); - // The contextual bar closes after the save, because of that it has to be opened again - // Also, this flow assumes the data is not stale which can cause false positives - // TODO: If this feature is not removed in the future, Use api to check if the room is default for test optimization await poAdmin.getRoomRow(targetChannel).click(); await expect(poAdmin.defaultInput).toBeChecked(); }); @@ -107,9 +104,7 @@ test.describe.parallel('administration', () => { await poAdmin.getRoomRow(targetChannel).click(); await poAdmin.favoriteLabel.click(); await poAdmin.btnSave.click(); - - // Same as the previous test - // TODO: If this feature is not removed in the future, Use api to check if the room is default for test optimization + await poAdmin.getRoomRow(targetChannel).click(); await expect(poAdmin.favoriteInput).toBeChecked(); }); From 256451ef170d10333bb6e987392c1056ad1cca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrique=20Guimar=C3=A3es=20Ribeiro?= Date: Fri, 2 Feb 2024 20:52:39 -0300 Subject: [PATCH 8/8] Create serious-cows-compete.md --- .changeset/serious-cows-compete.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/serious-cows-compete.md diff --git a/.changeset/serious-cows-compete.md b/.changeset/serious-cows-compete.md new file mode 100644 index 000000000000..be419a9bd9cd --- /dev/null +++ b/.changeset/serious-cows-compete.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed a bug on the rooms page's "Favorite" setting, which previously failed to designate selected rooms as favorites by default.