mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(archive): implement comment.archived and add archive page (#1074)
* feat(archive): implement comment.archived and add archive page Add isCommentArchived() utility, /board/:boardIdentifier/archive route, archive view with filtered feed, and UI integration (board buttons, edit menu, catalog row, post). Archived indicator on catalog and posts. * fix(archive): address review feedback from Bugbot and CodeRabbit Add missing i18n keys (archived, thread_archived, view, loading_archive), add /archive/settings route, replace hardcoded English in archive.tsx, and fix mobile test state.
This commit is contained in:
@@ -127,6 +127,9 @@ const basePost = {
|
||||
removed: false,
|
||||
spoiler: false,
|
||||
communityAddress: 'music-posting.eth',
|
||||
commentModeration: {
|
||||
archived: false,
|
||||
},
|
||||
} as Record<string, any>;
|
||||
|
||||
const renderMenu = async (post = basePost) => {
|
||||
@@ -276,6 +279,7 @@ describe('EditMenu', () => {
|
||||
await click(getCheckbox('removed'));
|
||||
await click(getCheckbox('purged'));
|
||||
await click(getCheckbox('locked'));
|
||||
await click(getCheckbox('archived'));
|
||||
await click(getCheckbox('spoiler'));
|
||||
await click(getCheckbox('pinned'));
|
||||
await click(getCheckbox('banUser'));
|
||||
@@ -302,6 +306,7 @@ describe('EditMenu', () => {
|
||||
});
|
||||
expect(testState.modOptions?.commentModeration).toMatchObject({
|
||||
reason: 'rule violation',
|
||||
archived: true,
|
||||
locked: true,
|
||||
pinned: true,
|
||||
purged: true,
|
||||
@@ -329,6 +334,26 @@ describe('EditMenu', () => {
|
||||
expect(testState.modOptions?.commentModeration?.purged).toBe(false);
|
||||
});
|
||||
|
||||
it('shows archive control only for top-level comments', async () => {
|
||||
testState.privileges = {
|
||||
isAccountCommentAuthor: false,
|
||||
isAccountMod: true,
|
||||
isCommentAuthorMod: false,
|
||||
};
|
||||
|
||||
await renderMenu(basePost);
|
||||
await openMenu();
|
||||
expect(getCheckbox('archived')).not.toBeNull();
|
||||
|
||||
await renderMenu({
|
||||
...basePost,
|
||||
cid: 'reply-comment',
|
||||
parentCid: 'parent-cid',
|
||||
});
|
||||
await openMenu();
|
||||
expect(getCheckbox('archived')).toBeNull();
|
||||
});
|
||||
|
||||
it('runs both the author edit and moderation publication paths when the user has both privileges', async () => {
|
||||
testState.privileges = {
|
||||
isAccountCommentAuthor: true,
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import styles from './edit-menu.module.css';
|
||||
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
|
||||
import { isCommentArchived } from '../../lib/utils/comment-moderation-utils';
|
||||
import useChallengesStore from '../../stores/use-challenges-store';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
@@ -36,6 +37,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
|
||||
const resolvedPost = withResolvedCommentCommunityAddress(post);
|
||||
const { author, cid, content, deleted, locked, parentCid, pinned, postCid, reason, removed, spoiler } = resolvedPost || {};
|
||||
const communityAddress = getCommentCommunityAddress(resolvedPost);
|
||||
const archived = isCommentArchived(resolvedPost);
|
||||
const authorDisplayName = resolvedPost?.author?.displayName;
|
||||
const modBanExpiresAt = resolvedPost?.commentModeration?.author?.banExpiresAt;
|
||||
const purged = resolvedPost?.commentModeration?.purged ?? false;
|
||||
@@ -67,6 +69,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
|
||||
commentModeration: isAccountMod
|
||||
? {
|
||||
locked: locked ?? false,
|
||||
archived: parentCid === undefined ? (archived ?? false) : undefined,
|
||||
pinned: pinned ?? false,
|
||||
removed: removed ?? false,
|
||||
purged: purged ?? false,
|
||||
@@ -82,7 +85,23 @@ const EditMenu = ({ post }: { post: Comment }) => {
|
||||
alert('Comment edit failed. ' + error.message);
|
||||
},
|
||||
};
|
||||
}, [isAccountMod, isAccountCommentAuthor, cid, content, deleted, locked, pinned, reason, removed, purged, spoiler, communityAddress, modBanExpiresAt, onChallenge]);
|
||||
}, [
|
||||
isAccountMod,
|
||||
isAccountCommentAuthor,
|
||||
archived,
|
||||
cid,
|
||||
content,
|
||||
deleted,
|
||||
locked,
|
||||
pinned,
|
||||
reason,
|
||||
removed,
|
||||
purged,
|
||||
spoiler,
|
||||
communityAddress,
|
||||
modBanExpiresAt,
|
||||
onChallenge,
|
||||
]);
|
||||
|
||||
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState<PublishCommentEditOptions>(defaultPublishEditOptions);
|
||||
|
||||
@@ -112,6 +131,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
|
||||
communityAddress,
|
||||
commentModeration: {
|
||||
locked: parentCid === undefined ? publishCommentEditOptions.commentModeration?.locked : undefined,
|
||||
archived: parentCid === undefined ? publishCommentEditOptions.commentModeration?.archived : undefined,
|
||||
pinned: publishCommentEditOptions.commentModeration?.pinned,
|
||||
removed: publishCommentEditOptions.commentModeration?.removed,
|
||||
purged: publishCommentEditOptions.commentModeration?.purged,
|
||||
@@ -337,6 +357,16 @@ const EditMenu = ({ post }: { post: Comment }) => {
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
{!parentCid && (
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.archived ?? false} type='checkbox' id='archived' />
|
||||
{capitalize(t('archived'))}?
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
|
||||
Reference in New Issue
Block a user