import React, { useEffect, useState, useCallback } from 'react'; import { PageGrant } from '@growi/core'; import { useTranslation } from 'react-i18next'; import { Modal, ModalHeader, ModalBody, ModalFooter, } from 'reactstrap'; import { apiv3Put } from '~/client/util/apiv3-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { IPageGrantData } from '~/interfaces/page'; import { ApplicableGroup, IRecordApplicableGrant, IResIsGrantNormalizedGrantData } from '~/interfaces/page-grant'; import { useCurrentUser } from '~/stores/context'; import { useSWRxApplicableGrant, useSWRxIsGrantNormalized, useSWRxCurrentPage } from '~/stores/page'; type ModalProps = { isOpen: boolean pageId: string dataApplicableGrant: IRecordApplicableGrant currentAndParentPageGrantData: IResIsGrantNormalizedGrantData close(): void } const FixPageGrantModal = (props: ModalProps): JSX.Element => { const { t } = useTranslation(); const { isOpen, pageId, dataApplicableGrant, currentAndParentPageGrantData, close, } = props; const [selectedGrant, setSelectedGrant] = useState(PageGrant.GRANT_RESTRICTED); const [selectedGroup, setSelectedGroup] = useState(undefined); // Alert message state const [shouldShowModalAlert, setShowModalAlert] = useState(false); const applicableGroups = dataApplicableGrant[PageGrant.GRANT_USER_GROUP]?.applicableGroups; // Reset state when opened useEffect(() => { if (isOpen) { setSelectedGrant(PageGrant.GRANT_RESTRICTED); setSelectedGroup(undefined); setShowModalAlert(false); } }, [isOpen]); const submit = async() => { // Validate input values if (selectedGrant === PageGrant.GRANT_USER_GROUP && selectedGroup == null) { setShowModalAlert(true); return; } close(); try { await apiv3Put(`/page/${pageId}/grant`, { grant: selectedGrant, grantedGroups: selectedGroup?.item._id != null ? [{ item: selectedGroup?.item._id, type: selectedGroup.type }] : null, }); toastSuccess(t('Successfully updated')); } catch (err) { toastError(t('Failed to update')); } }; const getGrantLabel = useCallback((isForbidden: boolean, grantData?: IPageGrantData): string => { if (isForbidden) { return t('fix_page_grant.modal.grant_label.isForbidden'); } if (grantData == null) { return t('fix_page_grant.modal.grant_label.isForbidden'); } if (grantData.grant === 1) { return t('fix_page_grant.modal.grant_label.public'); } if (grantData.grant === 4) { return t('fix_page_grant.modal.radio_btn.only_me'); } if (grantData.grant === 5) { if (grantData.grantedGroups == null || grantData.grantedGroups.length === 0) { return t('fix_page_grant.modal.grant_label.isForbidden'); } return `${t('fix_page_grant.modal.radio_btn.grant_group')} (${grantData.grantedGroups.map(g => g.name).join(', ')})`; } throw Error('cannot get grant label'); // this error can't be throwed }, [t]); const renderGrantDataLabel = useCallback(() => { const { isForbidden, currentPageGrant, parentPageGrant } = currentAndParentPageGrantData; const currentGrantLabel = getGrantLabel(false, currentPageGrant); const parentGrantLabel = getGrantLabel(isForbidden, parentPageGrant); return ( <>

{ t('fix_page_grant.modal.grant_label.parentPageGrantLabel') + parentGrantLabel }

{ t('fix_page_grant.modal.grant_label.currentPageGrantLabel') + currentGrantLabel }

{/* eslint-disable-next-line react/no-danger */}

); }, [t, currentAndParentPageGrantData, getGrantLabel]); const renderModalBodyAndFooter = () => { const isGrantAvailable = Object.keys(dataApplicableGrant || {}).length > 0; if (!isGrantAvailable) { return (

{ t('fix_page_grant.modal.no_grant_available') }

); } return ( <>
{/* eslint-disable-next-line react/no-danger */}

{/* grant data label */} {renderGrantDataLabel()}

setSelectedGrant(PageGrant.GRANT_RESTRICTED)} />
setSelectedGrant(PageGrant.GRANT_OWNER)} />
setSelectedGrant(PageGrant.GRANT_USER_GROUP)} />
{ applicableGroups != null && applicableGroups.map(g => ( )) }
{ shouldShowModalAlert && (

{t('fix_page_grant.modal.alert_message')}

) }
); }; return ( { t('fix_page_grant.modal.title') } {renderModalBodyAndFooter()} ); }; export const FixPageGrantAlert = (): JSX.Element => { const { t } = useTranslation(); const { data: currentUser } = useCurrentUser(); const { data: pageData } = useSWRxCurrentPage(); const hasParent = pageData != null ? pageData.parent != null : false; const pageId = pageData?._id; const [isOpen, setOpen] = useState(false); const { data: dataIsGrantNormalized } = useSWRxIsGrantNormalized(currentUser != null ? pageId : null); const { data: dataApplicableGrant } = useSWRxApplicableGrant(currentUser != null ? pageId : null); // Dependencies if (pageData == null) { return <>; } if (!hasParent) { return <>; } if (dataIsGrantNormalized?.isGrantNormalized == null || dataIsGrantNormalized.isGrantNormalized) { return <>; } return ( <>