import React, { useCallback, useState } from 'react'; import { isPopulated } from '@growi/core'; import { useTranslation } from 'next-i18next'; import DropdownItem from 'reactstrap/es/DropdownItem'; import DropdownMenu from 'reactstrap/es/DropdownMenu'; import DropdownToggle from 'reactstrap/es/DropdownToggle'; import Modal from 'reactstrap/es/Modal'; import ModalBody from 'reactstrap/es/ModalBody'; import ModalHeader from 'reactstrap/es/ModalHeader'; import UncontrolledDropdown from 'reactstrap/es/UncontrolledDropdown'; import { IPageGrantData } from '~/interfaces/page'; import { IUserGroupHasId } from '~/interfaces/user'; import { useCurrentUser } from '~/stores/context'; import { useSWRxMyUserGroupRelations } from '~/stores/user-group'; const AVAILABLE_GRANTS = [ { grant: 1, iconClass: 'icon-people', btnStyleClass: 'outline-info', label: 'Public', }, { grant: 2, iconClass: 'icon-link', btnStyleClass: 'outline-teal', label: 'Anyone with the link', }, // { grant: 3, iconClass: '', label: 'Specified users only' }, { grant: 4, iconClass: 'icon-lock', btnStyleClass: 'outline-danger', label: 'Only me', }, { grant: 5, iconClass: 'icon-options', btnStyleClass: 'outline-purple', label: 'Only inside the group', reselectLabel: 'Reselect the group', }, ]; type Props = { disabled?: boolean, grant: number, grantGroupId?: string, grantGroupName?: string, onUpdateGrant?: (grantData: IPageGrantData) => void, } /** * Page grant select component */ const GrantSelector = (props: Props): JSX.Element => { const { t } = useTranslation(); const { disabled, grantGroupName, onUpdateGrant, grant: currentGrant, grantGroupId, } = props; const [isSelectGroupModalShown, setIsSelectGroupModalShown] = useState(false); const { data: currentUser } = useCurrentUser(); const shouldFetch = isSelectGroupModalShown; const { data: myUserGroupRelations, mutate: mutateMyUserGroupRelations } = useSWRxMyUserGroupRelations(shouldFetch); const showSelectGroupModal = useCallback(() => { mutateMyUserGroupRelations(); setIsSelectGroupModalShown(true); }, [mutateMyUserGroupRelations]); /** * change event handler for grant selector */ const changeGrantHandler = useCallback((grant: number) => { // select group if (grant === 5) { showSelectGroupModal(); return; } if (onUpdateGrant != null) { onUpdateGrant({ grant, grantedGroup: undefined }); } }, [onUpdateGrant, showSelectGroupModal]); const groupListItemClickHandler = useCallback((grantGroup: IUserGroupHasId) => { if (onUpdateGrant != null) { onUpdateGrant({ grant: 5, grantedGroup: { id: grantGroup._id, name: grantGroup.name } }); } // hide modal setIsSelectGroupModalShown(false); }, [onUpdateGrant]); /** * Render grant selector DOM. */ const renderGrantSelector = useCallback(() => { let dropdownToggleBtnColor; let dropdownToggleLabelElm; const dropdownMenuElems = AVAILABLE_GRANTS.map((opt) => { const label = ((opt.grant === 5 && opt.reselectLabel != null) && grantGroupId != null) ? opt.reselectLabel // when grantGroup is selected : opt.label; const labelElm = ( {t(label)} ); // set dropdownToggleBtnColor, dropdownToggleLabelElm if (opt.grant === 1 || opt.grant === currentGrant) { dropdownToggleBtnColor = opt.btnStyleClass; dropdownToggleLabelElm = labelElm; } return changeGrantHandler(opt.grant)}>{labelElm}; }); // add specified group option if (grantGroupId != null) { const labelElm = ( {grantGroupName} ); // set dropdownToggleLabelElm dropdownToggleLabelElm = labelElm; dropdownMenuElems.push({labelElm}); } return (
{dropdownToggleLabelElm} {dropdownMenuElems}
); }, [changeGrantHandler, currentGrant, disabled, grantGroupId, grantGroupName, t]); /** * Render select grantgroup modal. */ const renderSelectGroupModalContent = useCallback(() => { if (!shouldFetch) { return <>; } // show spinner if (myUserGroupRelations == null) { return (
); } // extract IUserGroupHasId const userRelatedGroups: IUserGroupHasId[] = myUserGroupRelations .map((relation) => { // relation.relatedGroup should be populated by server return isPopulated(relation.relatedGroup) ? relation.relatedGroup : undefined; }) // exclude undefined elements .filter((elem): elem is IUserGroupHasId => elem != null); if (userRelatedGroups.length === 0) { return (

{t('user_group.belonging_to_no_group')}

{ currentUser?.admin && (

{t('user_group.manage_user_groups')}

) }
); } return (
{ userRelatedGroups.map((group) => { return ( ); }) }
); }, [currentUser?.admin, groupListItemClickHandler, myUserGroupRelations, shouldFetch, t]); return ( <> { renderGrantSelector() } {/* render modal */} { !disabled && currentUser != null && ( setIsSelectGroupModalShown(false)} > setIsSelectGroupModalShown(false)} className="bg-purple text-light"> {t('user_group.select_group')} {renderSelectGroupModalContent()} ) } ); }; export default GrantSelector;