mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(rules): show friendly loading state string for board rules
Replace hardcoded loading text in BoardRulesDisplay with useStateString and LoadingEllipsis so rules loading matches other views like board downloads from peers.
This commit is contained in:
@@ -35,6 +35,9 @@ vi.mock('react-router-dom', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
vi.mock('@bitsocial/bitsocial-react-hooks', () => ({
|
vi.mock('@bitsocial/bitsocial-react-hooks', () => ({
|
||||||
|
useClientsStates: () => ({
|
||||||
|
states: {},
|
||||||
|
}),
|
||||||
useCommunity: (options?: { communityAddress?: string; community?: { name?: string; publicKey?: string } }) => {
|
useCommunity: (options?: { communityAddress?: string; community?: { name?: string; publicKey?: string } }) => {
|
||||||
const communityAddress = options?.communityAddress ?? options?.community?.name ?? options?.community?.publicKey;
|
const communityAddress = options?.communityAddress ?? options?.community?.name ?? options?.community?.publicKey;
|
||||||
return communityAddress ? testState.communities[communityAddress] : undefined;
|
return communityAddress ? testState.communities[communityAddress] : undefined;
|
||||||
@@ -58,6 +61,14 @@ vi.mock('../../../components/markdown', () => ({
|
|||||||
default: ({ content }: { content: string }) => createElement('div', { 'data-testid': 'markdown' }, content),
|
default: ({ content }: { content: string }) => createElement('div', { 'data-testid': 'markdown' }, content),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('lodash/debounce', () => ({
|
||||||
|
default: <T extends (...args: any[]) => unknown>(fn: T) => {
|
||||||
|
const wrapped = ((...args: Parameters<T>) => fn(...args)) as T & { cancel: () => void };
|
||||||
|
wrapped.cancel = () => undefined;
|
||||||
|
return wrapped;
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
let container: HTMLDivElement;
|
let container: HTMLDivElement;
|
||||||
let root: Root;
|
let root: Root;
|
||||||
|
|
||||||
@@ -124,4 +135,18 @@ describe('Rules', () => {
|
|||||||
expect(Array.from(select?.options ?? []).map((option) => option.value)).toEqual(['', 'anime-posting.eth', 'random-posting.eth']);
|
expect(Array.from(select?.options ?? []).map((option) => option.value)).toEqual(['', 'anime-posting.eth', 'random-posting.eth']);
|
||||||
expect(container.textContent).toContain('Rules for: /a/ - Anime & Manga');
|
expect(container.textContent).toContain('Rules for: /a/ - Anime & Manga');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows a friendly loading state string while board rules are downloading', async () => {
|
||||||
|
testState.boardIdentifier = 'a';
|
||||||
|
testState.communities = {
|
||||||
|
'anime-posting.eth': {
|
||||||
|
state: 'fetching-ipns',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderRules();
|
||||||
|
|
||||||
|
expect(container.textContent).toContain('Downloading board from peers');
|
||||||
|
expect(container.textContent).not.toContain('loading...');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { useDirectories, DirectoryCommunity, findDirectoryByAddress } from '../.
|
|||||||
import { useCommunityIdentifier } from '../../hooks/use-community-identifiers';
|
import { useCommunityIdentifier } from '../../hooks/use-community-identifiers';
|
||||||
import { getCommunityAddress, getBoardPath } from '../../lib/utils/route-utils';
|
import { getCommunityAddress, getBoardPath } from '../../lib/utils/route-utils';
|
||||||
import Markdown from '../../components/markdown';
|
import Markdown from '../../components/markdown';
|
||||||
|
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||||
|
import useStateString from '../../hooks/use-state-string';
|
||||||
import styles from './rules.module.css';
|
import styles from './rules.module.css';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import lowerCase from 'lodash/lowerCase';
|
import lowerCase from 'lodash/lowerCase';
|
||||||
@@ -23,30 +25,11 @@ const getBoardName = (title?: string): string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const BoardRulesDisplay = ({ communityAddress, directories }: { communityAddress: string; directories: DirectoryCommunity[] }) => {
|
const BoardRulesDisplay = ({ communityAddress, directories }: { communityAddress: string; directories: DirectoryCommunity[] }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const communityIdentifier = useCommunityIdentifier(communityAddress);
|
const communityIdentifier = useCommunityIdentifier(communityAddress);
|
||||||
const community = useCommunity(communityIdentifier ? { community: communityIdentifier } : undefined);
|
const community = useCommunity(communityIdentifier ? { community: communityIdentifier } : undefined);
|
||||||
const { rules, state, title, shortAddress } = community || {};
|
const { rules, state, title, shortAddress } = community || {};
|
||||||
|
const stateString = useStateString(community) || t('downloading_board');
|
||||||
let loadingText: string | null = null;
|
|
||||||
if (!community) {
|
|
||||||
loadingText = 'connecting...';
|
|
||||||
} else {
|
|
||||||
switch (state) {
|
|
||||||
case 'fetching-ipns':
|
|
||||||
case 'fetching-ipfs':
|
|
||||||
loadingText = 'loading...';
|
|
||||||
break;
|
|
||||||
case 'failed':
|
|
||||||
loadingText = 'failed to load';
|
|
||||||
break;
|
|
||||||
case 'succeeded':
|
|
||||||
loadingText = null;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
loadingText = state ? `${state}...` : 'loading...';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isLoaded = state === 'succeeded';
|
const isLoaded = state === 'succeeded';
|
||||||
|
|
||||||
const defaultSub = directories.find((sub) => sub.address === communityAddress);
|
const defaultSub = directories.find((sub) => sub.address === communityAddress);
|
||||||
@@ -75,7 +58,7 @@ const BoardRulesDisplay = ({ communityAddress, directories }: { communityAddress
|
|||||||
<div className={styles.boxContent}>
|
<div className={styles.boxContent}>
|
||||||
{!isLoaded ? (
|
{!isLoaded ? (
|
||||||
<p>
|
<p>
|
||||||
<em>{loadingText}</em>
|
<em>{state === 'failed' ? t('failed') : <LoadingEllipsis string={stateString} />}</em>
|
||||||
</p>
|
</p>
|
||||||
) : rules && rules.length > 0 ? (
|
) : rules && rules.length > 0 ? (
|
||||||
<ol>
|
<ol>
|
||||||
|
|||||||
Reference in New Issue
Block a user