Add pages for Popular / Suggested Groups
This commit is contained in:
parent
1b542c3ed7
commit
821b90c372
9 changed files with 297 additions and 22 deletions
|
@ -7,10 +7,10 @@ import { useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
import { Card, CardBody, CardHeader, CardTitle } from '../card/card';
|
import { Card, CardBody, CardHeader, CardTitle } from '../card/card';
|
||||||
|
|
||||||
type IColumnHeader = Pick<IColumn, 'label' | 'backHref' |'className'>;
|
type IColumnHeader = Pick<IColumn, 'label' | 'backHref' | 'className' | 'action'>;
|
||||||
|
|
||||||
/** Contains the column title with optional back button. */
|
/** Contains the column title with optional back button. */
|
||||||
const ColumnHeader: React.FC<IColumnHeader> = ({ label, backHref, className }) => {
|
const ColumnHeader: React.FC<IColumnHeader> = ({ label, backHref, className, action }) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const handleBackClick = () => {
|
const handleBackClick = () => {
|
||||||
|
@ -29,6 +29,12 @@ const ColumnHeader: React.FC<IColumnHeader> = ({ label, backHref, className }) =
|
||||||
return (
|
return (
|
||||||
<CardHeader className={className} onBackClick={handleBackClick}>
|
<CardHeader className={className} onBackClick={handleBackClick}>
|
||||||
<CardTitle title={label} />
|
<CardTitle title={label} />
|
||||||
|
|
||||||
|
{action && (
|
||||||
|
<div className='flex grow justify-end'>
|
||||||
|
{action}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -48,11 +54,12 @@ export interface IColumn {
|
||||||
ref?: React.Ref<HTMLDivElement>
|
ref?: React.Ref<HTMLDivElement>
|
||||||
/** Children to display in the column. */
|
/** Children to display in the column. */
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
|
action?: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A backdrop for the main section of the UI. */
|
/** A backdrop for the main section of the UI. */
|
||||||
const Column: React.FC<IColumn> = React.forwardRef((props, ref: React.ForwardedRef<HTMLDivElement>): JSX.Element => {
|
const Column: React.FC<IColumn> = React.forwardRef((props, ref: React.ForwardedRef<HTMLDivElement>): JSX.Element => {
|
||||||
const { backHref, children, label, transparent = false, withHeader = true, className } = props;
|
const { backHref, children, label, transparent = false, withHeader = true, className, action } = props;
|
||||||
const soapboxConfig = useSoapboxConfig();
|
const soapboxConfig = useSoapboxConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -75,6 +82,7 @@ const Column: React.FC<IColumn> = React.forwardRef((props, ref: React.ForwardedR
|
||||||
label={label}
|
label={label}
|
||||||
backHref={backHref}
|
backHref={backHref}
|
||||||
className={clsx({ 'px-4 pt-4 sm:p-0': transparent })}
|
className={clsx({ 'px-4 pt-4 sm:p-0': transparent })}
|
||||||
|
action={action}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
|
import Link from 'soapbox/components/link';
|
||||||
|
import { Carousel, HStack, 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';
|
||||||
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
||||||
|
|
||||||
|
@ -15,12 +16,23 @@ const PopularGroups = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<Text size='xl' weight='bold'>
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
<FormattedMessage
|
<Text size='xl' weight='bold'>
|
||||||
id='groups.discover.popular.title'
|
<FormattedMessage
|
||||||
defaultMessage='Popular Groups'
|
id='groups.discover.popular.title'
|
||||||
/>
|
defaultMessage='Popular Groups'
|
||||||
</Text>
|
/>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Link to='/groups/popular'>
|
||||||
|
<Text tag='span' weight='medium' size='sm' theme='inherit'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='groups.discover.popular.show_more'
|
||||||
|
defaultMessage='Show More'
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
{isEmpty ? (
|
{isEmpty ? (
|
||||||
<Text theme='muted'>
|
<Text theme='muted'>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
|
import Link from 'soapbox/components/link';
|
||||||
|
import { Carousel, HStack, 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';
|
||||||
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
||||||
|
|
||||||
|
@ -15,12 +16,23 @@ const SuggestedGroups = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<Text size='xl' weight='bold'>
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
<FormattedMessage
|
<Text size='xl' weight='bold'>
|
||||||
id='groups.discover.suggested.title'
|
<FormattedMessage
|
||||||
defaultMessage='Suggested For You'
|
id='groups.discover.suggested.title'
|
||||||
/>
|
defaultMessage='Suggested For You'
|
||||||
</Text>
|
/>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Link to='/groups/suggested'>
|
||||||
|
<Text tag='span' weight='medium' size='sm' theme='inherit'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='groups.discover.suggested.show_more'
|
||||||
|
defaultMessage='Show More'
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
{isEmpty ? (
|
{isEmpty ? (
|
||||||
<Text theme='muted'>
|
<Text theme='muted'>
|
||||||
|
|
|
@ -60,9 +60,13 @@ const Groups: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
|
{features.groupsDiscovery && (
|
||||||
|
<TabBar activeTab={TabItems.MY_GROUPS} />
|
||||||
|
)}
|
||||||
|
|
||||||
{canCreateGroup && (
|
{canCreateGroup && (
|
||||||
<Button
|
<Button
|
||||||
className='sm:w-fit sm:self-end xl:hidden'
|
className='xl:hidden'
|
||||||
icon={require('@tabler/icons/circles.svg')}
|
icon={require('@tabler/icons/circles.svg')}
|
||||||
onClick={createGroup}
|
onClick={createGroup}
|
||||||
theme='secondary'
|
theme='secondary'
|
||||||
|
@ -72,10 +76,6 @@ const Groups: React.FC = () => {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{features.groupsDiscovery && (
|
|
||||||
<TabBar activeTab={TabItems.MY_GROUPS} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<PendingGroupsRow />
|
<PendingGroupsRow />
|
||||||
|
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
|
|
114
app/soapbox/features/groups/popular.tsx
Normal file
114
app/soapbox/features/groups/popular.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
||||||
|
|
||||||
|
import { Column, HStack, Icon } from 'soapbox/components/ui';
|
||||||
|
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
||||||
|
|
||||||
|
import GroupGridItem from './components/discover/group-grid-item';
|
||||||
|
import GroupListItem from './components/discover/group-list-item';
|
||||||
|
|
||||||
|
import type { Group } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
label: { id: 'groups.popular.label', defaultMessage: 'Popular Groups' },
|
||||||
|
});
|
||||||
|
|
||||||
|
enum Layout {
|
||||||
|
LIST = 'LIST',
|
||||||
|
GRID = 'GRID'
|
||||||
|
}
|
||||||
|
|
||||||
|
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
|
const { context, ...rest } = props;
|
||||||
|
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Popular: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const [layout, setLayout] = useState<Layout>(Layout.LIST);
|
||||||
|
|
||||||
|
const { groups, hasNextPage, fetchNextPage } = usePopularGroups();
|
||||||
|
|
||||||
|
const handleLoadMore = () => {
|
||||||
|
if (hasNextPage) {
|
||||||
|
fetchNextPage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderGroupList = useCallback((group: Group, index: number) => (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
clsx({
|
||||||
|
'pt-4': index !== 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<GroupListItem group={group} withJoinAction />
|
||||||
|
</div>
|
||||||
|
), []);
|
||||||
|
|
||||||
|
const renderGroupGrid = useCallback((group: Group, index: number) => (
|
||||||
|
<div className='pb-4'>
|
||||||
|
<GroupGridItem group={group} />
|
||||||
|
</div>
|
||||||
|
), []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column
|
||||||
|
label={intl.formatMessage(messages.label)}
|
||||||
|
action={
|
||||||
|
<HStack alignItems='center'>
|
||||||
|
<button onClick={() => setLayout(Layout.LIST)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-list.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === Layout.LIST,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button onClick={() => setLayout(Layout.GRID)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-grid.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === Layout.GRID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</HStack>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{layout === Layout.LIST ? (
|
||||||
|
<Virtuoso
|
||||||
|
useWindowScroll
|
||||||
|
data={groups}
|
||||||
|
itemContent={(index, group) => renderGroupList(group, index)}
|
||||||
|
endReached={handleLoadMore}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<VirtuosoGrid
|
||||||
|
useWindowScroll
|
||||||
|
data={groups}
|
||||||
|
itemContent={(index, group) => renderGroupGrid(group, index)}
|
||||||
|
components={{
|
||||||
|
Item: (props) => (
|
||||||
|
<div {...props} className='w-1/2 flex-none' />
|
||||||
|
),
|
||||||
|
List: GridList,
|
||||||
|
}}
|
||||||
|
endReached={handleLoadMore}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Popular;
|
114
app/soapbox/features/groups/suggested.tsx
Normal file
114
app/soapbox/features/groups/suggested.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
||||||
|
|
||||||
|
import { Column, HStack, Icon } from 'soapbox/components/ui';
|
||||||
|
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
||||||
|
|
||||||
|
import GroupGridItem from './components/discover/group-grid-item';
|
||||||
|
import GroupListItem from './components/discover/group-list-item';
|
||||||
|
|
||||||
|
import type { Group } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
label: { id: 'groups.popular.label', defaultMessage: 'Suggested Groups' },
|
||||||
|
});
|
||||||
|
|
||||||
|
enum Layout {
|
||||||
|
LIST = 'LIST',
|
||||||
|
GRID = 'GRID'
|
||||||
|
}
|
||||||
|
|
||||||
|
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
|
const { context, ...rest } = props;
|
||||||
|
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Suggested: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const [layout, setLayout] = useState<Layout>(Layout.LIST);
|
||||||
|
|
||||||
|
const { groups, hasNextPage, fetchNextPage } = useSuggestedGroups();
|
||||||
|
|
||||||
|
const handleLoadMore = () => {
|
||||||
|
if (hasNextPage) {
|
||||||
|
fetchNextPage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderGroupList = useCallback((group: Group, index: number) => (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
clsx({
|
||||||
|
'pt-4': index !== 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<GroupListItem group={group} withJoinAction />
|
||||||
|
</div>
|
||||||
|
), []);
|
||||||
|
|
||||||
|
const renderGroupGrid = useCallback((group: Group, index: number) => (
|
||||||
|
<div className='pb-4'>
|
||||||
|
<GroupGridItem group={group} />
|
||||||
|
</div>
|
||||||
|
), []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column
|
||||||
|
label={intl.formatMessage(messages.label)}
|
||||||
|
action={
|
||||||
|
<HStack alignItems='center'>
|
||||||
|
<button onClick={() => setLayout(Layout.LIST)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-list.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === Layout.LIST,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button onClick={() => setLayout(Layout.GRID)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-grid.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === Layout.GRID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</HStack>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{layout === Layout.LIST ? (
|
||||||
|
<Virtuoso
|
||||||
|
useWindowScroll
|
||||||
|
data={groups}
|
||||||
|
itemContent={(index, group) => renderGroupList(group, index)}
|
||||||
|
endReached={handleLoadMore}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<VirtuosoGrid
|
||||||
|
useWindowScroll
|
||||||
|
data={groups}
|
||||||
|
itemContent={(index, group) => renderGroupGrid(group, index)}
|
||||||
|
components={{
|
||||||
|
Item: (props) => (
|
||||||
|
<div {...props} className='w-1/2 flex-none' />
|
||||||
|
),
|
||||||
|
List: GridList,
|
||||||
|
}}
|
||||||
|
endReached={handleLoadMore}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Suggested;
|
|
@ -118,6 +118,8 @@ import {
|
||||||
Events,
|
Events,
|
||||||
Groups,
|
Groups,
|
||||||
GroupsDiscover,
|
GroupsDiscover,
|
||||||
|
GroupsPopular,
|
||||||
|
GroupsSuggested,
|
||||||
PendingGroupRequests,
|
PendingGroupRequests,
|
||||||
GroupMembers,
|
GroupMembers,
|
||||||
GroupTimeline,
|
GroupTimeline,
|
||||||
|
@ -289,6 +291,8 @@ const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) =>
|
||||||
|
|
||||||
{features.groups && <WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} />}
|
{features.groups && <WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} />}
|
||||||
{features.groupsDiscovery && <WrappedRoute path='/groups/discover' exact page={GroupsPage} component={GroupsDiscover} content={children} />}
|
{features.groupsDiscovery && <WrappedRoute path='/groups/discover' exact page={GroupsPage} component={GroupsDiscover} content={children} />}
|
||||||
|
{features.groupsDiscovery && <WrappedRoute path='/groups/popular' exact page={GroupsPendingPage} component={GroupsPopular} content={children} />}
|
||||||
|
{features.groupsDiscovery && <WrappedRoute path='/groups/suggested' exact page={GroupsPendingPage} component={GroupsSuggested} content={children} />}
|
||||||
{features.groupsPending && <WrappedRoute path='/groups/pending-requests' exact page={GroupsPendingPage} component={PendingGroupRequests} content={children} />}
|
{features.groupsPending && <WrappedRoute path='/groups/pending-requests' exact page={GroupsPendingPage} component={PendingGroupRequests} content={children} />}
|
||||||
{features.groups && <WrappedRoute path='/groups/:id' exact page={GroupPage} component={GroupTimeline} content={children} />}
|
{features.groups && <WrappedRoute path='/groups/:id' exact page={GroupPage} component={GroupTimeline} content={children} />}
|
||||||
{features.groups && <WrappedRoute path='/groups/:id/members' exact page={GroupPage} component={GroupMembers} content={children} />}
|
{features.groups && <WrappedRoute path='/groups/:id/members' exact page={GroupPage} component={GroupMembers} content={children} />}
|
||||||
|
|
|
@ -550,6 +550,14 @@ export function GroupsDiscover() {
|
||||||
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/discover');
|
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/discover');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GroupsPopular() {
|
||||||
|
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/popular');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GroupsSuggested() {
|
||||||
|
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/suggested');
|
||||||
|
}
|
||||||
|
|
||||||
export function PendingGroupRequests() {
|
export function PendingGroupRequests() {
|
||||||
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/pending-requests');
|
return import(/* webpackChunkName: "features/groups/discover" */'../../groups/pending-requests');
|
||||||
}
|
}
|
||||||
|
|
|
@ -800,6 +800,7 @@
|
||||||
"group.tabs.members": "Members",
|
"group.tabs.members": "Members",
|
||||||
"group.upload_banner": "Upload photo",
|
"group.upload_banner": "Upload photo",
|
||||||
"groups.discover.popular.empty": "Unable to fetch popular groups at this time. Please check back later.",
|
"groups.discover.popular.empty": "Unable to fetch popular groups at this time. Please check back later.",
|
||||||
|
"groups.discover.popular.show_more": "Show More",
|
||||||
"groups.discover.popular.title": "Popular Groups",
|
"groups.discover.popular.title": "Popular Groups",
|
||||||
"groups.discover.search.error.subtitle": "Please try again later.",
|
"groups.discover.search.error.subtitle": "Please try again later.",
|
||||||
"groups.discover.search.error.title": "An error occurred",
|
"groups.discover.search.error.title": "An error occurred",
|
||||||
|
@ -813,6 +814,7 @@
|
||||||
"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.suggested.empty": "Unable to fetch suggested groups at this time. Please check back later.",
|
"groups.discover.suggested.empty": "Unable to fetch suggested groups at this time. Please check back later.",
|
||||||
|
"groups.discover.suggested.show_more": "Show More",
|
||||||
"groups.discover.suggested.title": "Suggested For You",
|
"groups.discover.suggested.title": "Suggested For You",
|
||||||
"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",
|
||||||
|
@ -820,6 +822,7 @@
|
||||||
"groups.pending.empty.subtitle": "You have no pending requests at this time.",
|
"groups.pending.empty.subtitle": "You have no pending requests at this time.",
|
||||||
"groups.pending.empty.title": "No pending requests",
|
"groups.pending.empty.title": "No pending requests",
|
||||||
"groups.pending.label": "Pending Requests",
|
"groups.pending.label": "Pending Requests",
|
||||||
|
"groups.popular.label": "Suggested Groups",
|
||||||
"hashtag.column_header.tag_mode.all": "and {additional}",
|
"hashtag.column_header.tag_mode.all": "and {additional}",
|
||||||
"hashtag.column_header.tag_mode.any": "or {additional}",
|
"hashtag.column_header.tag_mode.any": "or {additional}",
|
||||||
"hashtag.column_header.tag_mode.none": "without {additional}",
|
"hashtag.column_header.tag_mode.none": "without {additional}",
|
||||||
|
|
Loading…
Reference in a new issue