UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

191 lines (182 loc) • 10.2 kB
import { __rest } from "tslib"; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useEffect, useMemo, useState } from 'react'; import { styled } from '@mui/material/styles'; import { Divider, Icon, IconButton, List, ListItem, ListItemButton, ListItemText, Menu, MenuItem, Slide, SwipeableDrawer, useMediaQuery, useTheme } from '@mui/material'; import { Link, UserUtils, useSCContext, useSCFetchUser, useSCUser } from '@selfcommunity/react-core'; import { http, Endpoints } from '@selfcommunity/api-services'; import classNames from 'classnames'; import { useThemeProps } from '@mui/system'; import { FormattedMessage } from 'react-intl'; import UserInfoDialog from '../UserInfoDialog'; import ConfirmDialog from '../../shared/ConfirmDialog/ConfirmDialog'; import { useSnackbar } from 'notistack'; const PREFIX = 'SCUserActionIconButton'; const classes = { root: `${PREFIX}-root`, drawerRoot: `${PREFIX}-drawer-root`, menuRoot: `${PREFIX}-menu-root` }; const Root = styled(IconButton, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.root })(({ theme }) => ({})); const SwipeableDrawerRoot = styled(SwipeableDrawer, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.drawerRoot })(({ theme }) => ({})); const MenuRoot = styled(Menu, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.menuRoot })(({ theme }) => ({})); const Transition = React.forwardRef(function Transition(props, ref) { return _jsx(Slide, Object.assign({ direction: "up", ref: ref }, props)); }); /** * > API documentation for the Community-JS User Action Menu component. Learn about the available props and the CSS API. #### Import ```jsx import {UserActionIconButton} from '@selfcommunity/react-ui'; ``` #### Component Name The name `SUserActionIconButton` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SUserActionIconButton-root|Styles applied to the root element.| * @param inProps */ export default function UserActionIconButton(inProps) { // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { className = null, userId = null, user = null, items = [] } = props, rest = __rest(props, ["className", "userId", "user", "items"]); // CONTEXT const scUserContext = useSCUser(); const scContext = useSCContext(); // STATE const [anchorEl, setAnchorEl] = useState(null); const [infoOpen, setInfoOpen] = useState(false); const [isHiddenLoading, setHiddenLoading] = useState(false); const [hidden, setHidden] = useState(null); const [openHideDialog, setOpenHideDialog] = useState(false); // HOOKS const { scUser } = useSCFetchUser({ id: userId, user }); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const { enqueueSnackbar } = useSnackbar(); // HANDLERS const handleOpen = (event) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const handleInfoOpen = () => { setInfoOpen(true); setAnchorEl(null); }; const handleInfoClose = () => { setInfoOpen(false); }; const handleHideToggle = () => { setHiddenLoading(true); scUserContext.managers.blockedUsers .block(scUser) .then((blocked) => { setHidden(blocked); }) .then(() => setHiddenLoading(false)) .catch(() => { enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.common.action.notPermitted", defaultMessage: "ui.common.action.notPermitted" }), { variant: 'warning', autoHideDuration: 7000 }); setHiddenLoading(false); handleHide(); }); }; const handleHide = useMemo(() => () => { setOpenHideDialog((prev) => !prev); handleClose(); }, [setOpenHideDialog, handleClose]); // MEMO const isMe = scUserContext.user && scUser.id === scUserContext.user.id; const roles = useMemo(() => scUserContext.user && (scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user.role), [scUserContext.user]); const canModerate = useMemo(() => roles && (roles.includes('admin') || roles.includes('moderator')) && !isMe, [roles, isMe]); /** * Fetches platform url */ function fetchPlatform(query) { http .request({ url: Endpoints.Platform.url(), method: Endpoints.Platform.method, params: { next: query } }) .then((res) => { handleClose(); const platformUrl = res.data.platform_url; window.open(platformUrl, '_blank').focus(); }) .catch((error) => { console.log(error); }); } // EFFECTS useEffect(() => { if (anchorEl && hidden === null && scUser) { setHidden(scUserContext.managers.blockedUsers.isBlocked(scUser)); } }, [anchorEl, scUser]); // RENDER if (!scUserContext.user) { return null; } const renderList = () => { if (isMobile) { return [ ...items.map((item, index) => (_jsx(ListItem, { children: _jsx(ListItemButton, Object.assign({ component: Link, to: item.to }, { children: _jsx(ListItemText, { primary: item.label }) })) }, index))), _jsx(ListItem, { children: _jsx(ListItemButton, Object.assign({ onClick: handleInfoOpen }, { children: _jsx(ListItemText, { primary: _jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.information", id: "ui.userActionIconButton.information" }) }) })) }, "info"), ...(isMe ? [] : [ _jsx(Divider, {}, "divider"), _jsx(ListItem, { children: _jsx(ListItemButton, Object.assign({ onClick: handleHideToggle, disabled: isHiddenLoading || scUser.community_badge || (!hidden && UserUtils.isStaff(scUser)) }, { children: _jsx(ListItemText, { primary: hidden ? (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.show", id: "ui.userActionIconButton.show" })) : (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.hide", id: "ui.userActionIconButton.hide" })) }) })) }, "hide"), ...(canModerate ? [ _jsx(Divider, {}, "divider_moderate"), _jsx(ListItem, { children: _jsx(ListItemButton, Object.assign({ component: Link, onClick: () => fetchPlatform(`/moderation/user/?username=${scUser.username}`) }, { children: _jsx(ListItemText, { primary: _jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.moderate", id: "ui.userActionIconButton.moderate" }) }) })) }, "moderate") ] : []) ]) ]; } else { return [ ...items.map((item, index) => (_jsx(MenuItem, Object.assign({ component: Link, to: item.to, onClick: handleClose }, { children: item.label }), index))), _jsx(MenuItem, Object.assign({ onClick: handleInfoOpen }, { children: _jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.information", id: "ui.userActionIconButton.information" }) }), "info"), ...(isMe ? [] : [ _jsx(Divider, {}, "divider"), _jsx(MenuItem, Object.assign({ onClick: handleHide, disabled: isHiddenLoading || scUser.community_badge }, { children: hidden ? (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.show", id: "ui.userActionIconButton.show" })) : (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.hide", id: "ui.userActionIconButton.hide" })) }), "hide"), ...(canModerate ? [ _jsx(Divider, {}, "divider_moderate"), _jsx(MenuItem, Object.assign({ component: Link, onClick: () => fetchPlatform(`/moderation/user/?username=${scUser.username}`) }, { children: _jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.moderate", id: "ui.userActionIconButton.moderate" }) }), "moderate") ] : []) ]) ]; } }; return (_jsxs(_Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { onClick: handleOpen }, { children: _jsx(Icon, { children: "more_vert" }) })), Boolean(anchorEl) && (_jsx(_Fragment, { children: isMobile ? (_jsx(SwipeableDrawerRoot, Object.assign({ className: classes.drawerRoot, anchor: "bottom", open: true, onClose: handleClose, onOpen: handleOpen, disableSwipeToOpen: true }, { children: _jsx(List, { children: renderList() }) }))) : (_jsx(MenuRoot, Object.assign({ className: classes.menuRoot, anchorEl: anchorEl, open: true, onClose: handleClose }, { children: renderList() }))) })), _jsx(UserInfoDialog, { userId: userId, user: scUser, open: infoOpen, onClose: handleInfoClose }), openHideDialog && (_jsx(ConfirmDialog, { open: openHideDialog, isUpdating: isHiddenLoading, TransitionComponent: Transition, keepMounted: true, title: hidden ? (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.show", id: "ui.userActionIconButton.show" })) : (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.hide", id: "ui.userActionIconButton.hide" })), content: hidden ? (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.dialogShowAction", id: "ui.userActionIconButton.dialogShowAction" })) : (_jsx(FormattedMessage, { defaultMessage: "ui.userActionIconButton.dialogHideAction", id: "ui.userActionIconButton.dialogHideAction" })), onConfirm: handleHideToggle, onClose: () => setOpenHideDialog(false) }))] })); }