From 65a49a5ac9311fcde92f05758add26f0b62596cd Mon Sep 17 00:00:00 2001 From: MartinSchoeler Date: Fri, 20 Dec 2024 08:53:08 -0300 Subject: [PATCH 01/10] feat: Room roles visibility in members panel --- apps/meteor/app/api/server/v1/rooms.ts | 5 +++ .../client/views/hooks/useMembersList.ts | 5 ++- .../RoomMembers/MembersListDivider.tsx | 18 ++++++++ .../contextualBar/RoomMembers/RoomMembers.tsx | 43 +++++++++++++++---- .../actions/useChangeOwnerAction.tsx | 29 +++++++++++++ packages/i18n/src/locales/en.i18n.json | 2 + 6 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 589b7af3d883..73cba79b1a39 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -13,6 +13,7 @@ import { isRoomsOpenProps, isRoomsMembersOrderedByRoleProps, } from '@rocket.chat/rest-typings'; +import { MembershipCache } from 'matrix-appservice-bridge'; import { Meteor } from 'meteor/meteor'; import { isTruthy } from '../../../../lib/isTruthy'; @@ -903,6 +904,10 @@ API.v1.addRoute( sort, }); + members.forEach((member) => { + console.log(member.roles); + }); + return API.v1.success({ members, count: members.length, diff --git a/apps/meteor/client/views/hooks/useMembersList.ts b/apps/meteor/client/views/hooks/useMembersList.ts index 84c95c2d373b..dfd6e769f8a6 100644 --- a/apps/meteor/client/views/hooks/useMembersList.ts +++ b/apps/meteor/client/views/hooks/useMembersList.ts @@ -11,8 +11,8 @@ type MembersListOptions = { const endpointsByRoomType = { d: '/v1/im.members', - p: '/v1/groups.members', - c: '/v1/channels.members', + p: '/v1/rooms.membersOrderedByRole', + c: '/v1/rooms.membersOrderedByRole', } as const; export const useMembersList = (options: MembersListOptions) => { @@ -27,6 +27,7 @@ export const useMembersList = (options: MembersListOptions) => { roomId: options.rid, offset: start, count: 20, + rolesOrder: ['owner', 'moderator'], ...(options.debouncedText && { filter: options.debouncedText }), ...(options.type !== 'all' && { status: [options.type] }), }); diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx new file mode 100644 index 000000000000..4d2208fdca05 --- /dev/null +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx @@ -0,0 +1,18 @@ +import { Box } from '@rocket.chat/fuselage'; +import type { TranslationKey } from '@rocket.chat/ui-contexts'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +type MembersListDividerProps = { + title: TranslationKey; +}; + +export const MembersListDivider = ({ title }: MembersListDividerProps) => { + const { t } = useTranslation(); + + return ( + + {t(title)} + + ); +}; diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx index 9ace69a77b02..a34e0cc6bc40 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx @@ -1,12 +1,13 @@ -import type { IRoom, IUser } from '@rocket.chat/core-typings'; +import type { IRoom, IUser, IRole } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; import { Box, Icon, TextInput, Select, Throbber, ButtonGroup, Button, Callout } from '@rocket.chat/fuselage'; import { useAutoFocus, useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement, FormEventHandler, ComponentProps, MouseEvent } from 'react'; import { useMemo } from 'react'; -import { Virtuoso } from 'react-virtuoso'; +import { GroupedVirtuoso } from 'react-virtuoso'; +import { MembersListDivider } from './MembersListDivider'; import RoomMembersRow from './RoomMembersRow'; import { ContextualbarHeader, @@ -21,7 +22,7 @@ import { import { VirtuosoScrollbars } from '../../../../components/CustomScrollbars'; import InfiniteListAnchor from '../../../../components/InfiniteListAnchor'; -type RoomMemberUser = Pick; +type RoomMemberUser = Pick & { roles: IRole['_id'] }; type RoomMembersProps = { rid: IRoom['_id']; @@ -86,6 +87,32 @@ const RoomMembers = ({ const useRealName = useSetting('UI_Use_Real_Name', false); + const { counts, titles } = useMemo(() => { + const owners = members.filter((member) => member.roles?.includes('owner')); + const moderators = members.filter((member) => !member.roles?.includes('owner') && member.roles?.includes('moderator')); + const normalMembers = members.filter((member) => !member.roles?.includes('owner') && !member.roles?.includes('moderator')); + + const counts = []; + const titles = []; + + if (owners.length > 0) { + counts.push(owners.length); + titles.push(); + } + + if (moderators.length > 0) { + counts.push(moderators.length); + titles.push(); + } + + if (members.length > 0) { + counts.push(normalMembers.length); + titles.push(); + } + + return { counts, titles }; + }, [members]); + return ( <> @@ -129,18 +156,18 @@ const RoomMembers = ({ - titles[index]} // eslint-disable-next-line react/no-multi-comp components={{ Scroller: VirtuosoScrollbars, Footer: () => }} - itemContent={(index, data): ReactElement => ( - + itemContent={(index): ReactElement => ( + )} /> diff --git a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx index 9a0f78110c8f..1d17582d5e38 100644 --- a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx +++ b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx @@ -58,7 +58,12 @@ export const useChangeOwnerAction = (user: Pick, rid: const setModal = useSetModal(); const { _id: loggedUserId = '' } = useUser() || {}; const loggedUserIsOwner = useUserHasRoomRole(loggedUserId, rid, 'owner'); +<<<<<<< HEAD const dispatchToastMessage = useToastMessageDispatch(); +======= + const closeModal = useCallback(() => setModal(null), [setModal]); + const queryClient = useQueryClient(); +>>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) if (!room) { throw Error('Room not provided'); @@ -86,12 +91,29 @@ export const useChangeOwnerAction = (user: Pick, rid: }, }); +<<<<<<< HEAD const handleChangeOwner = useCallback(() => { if (!isRoomFederated(room)) { return toggleOwnerMutation.mutateAsync({ roomId: rid, userId: uid }); } const changingOwnRole = uid === loggedUserId; +======= + const handleConfirm = useCallback(async () => { + await changeOwner({ roomId: rid, userId: uid }); + queryClient.invalidateQueries({ queryKey: ['members'] }); + closeModal(); + }, [changeOwner, rid, uid, queryClient, closeModal]); + + const handleChangeOwner = useCallback( + async ({ userId }) => { + if (!isRoomFederated(room)) { + await changeOwner({ roomId: rid, userId: uid }); + queryClient.invalidateQueries({ queryKey: ['members'] }); + return; + } + const changingOwnRole = userId === loggedUserId; +>>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) const closeModal = () => { setModal(null); @@ -102,6 +124,7 @@ export const useChangeOwnerAction = (user: Pick, rid: closeModal(); }; +<<<<<<< HEAD if (changingOwnRole && loggedUserIsOwner) { return setModal( getWarningModalForFederatedRooms( @@ -130,6 +153,12 @@ export const useChangeOwnerAction = (user: Pick, rid: }, [room, loggedUserId, loggedUserIsOwner, toggleOwnerMutation, rid, uid, t, setModal]); const changeOwnerAction = useEffectEvent(async () => handleChangeOwner()); +======= + changeOwner({ roomId: rid, userId: uid }); + }, + [room, loggedUserId, loggedUserIsOwner, changeOwner, rid, uid, queryClient, setModal, closeModal, handleConfirm, t], + ); +>>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) const changeOwnerOption = useMemo( () => diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index d8fa2449a212..c0c0edf537a8 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -3833,6 +3833,7 @@ "mobile-upload-file_description": "Permission to allow file upload on mobile devices", "Mobile_Push_Notifications_Default_Alert": "Push Notifications Default Alert", "Moderation": "Moderation", + "Moderators": "Moderators", "Moderation_Show_reports": "Show reports", "Moderation_See_reports": "See reports", "Moderation_Go_to_message": "Go to message", @@ -4269,6 +4270,7 @@ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Override URL to which files are uploaded. This url also used for downloads unless a CDN is given", "Override_Destination_Channel": "Allow to overwrite destination channel in the body parameters", "Owner": "Owner", + "Owners": "Owners", "Play": "Play", "Page_not_exist_or_not_permission": "The page does not exist or you may not have access permission", "Page_not_found": "Page not found", From b4304808020dd6347470c961fac6035f2f01612e Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 15 Jan 2025 19:52:18 +0530 Subject: [PATCH 02/10] resolve conflicts Signed-off-by: Abhinav Kumar --- .../actions/useChangeOwnerAction.tsx | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx index 1d17582d5e38..9a0f78110c8f 100644 --- a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx +++ b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useChangeOwnerAction.tsx @@ -58,12 +58,7 @@ export const useChangeOwnerAction = (user: Pick, rid: const setModal = useSetModal(); const { _id: loggedUserId = '' } = useUser() || {}; const loggedUserIsOwner = useUserHasRoomRole(loggedUserId, rid, 'owner'); -<<<<<<< HEAD const dispatchToastMessage = useToastMessageDispatch(); -======= - const closeModal = useCallback(() => setModal(null), [setModal]); - const queryClient = useQueryClient(); ->>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) if (!room) { throw Error('Room not provided'); @@ -91,29 +86,12 @@ export const useChangeOwnerAction = (user: Pick, rid: }, }); -<<<<<<< HEAD const handleChangeOwner = useCallback(() => { if (!isRoomFederated(room)) { return toggleOwnerMutation.mutateAsync({ roomId: rid, userId: uid }); } const changingOwnRole = uid === loggedUserId; -======= - const handleConfirm = useCallback(async () => { - await changeOwner({ roomId: rid, userId: uid }); - queryClient.invalidateQueries({ queryKey: ['members'] }); - closeModal(); - }, [changeOwner, rid, uid, queryClient, closeModal]); - - const handleChangeOwner = useCallback( - async ({ userId }) => { - if (!isRoomFederated(room)) { - await changeOwner({ roomId: rid, userId: uid }); - queryClient.invalidateQueries({ queryKey: ['members'] }); - return; - } - const changingOwnRole = userId === loggedUserId; ->>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) const closeModal = () => { setModal(null); @@ -124,7 +102,6 @@ export const useChangeOwnerAction = (user: Pick, rid: closeModal(); }; -<<<<<<< HEAD if (changingOwnRole && loggedUserIsOwner) { return setModal( getWarningModalForFederatedRooms( @@ -153,12 +130,6 @@ export const useChangeOwnerAction = (user: Pick, rid: }, [room, loggedUserId, loggedUserIsOwner, toggleOwnerMutation, rid, uid, t, setModal]); const changeOwnerAction = useEffectEvent(async () => handleChangeOwner()); -======= - changeOwner({ roomId: rid, userId: uid }); - }, - [room, loggedUserId, loggedUserIsOwner, changeOwner, rid, uid, queryClient, setModal, closeModal, handleConfirm, t], - ); ->>>>>>> 89ab3a4f1b (feat: Room roles visibility in members panel) const changeOwnerOption = useMemo( () => From 15f7d2a2655bd0055af5af69bf97a5fbd0b3a1ab Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Thu, 16 Jan 2025 02:39:03 +0530 Subject: [PATCH 03/10] showing roles count Signed-off-by: Abhinav Kumar --- apps/meteor/app/api/server/v1/rooms.ts | 5 ----- .../client/views/hooks/useMembersList.ts | 1 - .../RoomMembers/MembersListDivider.tsx | 18 +++++++++++++++--- .../contextualBar/RoomMembers/RoomMembers.tsx | 12 ++++++------ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 73cba79b1a39..589b7af3d883 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -13,7 +13,6 @@ import { isRoomsOpenProps, isRoomsMembersOrderedByRoleProps, } from '@rocket.chat/rest-typings'; -import { MembershipCache } from 'matrix-appservice-bridge'; import { Meteor } from 'meteor/meteor'; import { isTruthy } from '../../../../lib/isTruthy'; @@ -904,10 +903,6 @@ API.v1.addRoute( sort, }); - members.forEach((member) => { - console.log(member.roles); - }); - return API.v1.success({ members, count: members.length, diff --git a/apps/meteor/client/views/hooks/useMembersList.ts b/apps/meteor/client/views/hooks/useMembersList.ts index dfd6e769f8a6..021f1473d898 100644 --- a/apps/meteor/client/views/hooks/useMembersList.ts +++ b/apps/meteor/client/views/hooks/useMembersList.ts @@ -27,7 +27,6 @@ export const useMembersList = (options: MembersListOptions) => { roomId: options.rid, offset: start, count: 20, - rolesOrder: ['owner', 'moderator'], ...(options.debouncedText && { filter: options.debouncedText }), ...(options.type !== 'all' && { status: [options.type] }), }); diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx index 4d2208fdca05..a4ae591cd761 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx @@ -1,18 +1,30 @@ import { Box } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import React from 'react'; import { useTranslation } from 'react-i18next'; type MembersListDividerProps = { title: TranslationKey; + count: number; }; -export const MembersListDivider = ({ title }: MembersListDividerProps) => { +export const MembersListDivider = ({ title, count }: MembersListDividerProps) => { const { t } = useTranslation(); return ( - + {t(title)} + {count} ); }; diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx index a34e0cc6bc40..c577c8ecd3b1 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx @@ -22,7 +22,7 @@ import { import { VirtuosoScrollbars } from '../../../../components/CustomScrollbars'; import InfiniteListAnchor from '../../../../components/InfiniteListAnchor'; -type RoomMemberUser = Pick & { roles: IRole['_id'] }; +type RoomMemberUser = Pick & { roles?: IRole['_id'] }; type RoomMembersProps = { rid: IRoom['_id']; @@ -97,17 +97,17 @@ const RoomMembers = ({ if (owners.length > 0) { counts.push(owners.length); - titles.push(); + titles.push(); } if (moderators.length > 0) { counts.push(moderators.length); - titles.push(); + titles.push(); } - if (members.length > 0) { + if (normalMembers.length > 0) { counts.push(normalMembers.length); - titles.push(); + titles.push(); } return { counts, titles }; @@ -149,7 +149,7 @@ const RoomMembers = ({ {!loading && members.length > 0 && ( <> - + {t('Showing_current_of_total', { current: members.length, total })} From 9789a47c69fe40c283ff958df23f3d86b4cb0568 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Thu, 16 Jan 2025 03:16:20 +0530 Subject: [PATCH 04/10] ui improvements according to figma design Signed-off-by: Abhinav Kumar --- .../room/contextualBar/RoomMembers/MembersListDivider.tsx | 4 +++- .../views/room/contextualBar/RoomMembers/RoomMembers.tsx | 6 +++--- .../room/contextualBar/RoomMembers/RoomMembersItem.tsx | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx index a4ae591cd761..8e9abf5c567d 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/MembersListDivider.tsx @@ -18,10 +18,12 @@ export const MembersListDivider = ({ title, count }: MembersListDividerProps) => fontScale='p2m' color='defaut' paddingBlock={8} - paddingInline={16} + paddingInline={24} display='flex' flexDirection='row' justifyContent='space-between' + borderBlockEndWidth={1} + borderBlockEndColor='extra-light' > {t(title)} {count} diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx index c577c8ecd3b1..729a8b2229d5 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx @@ -132,7 +132,7 @@ const RoomMembers = ({