import * as React from 'react'; import { Box, Chip, Divider, FormControl, IconButton, InputLabel, Link, List, ListItem, ListItemButton, MenuItem, Paper, Select, SelectChangeEvent, Typography } from '@mui/material'; import { useOutletContext } from 'react-router'; import { WikiContext } from './WikiSpaceView'; import { useObjectState } from '@hyper-hyper-space/react'; import { PermFlag, PermFlagEveryone, PermFlagMembers, PermFlagModerators, PermFlagOwners } from '@hyper-hyper-space/wiki-collab'; import ContactSelectorDialog from '../../home/components/ContactSelectorDialog'; import { CausalSet, Identity } from '@hyper-hyper-space/core'; import { Contact, ProfileUtils } from '../../../model/ProfileUtils'; import ContactListDisplay from '../../home/components/ContactListDisplay'; import { AdminPanelSettings, SupervisedUserCircle, LockPerson, Public } from '@mui/icons-material'; import Menu from '@mui/material/Menu'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import { size, sortBy } from 'lodash-es'; import InfoDialog from '../../../components/InfoDialog'; import { MemberInfo, ReadInfo, WriteInfo } from './WikiSpaceInfoTips'; const ITEM_HEIGHT = 48; const ADD_TO_MODERATORS = 'Add to moderators'; const REMOVE_FROM_MODERATORS = 'Remove from moderators'; const REMOVE_FROM_MEMBERS = 'Remove from members'; export function MemberActionMenu(props: {memberId: Identity}) { const {memberId} = props const { spaceContext, wiki } = useOutletContext(); const author = spaceContext?.home?.getAuthor(); const membersState = useObjectState(wiki?.permissionLogic?.members) const moderatorsState = useObjectState(wiki?.permissionLogic?.moderators) const owners = wiki.owners! const generateMemberActions = async () => { const actions: { [key: string]: Function } = {}; const canAddToModerators = (await moderatorsState?.getValue()?.canAdd(memberId, author)) && !moderatorsState?.value?.has(memberId); if (canAddToModerators) { actions[ADD_TO_MODERATORS] = () => { moderatorsState?.getValue()?.add(memberId, author); moderatorsState?.getValue()?.save(); }; } const canRemoveFromModerators = (await moderatorsState?.getValue()?.canDelete(memberId, author)) && moderatorsState?.value?.has(memberId); if (canRemoveFromModerators) { actions[REMOVE_FROM_MODERATORS] = () => { moderatorsState?.getValue()?.delete(memberId, author); moderatorsState?.getValue()?.save(); }; } const canRemoveFromMembers = await membersState?.value?.canDelete(memberId, author); if (canRemoveFromMembers) { actions[REMOVE_FROM_MEMBERS] = () => { membersState?.getValue()?.delete(memberId, author); membersState?.getValue()?.save(); moderatorsState?.getValue()?.delete(memberId, author); moderatorsState?.getValue()?.save(); }; } return actions; }; const [actions, setActions] = React.useState<{[key: string]: Function | null}>({}) React.useEffect(() => { let cancel = false generateMemberActions().then(memberActions => { if (cancel) return; setActions(memberActions) }) return () => { cancel = true } }, [moderatorsState]) const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return (
{size(actions) > 0 && } {Object.entries(actions).map(([action, handler]) => ( { handler && handler() handleClose() }}> {action} ))}
); } function PermFlagToggle(props: { flag: CausalSet, name: String, info?: JSX.Element }) { const { spaceContext } = useOutletContext(); const flagState = useObjectState(props.flag); const author = spaceContext?.home?.getAuthor(); const [infoTipOpen, setInfoTipOpen] = React.useState(false); const handleChange = async ( event: SelectChangeEvent, ) => { const flag = event.target.value; // could be nice if there was a better way to do this! if (flag === PermFlagEveryone) { await flagState?.getValue()?.add(PermFlagEveryone, author); await flagState?.getValue()?.delete(PermFlagMembers, author); await flagState?.getValue()?.delete(PermFlagModerators, author); await flagState?.getValue()?.save() // console.log('wiki permissions set', props.name, [...flagState?.getValue()?.values()!]) } else if (flag === PermFlagMembers) { await flagState?.getValue()?.delete(PermFlagEveryone, author); await flagState?.getValue()?.add(PermFlagMembers, author); await flagState?.getValue()?.delete(PermFlagModerators, author); await flagState?.getValue()?.save() // console.log('wiki permissions set', props.name, [...flagState?.getValue()?.values()!]) } else if (flag === PermFlagModerators) { await flagState?.getValue()?.delete(PermFlagEveryone, author); await flagState?.getValue()?.delete(PermFlagMembers, author); await flagState?.getValue()?.add(PermFlagModerators, author); await flagState?.getValue()?.save() // console.log('wiki permissions set', props.name, [...flagState?.getValue()?.values()!]) } else if (flag === PermFlagOwners) { await flagState?.getValue()?.delete(PermFlagEveryone, author); await flagState?.getValue()?.delete(PermFlagMembers, author); await flagState?.getValue()?.delete(PermFlagModerators, author); await flagState?.getValue()?.save() // console.log('wiki permissions set', props.name, [...flagState?.getValue()?.values()!]) } }; const flag = flagState?.getValue()?.has(PermFlagEveryone) ? PermFlagEveryone : flagState?.getValue()?.has(PermFlagMembers) ? PermFlagMembers : flagState?.getValue()?.has(PermFlagModerators) ? PermFlagModerators : PermFlagOwners const statusText = ( props.info ? Who can setInfoTipOpen(true)}>{ props.name }: setInfoTipOpen(false)}/> : Who can { props.name}: ) return ( <> { statusText } { flag === PermFlagEveryone ? : flag === PermFlagMembers ? : flag === PermFlagModerators ? : flag === PermFlagOwners ? : } ); } function MemberList() { const { wiki } = useOutletContext(); const membersState = useObjectState(wiki?.permissionLogic?.members) const moderatorsState = useObjectState(wiki?.permissionLogic?.moderators) const owners = wiki.owners! const [infoTipOpen, setInfoTipOpen] = React.useState(false); return setInfoTipOpen(true)}>Members setInfoTipOpen(false)}/> {[...owners.values()!].map(id => }/> ]}/> )} {sortBy([...membersState?.value?.values()!], [ // id => moderatorsState?.value?.has(id) ? -1 : 1, id => ProfileUtils.createContact(id).name, ]).map(id => { return }/> ] : []}/> } )} } export default function WikiSpacePermissionSettings() { const { spaceContext, wiki } = useOutletContext(); const { home, homeResources, resources } = spaceContext; const membersState = useObjectState(wiki?.permissionLogic?.members) const owners = wiki.owners! return ( {/* Permissions */}
{/* */}
id.getLastHash())} handleSelect={async (contact: Contact | Identity) => { // console.log('attempting to select', contact) const identity = contact instanceof Identity ? contact : await homeResources?.store.load(contact.hash)! as Identity membersState?.value?.add(identity, home?.getAuthor()!) membersState?.value?.save() }} />
); }