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:
@@ -185,6 +185,7 @@ const renderWithRoute = async (element: React.ReactElement, initialEntry: string
|
||||
createElement(Route, { path: '/all/catalog', element }),
|
||||
createElement(Route, { path: '/mod/queue', element }),
|
||||
createElement(Route, { path: '/:boardIdentifier/catalog', element }),
|
||||
createElement(Route, { path: '/:boardIdentifier/archive', element }),
|
||||
createElement(Route, { path: '/:boardIdentifier/thread/:commentCid', element }),
|
||||
createElement(Route, { path: '/:boardIdentifier', element }),
|
||||
),
|
||||
@@ -288,8 +289,9 @@ describe('BoardButtons', () => {
|
||||
|
||||
expect(testState.resetMock).toHaveBeenCalledTimes(1);
|
||||
expect(testState.subscribeMock).toHaveBeenCalledTimes(1);
|
||||
expect(testState.navigateMock).toHaveBeenCalledWith('/mu/archive');
|
||||
expect(globalThis.alert).toHaveBeenNthCalledWith(1, 'vote_button_unavailable_intro\n\nvote_button_unavailable_outro');
|
||||
expect(globalThis.alert).toHaveBeenNthCalledWith(2, 'Work in progress');
|
||||
expect(globalThis.alert).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('renders desktop catalog controls and wires sort, style, filter, and refresh updates', async () => {
|
||||
@@ -299,6 +301,7 @@ describe('BoardButtons', () => {
|
||||
|
||||
expect(container.textContent).toContain('filtered_threads');
|
||||
expect(container.textContent).toContain('4');
|
||||
expect(container.textContent).not.toContain('archive');
|
||||
expect(container.querySelector('[data-testid="catalog-filters"]')?.textContent).toBe('catalog-filters');
|
||||
expect(container.querySelector('[data-testid="catalog-search"]')?.textContent).toBe('catalog-search');
|
||||
|
||||
@@ -322,6 +325,7 @@ describe('BoardButtons', () => {
|
||||
testState.commentsByCid = {
|
||||
'comment-1': {
|
||||
cid: 'comment-1',
|
||||
archived: true,
|
||||
closed: true,
|
||||
number: 99,
|
||||
pinned: true,
|
||||
@@ -335,6 +339,7 @@ describe('BoardButtons', () => {
|
||||
const tooltips = Array.from(container.querySelectorAll<HTMLElement>('[data-testid="tooltip"]'));
|
||||
expect(tooltips.map((tooltip) => tooltip.dataset.content)).toEqual(['Replies', 'Links', 'pagination.pageLabel']);
|
||||
expect(tooltips.map((tooltip) => tooltip.textContent)).toEqual(['9', '3', '7']);
|
||||
expect(container.textContent).toContain('Archived /');
|
||||
expect(container.textContent).toContain('Sticky /');
|
||||
expect(container.textContent).toContain('Closed /');
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import CatalogFilters from '../catalog-filters';
|
||||
import CatalogSearch from '../catalog-search';
|
||||
import Tooltip from '../tooltip';
|
||||
import { ModQueueButton } from '../../views/mod-queue/mod-queue';
|
||||
import { isCommentArchived } from '../../lib/utils/comment-moderation-utils';
|
||||
import styles from './board-buttons.module.css';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
|
||||
@@ -59,13 +60,21 @@ export const CatalogButton = ({ address, isInAllView, isInSubscriptionsView, isI
|
||||
|
||||
export const ArchiveButton = ({ address, isInAllView, isInSubscriptionsView, isInModView }: BoardButtonsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const directories = useDirectories();
|
||||
|
||||
const handleClick = () => {
|
||||
window.alert('Work in progress');
|
||||
};
|
||||
const isInvalidArchiveContext = isInAllView || isInSubscriptionsView || isInModView;
|
||||
const boardIdentifier = params.boardIdentifier || params.subplebbitAddress;
|
||||
const archiveBoardIdentifier = address ? getBoardPath(address, directories) : boardIdentifier ? getBoardPath(boardIdentifier, directories) : '';
|
||||
const archivePath = archiveBoardIdentifier ? `/${archiveBoardIdentifier}/archive` : '';
|
||||
|
||||
if (isInvalidArchiveContext || !archivePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button className='button' onClick={handleClick}>
|
||||
<button className='button' onClick={() => navigate(archivePath)}>
|
||||
{t('archive')}
|
||||
</button>
|
||||
);
|
||||
@@ -183,7 +192,7 @@ export const AutoButton = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const BottomButton = () => {
|
||||
export const BottomButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const handleClick = () => {
|
||||
window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'instant' });
|
||||
@@ -495,6 +504,7 @@ export const PostPageStats = () => {
|
||||
const postCid = comment?.postCid ?? commentCid;
|
||||
const post = useComment({ commentCid: postCid });
|
||||
|
||||
const archived = isCommentArchived(post);
|
||||
const { closed, pinned, replyCount } = post || {};
|
||||
const linkCount = useCountLinksInReplies(post);
|
||||
const directoryEntry = useDirectoryByAddress(communityAddress);
|
||||
@@ -513,6 +523,7 @@ export const PostPageStats = () => {
|
||||
return (
|
||||
<span>
|
||||
{pinned && `${capitalize(t('sticky'))} / `}
|
||||
{archived && `${capitalize(t('archived'))} / `}
|
||||
{closed && `${capitalize(t('closed'))} / `}
|
||||
<Tooltip content={replyCountTooltip}>{displayReplyCount}</Tooltip> /{' '}
|
||||
<Tooltip content={capitalize(requirePostLinkIsMedia ? t('images') : t('links'))}>{linkCount?.toString()}</Tooltip>
|
||||
|
||||
Reference in New Issue
Block a user