mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'codex/fix/directory-loading-center'
This commit is contained in:
@@ -145,8 +145,16 @@
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.ownerCell {
|
||||
.ownerCell,
|
||||
.statusCell {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.statusLoading {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.ownerName {
|
||||
|
||||
@@ -135,7 +135,9 @@ const DirectoryRow = ({ board, nowSeconds, rank, onVote }: DirectoryRowProps) =>
|
||||
</Tooltip>
|
||||
</span>
|
||||
) : status === 'loading' ? (
|
||||
<LoadingEllipsis string={t('loading')} />
|
||||
<span className={styles.statusLoading}>
|
||||
<LoadingEllipsis string={t('loading')} />
|
||||
</span>
|
||||
) : status === 'unknown' ? (
|
||||
<span className={styles.statusUnavailable}>{DIRECTORY_STATUS_UNAVAILABLE_MARKER}</span>
|
||||
) : (
|
||||
|
||||
@@ -3,6 +3,7 @@ import { createElement } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { useFeedStateString } from '../../../hooks/use-state-string';
|
||||
import Home from '../home';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
@@ -19,6 +20,7 @@ const testState = vi.hoisted(() => ({
|
||||
navigateMock: vi.fn(),
|
||||
communities: {} as Record<string, unknown>,
|
||||
communityStats: {} as Record<string, { allPostCount?: number; weekActiveUserCount?: number; state?: string }>,
|
||||
feedStateString: 'Downloading boards',
|
||||
}));
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
@@ -76,6 +78,10 @@ vi.mock('../../../hooks/use-now-seconds', () => ({
|
||||
useNowSeconds: () => testState.nowSeconds,
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-state-string', () => ({
|
||||
useFeedStateString: vi.fn(() => testState.feedStateString),
|
||||
}));
|
||||
|
||||
vi.mock('../../../components/loading-ellipsis', () => ({
|
||||
default: ({ string }: { string: string }) => createElement('span', { 'data-testid': 'loading-ellipsis' }, string),
|
||||
}));
|
||||
@@ -139,6 +145,7 @@ describe('Home', () => {
|
||||
'music-posting.eth': { allPostCount: 5, weekActiveUserCount: 2 },
|
||||
'tech-posting.eth': { allPostCount: 7, weekActiveUserCount: 5 },
|
||||
};
|
||||
testState.feedStateString = 'Downloading boards';
|
||||
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
@@ -153,6 +160,7 @@ describe('Home', () => {
|
||||
it('renders the home view chrome, child sections, collectors, and aggregated stats', () => {
|
||||
renderHome();
|
||||
|
||||
expect(vi.mocked(useFeedStateString)).not.toHaveBeenCalled();
|
||||
expect(document.title).toBe('5chan');
|
||||
expect(container.querySelector('[data-testid="disclaimer-modal"]')?.textContent).toBe('disclaimer-modal');
|
||||
expect(container.querySelector('[data-testid="directory-modal"]')?.textContent).toBe('directory-modal');
|
||||
@@ -175,8 +183,12 @@ describe('Home', () => {
|
||||
renderHome();
|
||||
|
||||
const loadingValues = Array.from(container.querySelectorAll('[data-testid="loading-ellipsis"]'));
|
||||
expect(loadingValues).toHaveLength(3);
|
||||
expect(loadingValues.map((value) => value.textContent)).toEqual(['loading', 'loading', 'loading']);
|
||||
expect(loadingValues).toHaveLength(1);
|
||||
expect(loadingValues[0]?.textContent).toBe('Downloading boards');
|
||||
expect(vi.mocked(useFeedStateString)).toHaveBeenCalledWith(['music-posting.eth', 'tech-posting.eth']);
|
||||
expect(container.textContent).not.toContain('total_posts');
|
||||
expect(container.textContent).not.toContain('current_users');
|
||||
expect(container.textContent).not.toContain('boards_tracked');
|
||||
expect(container.textContent).not.toContain('total_posts 5');
|
||||
expect(container.textContent).not.toContain('current_users 2');
|
||||
expect(container.textContent).not.toContain('boards_tracked 1');
|
||||
|
||||
+22
-18
@@ -9,6 +9,7 @@ import PopularThreadsBox from './popular-threads-box';
|
||||
import BoardsList from './boards-list';
|
||||
import SiteLegalMeta from '../../components/site-legal-meta';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import { useFeedStateString } from '../../hooks/use-state-string';
|
||||
import useDirectoryModalStore from '../../stores/use-directory-modal-store';
|
||||
import DisclaimerModal from '../../components/disclaimer-modal';
|
||||
import DirectoryModal from '../../components/directory-modal';
|
||||
@@ -99,19 +100,18 @@ const InfoBox = () => {
|
||||
);
|
||||
};
|
||||
|
||||
interface StatValueProps {
|
||||
isLoaded: boolean;
|
||||
loadingLabel: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
type HomepageStats = {
|
||||
allPostCount?: number;
|
||||
weekActiveUserCount?: number;
|
||||
state?: string;
|
||||
};
|
||||
|
||||
const StatValue = ({ isLoaded, loadingLabel, value }: StatValueProps) => (isLoaded ? <>{value}</> : <LoadingEllipsis string={loadingLabel} />);
|
||||
const StatsLoading = ({ communityAddresses }: { communityAddresses: string[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const loadingStateString = useFeedStateString(communityAddresses) || t('loading');
|
||||
|
||||
return <LoadingEllipsis string={loadingStateString} />;
|
||||
};
|
||||
|
||||
const STATS_DIRECTORY_FALLBACK_DELAY_SECONDS = 30;
|
||||
|
||||
@@ -204,8 +204,6 @@ const Stats = ({ directories }: { directories: DirectoryCommunity[] }) => {
|
||||
};
|
||||
}, [communitiesStats, defaultDirectoryAddresses, directories, listsByCode]);
|
||||
|
||||
const loadingLabel = t('loading');
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Render collectors to fetch stats for each community */}
|
||||
@@ -217,15 +215,21 @@ const Stats = ({ directories }: { directories: DirectoryCommunity[] }) => {
|
||||
<h2 className='capitalize'>{t('stats')}</h2>
|
||||
</div>
|
||||
<div className={`${styles.boxContent} ${styles.stats}`}>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('total_posts')}</b> <StatValue isLoaded={allDirectoryStatsLoaded} loadingLabel={loadingLabel} value={totalPosts} />
|
||||
</div>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('current_users')}</b> <StatValue isLoaded={allDirectoryStatsLoaded} loadingLabel={loadingLabel} value={currentUsers} />
|
||||
</div>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('boards_tracked')}</b> <StatValue isLoaded={allDirectoryStatsLoaded} loadingLabel={loadingLabel} value={boardsTracked} />
|
||||
</div>
|
||||
{allDirectoryStatsLoaded ? (
|
||||
<>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('total_posts')}</b> {totalPosts}
|
||||
</div>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('current_users')}</b> {currentUsers}
|
||||
</div>
|
||||
<div className={styles.stat}>
|
||||
<b>{t('boards_tracked')}</b> {boardsTracked}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<StatsLoading communityAddresses={collectorAddresses} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user