refactor: rename mod menu to edit menu, add author edit

This commit is contained in:
Tom (plebeius.eth)
2024-06-03 21:32:00 +02:00
parent 6f003f9c11
commit b260fa35bf
5 changed files with 88 additions and 63 deletions
@@ -2,19 +2,21 @@ import { useState } from 'react';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react'; import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
import { PublishCommentEditOptions, useComment, useEditedComment, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks'; import { PublishCommentEditOptions, useComment, useEditedComment, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks';
import styles from './mod-menu.module.css'; import styles from './edit-menu.module.css';
import { alertChallengeVerificationFailed } from '../../../lib/utils/challenge-utils'; import { alertChallengeVerificationFailed } from '../../../lib/utils/challenge-utils';
import useChallengesStore from '../../../stores/use-challenges-store'; import useChallengesStore from '../../../stores/use-challenges-store';
import _ from 'lodash'; import _ from 'lodash';
const { addChallenge } = useChallengesStore.getState(); const { addChallenge } = useChallengesStore.getState();
type ModMenuProps = { type EditMenuProps = {
cid: string; cid: string;
isAccountMod?: boolean;
isAccountCommentAuthor?: boolean;
isCommentAuthorMod?: boolean; isCommentAuthorMod?: boolean;
}; };
const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => { const EditMenu = ({ cid, isAccountMod, isAccountCommentAuthor, isCommentAuthorMod }: EditMenuProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
let post: any; let post: any;
@@ -26,9 +28,10 @@ const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => {
post = comment; post = comment;
} }
const isReply = post?.parentCid; const isReply = post?.parentCid;
const [isModMenuOpen, setIsModMenuOpen] = useState(false); const [isEditMenuOpen, setIsEditMenuOpen] = useState(false);
const defaultPublishOptions: PublishCommentEditOptions = { const defaultPublishOptions: PublishCommentEditOptions = {
deleted: post?.deleted,
removed: post?.removed, removed: post?.removed,
locked: post?.locked, locked: post?.locked,
spoiler: post?.spoiler, spoiler: post?.spoiler,
@@ -81,8 +84,8 @@ const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => {
const { refs, floatingStyles, context } = useFloating({ const { refs, floatingStyles, context } = useFloating({
placement: 'bottom-start', placement: 'bottom-start',
open: isModMenuOpen, open: isEditMenuOpen,
onOpenChange: setIsModMenuOpen, onOpenChange: setIsEditMenuOpen,
middleware: [offset(2), flip({ fallbackAxisSideDirection: 'end' }), shift()], middleware: [offset(2), flip({ fallbackAxisSideDirection: 'end' }), shift()],
whileElementsMounted: autoUpdate, whileElementsMounted: autoUpdate,
}); });
@@ -97,65 +100,82 @@ const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => {
const handleSaveClick = async () => { const handleSaveClick = async () => {
await publishCommentEdit(); await publishCommentEdit();
setIsModMenuOpen(false); setIsEditMenuOpen(false);
}; };
return ( return (
<> <>
<span className={styles.checkbox} ref={refs.setReference} {...(cid && getReferenceProps())}> <span className={styles.checkbox} ref={refs.setReference} {...(cid && getReferenceProps())}>
<input type='checkbox' onChange={() => cid && setIsModMenuOpen(!isModMenuOpen)} checked={isModMenuOpen} /> <input type='checkbox' onChange={() => cid && setIsEditMenuOpen(!isEditMenuOpen)} checked={isEditMenuOpen} />
</span> </span>
{isModMenuOpen && ( {isEditMenuOpen && (isAccountCommentAuthor || isAccountMod) && (
<FloatingFocusManager context={context} modal={false}> <FloatingFocusManager context={context} modal={false}>
<div className={styles.modal} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}> <div className={styles.modal} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
<div className={styles.ModMenu}> <div className={styles.editMenu}>
<div className={styles.menuItem}> {isAccountCommentAuthor && (
<label> <>
[ <div className={styles.menuItem}>
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' /> <label>
{_.capitalize(t('remove'))}? ] [
</label> <input onChange={onCheckbox} checked={publishCommentEditOptions.deleted} type='checkbox' id='deleted' />
</div> {_.capitalize(t('delete'))}? ]
{!isReply && ( </label>
<div className={styles.menuItem}> </div>
[ </>
<label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' id='locked' />
{_.capitalize(t('close_thread'))}?
</label>
]
</div>
)} )}
<div className={styles.menuItem}> {isAccountMod && (
[ <>
<label> <div className={styles.menuItem}>
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' id='spoiler' /> <label>
{_.capitalize(t('spoiler'))}? [
</label> <input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' />
] {_.capitalize(t('remove'))}? ]
</div> </label>
<div className={styles.menuItem}> </div>
[ {!isReply && (
<label> <div className={styles.menuItem}>
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' id='pinned' /> [
{_.capitalize(t('sticky'))}? <label>
</label> <input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' id='locked' />
] {_.capitalize(t('close_thread'))}?
</div> </label>
{!isCommentAuthorMod && ( ]
<div className={styles.menuItem}> </div>
[ )}
<label> <div className={styles.menuItem}>
<input onChange={onCheckbox} checked={!!publishCommentEditOptions.commentAuthor?.banExpiresAt} type='checkbox' id='banUser' /> [
<Trans <label>
i18nKey='ban_user_for' <input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' id='spoiler' />
shouldUnescape={true} {_.capitalize(t('spoiler'))}?
components={{ 1: <input className={styles.banInput} onChange={onBanDurationChange} type='number' min={1} max={100} defaultValue={banDuration} /> }} </label>
/> ]
? </div>
</label> <div className={styles.menuItem}>
] [
</div> <label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' id='pinned' />
{_.capitalize(t('sticky'))}?
</label>
]
</div>
{!isCommentAuthorMod && (
<div className={styles.menuItem}>
[
<label>
<input onChange={onCheckbox} checked={!!publishCommentEditOptions.commentAuthor?.banExpiresAt} type='checkbox' id='banUser' />
<Trans
i18nKey='ban_user_for'
shouldUnescape={true}
components={{
1: <input className={styles.banInput} onChange={onBanDurationChange} type='number' min={1} max={100} defaultValue={banDuration} />,
}}
/>
?
</label>
]
</div>
)}
</>
)} )}
<div className={`${styles.menuItem} ${styles.menuReason}`}> <div className={`${styles.menuItem} ${styles.menuReason}`}>
{_.capitalize(t('reason'))}? {_.capitalize(t('reason'))}?
@@ -172,4 +192,4 @@ const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => {
); );
}; };
export default ModMenu; export default EditMenu;
+1
View File
@@ -0,0 +1 @@
export { default } from './edit-menu';
-1
View File
@@ -1 +0,0 @@
export { default } from './mod-menu';
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router-dom';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useAccount, useBlock, useEditedComment } from '@plebbit/plebbit-react-hooks'; import { useAccount, useBlock, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import styles from '../post.module.css'; import styles from '../post.module.css';
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../../lib/utils/media-utils'; import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../../lib/utils/media-utils';
@@ -17,9 +17,9 @@ import { canEmbed } from '../../embed';
import LoadingEllipsis from '../../loading-ellipsis'; import LoadingEllipsis from '../../loading-ellipsis';
import Markdown from '../../markdown'; import Markdown from '../../markdown';
import PostMenuDesktop from './post-menu-desktop/'; import PostMenuDesktop from './post-menu-desktop/';
import EditMenu from '../edit-menu/edit-menu';
import { PostProps } from '../post'; import { PostProps } from '../post';
import _ from 'lodash'; import _ from 'lodash';
import ModMenu from '../mod-menu';
const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => { const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -39,13 +39,18 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
const authorRole = roles?.[address]?.role; const authorRole = roles?.[address]?.role;
const displayTitle = title && title.length > 75 ? title?.slice(0, 75) + '...' : title; const displayTitle = title && title.length > 75 ? title?.slice(0, 75) + '...' : title;
// pending reply by account is not yet published
const account = useAccount(); const account = useAccount();
const accountShortAddress = account?.author?.shortAddress; const accountShortAddress = account?.author?.shortAddress; // if reply by account is pending, it doesn't have an author yet
const subplebbit = useSubplebbit({ subplebbitAddress });
const commentAuthorRole = subplebbit?.roles?.[author?.address]?.role;
const isCommentAuthorMod = commentAuthorRole === 'admin' || commentAuthorRole === 'owner' || commentAuthorRole === 'moderator';
const accountAuthorRole = subplebbit?.roles?.[account?.author?.address]?.role;
const isAccountMod = accountAuthorRole === 'admin' || accountAuthorRole === 'owner' || accountAuthorRole === 'moderator';
const isAccountCommentAuthor = account?.author?.address === author?.address;
return ( return (
<div className={styles.postInfo}> <div className={styles.postInfo}>
{!isHidden && <ModMenu cid={cid} />} {!isHidden && <EditMenu cid={cid} isAccountCommentAuthor={isAccountCommentAuthor} isAccountMod={isAccountMod} isCommentAuthorMod={isCommentAuthorMod} />}
{title && <span className={styles.subject}>{displayTitle} </span>} {title && <span className={styles.subject}>{displayTitle} </span>}
<span className={styles.nameBlock}> <span className={styles.nameBlock}>
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}> <span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>