feat(mod-queue): add number column, improve time display, and use edited comments

- Add 'No.' column displaying post number
- Change 'waiting' to 'submitted' column with formatted date + ago format
- Show blinking relative time in parentheses for items awaiting approval
- Use useEditedComment hook to display pending edits
- Make time column width auto to fit content
- Remove unused translation keys (waiting, mod_queue_alert_threshold_tip, view)
- Add 'submitted' translation key in all languages
This commit is contained in:
plebeius
2026-01-11 12:28:21 +01:00
parent a23f5bc238
commit a33b2e5a9a
37 changed files with 105 additions and 148 deletions
+17 -3
View File
@@ -50,6 +50,12 @@
background: var(--mod-queue-header-background-color);
font-weight: bold;
font-size: 13px;
text-transform: capitalize;
}
.numberHeader {
width: 60px;
flex-shrink: 0;
}
.boardHeader {
@@ -62,9 +68,10 @@
}
.timeHeader {
width: 80px;
width: auto;
text-align: right;
flex-shrink: 0;
white-space: nowrap;
}
.actionsHeader {
@@ -98,6 +105,12 @@
background-color: var(--mod-queue-row-hover-background-color);
}
.number {
width: 60px;
flex-shrink: 0;
font-weight: bold;
}
.board {
width: 50px;
flex-shrink: 0;
@@ -123,13 +136,14 @@
}
.time {
width: 80px;
width: auto;
flex-shrink: 0;
text-align: right;
color: var(--mod-queue-time-color);
white-space: nowrap;
}
.time.alert {
.time .alert {
color: var(--mod-queue-alert-color);
font-weight: bold;
animation: blink 2s infinite;
+18 -5
View File
@@ -1,7 +1,7 @@
import React, { useMemo, useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams, Link } from 'react-router-dom';
import { useAccountSubplebbits, useFeed, Comment, usePublishCommentModeration } from '@plebbit/plebbit-react-hooks';
import { useAccountSubplebbits, useFeed, Comment, usePublishCommentModeration, useEditedComment } from '@plebbit/plebbit-react-hooks';
import { Virtuoso } from 'react-virtuoso';
import { formatDistanceToNow } from 'date-fns';
import styles from './mod-queue.module.css';
@@ -13,6 +13,7 @@ import { getSubplebbitAddress, getBoardPath } from '../../lib/utils/route-utils'
import { useDefaultSubplebbits, MultisubSubplebbit } from '../../hooks/use-default-subplebbits';
import { useBoardPath } from '../../hooks/use-resolved-subplebbit-address';
import { getHasThumbnail, getCommentMediaInfo } from '../../lib/utils/media-utils';
import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils';
import useFeedResetStore from '../../stores/use-feed-reset-store';
import useChallengesStore from '../../stores/use-challenges-store';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
@@ -50,7 +51,11 @@ const ModQueueRow = ({ comment, showBoardColumn = false }: ModQueueRowProps) =>
const { alertThresholdHours } = useModQueueStore();
const [initiatedAction, setInitiatedAction] = useState<ModerationAction>(null);
const { content, title, timestamp, subplebbitAddress, cid, threadCid, link, thumbnailUrl, linkWidth, linkHeight, removed, approved } = comment;
// handle pending mod or author edit
const { editedComment } = useEditedComment({ comment });
const displayComment = editedComment || comment;
const { content, title, timestamp, subplebbitAddress, cid, threadCid, link, thumbnailUrl, linkWidth, linkHeight, removed, approved, number } = displayComment;
// Check if already moderated (from previous session or API update)
// Note: `approved` and `removed` are direct fields on the comment from CommentUpdate,
@@ -180,6 +185,7 @@ const ModQueueRow = ({ comment, showBoardColumn = false }: ModQueueRowProps) =>
return (
<div className={styles.row}>
<div className={styles.number}>{number ?? '—'}</div>
{showBoardColumn && <div className={styles.board}>{boardPath ? <Link to={`/${boardPath}`}>/{boardPath}/</Link> : <span></span>}</div>}
<div className={styles.excerpt}>
{postUrl ? (
@@ -190,8 +196,14 @@ const ModQueueRow = ({ comment, showBoardColumn = false }: ModQueueRowProps) =>
<span title={excerpt}>{excerpt}</span>
)}
</div>
<div className={`${styles.time} ${isOverThreshold && isAwaitingApproval && !approveSucceeded && !rejectSucceeded ? styles.alert : ''}`}>
{formatDistanceToNow(timestamp * 1000, { addSuffix: false })}
<div className={styles.time}>
{isAwaitingApproval ? (
<>
{getFormattedDate(timestamp)} (<span className={`${isOverThreshold ? styles.alert : ''}`}>{getFormattedTimeAgo(timestamp)}</span>)
</>
) : (
getFormattedDate(timestamp)
)}
</div>
<div className={styles.actions}>{renderActions()}</div>
</div>
@@ -443,9 +455,10 @@ export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueV
) : (
<>
<div className={styles.tableHeader}>
<div className={styles.numberHeader}>No.</div>
{showBoardColumn && <div className={styles.boardHeader}>{t('board')}</div>}
<div className={styles.excerptHeader}>{t('excerpt')}</div>
<div className={styles.timeHeader}>{t('waiting')}</div>
<div className={styles.timeHeader}>{t('submitted')}</div>
<div className={styles.actionsHeader}>{t('actions')}</div>
</div>