Improve error handling for Groups Discover page

develop^2
Chewbacca 2023-03-06 08:11:58 -05:00
rodzic e7b3af5260
commit 287fda6d6c
6 zmienionych plików z 156 dodań i 89 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { Carousel, Stack, Text } from 'soapbox/components/ui'; import { Carousel, Stack, Text } from 'soapbox/components/ui';
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover'; import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
@ -7,46 +8,59 @@ import { usePopularGroups } from 'soapbox/queries/groups';
import Group from './group'; import Group from './group';
const PopularGroups = () => { const PopularGroups = () => {
const { groups, isFetching } = usePopularGroups(); const { groups, isFetching, isFetched, isError } = usePopularGroups();
const isEmpty = (isFetched && groups.length === 0) || isError;
const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null); const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
return ( return (
<Stack space={4}> <Stack space={4}>
<Text size='xl' weight='bold'> <Text size='xl' weight='bold'>
Popular Groups <FormattedMessage
id='groups.discover.popular.title'
defaultMessage='Popular Groups'
/>
</Text> </Text>
<Carousel {isEmpty ? (
itemWidth={250} <Text theme='muted'>
itemCount={groups.length} <FormattedMessage
controlsHeight={groupCover?.clientHeight} id='groups.discover.popular.empty'
> defaultMessage='Unable to fetch popular groups at this time. Please check back later.'
{({ width }: { width: number }) => ( />
<> </Text>
{isFetching ? ( ) : (
new Array(20).fill(0).map((_, idx) => ( <Carousel
<div itemWidth={250}
className='relative flex shrink-0 flex-col space-y-2 px-0.5' itemCount={groups.length}
style={{ width: width || 'auto' }} controlsHeight={groupCover?.clientHeight}
key={idx} >
> {({ width }: { width: number }) => (
<PlaceholderGroupDiscover /> <>
</div> {isFetching ? (
)) new Array(20).fill(0).map((_, idx) => (
) : ( <div
groups.map((group) => ( className='relative flex shrink-0 flex-col space-y-2 px-0.5'
<Group style={{ width: width || 'auto' }}
key={group.id} key={idx}
group={group} >
width={width} <PlaceholderGroupDiscover />
ref={setGroupCover} </div>
/> ))
)) ) : (
)} groups.map((group) => (
</> <Group
)} key={group.id}
</Carousel> group={group}
width={width}
ref={setGroupCover}
/>
))
)}
</>
)}
</Carousel>
)}
</Stack> </Stack>
); );
}; };

Wyświetl plik

@ -0,0 +1,20 @@
import React from 'react';
import { Stack, Text } from 'soapbox/components/ui';
interface Props {
title: React.ReactNode | string
subtitle: React.ReactNode | string
}
export default ({ title, subtitle }: Props) => (
<Stack space={2} className='px-4 py-2' data-testid='no-results'>
<Text weight='bold' size='lg'>
{title}
</Text>
<Text theme='muted'>
{subtitle}
</Text>
</Stack>
);

Wyświetl plik

@ -1,22 +0,0 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Stack, Text } from 'soapbox/components/ui';
export default () => (
<Stack space={2} className='px-4 py-2' data-testid='no-results'>
<Text weight='bold' size='lg'>
<FormattedMessage
id='groups.discover.search.no_results.title'
defaultMessage='No matches found'
/>
</Text>
<Text theme='muted'>
<FormattedMessage
id='groups.discover.search.no_results.subtitle'
defaultMessage='Try searching for another group.'
/>
</Text>
</Stack>
);

Wyświetl plik

@ -1,4 +1,5 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { Stack } from 'soapbox/components/ui'; import { Stack } from 'soapbox/components/ui';
import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search'; import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
@ -6,7 +7,7 @@ import { useDebounce, useOwnAccount } from 'soapbox/hooks';
import { useGroupSearch } from 'soapbox/queries/groups/search'; import { useGroupSearch } from 'soapbox/queries/groups/search';
import { saveGroupSearch } from 'soapbox/utils/groups'; import { saveGroupSearch } from 'soapbox/utils/groups';
import NoResultsBlankslate from './no-results-blankslate'; import Blankslate from './blankslate';
import RecentSearches from './recent-searches'; import RecentSearches from './recent-searches';
import Results from './results'; import Results from './results';
@ -25,7 +26,7 @@ export default (props: Props) => {
const debouncedValueToSave = debounce(searchValue as string, 1000); const debouncedValueToSave = debounce(searchValue as string, 1000);
const groupSearchResult = useGroupSearch(debouncedValue); const groupSearchResult = useGroupSearch(debouncedValue);
const { groups, isFetching, isFetched } = groupSearchResult; const { groups, isFetching, isFetched, isError } = groupSearchResult;
const hasSearchResults = isFetched && groups.length > 0; const hasSearchResults = isFetched && groups.length > 0;
const hasNoSearchResults = isFetched && groups.length === 0; const hasNoSearchResults = isFetched && groups.length === 0;
@ -46,8 +47,42 @@ export default (props: Props) => {
); );
} }
if (isError) {
return (
<Blankslate
title={
<FormattedMessage
id='groups.discover.search.error.title'
defaultMessage='An error occurred'
/>
}
subtitle={
<FormattedMessage
id='groups.discover.search.error.subtitle'
defaultMessage='Please try again later.'
/>
}
/>
);
}
if (hasNoSearchResults) { if (hasNoSearchResults) {
return <NoResultsBlankslate />; return (
<Blankslate
title={
<FormattedMessage
id='groups.discover.search.no_results.title'
defaultMessage='No matches found'
/>
}
subtitle={
<FormattedMessage
id='groups.discover.search.no_results.subtitle'
defaultMessage='Try searching for another group.'
/>
}
/>
);
} }
if (hasSearchResults) { if (hasSearchResults) {

Wyświetl plik

@ -1,4 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { Carousel, Stack, Text } from 'soapbox/components/ui'; import { Carousel, Stack, Text } from 'soapbox/components/ui';
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover'; import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
@ -7,46 +8,59 @@ import { useSuggestedGroups } from 'soapbox/queries/groups';
import Group from './group'; import Group from './group';
const SuggestedGroups = () => { const SuggestedGroups = () => {
const { groups, isFetching } = useSuggestedGroups(); const { groups, isFetching, isFetched, isError } = useSuggestedGroups();
const isEmpty = (isFetched && groups.length === 0) || isError;
const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null); const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
return ( return (
<Stack space={4}> <Stack space={4}>
<Text size='xl' weight='bold'> <Text size='xl' weight='bold'>
Suggested For You <FormattedMessage
id='groups.discover.suggested.title'
defaultMessage='Suggested For You'
/>
</Text> </Text>
<Carousel {isEmpty ? (
itemWidth={250} <Text theme='muted'>
itemCount={groups.length} <FormattedMessage
controlsHeight={groupCover?.clientHeight} id='groups.discover.suggested.empty'
> defaultMessage='Unable to fetch suggested groups at this time. Please check back later.'
{({ width }: { width: number }) => ( />
<> </Text>
{isFetching ? ( ) : (
new Array(20).fill(0).map((_, idx) => ( <Carousel
<div itemWidth={250}
className='relative flex shrink-0 flex-col space-y-2 px-0.5' itemCount={groups.length}
style={{ width: width || 'auto' }} controlsHeight={groupCover?.clientHeight}
key={idx} >
> {({ width }: { width: number }) => (
<PlaceholderGroupDiscover /> <>
</div> {isFetching ? (
)) new Array(20).fill(0).map((_, idx) => (
) : ( <div
groups.map((group) => ( className='relative flex shrink-0 flex-col space-y-2 px-0.5'
<Group style={{ width: width || 'auto' }}
key={group.id} key={idx}
group={group} >
width={width} <PlaceholderGroupDiscover />
ref={setGroupCover} </div>
/> ))
)) ) : (
)} groups.map((group) => (
</> <Group
)} key={group.id}
</Carousel> group={group}
width={width}
ref={setGroupCover}
/>
))
)}
</>
)}
</Carousel>
)}
</Stack> </Stack>
); );
}; };

Wyświetl plik

@ -803,6 +803,8 @@
"group.user_subheading": "Users", "group.user_subheading": "Users",
"groups.discover.search.no_results.subtitle": "Try searching for another group.", "groups.discover.search.no_results.subtitle": "Try searching for another group.",
"groups.discover.search.no_results.title": "No matches found", "groups.discover.search.no_results.title": "No matches found",
"groups.discover.search.error.subtitle": "Please try again later.",
"groups.discover.search.error.title": "An error occurred",
"groups.discover.search.placeholder": "Search", "groups.discover.search.placeholder": "Search",
"groups.discover.search.recent_searches.blankslate.subtitle": "Search group names, topics or keywords", "groups.discover.search.recent_searches.blankslate.subtitle": "Search group names, topics or keywords",
"groups.discover.search.recent_searches.blankslate.title": "No recent searches", "groups.discover.search.recent_searches.blankslate.title": "No recent searches",
@ -810,6 +812,10 @@
"groups.discover.search.recent_searches.title": "Recent searches", "groups.discover.search.recent_searches.title": "Recent searches",
"groups.discover.search.results.groups": "Groups", "groups.discover.search.results.groups": "Groups",
"groups.discover.search.results.member_count": "{members, plural, one {member} other {members}}", "groups.discover.search.results.member_count": "{members, plural, one {member} other {members}}",
"groups.discover.popular.title": "Popular Groups",
"groups.discover.popular.empty": "Unable to fetch popular groups at this time. Please check back later.",
"groups.discover.suggested.title": "Suggested For You",
"groups.discover.suggested.empty": "Unable to fetch suggested groups at this time. Please check back later.",
"groups.empty.subtitle": "Start discovering groups to join or create your own.", "groups.empty.subtitle": "Start discovering groups to join or create your own.",
"groups.empty.title": "No Groups yet", "groups.empty.title": "No Groups yet",
"hashtag.column_header.tag_mode.all": "and {additional}", "hashtag.column_header.tag_mode.all": "and {additional}",