snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
import type { StoryObj, Meta } from '@storybook/react';
import { action } from 'storybook/actions';
import LeaveTeamModal from './LeaveTeamModal';
import LeaveTeamModalChannels from './LeaveTeamModalChannels';
import LeaveTeamModalConfirmation from './LeaveTeamModalConfirmation';
export default {
component: LeaveTeamModal,
parameters: {
layout: 'fullscreen',
},
} satisfies Meta<typeof LeaveTeamModal>;
export const ChannelsStep: StoryObj<typeof LeaveTeamModalChannels> = {
render: (args) => <LeaveTeamModalChannels {...args} />,
name: 'LeaveTeamModalChannels',
args: {
rooms: Array.from({ length: 15 }).map((_, i) => ({
_id: `${i}`,
fname: `Room #${i}`,
name: `room-${i}`,
usersCount: 10 * i,
type: 'p',
t: 'p',
isLastOwner: false,
msgs: 10,
u: {
_id: 'user',
},
autoTranslateLanguage: 'english',
_updatedAt: '2022-02-02 09:00',
})),
selectedRooms: {},
onConfirm: action('onConfirm'),
onCancel: action('onCancel'),
onChangeRoomSelection: action('onChangeRoomSelection'),
onToggleAllRooms: action('onToggleAllRooms'),
},
};
export const ConfirmationStep: StoryObj<typeof LeaveTeamModalConfirmation> = {
render: (args) => <LeaveTeamModalConfirmation {...args} />,
name: 'StepTwo',
args: {
onConfirm: action('onConfirm'),
onCancel: action('onCancel'),
onClose: action('onClose'),
},
};

View File

@@ -0,0 +1,73 @@
import type { IRoom, Serialized } from '@rocket.chat/core-typings';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { useState, useCallback, useMemo } from 'react';
import LeaveTeamModalChannels from './LeaveTeamModalChannels';
import LeaveTeamModalConfirmation from './LeaveTeamModalConfirmation';
const LEAVE_TEAM_STEPS = {
LIST_ROOMS: 'LIST_ROOMS',
CONFIRM_LEAVE: 'CONFIRM_LEAVE',
} as const;
export type LeaveTeamModalProps = {
rooms: (Serialized<IRoom> & { isLastOwner?: boolean })[];
onCancel: () => void;
onConfirm: () => void;
};
const LeaveTeamModal = ({ rooms, onCancel, onConfirm }: LeaveTeamModalProps) => {
const memoizedRooms = useMemo(() => rooms, [rooms]);
const [step, setStep] = useState(memoizedRooms.length === 0 ? LEAVE_TEAM_STEPS.CONFIRM_LEAVE : LEAVE_TEAM_STEPS.LIST_ROOMS);
const [selectedRooms, setSelectedRooms] = useState<{ [key: string]: Serialized<IRoom> & { isLastOwner?: boolean } }>({});
const lastOwnerRooms = rooms.filter(({ isLastOwner }) => isLastOwner);
const handleContinue = useCallback(() => setStep(LEAVE_TEAM_STEPS.CONFIRM_LEAVE), []);
const handleReturn = useCallback(() => setStep(LEAVE_TEAM_STEPS.LIST_ROOMS), []);
const onChangeRoomSelection = useCallback((room: Serialized<IRoom>) => {
setSelectedRooms((selectedRooms) => {
if (selectedRooms[room._id]) {
delete selectedRooms[room._id];
return { ...selectedRooms };
}
return { ...selectedRooms, [room._id]: room };
});
}, []);
const onToggleAllRooms = useStableCallback(() => {
setSelectedRooms((selectedRooms) => {
if (Object.values(selectedRooms).filter(Boolean).length === 0) {
return Object.fromEntries(rooms.filter(({ isLastOwner }) => !isLastOwner).map((room) => [room._id, room]));
}
return {};
});
});
if (step === LEAVE_TEAM_STEPS.CONFIRM_LEAVE) {
return (
<LeaveTeamModalConfirmation
selectedRooms={selectedRooms}
onConfirm={onConfirm}
onClose={onCancel}
onCancel={rooms.length > 0 ? handleReturn : undefined}
/>
);
}
return (
<LeaveTeamModalChannels
rooms={rooms}
onCancel={onCancel}
eligibleRoomsLength={rooms.length - lastOwnerRooms.length}
selectedRooms={selectedRooms}
onToggleAllRooms={onToggleAllRooms}
onConfirm={handleContinue}
onChangeRoomSelection={onChangeRoomSelection}
/>
);
};
export default LeaveTeamModal;

View File

@@ -0,0 +1,52 @@
import type { IRoom, Serialized } from '@rocket.chat/core-typings';
import { GenericModal } from '@rocket.chat/ui-client';
import { useTranslation } from 'react-i18next';
import ChannelDesertionTable from '../../../../ChannelDesertionTable';
export type LeaveTeamModalChannelsProps = {
rooms?: (Serialized<IRoom> & { isLastOwner?: boolean })[];
onToggleAllRooms: () => void;
onChangeRoomSelection: (room: Serialized<IRoom> & { isLastOwner?: boolean }) => void;
onConfirm: () => void;
onCancel: () => void;
eligibleRoomsLength: number;
selectedRooms: {
[key: string]: Serialized<IRoom> & { isLastOwner?: boolean };
};
};
const LeaveTeamModalChannels = ({
rooms,
onToggleAllRooms,
onChangeRoomSelection,
onConfirm,
onCancel,
eligibleRoomsLength,
selectedRooms,
}: LeaveTeamModalChannelsProps) => {
const { t } = useTranslation();
return (
<GenericModal
variant='warning'
title={t('Teams_leave')}
onConfirm={onConfirm}
onCancel={onCancel}
onClose={onCancel}
confirmText={t('Continue')}
>
{t('Teams_leave_channels')}
<ChannelDesertionTable
rooms={rooms}
lastOwnerWarning={t('Teams_channels_last_owner_leave_channel_warning')}
onToggleAllRooms={onToggleAllRooms}
eligibleRoomsLength={eligibleRoomsLength}
onChangeRoomSelection={onChangeRoomSelection}
selectedRooms={selectedRooms}
/>
</GenericModal>
);
};
export default LeaveTeamModalChannels;

View File

@@ -0,0 +1,32 @@
import type { IRoom, Serialized } from '@rocket.chat/core-typings';
import { GenericModal } from '@rocket.chat/ui-client';
import { useTranslation } from 'react-i18next';
export type LeaveTeamModalConfirmationProps = {
onConfirm: (selectedRooms?: { [key: string]: Serialized<IRoom> & { isLastOwner?: boolean } }) => void;
onClose: () => void;
onCancel?: () => void;
selectedRooms: {
[key: string]: Serialized<IRoom> & { isLastOwner?: boolean };
};
};
const LeaveTeamModalConfirmation = ({ selectedRooms, onConfirm, onCancel, onClose }: LeaveTeamModalConfirmationProps) => {
const { t } = useTranslation();
return (
<GenericModal
variant='danger'
title={t('Confirmation')}
onConfirm={(): void => onConfirm(selectedRooms)}
onCancel={onCancel || onClose}
onClose={onClose}
confirmText={t('Leave')}
cancelText={onCancel ? t('Back') : t('Cancel')}
>
{t('Teams_leaving_team')}
</GenericModal>
);
};
export default LeaveTeamModalConfirmation;

View File

@@ -0,0 +1,34 @@
import type { ITeam } from '@rocket.chat/core-typings';
import { GenericModalSkeleton } from '@rocket.chat/ui-client';
import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import LeaveTeamModal from './LeaveTeamModal/LeaveTeamModal';
export type LeaveTeamWithDataProps = {
teamId: ITeam['_id'];
onCancel: () => void;
onConfirm: () => void;
};
const LeaveTeamWithData = ({ teamId, onCancel, onConfirm }: LeaveTeamWithDataProps) => {
const userId = useUserId();
if (!userId) {
throw Error('No user found');
}
const getRoomsOfUser = useEndpoint('GET', '/v1/teams.listRoomsOfUser');
const { data, isLoading } = useQuery({
queryKey: ['teams.listRoomsOfUser'],
queryFn: () => getRoomsOfUser({ teamId, userId }),
});
if (isLoading) {
return <GenericModalSkeleton />;
}
return <LeaveTeamModal onCancel={onCancel} onConfirm={onConfirm} rooms={data?.rooms || []} />;
};
export default LeaveTeamWithData;

View File

@@ -0,0 +1 @@
export { default } from './LeaveTeamWithData';