import React, { useCallback, useState } from 'react'; import { isPopulated, GroupType, type IGrantedGroup } from '@growi/core'; import { useTranslation } from 'next-i18next'; import { UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem, Modal, ModalHeader, ModalBody, } from 'reactstrap'; import type { IPageGrantData } from '~/interfaces/page'; import { useCurrentUser } from '~/stores/context'; import { useMyUserGroups } from './use-my-user-groups'; 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, grantedGroups?: { id: string, name: string, type: GroupType, }[] onUpdateGrant?: (grantData: IPageGrantData) => void, } /** * Page grant select component */ export const GrantSelector = (props: Props): JSX.Element => { const { t } = useTranslation(); const { disabled, grantedGroups, onUpdateGrant, grant: currentGrant, } = props; const [isSelectGroupModalShown, setIsSelectGroupModalShown] = useState(false); const { data: currentUser } = useCurrentUser(); const shouldFetch = isSelectGroupModalShown; const { data: myUserGroups, update: updateMyUserGroups } = useMyUserGroups(shouldFetch); const showSelectGroupModal = useCallback(() => { updateMyUserGroups(); setIsSelectGroupModalShown(true); }, [updateMyUserGroups]); /** * change event handler for grant selector */ const changeGrantHandler = useCallback((grant: number) => { // select group if (grant === 5) { showSelectGroupModal(); return; } if (onUpdateGrant != null) { onUpdateGrant({ grant, grantedGroups: undefined }); } }, [onUpdateGrant, showSelectGroupModal]); const groupListItemClickHandler = useCallback((grantGroup: IGrantedGroup) => { if (onUpdateGrant != null && isPopulated(grantGroup.item)) { let grantedGroupsCopy = grantedGroups != null ? [...grantedGroups] : []; const grantGroupInfo = { id: grantGroup.item._id, name: grantGroup.item.name, type: grantGroup.type }; if (grantedGroupsCopy.find(group => group.id === grantGroupInfo.id) == null) { grantedGroupsCopy.push(grantGroupInfo); } else { grantedGroupsCopy = grantedGroupsCopy.filter(group => group.id !== grantGroupInfo.id); } onUpdateGrant({ grant: 5, grantedGroups: grantedGroupsCopy }); } }, [onUpdateGrant, grantedGroups]); /** * 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) && grantedGroups != null && grantedGroups.length > 0) ? 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 (grantedGroups != null && grantedGroups.length > 0) { const labelElm = ( {grantedGroups.length > 1 ? ( {`${grantedGroups[0].name}... `} +{grantedGroups.length - 1} ) : grantedGroups[0].name} ); // set dropdownToggleLabelElm dropdownToggleLabelElm = labelElm; dropdownMenuElems.push({labelElm}); } return (
{dropdownToggleLabelElm} {dropdownMenuElems}
); }, [changeGrantHandler, currentGrant, disabled, grantedGroups, t]); /** * Render select grantgroup modal. */ const renderSelectGroupModalContent = useCallback(() => { if (!shouldFetch) { return <>; } // show spinner if (myUserGroups == null) { return (
); } if (myUserGroups.length === 0) { return (

{t('user_group.belonging_to_no_group')}

{ currentUser?.admin && (

{t('user_group.manage_user_groups')}

) }
); } return ( <> { myUserGroups.map((group) => { const groupIsGranted = grantedGroups?.find(g => g.id === group.item._id) != null; const activeClass = groupIsGranted ? 'active' : ''; return ( ); }) } ); }, [currentUser?.admin, groupListItemClickHandler, myUserGroups, shouldFetch, t, grantedGroups]); return ( <> { renderGrantSelector() } {/* render modal */} { !disabled && currentUser != null && ( setIsSelectGroupModalShown(false)} > setIsSelectGroupModalShown(false)} className="bg-purple text-light"> {t('user_group.select_group')} {renderSelectGroupModalContent()} ) } ); };