@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
192 lines (191 loc) • 9.24 kB
JavaScript
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) }))] })));
}