update mod queue

This commit is contained in:
plebeius
2026-01-08 16:43:14 +01:00
parent 4e13efca5f
commit e899ac7fb9
5 changed files with 272 additions and 73 deletions
+75 -50
View File
@@ -34,16 +34,20 @@
.alertThresholdInput {
width: 50px;
padding: 4px;
border: 1px solid var(--border-color);
background: var(--input-background-color);
color: var(--text-color);
border: var(--mod-queue-table-border);
background: var(--mod-queue-header-background-color);
color: var(--body-font-color);
}
.tableWrapper {
border: var(--mod-queue-table-border);
}
.tableHeader {
display: flex;
padding: 8px;
border-bottom: 2px solid var(--border-color);
background: var(--header-background-color);
border-bottom: var(--mod-queue-header-border-bottom);
background: var(--mod-queue-header-background-color);
font-weight: bold;
font-size: 13px;
}
@@ -72,23 +76,26 @@
.empty {
padding: 20px;
text-align: center;
color: var(--secondary-text-color);
color: var(--mod-queue-time-color);
}
/* ModQueueRow styles */
.row {
display: flex;
padding: 4px 8px;
border-bottom: 1px solid var(--border-color);
border-top: none;
border-left: none;
border-right: none;
border-bottom: var(--mod-queue-row-border-bottom);
align-items: center;
gap: 8px;
background-color: var(--post-background-color);
color: var(--text-color);
background-color: var(--mod-queue-row-background-color);
color: var(--body-font-color);
font-size: 13px;
}
.row:hover {
background-color: var(--post-highlight-color);
background-color: var(--mod-queue-row-hover-background-color);
}
.board {
@@ -106,23 +113,24 @@
}
.excerpt a {
text-decoration: none;
color: var(--link-color);
text-decoration: var(--post-link-text-decoration);
color: var(--post-link-text-color);
}
.excerpt a:hover {
text-decoration: underline;
text-decoration: var(--post-link-text-decoration-hover);
color: var(--post-link-text-color-hover);
}
.time {
width: 80px;
flex-shrink: 0;
text-align: right;
color: var(--secondary-text-color);
color: var(--mod-queue-time-color);
}
.time.alert {
color: red;
color: var(--mod-queue-alert-color);
font-weight: bold;
animation: blink 2s infinite;
}
@@ -141,27 +149,39 @@
justify-content: flex-end;
}
.button {
cursor: pointer;
padding: 2px 6px;
border: 1px solid var(--border-color);
background: var(--button-background);
color: var(--button-text);
font-size: 11px;
text-decoration: none;
display: inline-block;
}
/* Desktop: buttons styled as text links */
@media (min-width: 640px) {
.button {
all: unset;
cursor: pointer;
padding: 0;
color: var(--mod-queue-button-text-color);
font-size: 11px;
text-decoration: var(--mod-queue-button-text-decoration);
display: inline-block;
font-family: inherit;
}
.button:hover {
background: var(--button-hover-background);
.button:hover {
color: var(--mod-queue-button-text-color-hover);
text-decoration: var(--mod-queue-button-text-decoration);
}
}
.approve {
color: green;
color: var(--mod-queue-approve-color);
}
.approve:hover {
color: var(--mod-queue-approve-color-hover);
}
.reject {
color: red;
color: var(--mod-queue-reject-color);
}
.reject:hover {
color: var(--mod-queue-reject-color-hover);
}
/* ModQueueBoardFilter styles */
@@ -174,34 +194,31 @@
.filterSelect {
padding: 4px;
border: 1px solid var(--border-color);
background: var(--input-background-color);
color: var(--text-color);
border: var(--mod-queue-table-border);
background: var(--mod-queue-header-background-color);
color: var(--body-font-color);
}
/* ModQueueButton styles */
.modQueueButton {
cursor: pointer;
display: inline-flex;
align-items: center;
margin-left: 8px;
text-decoration: none;
color: var(--text-color);
font-size: 13px;
}
.modQueueButton:hover {
text-decoration: underline;
}
.modQueueButtonCount {
margin-left: 4px;
font-weight: bold;
}
.modQueueButtonAlert {
color: red;
animation: blink 2s infinite;
/* Number blinking, changing color to red */
.modQueueButtonCountAlert {
animation: blinkColor 2s infinite;
}
@keyframes blinkColor {
0% {
color: inherit;
}
50% {
color: var(--mod-queue-alert-color);
}
100% {
color: inherit;
}
}
/* Mobile Layout */
@@ -243,6 +260,14 @@
flex: 1;
text-align: center;
padding: 8px;
border: var(--button-border-mobile);
background: var(--button-background-color-mobile);
color: var(--button-text-color-mobile);
text-decoration: none;
}
.button:hover {
background: var(--button-background-color-mobile);
}
.header {
+60 -23
View File
@@ -148,16 +148,25 @@ export const ModQueueButton = ({ boardIdentifier, isMobile }: ModQueueButtonProp
const { alertThresholdHours } = useModQueueStore();
const { accountSubplebbits } = useAccountSubplebbits();
const accountSubplebbitAddresses = useMemo(() => Object.keys(accountSubplebbits || {}), [accountSubplebbits]);
const defaultSubplebbits = useDefaultSubplebbits();
// Resolve boardIdentifier to address if it exists
const resolvedAddress = useMemo(() => {
if (boardIdentifier) {
return getSubplebbitAddress(boardIdentifier, defaultSubplebbits);
}
return undefined;
}, [boardIdentifier, defaultSubplebbits]);
const subplebbitAddresses = useMemo(() => {
if (boardIdentifier) {
return [boardIdentifier];
if (resolvedAddress) {
return [resolvedAddress];
}
return accountSubplebbitAddresses;
}, [boardIdentifier, accountSubplebbitAddresses]);
}, [resolvedAddress, accountSubplebbitAddresses]);
// If specific board, check if user is mod
const isModOfBoard = boardIdentifier ? accountSubplebbitAddresses.includes(boardIdentifier) : true;
// If specific board, check if user is mod using resolved address
const isModOfBoard = resolvedAddress ? accountSubplebbitAddresses.includes(resolvedAddress) : true;
// Only fetch if we have addresses to check and permissions
const shouldFetch = subplebbitAddresses.length > 0 && isModOfBoard;
@@ -172,29 +181,57 @@ export const ModQueueButton = ({ boardIdentifier, isMobile }: ModQueueButtonProp
return null;
}
const count = feed.length;
// Separate comments into normal and urgent based on threshold
// Match ModQueueRow logic: use > (strictly greater) to be consistent
const { normalCount, urgentCount } = useMemo(() => {
const thresholdSeconds = alertThresholdHours * 3600;
const now = Date.now() / 1000;
const hasAlert = feed.some((item) => {
const timeWaiting = Date.now() / 1000 - item.timestamp;
return timeWaiting > alertThresholdHours * 3600;
});
let normal = 0;
let urgent = 0;
for (const item of feed) {
const timeWaiting = now - item.timestamp;
if (timeWaiting > thresholdSeconds) {
urgent++;
} else {
normal++;
}
}
return { normalCount: normal, urgentCount: urgent };
}, [feed, alertThresholdHours]);
const totalCount = normalCount + urgentCount;
// Use boardIdentifier for the route, but resolvedAddress for mod check
const to = boardIdentifier ? `/${boardIdentifier}/queue` : '/mod/queue';
if (count === 0) {
// If we are on a specific board and the user is a mod, we still show the button
// If we are in global mod view, we show it too
return (
<Link to={to} className={styles.modQueueButton}>
[{t('mod_queue')}]
</Link>
);
}
return (
<Link to={to} className={`${styles.modQueueButton} ${hasAlert ? styles.modQueueButtonAlert : ''}`}>
[{t('mod_queue')} <span className={styles.modQueueButtonCount}>{count}</span>]
</Link>
<button className='button'>
<Link to={to}>
{t('mod_queue')}
{totalCount > 0 && (
<strong>
(
{urgentCount > 0 && normalCount > 0 ? (
<>
<span className={styles.modQueueButtonCount}>{normalCount}</span>
<span className={`${styles.modQueueButtonCount} ${styles.modQueueButtonCountAlert}`}>
{'+'}
{urgentCount}
</span>
</>
) : urgentCount > 0 ? (
<span className={`${styles.modQueueButtonCount} ${styles.modQueueButtonCountAlert}`}>{urgentCount}</span>
) : (
<span className={styles.modQueueButtonCount}>{totalCount}</span>
)}
)
</strong>
)}
</Link>
</button>
);
};