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
177 lines
4.9 KiB
TypeScript
177 lines
4.9 KiB
TypeScript
import { isDirectMessageRoom } from '@rocket.chat/core-typings';
|
|
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
|
|
import { GenericModal } from '@rocket.chat/ui-client';
|
|
import { useSetModal, useToastMessageDispatch, useEndpoint, useRoomToolbox } from '@rocket.chat/ui-contexts';
|
|
import { useCallback, useMemo, useState } from 'react';
|
|
import { useForm, FormProvider } from 'react-hook-form';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import PruneMessages from './PruneMessages';
|
|
import { formatDate } from '../../../../lib/utils/dateFormat';
|
|
import { useRoom } from '../../contexts/RoomContext';
|
|
|
|
const getTimeZoneOffset = (): string => {
|
|
const offset = new Date().getTimezoneOffset();
|
|
const absOffset = Math.abs(offset);
|
|
return `${offset < 0 ? '+' : '-'}${`00${Math.floor(absOffset / 60)}`.slice(-2)}:${`00${absOffset % 60}`.slice(-2)}`;
|
|
};
|
|
|
|
export const initialValues = {
|
|
newer: {
|
|
date: '',
|
|
time: '',
|
|
},
|
|
older: {
|
|
date: '',
|
|
time: '',
|
|
},
|
|
users: [],
|
|
inclusive: false,
|
|
pinned: false,
|
|
discussion: false,
|
|
threads: false,
|
|
attached: false,
|
|
};
|
|
|
|
const DEFAULT_PRUNE_LIMIT = 2000;
|
|
|
|
const PruneMessagesWithData = () => {
|
|
const { t } = useTranslation();
|
|
const room = useRoom();
|
|
const setModal = useSetModal();
|
|
const { closeTab: close } = useRoomToolbox();
|
|
const closeModal = useCallback(() => setModal(null), [setModal]);
|
|
const dispatchToastMessage = useToastMessageDispatch();
|
|
const pruneMessagesAction = useEndpoint('POST', '/v1/rooms.cleanHistory');
|
|
|
|
const [counter, setCounter] = useState(0);
|
|
|
|
const methods = useForm({ defaultValues: initialValues });
|
|
|
|
const {
|
|
newer: { date: newerDate, time: newerTime },
|
|
older: { date: olderDate, time: olderTime },
|
|
users,
|
|
inclusive,
|
|
pinned,
|
|
discussion,
|
|
threads,
|
|
attached,
|
|
} = methods.watch();
|
|
|
|
const fromDate = useMemo(() => {
|
|
return new Date(`${newerDate || '0001-01-01'}T${newerTime || '00:00'}:00${getTimeZoneOffset()}`);
|
|
}, [newerDate, newerTime]);
|
|
|
|
const toDate = useMemo(() => {
|
|
return new Date(`${olderDate || '9999-12-31'}T${olderTime || '23:59'}:59${getTimeZoneOffset()}`);
|
|
}, [olderDate, olderTime]);
|
|
|
|
const handlePrune = useStableCallback((): void => {
|
|
const handlePruneAction = async () => {
|
|
const limit = DEFAULT_PRUNE_LIMIT;
|
|
|
|
try {
|
|
if (counter === limit) {
|
|
return;
|
|
}
|
|
|
|
const { count } = await pruneMessagesAction({
|
|
roomId: room._id,
|
|
latest: toDate.toISOString(),
|
|
oldest: fromDate.toISOString(),
|
|
inclusive,
|
|
limit,
|
|
excludePinned: pinned,
|
|
filesOnly: attached,
|
|
ignoreDiscussion: discussion,
|
|
ignoreThreads: threads,
|
|
users,
|
|
});
|
|
|
|
setCounter(count);
|
|
|
|
if (count < 1) {
|
|
throw new Error(attached ? t('No_files_found_to_prune') : t('No_messages_found_to_prune'));
|
|
}
|
|
|
|
dispatchToastMessage({
|
|
type: 'success',
|
|
message: attached ? t('__count__file_pruned', { count }) : t('__count__message_pruned', { count }),
|
|
});
|
|
methods.reset();
|
|
} catch (error: unknown) {
|
|
dispatchToastMessage({ type: 'error', message: error });
|
|
} finally {
|
|
closeModal();
|
|
}
|
|
};
|
|
|
|
return setModal(
|
|
<GenericModal
|
|
variant='danger'
|
|
onClose={closeModal}
|
|
onCancel={closeModal}
|
|
onConfirm={handlePruneAction}
|
|
confirmText={t('Yes_prune_them')}
|
|
>
|
|
{t('Prune_Modal')}
|
|
</GenericModal>,
|
|
);
|
|
});
|
|
|
|
const callOutText = useMemo(() => {
|
|
const name = room && ((isDirectMessageRoom(room) && room.usernames?.join(' x ')) || room.fname || room.name);
|
|
const exceptPinned = pinned ? ` ${t('except_pinned')}` : '';
|
|
const ifFrom = users.length ? ` ${t('if_they_are_from', { users: users.map((element) => element).join(', ') })}` : '';
|
|
const filesOrMessages = attached ? t('files') : t('messages');
|
|
|
|
if (newerDate && olderDate) {
|
|
return (
|
|
t('Prune_Warning_between', {
|
|
items: filesOrMessages,
|
|
roomName: name,
|
|
fromDate: formatDate(fromDate, 'L LT'),
|
|
toDate: formatDate(toDate, 'L LT'),
|
|
}) +
|
|
exceptPinned +
|
|
ifFrom
|
|
);
|
|
}
|
|
|
|
if (newerDate) {
|
|
return (
|
|
t('Prune_Warning_after', { items: filesOrMessages, roomName: name, fromDate: formatDate(fromDate, 'L LT') }) + exceptPinned + ifFrom
|
|
);
|
|
}
|
|
|
|
if (olderDate) {
|
|
return (
|
|
t('Prune_Warning_before', { items: filesOrMessages, roomName: name, toDate: formatDate(toDate, 'L LT') }) + exceptPinned + ifFrom
|
|
);
|
|
}
|
|
|
|
return t('Prune_Warning_all', { items: filesOrMessages, roomName: name }) + exceptPinned + ifFrom;
|
|
}, [attached, fromDate, newerDate, olderDate, pinned, room, t, toDate, users]);
|
|
|
|
const validateText = useMemo(() => {
|
|
if (fromDate > toDate) {
|
|
return t('Newer_than_may_not_exceed_Older_than');
|
|
}
|
|
|
|
if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) {
|
|
return t('error-invalid-date');
|
|
}
|
|
|
|
return undefined;
|
|
}, [fromDate, t, toDate]);
|
|
|
|
return (
|
|
<FormProvider {...methods}>
|
|
<PruneMessages callOutText={callOutText} validateText={validateText} users={users} onClickClose={close} onClickPrune={handlePrune} />
|
|
</FormProvider>
|
|
);
|
|
};
|
|
|
|
export default PruneMessagesWithData;
|