import React, { useCallback, useState, useEffect, type JSX, } from 'react'; import { useTranslation } from 'next-i18next'; import { Modal, ModalHeader, ModalBody, ModalFooter, } from 'reactstrap'; import { apiPost } from '~/client/util/apiv1-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; const GROUPS_PAGE = [ 'pages', 'revisions', 'tags', 'pagetagrelations', 'pageredirects', 'comments', 'sharelinks', ]; const GROUPS_USER = [ 'users', 'externalaccounts', 'usergroups', 'usergrouprelations', 'externalusergroups', 'externalusergrouprelations', 'useruisettings', 'editorsettings', 'bookmarks', 'bookmarkfolders', 'subscriptions', 'inappnotificationsettings', ]; const GROUPS_CONFIG = [ 'configs', 'migrations', 'updateposts', 'globalnotificationsettings', 'slackappintegrations', 'growiplugins', ]; const ALL_GROUPED_COLLECTIONS = GROUPS_PAGE.concat(GROUPS_USER).concat(GROUPS_CONFIG); type Props = { isOpen: boolean, onExportingRequested: () => void, onClose: () => void, collections: string[], isAllChecked?: boolean, }; const SelectCollectionsModal = (props: Props): JSX.Element => { const { t } = useTranslation(); const { isOpen, onExportingRequested, onClose, collections, isAllChecked, } = props; const [selectedCollections, setSelectedCollections] = useState>(new Set()); const toggleCheckbox = useCallback((e) => { const { target } = e; const { name, checked } = target; setSelectedCollections((prevState) => { const selectedCollections = new Set(prevState); if (checked) { selectedCollections.add(name); } else { selectedCollections.delete(name); } return selectedCollections; }); }, []); const checkAll = useCallback(() => { setSelectedCollections(new Set(collections)); }, [collections]); const uncheckAll = useCallback(() => { setSelectedCollections(new Set()); }, []); const doExport = useCallback(async(e) => { e.preventDefault(); try { // TODO: use apiv3Post const result = await apiPost('/v3/export', { collections: Array.from(selectedCollections) }); if (!result.ok) { throw new Error('Error occured.'); } toastSuccess('Export process has requested.'); onExportingRequested(); onClose(); uncheckAll(); } catch (err) { toastError(err); } }, [onClose, onExportingRequested, selectedCollections, uncheckAll]); const validateForm = useCallback(() => { return selectedCollections.size > 0; }, [selectedCollections.size]); const renderWarnForUser = useCallback(() => { // whether selectedCollections includes one of GROUPS_USER const isUserRelatedDataSelected = GROUPS_USER.some((collectionName) => { return selectedCollections.has(collectionName); }); if (!isUserRelatedDataSelected) { return <>; } const html = t('admin:export_management.desc_password_seed'); return (
{/* eslint-disable-next-line react/no-danger */}

); }, [selectedCollections, t]); const renderCheckboxes = useCallback((collectionNames, color?) => { const checkboxColor = color ? `form-check-${color}` : 'form-check-info'; return (
{collectionNames.map((collectionName) => { return (
); })}
); }, [selectedCollections, toggleCheckbox]); const renderGroups = useCallback((groupList, color?) => { const collectionNames = groupList.filter((collectionName) => { return collections.includes(collectionName); }); return renderCheckboxes(collectionNames, color); }, [collections, renderCheckboxes]); const renderOthers = useCallback(() => { const collectionNames = collections.filter((collectionName) => { return !ALL_GROUPED_COLLECTIONS.includes(collectionName); }); return renderCheckboxes(collectionNames); }, [collections, renderCheckboxes]); useEffect(() => { if (isAllChecked) checkAll(); }, [isAllChecked, checkAll]); return ( {t('admin:export_management.export_collections')}

MongoDB Page Collections

{renderGroups(GROUPS_PAGE)}

MongoDB User Collections

{renderGroups(GROUPS_USER, 'danger')} {renderWarnForUser()}

MongoDB Config Collections

{renderGroups(GROUPS_CONFIG)}

MongoDB Other Collections

{renderOthers()}
); }; export default SelectCollectionsModal;