import React, { useCallback, useEffect, useState } from 'react';
import {
PageGrant, GroupType, getIdForRef,
} from '@growi/core';
import { LoadingSpinner } from '@growi/ui/dist/components';
import { useTranslation } from 'next-i18next';
import {
UncontrolledDropdown,
DropdownToggle, DropdownMenu, DropdownItem,
Modal, ModalHeader, ModalBody,
} from 'reactstrap';
import type { UserRelatedGroupsData } from '~/interfaces/page';
import { UserGroupPageGrantStatus } from '~/interfaces/page';
import { useCurrentUser } from '~/stores/context';
import { useCurrentPageId, useSWRxCurrentGrantData } from '~/stores/page';
import { useSelectedGrant } from '~/stores/ui';
const AVAILABLE_GRANTS = [
{
grant: PageGrant.GRANT_PUBLIC, iconName: 'group', btnStyleClass: 'outline-info', label: 'Public',
},
{
grant: PageGrant.GRANT_RESTRICTED, iconName: 'link', btnStyleClass: 'outline-success', label: 'Anyone with the link',
},
// { grant: 3, iconClass: '', label: 'Specified users only' },
{
grant: PageGrant.GRANT_OWNER, iconName: 'lock', btnStyleClass: 'outline-danger', label: 'Only me',
},
{
grant: PageGrant.GRANT_USER_GROUP,
iconName: 'more_horiz',
btnStyleClass: 'outline-warning',
label: 'Only inside the group',
reselectLabel: 'Reselect the group',
},
];
type Props = {
disabled?: boolean,
openInModal?: boolean,
}
/**
* Page grant select component
*/
export const GrantSelector = (props: Props): JSX.Element => {
const { t } = useTranslation();
const {
disabled,
openInModal,
} = props;
const [isSelectGroupModalShown, setIsSelectGroupModalShown] = useState(false);
const { data: currentUser } = useCurrentUser();
const shouldFetch = isSelectGroupModalShown;
const { data: selectedGrant, mutate: mutateSelectedGrant } = useSelectedGrant();
const { data: currentPageId } = useCurrentPageId();
const { data: grantData } = useSWRxCurrentGrantData(currentPageId);
const currentPageGrantData = grantData?.grantData.currentPageGrant;
const groupGrantData = currentPageGrantData?.groupGrantData;
const applyCurrentPageGrantToSelectedGrant = useCallback(() => {
const currentPageGrant = grantData?.grantData.currentPageGrant;
if (currentPageGrant == null) return;
const userRelatedGrantedGroups = currentPageGrant.groupGrantData
?.userRelatedGroups.filter(group => group.status === UserGroupPageGrantStatus.isGranted)?.map((group) => {
return { item: group.id, type: group.type };
}) ?? [];
mutateSelectedGrant({
grant: currentPageGrant.grant,
userRelatedGrantedGroups,
});
}, [grantData?.grantData.currentPageGrant, mutateSelectedGrant]);
// sync grant data
useEffect(() => {
applyCurrentPageGrantToSelectedGrant();
}, [applyCurrentPageGrantToSelectedGrant]);
const showSelectGroupModal = useCallback(() => {
setIsSelectGroupModalShown(true);
}, []);
/**
* change event handler for grant selector
*/
const changeGrantHandler = useCallback((grant: PageGrant) => {
// select group
if (grant === 5) {
if (selectedGrant?.grant !== 5) applyCurrentPageGrantToSelectedGrant();
showSelectGroupModal();
return;
}
mutateSelectedGrant({ grant, userRelatedGrantedGroups: undefined });
}, [mutateSelectedGrant, showSelectGroupModal, applyCurrentPageGrantToSelectedGrant, selectedGrant?.grant]);
const groupListItemClickHandler = useCallback((clickedGroup: UserRelatedGroupsData) => {
const userRelatedGrantedGroups = selectedGrant?.userRelatedGrantedGroups ?? [];
let userRelatedGrantedGroupsCopy = [...userRelatedGrantedGroups];
if (userRelatedGrantedGroupsCopy.find(group => getIdForRef(group.item) === clickedGroup.id) == null) {
const grantGroupInfo = { item: clickedGroup.id, type: clickedGroup.type };
userRelatedGrantedGroupsCopy.push(grantGroupInfo);
}
else {
userRelatedGrantedGroupsCopy = userRelatedGrantedGroupsCopy.filter(group => getIdForRef(group.item) !== clickedGroup.id);
}
mutateSelectedGrant({ grant: 5, userRelatedGrantedGroups: userRelatedGrantedGroupsCopy });
}, [mutateSelectedGrant, selectedGrant?.userRelatedGrantedGroups]);
/**
* Render grant selector DOM.
*/
const renderGrantSelector = useCallback(() => {
let dropdownToggleBtnColor;
let dropdownToggleLabelElm;
const userRelatedGrantedGroups = groupGrantData?.userRelatedGroups.filter((group) => {
return selectedGrant?.userRelatedGrantedGroups?.some(grantedGroup => getIdForRef(grantedGroup.item) === group.id);
}) ?? [];
const nonUserRelatedGrantedGroups = groupGrantData?.nonUserRelatedGrantedGroups ?? [];
const dropdownMenuElems = AVAILABLE_GRANTS.map((opt) => {
const label = ((opt.grant === 5 && opt.reselectLabel != null) && userRelatedGrantedGroups.length > 0)
? opt.reselectLabel // when grantGroup is selected
: opt.label;
const labelElm = (
{opt.iconName}
{t(label)}
);
// set dropdownToggleBtnColor, dropdownToggleLabelElm
if (opt.grant === 1 || opt.grant === selectedGrant?.grant) {
dropdownToggleBtnColor = opt.btnStyleClass;
dropdownToggleLabelElm = labelElm;
}
return