UNPKG

@selfcommunity/react-ui

Version:

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

192 lines (191 loc) • 9.24 kB
import { __rest } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useContext, useMemo, useRef, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import CentralProgress from '../CentralProgress'; import { SCOPE_SC_UI } from '../../constants/Errors'; import { Logger } from '@selfcommunity/utils'; import { useSnackbar } from 'notistack'; import classNames from 'classnames'; import ConfirmDialog from '../ConfirmDialog/ConfirmDialog'; import { Box, CircularProgress, ClickAwayListener, Grow, IconButton, ListItemIcon, ListItemText, MenuItem, MenuList, Paper, SwipeableDrawer, useMediaQuery, useTheme, Icon, styled, Popper } from '@mui/material'; import { Endpoints, http } from '@selfcommunity/api-services'; import { SCContext, SCUserContext, UserUtils, useSCFetchLessonCommentObject } from '@selfcommunity/react-core'; const EDIT_COMMENT = '_edit_comment'; const DELETE_COMMENT = '_delete_comment'; const PREFIX = 'SCLessonCommentActionsMenu'; const classes = { root: `${PREFIX}-root`, button: `${PREFIX}-button`, popperRoot: `${PREFIX}-popper-root`, paper: `${PREFIX}-paper`, item: `${PREFIX}-item`, itemText: `${PREFIX}-item-text`, subItem: `${PREFIX}-sub-item` }; const PopperRoot = styled(Popper, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.popperRoot })(() => ({})); const Root = styled(Box, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.root })(() => ({})); export default function LessonCommentActionsMenu(props) { // PROPS const { className, lesson, commentObjectId, commentObject, onEdit, onDelete, PopperProps = {} } = props, rest = __rest(props, ["className", "lesson", "commentObjectId", "commentObject", "onEdit", "onDelete", "PopperProps"]); // CONTEXT const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const scContext = useContext(SCContext); const scUserContext = useContext(SCUserContext); const { enqueueSnackbar } = useSnackbar(); // COMMENT STATE const { obj: commentObj, setObj: setCommentObj } = useSCFetchLessonCommentObject({ id: commentObjectId, commentObject: commentObject, lesson: lesson }); // GENERAL POPPER STATE const [open, setOpen] = useState(false); // CONFIRM ACTION DIALOG STATE const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [currentAction, setCurrentAction] = useState(null); const [currentActionLoading, setCurrentActionLoading] = useState(null); // CONST let popperRef = useRef(null); /** * Handles open popup */ function handleOpen() { if (scUserContext.user) { setOpen(true); } else { scContext.settings.handleAnonymousAction(); } } /** * Closes popup */ function handleClose() { if (popperRef.current && popperRef.current.contains(event.target)) { return; } setOpen(false); if (rest.onClose) { rest.onClose(); } } /** * Perform delete comment */ const performDeleteComment = useMemo(() => () => { return http .request({ url: Endpoints.DeleteCourseComment.url({ id: lesson.course_id, section_id: lesson.section_id, lesson_id: lesson.id, comment_id: commentObject.id }), method: Endpoints.DeleteCourseComment.method }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } return Promise.resolve(res.data); }); }, [commentObj, lesson]); /** * handle action */ function handleAction(action) { if (UserUtils.isBlocked(scUserContext.user) && [EDIT_COMMENT].includes(action)) { // if user is blocked, deny edit and moderate enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.common.userBlocked", defaultMessage: "ui.common.userBlocked" }), { variant: 'warning', autoHideDuration: 3000 }); return; } if (action === EDIT_COMMENT) { onEdit && onEdit(commentObj); handleClose(); } else { setCurrentAction(DELETE_COMMENT); setOpenConfirmDialog(true); handleClose(); } } /** * Perform additional operations at the end of single action */ function performPostConfirmAction(success) { if (success) { setCurrentActionLoading(null); setCurrentAction(null); setOpenConfirmDialog(false); enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.lessonCommentActionMenu.actionSuccess", defaultMessage: "ui.lessonCommentActionMenu.actionSuccess" }), { variant: 'success', autoHideDuration: 3000 }); } else { setCurrentActionLoading(null); enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.lessonCommentActionMenu.actionError", defaultMessage: "ui.lessonCommentActionMenu.actionError" }), { variant: 'error', autoHideDuration: 3000 }); } } /** * Deletes a comment */ function handleConfirmedAction() { if (commentObj && !currentActionLoading) { if (currentAction === DELETE_COMMENT) { setCurrentActionLoading(DELETE_COMMENT); performDeleteComment() .then(() => { onDelete && onDelete(commentObj); performPostConfirmAction(true); }) .catch((error) => { Logger.error(SCOPE_SC_UI, error); performPostConfirmAction(false); }); } } } /** * CIf the authenticated user can modify the comment */ function canModifyContribution() { return scUserContext.user && scUserContext.user.id === commentObj.created_by.id; } /** * If the authenticated user can delete the comment */ function canDeleteContribution() { return scUserContext.user && scUserContext.user.id === commentObj.created_by.id; } /** * Renders comment menu content */ function renderContent() { return (_jsx(Box, { children: !commentObj ? (_jsx(CentralProgress, { size: 30 })) : (_jsxs(MenuList, { children: [canModifyContribution() && (_jsxs(MenuItem, Object.assign({ className: classes.subItem }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "edit" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.lessonCommentActionMenu.edit", defaultMessage: "ui.lessonCommentActionMenu.edit" }), onClick: () => handleAction(EDIT_COMMENT), classes: { root: classes.itemText } })] }))), canDeleteContribution() && (_jsxs(MenuItem, Object.assign({ className: classes.subItem }, { children: [_jsx(ListItemIcon, { children: currentActionLoading === DELETE_COMMENT ? _jsx(CircularProgress, { size: 20 }) : _jsx(Icon, { children: "delete" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.lessonCommentActionMenu.delete", defaultMessage: "ui.lessonCommentActionMenu.delete" }), onClick: () => handleAction(DELETE_COMMENT), classes: { root: classes.itemText } })] })))] })) })); } /** * Renders component */ return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, { children: [_jsx(IconButton // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore , Object.assign({ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore ref: (ref) => { popperRef.current = ref; }, "aria-haspopup": "true", onClick: handleOpen, className: classes.button, size: "small" }, { children: _jsx(Icon, { children: "more_vert" }) })), open && (_jsx(_Fragment, { children: isMobile ? (_jsx(SwipeableDrawer, Object.assign({ open: true, onClose: handleClose, onOpen: handleOpen, anchor: "bottom", disableSwipeToOpen: true }, { children: renderContent() }))) : (_jsx(PopperRoot, Object.assign({ open: true, anchorEl: popperRef.current, role: undefined, transition: true, className: classes.popperRoot }, PopperProps, { placement: "bottom-end" }, { children: ({ TransitionProps, placement }) => (_jsx(Grow, Object.assign({}, TransitionProps, { style: { transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' } }, { children: _jsx(Paper, Object.assign({ variant: 'outlined', className: classes.paper }, { children: _jsx(ClickAwayListener, Object.assign({ onClickAway: handleClose }, { children: renderContent() })) })) }))) }))) })), openConfirmDialog && (_jsx(ConfirmDialog, { open: openConfirmDialog, onConfirm: handleConfirmedAction, isUpdating: Boolean(currentActionLoading), onClose: () => setOpenConfirmDialog(false) }))] }))); }