Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/api/server/v1/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ API.v1.addRoute('teams.listRooms', { authRequired: true }, {
API.v1.addRoute('teams.listRoomsOfUser', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
const { teamId, teamName, userId } = this.queryParams;
const { teamId, teamName, userId, canUserDelete = false } = this.queryParams;

const team = teamId ? Promise.await(Team.getOneById(teamId)) : Promise.await(Team.getOneByName(teamName));
if (!team) {
Expand All @@ -219,7 +219,7 @@ API.v1.addRoute('teams.listRoomsOfUser', { authRequired: true }, {
return API.v1.unauthorized();
}

const { records, total } = Promise.await(Team.listRoomsOfUser(this.userId, team._id, userId, allowPrivateTeam, { offset, count }));
const { records, total } = Promise.await(Team.listRoomsOfUser(this.userId, team._id, userId, allowPrivateTeam, canUserDelete, { offset, count }));

return API.v1.success({
rooms: records,
Expand Down
2 changes: 2 additions & 0 deletions client/contexts/ServerContext/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { AutocompleteAvailableForTeamsEndpoint as RoomsAutocompleteTeamsEndpoint
import { AutocompleteChannelAndPrivateEndpoint as RoomsAutocompleteEndpoint } from './endpoints/v1/rooms/autocompleteChannelAndPrivate';
import { AddRoomsEndpoint as TeamsAddRoomsEndpoint } from './endpoints/v1/teams/addRooms';
import { ListRoomsEndpoint } from './endpoints/v1/teams/listRooms';
import { ListRoomsOfUserEndpoint } from './endpoints/v1/teams/listRoomsOfUser';
import { AutocompleteEndpoint as UsersAutocompleteEndpoint } from './endpoints/v1/users/autocomplete';

export type ServerEndpoints = {
Expand All @@ -47,6 +48,7 @@ export type ServerEndpoints = {
'rooms.autocomplete.channelAndPrivate': RoomsAutocompleteEndpoint;
'rooms.autocomplete.availableForTeams': RoomsAutocompleteTeamsEndpoint;
'teams.listRooms': ListRoomsEndpoint;
'teams.listRoomsOfUser': ListRoomsOfUserEndpoint;
'teams.addRooms': TeamsAddRoomsEndpoint;
'livechat/visitors.info': LivechatVisitorInfoEndpoint;
'livechat/room.onHold': LivechatRoomOnHoldEndpoint;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IRoom } from '../../../../../../definition/IRoom';
import { IRecordsWithTotal } from '../../../../../../definition/ITeam';

export type ListRoomsOfUserEndpoint = {
GET: (params: {
teamId: string;
teamName?: string;
userId?: string;
canUserDelete?: boolean;
offset?: number;
count?: number;
}) => Omit<IRecordsWithTotal<IRoom>, 'records'> & {
count: number;
offset: number;
rooms: IRecordsWithTotal<IRoom>['records'];
};
};
23 changes: 0 additions & 23 deletions client/views/room/contextualBar/Info/ConvertToTeamModal.js

This file was deleted.

14 changes: 12 additions & 2 deletions client/views/room/contextualBar/Info/RoomInfo/RoomInfoWithData.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { useEndpointActionExperimental } from '../../../../../hooks/useEndpointA
import WarningModal from '../../../../admin/apps/WarningModal';
import { useTabBarClose } from '../../../providers/ToolboxProvider';
import ChannelToTeamModal from '../ChannelToTeamModal/ChannelToTeamModal';
import ConvertToTeamModal from '../ConvertToTeamModal';
import RoomInfo from './RoomInfo';

const retentionPolicyMaxAge = {
Expand Down Expand Up @@ -180,7 +179,18 @@ const RoomInfoWithData = ({ rid, openEditing, onClickBack, onEnterRoom, resetSta
}
};

setModal(<ConvertToTeamModal onClose={closeModal} onConfirm={onConfirm} />);
setModal(
<GenericModal
title={t('Confirmation')}
variant='warning'
onClose={closeModal}
onCancel={closeModal}
onConfirm={onConfirm}
confirmText={t('Convert')}
>
{t('Converting_channel_to_a_team')}
</GenericModal>,
);
});

const onClickEnterRoom = useMutableCallback(() => onEnterRoom(room));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Box, CheckBox } from '@rocket.chat/fuselage';
import React from 'react';

import GenericTable from '../../../components/GenericTable';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime';
import ChannelRow from './ChannelRow';
import GenericTable from '../../components/GenericTable';
import { useTranslation } from '../../contexts/TranslationContext';
import { useFormatDateAndTime } from '../../hooks/useFormatDateAndTime';
import ChannelRow from './contextualBar/ChannelRow';

const ChannelDesertionTable = ({
rooms,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { FC, useState, useCallback } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import FirstStep from './ModalSteps/FirstStep';
import SecondStep from './ModalSteps/SecondStep';

const STEPS = {
LIST_ROOMS: 'LIST_ROOMS',
CONFIRM_CONVERT: 'CONFIRM_CONVERT',
};

type BaseConvertToChannelModalProps = {
onClose: () => void;
onCancel: () => void;
onConfirm: () => Array<IRoom>;
currentStep?: string;
rooms: Array<IRoom & { isLastOwner?: string }> | undefined;
Comment thread
dougfabris marked this conversation as resolved.
Outdated
selectedRooms: { [key: string]: IRoom };
};

const BaseConvertToChannelModal: FC<BaseConvertToChannelModalProps> = ({
onClose,
onCancel,
onConfirm,
rooms,
currentStep = rooms?.length === 0 ? STEPS.CONFIRM_CONVERT : STEPS.LIST_ROOMS,
}) => {
const [step, setStep] = useState(currentStep);
const [selectedRooms, setSelectedRooms] = useState<
BaseConvertToChannelModalProps['selectedRooms']
>({});

const onContinue = useMutableCallback(() => setStep(STEPS.CONFIRM_CONVERT));
const onReturn = useMutableCallback(() => setStep(STEPS.LIST_ROOMS));

const eligibleRooms = rooms;

const onChangeRoomSelection = useCallback((room) => {
setSelectedRooms((selectedRooms) => {
if (selectedRooms[room._id]) {
delete selectedRooms[room._id];
return { ...selectedRooms };
}
return { ...selectedRooms, [room._id]: room };
});
}, []);

const onToggleAllRooms = useMutableCallback(() => {
if (Object.values(selectedRooms).filter(Boolean).length === 0 && eligibleRooms) {
return setSelectedRooms(Object.fromEntries(eligibleRooms.map((room) => [room._id, room])));
}
setSelectedRooms({});
});

if (step === STEPS.CONFIRM_CONVERT) {
return (
<SecondStep
onConfirm={onConfirm}
onClose={onClose}
onCancel={rooms && rooms.length > 0 ? onReturn : onCancel}
deletedRooms={selectedRooms}
rooms={rooms}
/>
);
}

return (
<FirstStep
onConfirm={onContinue}
onClose={onClose}
onCancel={onCancel}
rooms={rooms}
selectedRooms={selectedRooms}
onToggleAllRooms={onToggleAllRooms}
onChangeRoomSelection={onChangeRoomSelection}
eligibleRoomsLength={eligibleRooms?.length}
/>
);
};

export default BaseConvertToChannelModal;
58 changes: 58 additions & 0 deletions client/views/teams/ConvertToChannelModal/ConvertToChannelModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Skeleton } from '@rocket.chat/fuselage';
import React, { FC, useMemo } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import GenericModal from '../../../components/GenericModal';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useEndpointData } from '../../../hooks/useEndpointData';
import { AsyncStatePhase } from '../../../lib/asyncState';
import BaseConvertToChannelModal from './BaseConvertToChannelModal';

type ConvertToChannelModalProps = {
onClose: () => void;
onCancel: () => void;
onConfirm: () => Array<IRoom>;
teamId: string;
userId: string;
};

const ConvertToChannelModal: FC<ConvertToChannelModalProps> = ({
onClose,
onCancel,
onConfirm,
teamId,
userId,
}) => {
const t = useTranslation();

const { value, phase } = useEndpointData(
'teams.listRoomsOfUser',
useMemo(() => ({ teamId, userId, canUserDelete: true }), [teamId, userId]),
);

if (phase === AsyncStatePhase.LOADING) {
return (
<GenericModal
variant='warning'
onClose={onClose}
title={<Skeleton width='50%' />}
confirmText={t('Cancel')}
onConfirm={onClose}
>
<Skeleton width='full' />
</GenericModal>
);
}

return (
<BaseConvertToChannelModal
onClose={onClose}
onCancel={onCancel}
onConfirm={onConfirm}
rooms={value?.rooms}
selectedRooms={{}}
Comment thread
dougfabris marked this conversation as resolved.
Outdated
/>
);
};

export default ConvertToChannelModal;
67 changes: 67 additions & 0 deletions client/views/teams/ConvertToChannelModal/ModalSteps/FirstStep.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Box } from '@rocket.chat/fuselage';
import React, { FC } from 'react';

import { IRoom } from '../../../../../definition/IRoom';
import GenericModal from '../../../../components/GenericModal';
import { useTranslation } from '../../../../contexts/TranslationContext';
import ChannelDesertionTable from '../../ChannelDesertionTable';

type FirstStepProps = {
onClose: () => void;
onCancel: () => void;
onConfirm: () => void;
onToggleAllRooms: () => void;
onChangeRoomSelection: (room: IRoom) => void;
rooms: Array<IRoom & { isLastOwner?: string }> | undefined;
eligibleRoomsLength: number | undefined;
selectedRooms: { [key: string]: IRoom };
};

const FirstStep: FC<FirstStepProps> = ({
onClose,
onCancel,
onConfirm,
rooms,
onToggleAllRooms,
onChangeRoomSelection,
selectedRooms,
eligibleRoomsLength,
...props
}) => {
const t = useTranslation();

return (
<GenericModal
variant='warning'
icon='warning'
title={t('Converting_team_to_channel')}
cancelText={t('Cancel')}
confirmText={t('Continue')}
onClose={onClose}
onCancel={onCancel}
onConfirm={onConfirm}
{...props}
>
<Box mbe='x24' fontScale='p1'>
{t('Select_the_teams_channels_you_would_like_to_delete')}
</Box>

<Box mbe='x24' fontScale='p1'>
{t('Notice_that_public_channels_will_be_public_and_visible_to_everyone')}
</Box>

<ChannelDesertionTable
lastOwnerWarning={undefined}
onToggleAllRooms={onToggleAllRooms}
rooms={rooms}
params={{}}
Comment thread
dougfabris marked this conversation as resolved.
Outdated
onChangeParams={(): void => undefined}
Comment thread
dougfabris marked this conversation as resolved.
Outdated
onChangeRoomSelection={onChangeRoomSelection}
selectedRooms={selectedRooms}
eligibleRoomsLength={eligibleRoomsLength}
/>
</GenericModal>
);
};

export default FirstStep;
45 changes: 45 additions & 0 deletions client/views/teams/ConvertToChannelModal/ModalSteps/SecondStep.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Icon } from '@rocket.chat/fuselage';
import React, { FC } from 'react';

import { IRoom } from '../../../../../definition/IRoom';
import GenericModal from '../../../../components/GenericModal';
import { useTranslation } from '../../../../contexts/TranslationContext';

type SecondStepsProps = {
onClose: () => void;
onCancel: () => void;
onConfirm: (deletedRooms: { [key: string]: IRoom }) => void;
deletedRooms: {
[key: string]: IRoom;
};
rooms: Array<IRoom & { isLastOwner?: string }> | undefined;
};

const SecondStep: FC<SecondStepsProps> = ({
onClose,
onCancel,
onConfirm,
deletedRooms = {},
rooms = [],
...props
}) => {
const t = useTranslation();

return (
<GenericModal
{...props}
variant='warning'
icon={<Icon name='modal-warning' size={24} color='warning' />}
cancelText={rooms?.length > 0 ? t('Back') : t('Cancel')}
confirmText={t('Convert')}
title={t('Confirmation')}
onClose={onClose}
onCancel={onCancel}
onConfirm={(): void => onConfirm(deletedRooms)}
>
{t('You_are_converting_team_to_channel')}
</GenericModal>
);
};

export default SecondStep;
1 change: 1 addition & 0 deletions client/views/teams/ConvertToChannelModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ConvertToChannelModal';
Loading