import type { FC } from 'react'; import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'next-i18next'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { useAdminSocket } from '~/features/admin/states/socket-io'; import type { PMEndedData, PMErrorCountData, PMMigratingData, PMStartedData, } from '~/interfaces/websocket'; import { SocketEventName } from '~/interfaces/websocket'; import AdminAppContainer from '../../../services/AdminAppContainer'; import { withUnstatedContainers } from '../../UnstatedUtils'; import LabeledProgressBar from '../Common/LabeledProgressBar'; import { ConfirmModal } from './ConfirmModal'; type Props = { adminAppContainer: typeof AdminAppContainer & { v5PageMigrationHandler: () => Promise<{ isV5Compatible: boolean }>; }; }; const V5PageMigration: FC = (props: Props) => { // Modal const [isV5PageMigrationModalShown, setIsV5PageMigrationModalShown] = useState(false); // Progress bar const [isInProgress, setProgressing] = useState( undefined, ); // use false as ended const [total, setTotal] = useState(0); const [skip, setSkip] = useState(0); const [current, setCurrent] = useState(0); const [isSucceeded, setSucceeded] = useState(undefined); const adminSocket = useAdminSocket(); const { t } = useTranslation(); const { adminAppContainer } = props; /* * Local components */ const renderResultMessage = useCallback( (isSucceeded: boolean) => { return ( <> {isSucceeded ? (

{t('admin:v5_page_migration.migration_succeeded')}

) : (

{t('admin:v5_page_migration.migration_failed')}

)} ); }, [t], ); const renderProgressBar = () => { if (isInProgress == null) { return <>; } return ( <> {isSucceeded != null && renderResultMessage(isSucceeded)} ); }; /* * Functions */ const onConfirm = async () => { setIsV5PageMigrationModalShown(false); try { const { isV5Compatible } = await adminAppContainer.v5PageMigrationHandler(); if (isV5Compatible) { return toastSuccess(t('admin:v5_page_migration.already_upgraded')); } toastSuccess(t('admin:v5_page_migration.successfully_started')); } catch (err) { toastError(err); } }; /* * Use Effect */ // Setup Admin Socket useEffect(() => { adminSocket?.once(SocketEventName.PMStarted, (data: PMStartedData) => { setProgressing(true); setTotal(data.total); }); adminSocket?.on(SocketEventName.PMMigrating, (data: PMMigratingData) => { setProgressing(true); setCurrent(data.count); }); adminSocket?.on(SocketEventName.PMErrorCount, (data: PMErrorCountData) => { setProgressing(true); setSkip(data.skip); }); adminSocket?.once(SocketEventName.PMEnded, (data: PMEndedData) => { setProgressing(false); setSucceeded(data.isSucceeded); }); return () => { adminSocket?.off(SocketEventName.PMStarted); adminSocket?.off(SocketEventName.PMMigrating); adminSocket?.off(SocketEventName.PMErrorCount); adminSocket?.off(SocketEventName.PMEnded); }; }, [adminSocket]); return ( <> setIsV5PageMigrationModalShown(false)} />

{t('admin:v5_page_migration.migration_desc')}

error {t('admin:v5_page_migration.migration_note')}

{renderProgressBar()}
); }; export default withUnstatedContainers(V5PageMigration, [AdminAppContainer]);