From 6ae9ef2a44734278d4f004aa092a53f5bcf6c9aa Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 11:41:10 -0300 Subject: [PATCH 01/31] feat: add references to room.info endpoint --- apps/meteor/app/api/server/v1/rooms.ts | 18 ++++++++++++++---- packages/rest-typings/src/v1/rooms.ts | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index e3296b98ef17..ae846f0bd752 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -1,4 +1,4 @@ -import { Media } from '@rocket.chat/core-services'; +import { Media, Team } from '@rocket.chat/core-services'; import type { IRoom, IUpload } from '@rocket.chat/core-typings'; import { Messages, Rooms, Users, Uploads } from '@rocket.chat/models'; import type { Notifications } from '@rocket.chat/rest-typings'; @@ -36,6 +36,7 @@ import { async function findRoomByIdOrName({ params, checkedArchived = true, + fields, }: { params: | { @@ -45,6 +46,7 @@ async function findRoomByIdOrName({ roomName?: string; }; checkedArchived?: boolean; + fields?: Partial; }): Promise { if ( (!('roomId' in params) && !('roomName' in params)) || @@ -53,7 +55,7 @@ async function findRoomByIdOrName({ throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required'); } - const projection = { ...API.v1.defaultFieldsToExclude }; + const projection = fields || { ...API.v1.defaultFieldsToExclude }; let room; if ('roomId' in params) { @@ -403,14 +405,22 @@ API.v1.addRoute( { authRequired: true }, { async get() { - const room = await findRoomByIdOrName({ params: this.queryParams }); const { fields } = await this.parseJsonQuery(); + const room = await findRoomByIdOrName({ params: this.queryParams, fields }); if (!room || !(await canAccessRoomAsync(room, { _id: this.userId }))) { return API.v1.failure('not-allowed', 'Not Allowed'); } - return API.v1.success({ room: (await Rooms.findOneByIdOrName(room._id, { projection: fields })) ?? undefined }); + const team = room.teamId && (await Team.getOneById(room.teamId)); + + const parent = room.prid && (await Rooms.findOneById(room.prid, { ...API.v1.defaultFieldsToExclude })); + + return API.v1.success({ + room: room ?? undefined, + ...(team && { team }), + ...(parent && { parent }), + }); }, }, ); diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 1c0b6a360f7b..2ec9b273c063 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -1,4 +1,4 @@ -import type { IMessage, IRoom, IUser, RoomAdminFieldsType, IUpload, IE2EEMessage } from '@rocket.chat/core-typings'; +import type { IMessage, IRoom, IUser, RoomAdminFieldsType, IUpload, IE2EEMessage, ITeam } from '@rocket.chat/core-typings'; import type { PaginatedRequest } from '../helpers/PaginatedRequest'; import type { PaginatedResult } from '../helpers/PaginatedResult'; @@ -555,6 +555,8 @@ export type RoomsEndpoints = { '/v1/rooms.info': { GET: (params: RoomsInfoProps) => { room: IRoom | undefined; + parent?: IRoom; + team?: ITeam; }; }; From 8cb49a3051ccbf18fb1afa63a2a7f5a38fd027c2 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 12:25:16 -0300 Subject: [PATCH 02/31] feat: display header based on new data from rooms endpoint --- .../views/room/Header/ParentRoomWithData.tsx | 19 ++++--- .../Header/ParentRoomWithEndpointData.tsx | 12 +++++ .../client/views/room/Header/ParentTeam.tsx | 53 ++++--------------- .../client/views/room/Header/RoomHeader.tsx | 4 +- 4 files changed, 35 insertions(+), 53 deletions(-) diff --git a/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx b/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx index 0e11c33aed4e..c76a9353220b 100644 --- a/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx @@ -10,20 +10,27 @@ type ParentRoomWithDataProps = { room: IRoom; }; -const ParentRoomWithData = ({ room }: ParentRoomWithDataProps): ReactElement => { - const { prid } = room; +const getParentId = ({ prid, teamId }: IRoom): string => { + if (prid) { + return prid; + } - if (!prid) { - throw new Error('Parent room ID is missing'); + if (teamId) { + return teamId; } - const subscription = useUserSubscription(prid); + throw new Error('Parent room ID is missing'); +}; + +const ParentRoomWithData = ({ room }: ParentRoomWithDataProps): ReactElement => { + const parentId = getParentId(room); + const subscription = useUserSubscription(parentId); if (subscription) { return ; } - return ; + return ; }; export default ParentRoomWithData; diff --git a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx index 06571dd02cce..d1872cced323 100644 --- a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx @@ -5,6 +5,7 @@ import React from 'react'; import { HeaderTagSkeleton } from '../../../components/Header'; import { useRoomInfoEndpoint } from '../../../hooks/useRoomInfoEndpoint'; import ParentRoom from './ParentRoom'; +import ParentTeam from './ParentTeam'; type ParentRoomWithEndpointDataProps = { rid: IRoom['_id']; @@ -21,6 +22,17 @@ const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps): R return null; } + if (data.parent) { + return ; + } + + if (data.team) { + if (data.team.roomId === rid) { + return null; + } + return ; + } + return ; }; diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index ed4a4588ef21..0a14a2b95c60 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -1,50 +1,23 @@ -import type { IRoom } from '@rocket.chat/core-typings'; +import type { ITeam } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; -import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React from 'react'; -import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; +import { HeaderTag, HeaderTagIcon } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; -type APIErrorResult = { success: boolean; error: string }; - -const ParentTeam = ({ room }: { room: IRoom }): ReactElement | null => { - const { teamId } = room; - const userId = useUserId(); - - if (!teamId) { - throw new Error('invalid rid'); - } - - if (!userId) { - throw new Error('invalid uid'); - } - - const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); - const userTeamsListEndpoint = useEndpoint('GET', '/v1/users.listTeams'); - - const { - data: teamInfoData, - isLoading: teamInfoLoading, - isError: teamInfoError, - } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, - retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, - }); - - const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); - - const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; - const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; +const ParentTeam = ({ team }: { team: ITeam }): ReactElement | null => { + const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; const redirectToMainRoom = (): void => { - const rid = teamInfoData?.teamInfo.roomId; + const rid = team.roomId; if (!rid) { return; } + const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; + // TODO how to know if belongs to team? + const userBelongsToTeam = false; if (!(isTeamPublic || userBelongsToTeam)) { return; } @@ -52,14 +25,6 @@ const ParentTeam = ({ room }: { room: IRoom }): ReactElement | null => { goToRoomById(rid); }; - if (teamInfoLoading || userTeamsLoading) { - return ; - } - - if (teamInfoError) { - return null; - } - return ( { onClick={redirectToMainRoom} > - {teamInfoData?.teamInfo.name} + {team.name} ); }; diff --git a/apps/meteor/client/views/room/Header/RoomHeader.tsx b/apps/meteor/client/views/room/Header/RoomHeader.tsx index 2e38e2110bbe..34a6299068fa 100644 --- a/apps/meteor/client/views/room/Header/RoomHeader.tsx +++ b/apps/meteor/client/views/room/Header/RoomHeader.tsx @@ -8,7 +8,6 @@ import { Header, HeaderAvatar, HeaderContent, HeaderContentRow, HeaderSubtitle, import MarkdownText from '../../../components/MarkdownText'; import FederatedRoomOriginServer from './FederatedRoomOriginServer'; import ParentRoomWithData from './ParentRoomWithData'; -import ParentTeam from './ParentTeam'; import RoomTitle from './RoomTitle'; import RoomToolbox from './RoomToolbox'; import Encrypted from './icons/Encrypted'; @@ -47,8 +46,7 @@ const RoomHeader = ({ room, topic = '', slots = {}, roomToolbox }: RoomHeaderPro - {room.prid && } - {room.teamId && !room.teamMain && } + {(room.prid || room.teamId) && } {isRoomFederated(room) && } From 1b7dcd8b74953e5cc4c48b29bd218f0386155174 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 14:13:46 -0300 Subject: [PATCH 03/31] fix endpoint behavior --- apps/meteor/app/api/server/v1/rooms.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index ae846f0bd752..ea9072393df3 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -405,8 +405,8 @@ API.v1.addRoute( { authRequired: true }, { async get() { + const room = await findRoomByIdOrName({ params: this.queryParams }); const { fields } = await this.parseJsonQuery(); - const room = await findRoomByIdOrName({ params: this.queryParams, fields }); if (!room || !(await canAccessRoomAsync(room, { _id: this.userId }))) { return API.v1.failure('not-allowed', 'Not Allowed'); @@ -417,7 +417,7 @@ API.v1.addRoute( const parent = room.prid && (await Rooms.findOneById(room.prid, { ...API.v1.defaultFieldsToExclude })); return API.v1.success({ - room: room ?? undefined, + room: (await Rooms.findOneById(room._id, { projection: fields })) ?? undefined, ...(team && { team }), ...(parent && { parent }), }); From f5af8c10b0350b8d8f6cfd453d88ffcaa34e617c Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 17:16:43 -0300 Subject: [PATCH 04/31] belong to team --- apps/meteor/client/views/room/Header/ParentTeam.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index 0a14a2b95c60..08ca592ac4cb 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -17,7 +17,7 @@ const ParentTeam = ({ team }: { team: ITeam }): ReactElement | null => { const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; // TODO how to know if belongs to team? - const userBelongsToTeam = false; + const userBelongsToTeam = true; if (!(isTeamPublic || userBelongsToTeam)) { return; } From 1bcb25c471d3edf4b00de467c8e88b46aa5e99db Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 18:13:21 -0300 Subject: [PATCH 05/31] return less data --- apps/meteor/app/api/server/v1/rooms.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index ea9072393df3..3734c0d90e89 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -412,9 +412,9 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } - const team = room.teamId && (await Team.getOneById(room.teamId)); + const team = room.teamId && (await Team.getOneById(room.teamId, { projection: { name: 1, roomId: 1, type: 1 } })); - const parent = room.prid && (await Rooms.findOneById(room.prid, { ...API.v1.defaultFieldsToExclude })); + const parent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1 } })); return API.v1.success({ room: (await Rooms.findOneById(room._id, { projection: fields })) ?? undefined, From 813c81a18aae4b66f801c2b3f1eb9023d92e3946 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 19:20:18 -0300 Subject: [PATCH 06/31] add hasSubscription --- apps/meteor/client/lib/rooms/roomCoordinator.tsx | 3 +++ apps/meteor/client/views/room/Header/ParentRoom.tsx | 7 ++++++- .../meteor/client/views/room/Header/ParentRoomWithData.tsx | 2 +- apps/meteor/client/views/room/Header/ParentTeam.tsx | 7 +++++-- apps/meteor/definition/IRoomTypeConfig.ts | 1 + 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/meteor/client/lib/rooms/roomCoordinator.tsx b/apps/meteor/client/lib/rooms/roomCoordinator.tsx index 31eda2982a12..11bbe0ef3a49 100644 --- a/apps/meteor/client/lib/rooms/roomCoordinator.tsx +++ b/apps/meteor/client/lib/rooms/roomCoordinator.tsx @@ -63,6 +63,9 @@ class RoomCoordinatorClient extends RoomCoordinator { canSendMessage(rid: string): boolean { return ChatSubscription.find({ rid }).count() > 0; }, + hasSubscription(rid: string): boolean { + return ChatSubscription.find({ rid }).count() > 0; + }, ...directives, config: roomConfig, }); diff --git a/apps/meteor/client/views/room/Header/ParentRoom.tsx b/apps/meteor/client/views/room/Header/ParentRoom.tsx index 5907b3019084..bbe2ec1e2652 100644 --- a/apps/meteor/client/views/room/Header/ParentRoom.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoom.tsx @@ -13,7 +13,12 @@ type ParentRoomProps = { const ParentRoom = ({ room }: ParentRoomProps): ReactElement => { const icon = useRoomIcon(room); - const handleRedirect = (): void => roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); + const handleRedirect = (): void => { + if (!roomCoordinator.getRoomDirectives(room.t).hasSubscription(room._id)) { + return; + } + roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); + }; return ( const subscription = useUserSubscription(parentId); if (subscription) { - return ; + return ; } return ; diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index 08ca592ac4cb..700132479691 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -1,5 +1,6 @@ import type { ITeam } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; +import { useUserSubscription } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; @@ -9,6 +10,8 @@ import { goToRoomById } from '../../../lib/utils/goToRoomById'; const ParentTeam = ({ team }: { team: ITeam }): ReactElement | null => { const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; + const subscription = useUserSubscription(team.roomId); + const redirectToMainRoom = (): void => { const rid = team.roomId; if (!rid) { @@ -16,8 +19,8 @@ const ParentTeam = ({ team }: { team: ITeam }): ReactElement | null => { } const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; - // TODO how to know if belongs to team? - const userBelongsToTeam = true; + const userBelongsToTeam = !!subscription; + if (!(isTeamPublic || userBelongsToTeam)) { return; } diff --git a/apps/meteor/definition/IRoomTypeConfig.ts b/apps/meteor/definition/IRoomTypeConfig.ts index 12a4bea39f05..83c0c28053c5 100644 --- a/apps/meteor/definition/IRoomTypeConfig.ts +++ b/apps/meteor/definition/IRoomTypeConfig.ts @@ -86,6 +86,7 @@ export interface IRoomTypeClientDirectives { showJoinLink: (roomId: string) => boolean; isLivechatRoom: () => boolean; canSendMessage: (rid: string) => boolean; + hasSubscription: (rid: string) => boolean; readOnly?: (rid: string, user: AtLeast) => boolean; } From 96c442f99207f500fdc79d7557ddd4ee4c8e01ed Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 8 Aug 2024 19:20:24 -0300 Subject: [PATCH 07/31] revert fields --- apps/meteor/app/api/server/v1/rooms.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 3734c0d90e89..3e2d7a67b819 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -36,7 +36,6 @@ import { async function findRoomByIdOrName({ params, checkedArchived = true, - fields, }: { params: | { @@ -46,7 +45,6 @@ async function findRoomByIdOrName({ roomName?: string; }; checkedArchived?: boolean; - fields?: Partial; }): Promise { if ( (!('roomId' in params) && !('roomName' in params)) || @@ -55,7 +53,7 @@ async function findRoomByIdOrName({ throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required'); } - const projection = fields || { ...API.v1.defaultFieldsToExclude }; + const projection = { ...API.v1.defaultFieldsToExclude }; let room; if ('roomId' in params) { From 33eff92498103c5b58ef024c60c4c7fdb464a0aa Mon Sep 17 00:00:00 2001 From: juliajforesti Date: Mon, 19 Aug 2024 19:57:53 -0300 Subject: [PATCH 08/31] feat: `rooms.info.teamAndParent` method --- apps/meteor/app/api/server/v1/rooms.ts | 26 ++++++++++++++++++- .../client/hooks/useRoomInfoEndpoint.ts | 4 +-- packages/rest-typings/src/v1/rooms.ts | 6 +++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 3e2d7a67b819..703a5094d4e2 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -410,14 +410,38 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } + return API.v1.success({ room: (await Rooms.findOneByIdOrName(room._id, { projection: fields })) ?? undefined }); + }, + }, +); + +API.v1.addRoute( + 'rooms.info.teamAndParent', + { authRequired: true }, + { + async get() { + const room = await findRoomByIdOrName({ params: this.queryParams }); + const { fields } = await this.parseJsonQuery(); + + if (!room || !(await canAccessRoomAsync(room, { _id: this.userId }))) { + return API.v1.failure('not-allowed', 'Not Allowed'); + } + const team = room.teamId && (await Team.getOneById(room.teamId, { projection: { name: 1, roomId: 1, type: 1 } })); - const parent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1 } })); + const teamParentRoom = + team !== '' && + team?.roomId && + !room.teamMain && + (await Rooms.findOneById(room.prid || team?.roomId, { projection: { name: 1, fname: 1, t: 1, sidepanel: 1 } })); + + const parent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1, sidepanel: 1 } })); return API.v1.success({ room: (await Rooms.findOneById(room._id, { projection: fields })) ?? undefined, ...(team && { team }), ...(parent && { parent }), + ...(teamParentRoom && { parent: teamParentRoom }), }); }, }, diff --git a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts index 47ea84af20b6..e3788078f8b4 100644 --- a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts +++ b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts @@ -6,8 +6,8 @@ import { useQuery } from '@tanstack/react-query'; import { minutesToMilliseconds } from 'date-fns'; import type { Meteor } from 'meteor/meteor'; -export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult> => { - const getRoomInfo = useEndpoint('GET', '/v1/rooms.info'); +export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult> => { + const getRoomInfo = useEndpoint('GET', '/v1/rooms.info.teamAndParent'); return useQuery(['/v1/rooms.info', rid], () => getRoomInfo({ roomId: rid }), { cacheTime: minutesToMilliseconds(15), staleTime: minutesToMilliseconds(5), diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 2ec9b273c063..577a00c69413 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -555,6 +555,12 @@ export type RoomsEndpoints = { '/v1/rooms.info': { GET: (params: RoomsInfoProps) => { room: IRoom | undefined; + }; + }; + + '/v1/rooms.info.teamAndParent': { + GET: (params: RoomsInfoProps) => { + room: IRoom; parent?: IRoom; team?: ITeam; }; From 8f7383820a9e82ee7f3ad3cf2714a623d814b1f3 Mon Sep 17 00:00:00 2001 From: juliajforesti Date: Tue, 20 Aug 2024 14:51:52 -0300 Subject: [PATCH 09/31] test: add `/rooms.info.teamAndParent` test case --- apps/meteor/tests/end-to-end/api/rooms.ts | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index d59d3722f1a4..e67706a127ff 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -1157,6 +1157,63 @@ describe('[Rooms]', () => { }); }); + describe('[/rooms.info.teamAndParent]', () => { + const testChannelName = `channel.test.${Date.now()}-${Math.random()}`; + const teamName = `test-team-${Date.now()}`; + const discussionName = `test-discussion-${Date.now()}`; + let testChannel: IRoom; + let testDiscussion: IRoom; + let testTeam: ITeam; + + before(async () => { + testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel; + + const teamResponse = await request.post(api('teams.create')).set(credentials).send({ name: teamName, type: 1 }).expect(200); + testTeam = teamResponse.body.team; + + const resDiscussion = await request.post(api('rooms.createDiscussion')).set(credentials).send({ + prid: testChannel._id, + t_name: discussionName, + }); + testDiscussion = resDiscussion.body.discussion; + + await request + .post(api('teams.addRooms')) + .set(credentials) + .send({ rooms: [testChannel._id], teamId: testTeam._id }); + }); + + after(() => + Promise.all([ + deleteRoom({ type: 'c', roomId: testChannel._id }), + deleteRoom({ type: 'p', roomId: testDiscussion._id }), + deleteTeam(credentials, teamName), + ]), + ); + + it('should return the channel info, team and parent info', async () => { + const result = await request.get(api('rooms.info.teamAndParent')).set(credentials).query({ roomId: testChannel._id }).expect(200); + + expect(result.body).to.have.property('success', true); + expect(result.body).to.have.property('team'); + expect(result.body).to.have.property('parent'); + expect(result.body.parent).to.have.property('_id').and.to.equal(testTeam.roomId); + }); + + it('should return the dicsussion room info and parent info', async () => { + await request + .get(api('rooms.info.teamAndParent')) + .set(credentials) + .query({ roomId: testDiscussion._id }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('parent').and.to.be.an('object'); + expect(res.body.parent).to.have.property('_id').and.to.be.equal(testChannel._id); + }); + }); + }); + describe('[/rooms.leave]', () => { let testChannel: IRoom; let testGroup: IRoom; From 6f2211f5772232670d1b15269a1fe1af9aa6c17c Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 27 Aug 2024 10:14:14 -0600 Subject: [PATCH 10/31] update rooms.info endp --- apps/meteor/app/api/server/v1/rooms.ts | 33 +--- .../client/hooks/useRoomInfoEndpoint.ts | 4 +- apps/meteor/tests/end-to-end/api/rooms.ts | 167 +++++++++++++----- packages/rest-typings/src/v1/rooms.ts | 6 - 4 files changed, 129 insertions(+), 81 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 7773230b38d0..edf9bac457fb 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -416,38 +416,19 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } - return API.v1.success({ room: (await Rooms.findOneByIdOrName(room._id, { projection: fields })) ?? undefined }); - }, - }, -); - -API.v1.addRoute( - 'rooms.info.teamAndParent', - { authRequired: true }, - { - async get() { - const room = await findRoomByIdOrName({ params: this.queryParams }); - const { fields } = await this.parseJsonQuery(); - - if (!room || !(await canAccessRoomAsync(room, { _id: this.userId }))) { - return API.v1.failure('not-allowed', 'Not Allowed'); - } - const team = room.teamId && (await Team.getOneById(room.teamId, { projection: { name: 1, roomId: 1, type: 1 } })); - + const discussionParent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1 } })); const teamParentRoom = - team !== '' && - team?.roomId && - !room.teamMain && - (await Rooms.findOneById(room.prid || team?.roomId, { projection: { name: 1, fname: 1, t: 1, sidepanel: 1 } })); - - const parent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1, sidepanel: 1 } })); + team && + room.teamId && + !room.teamMain && // if a room is the main room of a team, it has no parent room + (await Rooms.findOneById(team.roomId, { projection: { name: 1, fname: 1, t: 1 } })); + const parent = discussionParent || teamParentRoom; return API.v1.success({ - room: (await Rooms.findOneById(room._id, { projection: fields })) ?? undefined, + room: (await Rooms.findOneByIdOrName(room._id, { projection: fields })) ?? undefined, ...(team && { team }), ...(parent && { parent }), - ...(teamParentRoom && { parent: teamParentRoom }), }); }, }, diff --git a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts index e3788078f8b4..47ea84af20b6 100644 --- a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts +++ b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts @@ -6,8 +6,8 @@ import { useQuery } from '@tanstack/react-query'; import { minutesToMilliseconds } from 'date-fns'; import type { Meteor } from 'meteor/meteor'; -export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult> => { - const getRoomInfo = useEndpoint('GET', '/v1/rooms.info.teamAndParent'); +export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult> => { + const getRoomInfo = useEndpoint('GET', '/v1/rooms.info'); return useQuery(['/v1/rooms.info', rid], () => getRoomInfo({ roomId: rid }), { cacheTime: minutesToMilliseconds(15), staleTime: minutesToMilliseconds(5), diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index d85c299cc7cc..19349ad858e9 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -1229,65 +1229,138 @@ describe('[Rooms]', () => { }) .end(done); }); - }); - describe('[/rooms.info.teamAndParent]', () => { - const testChannelName = `channel.test.${Date.now()}-${Math.random()}`; - const teamName = `test-team-${Date.now()}`; - const discussionName = `test-discussion-${Date.now()}`; - let testChannel: IRoom; - let testDiscussion: IRoom; - let testTeam: ITeam; + it('should not return parent & team for room thats not on a team nor is a discussion', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ + roomId: testChannel._id, + }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('room').and.to.be.an('object'); + expect(res.body.room).to.not.have.property('team'); + expect(res.body.room).to.not.have.property('prid'); + }); + }); - before(async () => { - testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel; + describe('with team and parent data', () => { + const testChannelName = `channel.test.${Date.now()}-${Math.random()}`; + const teamName = `test-team-${Date.now()}`; + const discussionName = `test-discussion-${Date.now()}`; + const testChannelOutsideTeamname = `channel.test.outside.${Date.now()}-${Math.random()}`; + let testChannel: IRoom; + let testDiscussion: IRoom; + let testTeam: ITeam; + let testChannelOutside: IRoom; + let testDiscussionOutsideTeam: IRoom; + + before(async () => { + testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel; + + const teamResponse = await request.post(api('teams.create')).set(credentials).send({ name: teamName, type: 1 }).expect(200); + testTeam = teamResponse.body.team; - const teamResponse = await request.post(api('teams.create')).set(credentials).send({ name: teamName, type: 1 }).expect(200); - testTeam = teamResponse.body.team; + const resDiscussion = await request.post(api('rooms.createDiscussion')).set(credentials).send({ + prid: testChannel._id, + t_name: discussionName, + }); + testDiscussion = resDiscussion.body.discussion; - const resDiscussion = await request.post(api('rooms.createDiscussion')).set(credentials).send({ - prid: testChannel._id, - t_name: discussionName, + await request + .post(api('teams.addRooms')) + .set(credentials) + .send({ rooms: [testChannel._id], teamId: testTeam._id }); }); - testDiscussion = resDiscussion.body.discussion; - await request - .post(api('teams.addRooms')) - .set(credentials) - .send({ rooms: [testChannel._id], teamId: testTeam._id }); - }); + before(async () => { + testChannelOutside = (await createRoom({ type: 'c', name: testChannelOutsideTeamname })).body.channel; + testDiscussionOutsideTeam = ( + await request + .post(api('rooms.createDiscussion')) + .set(credentials) + .send({ + prid: testChannelOutside._id, + t_name: `test-discussion-${Date.now()}`, + }) + ).body.discussion; + }); - after(() => - Promise.all([ - deleteRoom({ type: 'c', roomId: testChannel._id }), - deleteRoom({ type: 'p', roomId: testDiscussion._id }), - deleteTeam(credentials, teamName), - ]), - ); + after(() => + Promise.all([ + deleteRoom({ type: 'c', roomId: testChannel._id }), + deleteRoom({ type: 'p', roomId: testDiscussion._id }), + deleteRoom({ type: 'c', roomId: testChannelOutside._id }), + deleteRoom({ type: 'p', roomId: testDiscussionOutsideTeam._id }), + deleteTeam(credentials, teamName), + ]), + ); + + it('should return the channel info, team and parent info', async () => { + const result = await request.get(api('rooms.info')).set(credentials).query({ roomId: testChannel._id }).expect(200); + + expect(result.body).to.have.property('success', true); + expect(result.body).to.have.property('team'); + expect(result.body).to.have.property('parent'); + expect(result.body.parent).to.have.property('_id').and.to.equal(testTeam.roomId); + }); - it('should return the channel info, team and parent info', async () => { - const result = await request.get(api('rooms.info.teamAndParent')).set(credentials).query({ roomId: testChannel._id }).expect(200); + it('should return the dicsussion room info and parent info', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ roomId: testDiscussion._id }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('parent').and.to.be.an('object'); + expect(res.body.parent).to.have.property('_id').and.to.be.equal(testChannel._id); + }); + }); - expect(result.body).to.have.property('success', true); - expect(result.body).to.have.property('team'); - expect(result.body).to.have.property('parent'); - expect(result.body.parent).to.have.property('_id').and.to.equal(testTeam.roomId); - }); + it('should not return parent info for the main room of the team', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ roomId: testTeam.roomId }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.not.have.property('parent'); + expect(res.body).to.have.property('team'); + }); + }); - it('should return the dicsussion room info and parent info', async () => { - await request - .get(api('rooms.info.teamAndParent')) - .set(credentials) - .query({ roomId: testDiscussion._id }) - .expect(200) - .expect((res) => { - expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('parent').and.to.be.an('object'); - expect(res.body.parent).to.have.property('_id').and.to.be.equal(testChannel._id); - }); + it('should not return team for room outside team', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ roomId: testChannelOutside._id }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.not.have.property('team'); + expect(res.body).to.not.have.property('parent'); + }); + }); + + it('should return the parent for discussion outside team', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ roomId: testDiscussionOutsideTeam._id }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('parent').and.to.be.an('object'); + expect(res.body.parent).to.have.property('_id').and.to.be.equal(testChannelOutside._id); + expect(res.body).to.not.have.property('team'); + }); + }); }); }); - describe('[/rooms.leave]', () => { let testChannel: IRoom; let testGroup: IRoom; diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 7454f9e45ae7..32dd152c44a4 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -570,12 +570,6 @@ export type RoomsEndpoints = { '/v1/rooms.info': { GET: (params: RoomsInfoProps) => { room: IRoom | undefined; - }; - }; - - '/v1/rooms.info.teamAndParent': { - GET: (params: RoomsInfoProps) => { - room: IRoom; parent?: IRoom; team?: ITeam; }; From d8a293b75db06eb4fcb828c5ebe0b036ffd5d54e Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 27 Aug 2024 10:42:50 -0600 Subject: [PATCH 11/31] move logic to service --- apps/meteor/app/api/server/v1/rooms.ts | 9 ++------ apps/meteor/server/services/team/service.ts | 23 +++++++++++++++++++ .../core-services/src/types/ITeamService.ts | 4 ++++ packages/rest-typings/src/v1/rooms.ts | 4 ++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index edf9bac457fb..e426de787c14 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -416,14 +416,9 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } - const team = room.teamId && (await Team.getOneById(room.teamId, { projection: { name: 1, roomId: 1, type: 1 } })); const discussionParent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1 } })); - const teamParentRoom = - team && - room.teamId && - !room.teamMain && // if a room is the main room of a team, it has no parent room - (await Rooms.findOneById(team.roomId, { projection: { name: 1, fname: 1, t: 1 } })); - const parent = discussionParent || teamParentRoom; + const { team, parentRoom } = await Team.getRoomInfo(room); + const parent = discussionParent || parentRoom; return API.v1.success({ room: (await Rooms.findOneByIdOrName(room._id, { projection: fields })) ?? undefined, diff --git a/apps/meteor/server/services/team/service.ts b/apps/meteor/server/services/team/service.ts index 190464f48da4..201229af35ff 100644 --- a/apps/meteor/server/services/team/service.ts +++ b/apps/meteor/server/services/team/service.ts @@ -20,6 +20,7 @@ import type { ITeam, ITeamMember, ITeamStats, + AtLeast, } from '@rocket.chat/core-typings'; import type { InsertionModel } from '@rocket.chat/model-typings'; import { Team, Rooms, Subscriptions, Users, TeamMember } from '@rocket.chat/models'; @@ -1053,4 +1054,26 @@ export class TeamService extends ServiceClassInternal implements ITeamService { return rooms; } + + async getParentRoom(team: AtLeast): Promise | null> { + return Rooms.findOneById>(team.roomId, { projection: { name: 1, fname: 1, t: 1 } }); + } + + async getRoomInfo(room: AtLeast): Promise<{ team?: Pick; parentRoom?: Pick }> { + if (!room.teamId) { + return {}; + } + + const team = await Team.findOneById(room.teamId, { projection: { _id: 1, name: 1, roomId: 1, type: 1 } }); + if (!team) { + return {}; + } + + if (room.teamMain) { + return { team }; + } + + const parentRoom = await this.getParentRoom(team); + return { team, ...(parentRoom && { parentRoom }) }; + } } diff --git a/packages/core-services/src/types/ITeamService.ts b/packages/core-services/src/types/ITeamService.ts index 2d67bf515fca..25457db6d19b 100644 --- a/packages/core-services/src/types/ITeamService.ts +++ b/packages/core-services/src/types/ITeamService.ts @@ -9,6 +9,7 @@ import type { IRoom, IUser, IRole, + AtLeast, } from '@rocket.chat/core-typings'; import type { Document, Filter, FindOptions } from 'mongodb'; @@ -125,4 +126,7 @@ export interface ITeamService { getStatistics(): Promise; findBySubscribedUserIds(userId: string, callerId?: string): Promise; addRolesToMember(teamId: string, userId: string, roles: Array): Promise; + getRoomInfo( + room: AtLeast, + ): Promise<{ team?: Pick; parentRoom?: Pick }>; } diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 32dd152c44a4..c2a880367d27 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -570,8 +570,8 @@ export type RoomsEndpoints = { '/v1/rooms.info': { GET: (params: RoomsInfoProps) => { room: IRoom | undefined; - parent?: IRoom; - team?: ITeam; + parent?: Pick; + team?: Pick; }; }; From af437b68d0beb2550385fc38d685aceba8a4b89c Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 27 Aug 2024 11:11:24 -0600 Subject: [PATCH 12/31] lint --- apps/meteor/server/services/team/service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/meteor/server/services/team/service.ts b/apps/meteor/server/services/team/service.ts index 201229af35ff..4dc027efa00a 100644 --- a/apps/meteor/server/services/team/service.ts +++ b/apps/meteor/server/services/team/service.ts @@ -1059,7 +1059,9 @@ export class TeamService extends ServiceClassInternal implements ITeamService { return Rooms.findOneById>(team.roomId, { projection: { name: 1, fname: 1, t: 1 } }); } - async getRoomInfo(room: AtLeast): Promise<{ team?: Pick; parentRoom?: Pick }> { + async getRoomInfo( + room: AtLeast, + ): Promise<{ team?: Pick; parentRoom?: Pick }> { if (!room.teamId) { return {}; } From 308e4da21c86d6376391a0cdc350fe2aa8ba9c1f Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 27 Aug 2024 11:25:44 -0600 Subject: [PATCH 13/31] ts --- apps/meteor/app/api/server/v1/rooms.ts | 2 +- apps/meteor/client/views/room/Header/ParentTeam.tsx | 2 +- packages/core-services/src/types/ITeamService.ts | 2 +- packages/rest-typings/src/v1/rooms.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index e426de787c14..b9e3a2e658de 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -416,7 +416,7 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } - const discussionParent = room.prid && (await Rooms.findOneById(room.prid, { projection: { name: 1, fname: 1, t: 1 } })); + const discussionParent = room.prid && (await Rooms.findOneById>(room.prid, { projection: { name: 1, fname: 1, t: 1, prid: 1, u: 1 } })); const { team, parentRoom } = await Team.getRoomInfo(room); const parent = discussionParent || parentRoom; diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index 700132479691..6a77f6fb0299 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { HeaderTag, HeaderTagIcon } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; -const ParentTeam = ({ team }: { team: ITeam }): ReactElement | null => { +const ParentTeam = ({ team }: { team: Pick }): ReactElement | null => { const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; const subscription = useUserSubscription(team.roomId); diff --git a/packages/core-services/src/types/ITeamService.ts b/packages/core-services/src/types/ITeamService.ts index 25457db6d19b..3caa6a2e97df 100644 --- a/packages/core-services/src/types/ITeamService.ts +++ b/packages/core-services/src/types/ITeamService.ts @@ -128,5 +128,5 @@ export interface ITeamService { addRolesToMember(teamId: string, userId: string, roles: Array): Promise; getRoomInfo( room: AtLeast, - ): Promise<{ team?: Pick; parentRoom?: Pick }>; + ): Promise<{ team?: Pick; parentRoom?: Pick }>; } diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index c2a880367d27..115ad690ed0e 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -570,7 +570,7 @@ export type RoomsEndpoints = { '/v1/rooms.info': { GET: (params: RoomsInfoProps) => { room: IRoom | undefined; - parent?: Pick; + parent?: Pick; team?: Pick; }; }; From 0b871bca75dec5b17a6f23e1773489b0ad4302ba Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 27 Aug 2024 11:56:24 -0600 Subject: [PATCH 14/31] dang --- apps/meteor/app/api/server/v1/rooms.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index b9e3a2e658de..b38a5eb9816c 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -416,7 +416,11 @@ API.v1.addRoute( return API.v1.failure('not-allowed', 'Not Allowed'); } - const discussionParent = room.prid && (await Rooms.findOneById>(room.prid, { projection: { name: 1, fname: 1, t: 1, prid: 1, u: 1 } })); + const discussionParent = + room.prid && + (await Rooms.findOneById>(room.prid, { + projection: { name: 1, fname: 1, t: 1, prid: 1, u: 1 }, + })); const { team, parentRoom } = await Team.getRoomInfo(room); const parent = discussionParent || parentRoom; From 70601af1e86c319d770afda1dff8077450be8ba2 Mon Sep 17 00:00:00 2001 From: juliajforesti Date: Thu, 29 Aug 2024 16:18:27 -0300 Subject: [PATCH 15/31] feat: replicate changes to `apps/meteor/client/views/room/HeaderV2/*` --- .../client/views/room/HeaderV2/ParentRoom.tsx | 7 ++- .../room/HeaderV2/ParentRoomWithData.tsx | 21 ++++--- .../HeaderV2/ParentRoomWithEndpointData.tsx | 12 ++++ .../client/views/room/HeaderV2/ParentTeam.tsx | 59 ++++--------------- .../client/views/room/HeaderV2/RoomHeader.tsx | 4 +- 5 files changed, 45 insertions(+), 58 deletions(-) diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx index 0c53d790caf8..24f3d9e0bf14 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx @@ -12,7 +12,12 @@ type ParentRoomProps = { const ParentRoom = ({ room }: ParentRoomProps) => { const icon = useRoomIcon(room); - const handleRedirect = (): void => roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); + const handleRedirect = (): void => { + if (!roomCoordinator.getRoomDirectives(room.t).hasSubscription(room._id)) { + return; + } + roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); + }; return ( { - const { prid } = room; +const getParentId = ({ prid, teamId }: IRoom): string => { + if (prid) { + return prid; + } - if (!prid) { - throw new Error('Parent room ID is missing'); + if (teamId) { + return teamId; } - const subscription = useUserSubscription(prid); + throw new Error('Parent room ID is missing'); +}; + +const ParentRoomWithData = ({ room }: ParentRoomWithDataProps) => { + const parentId = getParentId(room); + const subscription = useUserSubscription(parentId); if (subscription) { - return ; + return ; } - return ; + return ; }; export default ParentRoomWithData; diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx index 89d0ea1f8220..8318c2d8f83c 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { HeaderTagSkeleton } from '../../../components/Header'; import { useRoomInfoEndpoint } from '../../../hooks/useRoomInfoEndpoint'; import ParentRoom from './ParentRoom'; +import ParentTeam from './ParentTeam'; type ParentRoomWithEndpointDataProps = { rid: IRoom['_id']; @@ -20,6 +21,17 @@ const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps) => return null; } + if (data.parent) { + return ; + } + + if (data.team) { + if (data.team.roomId === rid) { + return null; + } + return ; + } + return ; }; diff --git a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx index 2f8bfa57c566..6a77f6fb0299 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx @@ -1,53 +1,26 @@ -import type { IRoom } from '@rocket.chat/core-typings'; +import type { ITeam } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; -import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { useUserSubscription } from '@rocket.chat/ui-contexts'; +import type { ReactElement } from 'react'; import React from 'react'; -import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; +import { HeaderTag, HeaderTagIcon } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; -type APIErrorResult = { success: boolean; error: string }; +const ParentTeam = ({ team }: { team: Pick }): ReactElement | null => { + const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; -type ParentTeamProps = { - room: IRoom; -}; - -const ParentTeam = ({ room }: ParentTeamProps) => { - const { teamId } = room; - const userId = useUserId(); - - if (!teamId) { - throw new Error('invalid rid'); - } - - if (!userId) { - throw new Error('invalid uid'); - } - - const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); - const userTeamsListEndpoint = useEndpoint('GET', '/v1/users.listTeams'); - - const { - data: teamInfoData, - isLoading: teamInfoLoading, - isError: teamInfoError, - } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, - retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, - }); - - const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); - - const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; - const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; + const subscription = useUserSubscription(team.roomId); const redirectToMainRoom = (): void => { - const rid = teamInfoData?.teamInfo.roomId; + const rid = team.roomId; if (!rid) { return; } + const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; + const userBelongsToTeam = !!subscription; + if (!(isTeamPublic || userBelongsToTeam)) { return; } @@ -55,14 +28,6 @@ const ParentTeam = ({ room }: ParentTeamProps) => { goToRoomById(rid); }; - if (teamInfoLoading || userTeamsLoading) { - return ; - } - - if (teamInfoError) { - return null; - } - return ( { onClick={redirectToMainRoom} > - {teamInfoData?.teamInfo.name} + {team.name} ); }; diff --git a/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx b/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx index 8ef21aecf0cd..07c6f1713fec 100644 --- a/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx +++ b/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx @@ -7,7 +7,6 @@ import React, { Suspense } from 'react'; import { Header, HeaderAvatar, HeaderContent, HeaderContentRow, HeaderToolbar } from '../../../components/Header'; import FederatedRoomOriginServer from './FederatedRoomOriginServer'; import ParentRoomWithData from './ParentRoomWithData'; -import ParentTeam from './ParentTeam'; import RoomTitle from './RoomTitle'; import RoomToolbox from './RoomToolbox'; import Encrypted from './icons/Encrypted'; @@ -45,8 +44,7 @@ const RoomHeader = ({ room, slots = {}, roomToolbox }: RoomHeaderProps) => { - {room.prid && } - {room.teamId && !room.teamMain && } + {(room.prid || room.teamId) && } {isRoomFederated(room) && } From de93d48fbd36fc1eca6a9b941700e60a55ef14f4 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:16 -0600 Subject: [PATCH 16/31] Discard changes to apps/meteor/client/lib/rooms/roomCoordinator.tsx --- apps/meteor/client/lib/rooms/roomCoordinator.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/meteor/client/lib/rooms/roomCoordinator.tsx b/apps/meteor/client/lib/rooms/roomCoordinator.tsx index 11bbe0ef3a49..31eda2982a12 100644 --- a/apps/meteor/client/lib/rooms/roomCoordinator.tsx +++ b/apps/meteor/client/lib/rooms/roomCoordinator.tsx @@ -63,9 +63,6 @@ class RoomCoordinatorClient extends RoomCoordinator { canSendMessage(rid: string): boolean { return ChatSubscription.find({ rid }).count() > 0; }, - hasSubscription(rid: string): boolean { - return ChatSubscription.find({ rid }).count() > 0; - }, ...directives, config: roomConfig, }); From 501f239fd1e0bd408f880f19ef88393d571ff7be Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:19 -0600 Subject: [PATCH 17/31] Discard changes to apps/meteor/client/views/room/Header/ParentRoom.tsx --- apps/meteor/client/views/room/Header/ParentRoom.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/meteor/client/views/room/Header/ParentRoom.tsx b/apps/meteor/client/views/room/Header/ParentRoom.tsx index bbe2ec1e2652..5907b3019084 100644 --- a/apps/meteor/client/views/room/Header/ParentRoom.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoom.tsx @@ -13,12 +13,7 @@ type ParentRoomProps = { const ParentRoom = ({ room }: ParentRoomProps): ReactElement => { const icon = useRoomIcon(room); - const handleRedirect = (): void => { - if (!roomCoordinator.getRoomDirectives(room.t).hasSubscription(room._id)) { - return; - } - roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); - }; + const handleRedirect = (): void => roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); return ( Date: Mon, 2 Sep 2024 12:01:23 -0600 Subject: [PATCH 18/31] Discard changes to apps/meteor/client/views/room/Header/ParentRoomWithData.tsx --- .../views/room/Header/ParentRoomWithData.tsx | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx b/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx index 7fec83205180..0e11c33aed4e 100644 --- a/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoomWithData.tsx @@ -10,27 +10,20 @@ type ParentRoomWithDataProps = { room: IRoom; }; -const getParentId = ({ prid, teamId }: IRoom): string => { - if (prid) { - return prid; - } +const ParentRoomWithData = ({ room }: ParentRoomWithDataProps): ReactElement => { + const { prid } = room; - if (teamId) { - return teamId; + if (!prid) { + throw new Error('Parent room ID is missing'); } - throw new Error('Parent room ID is missing'); -}; - -const ParentRoomWithData = ({ room }: ParentRoomWithDataProps): ReactElement => { - const parentId = getParentId(room); + const subscription = useUserSubscription(prid); - const subscription = useUserSubscription(parentId); if (subscription) { - return ; + return ; } - return ; + return ; }; export default ParentRoomWithData; From afd2bf27ed5d23de817b2c6fd55a5b50ded61724 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:26 -0600 Subject: [PATCH 19/31] Discard changes to apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx --- .../views/room/Header/ParentRoomWithEndpointData.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx index d1872cced323..06571dd02cce 100644 --- a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx @@ -5,7 +5,6 @@ import React from 'react'; import { HeaderTagSkeleton } from '../../../components/Header'; import { useRoomInfoEndpoint } from '../../../hooks/useRoomInfoEndpoint'; import ParentRoom from './ParentRoom'; -import ParentTeam from './ParentTeam'; type ParentRoomWithEndpointDataProps = { rid: IRoom['_id']; @@ -22,17 +21,6 @@ const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps): R return null; } - if (data.parent) { - return ; - } - - if (data.team) { - if (data.team.roomId === rid) { - return null; - } - return ; - } - return ; }; From 4f2abda895fb2c88a0428c133059b89576fdccc1 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:29 -0600 Subject: [PATCH 20/31] Discard changes to apps/meteor/client/views/room/Header/ParentTeam.tsx --- .../client/views/room/Header/ParentTeam.tsx | 54 +++++++++++++++---- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index 6a77f6fb0299..ed4a4588ef21 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -1,26 +1,50 @@ -import type { ITeam } from '@rocket.chat/core-typings'; +import type { IRoom } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; -import { useUserSubscription } from '@rocket.chat/ui-contexts'; +import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React from 'react'; -import { HeaderTag, HeaderTagIcon } from '../../../components/Header'; +import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; -const ParentTeam = ({ team }: { team: Pick }): ReactElement | null => { - const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; +type APIErrorResult = { success: boolean; error: string }; - const subscription = useUserSubscription(team.roomId); +const ParentTeam = ({ room }: { room: IRoom }): ReactElement | null => { + const { teamId } = room; + const userId = useUserId(); + + if (!teamId) { + throw new Error('invalid rid'); + } + + if (!userId) { + throw new Error('invalid uid'); + } + + const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); + const userTeamsListEndpoint = useEndpoint('GET', '/v1/users.listTeams'); + + const { + data: teamInfoData, + isLoading: teamInfoLoading, + isError: teamInfoError, + } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { + keepPreviousData: true, + retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, + }); + + const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); + + const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; + const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; const redirectToMainRoom = (): void => { - const rid = team.roomId; + const rid = teamInfoData?.teamInfo.roomId; if (!rid) { return; } - const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; - const userBelongsToTeam = !!subscription; - if (!(isTeamPublic || userBelongsToTeam)) { return; } @@ -28,6 +52,14 @@ const ParentTeam = ({ team }: { team: Pick }) goToRoomById(rid); }; + if (teamInfoLoading || userTeamsLoading) { + return ; + } + + if (teamInfoError) { + return null; + } + return ( }) onClick={redirectToMainRoom} > - {team.name} + {teamInfoData?.teamInfo.name} ); }; From bb167f4e00d75a6944bc477385861b41cf6d91e4 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:32 -0600 Subject: [PATCH 21/31] Discard changes to apps/meteor/client/views/room/Header/RoomHeader.tsx --- apps/meteor/client/views/room/Header/RoomHeader.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/meteor/client/views/room/Header/RoomHeader.tsx b/apps/meteor/client/views/room/Header/RoomHeader.tsx index 34a6299068fa..2e38e2110bbe 100644 --- a/apps/meteor/client/views/room/Header/RoomHeader.tsx +++ b/apps/meteor/client/views/room/Header/RoomHeader.tsx @@ -8,6 +8,7 @@ import { Header, HeaderAvatar, HeaderContent, HeaderContentRow, HeaderSubtitle, import MarkdownText from '../../../components/MarkdownText'; import FederatedRoomOriginServer from './FederatedRoomOriginServer'; import ParentRoomWithData from './ParentRoomWithData'; +import ParentTeam from './ParentTeam'; import RoomTitle from './RoomTitle'; import RoomToolbox from './RoomToolbox'; import Encrypted from './icons/Encrypted'; @@ -46,7 +47,8 @@ const RoomHeader = ({ room, topic = '', slots = {}, roomToolbox }: RoomHeaderPro - {(room.prid || room.teamId) && } + {room.prid && } + {room.teamId && !room.teamMain && } {isRoomFederated(room) && } From 3e8c021c0fc51365d51cf38b30c1673962f24cf9 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:35 -0600 Subject: [PATCH 22/31] Discard changes to apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx --- apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx index 24f3d9e0bf14..0c53d790caf8 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoom.tsx @@ -12,12 +12,7 @@ type ParentRoomProps = { const ParentRoom = ({ room }: ParentRoomProps) => { const icon = useRoomIcon(room); - const handleRedirect = (): void => { - if (!roomCoordinator.getRoomDirectives(room.t).hasSubscription(room._id)) { - return; - } - roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); - }; + const handleRedirect = (): void => roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }); return ( Date: Mon, 2 Sep 2024 12:01:40 -0600 Subject: [PATCH 23/31] Discard changes to apps/meteor/client/views/room/HeaderV2/ParentRoomWithData.tsx --- .../room/HeaderV2/ParentRoomWithData.tsx | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithData.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithData.tsx index 8dda3e75feb8..aed3adc53b39 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithData.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithData.tsx @@ -9,27 +9,20 @@ type ParentRoomWithDataProps = { room: IRoom; }; -const getParentId = ({ prid, teamId }: IRoom): string => { - if (prid) { - return prid; - } +const ParentRoomWithData = ({ room }: ParentRoomWithDataProps) => { + const { prid } = room; - if (teamId) { - return teamId; + if (!prid) { + throw new Error('Parent room ID is missing'); } - throw new Error('Parent room ID is missing'); -}; - -const ParentRoomWithData = ({ room }: ParentRoomWithDataProps) => { - const parentId = getParentId(room); + const subscription = useUserSubscription(prid); - const subscription = useUserSubscription(parentId); if (subscription) { - return ; + return ; } - return ; + return ; }; export default ParentRoomWithData; From 18344581d5bb8b7bc5e91389f4f0892036c2f929 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:43 -0600 Subject: [PATCH 24/31] Discard changes to apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx --- .../room/HeaderV2/ParentRoomWithEndpointData.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx index 8318c2d8f83c..89d0ea1f8220 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { HeaderTagSkeleton } from '../../../components/Header'; import { useRoomInfoEndpoint } from '../../../hooks/useRoomInfoEndpoint'; import ParentRoom from './ParentRoom'; -import ParentTeam from './ParentTeam'; type ParentRoomWithEndpointDataProps = { rid: IRoom['_id']; @@ -21,17 +20,6 @@ const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps) => return null; } - if (data.parent) { - return ; - } - - if (data.team) { - if (data.team.roomId === rid) { - return null; - } - return ; - } - return ; }; From 5c9cbc769f73c9c3c3d5af3cc3853d262d55588c Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:46 -0600 Subject: [PATCH 25/31] Discard changes to apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx --- .../client/views/room/HeaderV2/ParentTeam.tsx | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx index 6a77f6fb0299..2f8bfa57c566 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx @@ -1,26 +1,53 @@ -import type { ITeam } from '@rocket.chat/core-typings'; +import type { IRoom } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; -import { useUserSubscription } from '@rocket.chat/ui-contexts'; -import type { ReactElement } from 'react'; +import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; import React from 'react'; -import { HeaderTag, HeaderTagIcon } from '../../../components/Header'; +import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; -const ParentTeam = ({ team }: { team: Pick }): ReactElement | null => { - const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; +type APIErrorResult = { success: boolean; error: string }; - const subscription = useUserSubscription(team.roomId); +type ParentTeamProps = { + room: IRoom; +}; + +const ParentTeam = ({ room }: ParentTeamProps) => { + const { teamId } = room; + const userId = useUserId(); + + if (!teamId) { + throw new Error('invalid rid'); + } + + if (!userId) { + throw new Error('invalid uid'); + } + + const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); + const userTeamsListEndpoint = useEndpoint('GET', '/v1/users.listTeams'); + + const { + data: teamInfoData, + isLoading: teamInfoLoading, + isError: teamInfoError, + } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { + keepPreviousData: true, + retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, + }); + + const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); + + const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; + const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; const redirectToMainRoom = (): void => { - const rid = team.roomId; + const rid = teamInfoData?.teamInfo.roomId; if (!rid) { return; } - const isTeamPublic = team.type === TEAM_TYPE.PUBLIC; - const userBelongsToTeam = !!subscription; - if (!(isTeamPublic || userBelongsToTeam)) { return; } @@ -28,6 +55,14 @@ const ParentTeam = ({ team }: { team: Pick }) goToRoomById(rid); }; + if (teamInfoLoading || userTeamsLoading) { + return ; + } + + if (teamInfoError) { + return null; + } + return ( }) onClick={redirectToMainRoom} > - {team.name} + {teamInfoData?.teamInfo.name} ); }; From 7db9b2dd3c46f878b0d59c69b504f9722e37d68c Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:50 -0600 Subject: [PATCH 26/31] Discard changes to apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx --- apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx b/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx index 07c6f1713fec..8ef21aecf0cd 100644 --- a/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx +++ b/apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx @@ -7,6 +7,7 @@ import React, { Suspense } from 'react'; import { Header, HeaderAvatar, HeaderContent, HeaderContentRow, HeaderToolbar } from '../../../components/Header'; import FederatedRoomOriginServer from './FederatedRoomOriginServer'; import ParentRoomWithData from './ParentRoomWithData'; +import ParentTeam from './ParentTeam'; import RoomTitle from './RoomTitle'; import RoomToolbox from './RoomToolbox'; import Encrypted from './icons/Encrypted'; @@ -44,7 +45,8 @@ const RoomHeader = ({ room, slots = {}, roomToolbox }: RoomHeaderProps) => { - {(room.prid || room.teamId) && } + {room.prid && } + {room.teamId && !room.teamMain && } {isRoomFederated(room) && } From 93cdb347b6e5f1541fd5c18691463356d93116c6 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:01:54 -0600 Subject: [PATCH 27/31] Discard changes to apps/meteor/definition/IRoomTypeConfig.ts --- apps/meteor/definition/IRoomTypeConfig.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/meteor/definition/IRoomTypeConfig.ts b/apps/meteor/definition/IRoomTypeConfig.ts index 83c0c28053c5..12a4bea39f05 100644 --- a/apps/meteor/definition/IRoomTypeConfig.ts +++ b/apps/meteor/definition/IRoomTypeConfig.ts @@ -86,7 +86,6 @@ export interface IRoomTypeClientDirectives { showJoinLink: (roomId: string) => boolean; isLivechatRoom: () => boolean; canSendMessage: (rid: string) => boolean; - hasSubscription: (rid: string) => boolean; readOnly?: (rid: string, user: AtLeast) => boolean; } From 66da4a424841874d48afe14e3ca3d066e783cada Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 12:03:35 -0600 Subject: [PATCH 28/31] Create quiet-cherries-punch.md --- .changeset/quiet-cherries-punch.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/quiet-cherries-punch.md diff --git a/.changeset/quiet-cherries-punch.md b/.changeset/quiet-cherries-punch.md new file mode 100644 index 000000000000..25c08506db41 --- /dev/null +++ b/.changeset/quiet-cherries-punch.md @@ -0,0 +1,7 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/core-services": minor +"@rocket.chat/rest-typings": minor +--- + +Return `parent` and `team` information when calling `rooms.info` endpoint From cf375a4c8c615c4effcc8e53f195f9376f64e76d Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 2 Sep 2024 14:14:25 -0600 Subject: [PATCH 29/31] Update apps/meteor/server/services/team/service.ts --- apps/meteor/server/services/team/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/server/services/team/service.ts b/apps/meteor/server/services/team/service.ts index 4dc027efa00a..27f7af1f1b1c 100644 --- a/apps/meteor/server/services/team/service.ts +++ b/apps/meteor/server/services/team/service.ts @@ -1055,7 +1055,7 @@ export class TeamService extends ServiceClassInternal implements ITeamService { return rooms; } - async getParentRoom(team: AtLeast): Promise | null> { + private getParentRoom(team: AtLeast): Promise | null> { return Rooms.findOneById>(team.roomId, { projection: { name: 1, fname: 1, t: 1 } }); } From 9d80321af38309a6f44f0f4debb2eddb2b00f32b Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Wed, 4 Sep 2024 08:07:54 -0600 Subject: [PATCH 30/31] yet another test --- apps/meteor/tests/end-to-end/api/rooms.ts | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index 19349ad858e9..4c2dcfcc31f6 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -1246,13 +1246,14 @@ describe('[Rooms]', () => { }); }); - describe('with team and parent data', () => { + describe.only('with team and parent data', () => { const testChannelName = `channel.test.${Date.now()}-${Math.random()}`; const teamName = `test-team-${Date.now()}`; const discussionName = `test-discussion-${Date.now()}`; const testChannelOutsideTeamname = `channel.test.outside.${Date.now()}-${Math.random()}`; let testChannel: IRoom; let testDiscussion: IRoom; + let testDiscussionMainRoom: IRoom; let testTeam: ITeam; let testChannelOutside: IRoom; let testDiscussionOutsideTeam: IRoom; @@ -1269,6 +1270,16 @@ describe('[Rooms]', () => { }); testDiscussion = resDiscussion.body.discussion; + testDiscussionMainRoom = ( + await request + .post(api('rooms.createDiscussion')) + .set(credentials) + .send({ + prid: testTeam.roomId, + t_name: `test-discussion-${Date.now()}-team`, + }) + ).body.discussion; + await request .post(api('teams.addRooms')) .set(credentials) @@ -1294,6 +1305,7 @@ describe('[Rooms]', () => { deleteRoom({ type: 'p', roomId: testDiscussion._id }), deleteRoom({ type: 'c', roomId: testChannelOutside._id }), deleteRoom({ type: 'p', roomId: testDiscussionOutsideTeam._id }), + deleteRoom({ type: 'p', roomId: testDiscussionMainRoom._id }), deleteTeam(credentials, teamName), ]), ); @@ -1359,6 +1371,20 @@ describe('[Rooms]', () => { expect(res.body).to.not.have.property('team'); }); }); + + it('should return the parent for a discussion created from team main room', async () => { + await request + .get(api('rooms.info')) + .set(credentials) + .query({ roomId: testDiscussionMainRoom._id }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('parent').and.to.be.an('object'); + expect(res.body.parent).to.have.property('_id').and.to.be.equal(testTeam.roomId); + expect(res.body).to.not.have.property('team'); + }); + }); }); }); describe('[/rooms.leave]', () => { From 1bf0c9334dc8a14184e5aea9c94f4bdb634fbf12 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Wed, 4 Sep 2024 08:08:53 -0600 Subject: [PATCH 31/31] yet another test --- apps/meteor/tests/end-to-end/api/rooms.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index 4c2dcfcc31f6..724db717a1cf 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -1246,7 +1246,7 @@ describe('[Rooms]', () => { }); }); - describe.only('with team and parent data', () => { + describe('with team and parent data', () => { const testChannelName = `channel.test.${Date.now()}-${Math.random()}`; const teamName = `test-team-${Date.now()}`; const discussionName = `test-discussion-${Date.now()}`;