Merge branch 'search-my-groups' into 'develop'

Add ability to search my Groups

See merge request soapbox-pub/soapbox!2377
This commit is contained in:
Chewbacca 2023-03-28 14:02:25 +00:00
commit 1abcc95a0a
16 changed files with 49 additions and 22 deletions

View File

@ -5,7 +5,8 @@ import { fetchGroupBlocks, groupUnblock } from 'soapbox/actions/groups';
import Account from 'soapbox/components/account'; import Account from 'soapbox/components/account';
import ScrollableList from 'soapbox/components/scrollable-list'; import ScrollableList from 'soapbox/components/scrollable-list';
import { Button, Column, HStack, Spinner } from 'soapbox/components/ui'; import { Button, Column, HStack, Spinner } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useGroup } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { useGroup } from 'soapbox/hooks/api';
import { makeGetAccount } from 'soapbox/selectors'; import { makeGetAccount } from 'soapbox/selectors';
import toast from 'soapbox/toast'; import toast from 'soapbox/toast';

View File

@ -3,7 +3,7 @@ import React, { useMemo } from 'react';
import { PendingItemsRow } from 'soapbox/components/pending-items-row'; import { PendingItemsRow } from 'soapbox/components/pending-items-row';
import ScrollableList from 'soapbox/components/scrollable-list'; import ScrollableList from 'soapbox/components/scrollable-list';
import { useGroup } from 'soapbox/hooks'; import { useGroup } from 'soapbox/hooks/api';
import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests'; import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests';
import { useGroupMembers } from 'soapbox/hooks/api/useGroupMembers'; import { useGroupMembers } from 'soapbox/hooks/api/useGroupMembers';
import { GroupRoles } from 'soapbox/schemas/group-member'; import { GroupRoles } from 'soapbox/schemas/group-member';

View File

@ -5,7 +5,7 @@ import Account from 'soapbox/components/account';
import { AuthorizeRejectButtons } from 'soapbox/components/authorize-reject-buttons'; import { AuthorizeRejectButtons } from 'soapbox/components/authorize-reject-buttons';
import ScrollableList from 'soapbox/components/scrollable-list'; import ScrollableList from 'soapbox/components/scrollable-list';
import { Column, HStack, Spinner } from 'soapbox/components/ui'; import { Column, HStack, Spinner } from 'soapbox/components/ui';
import { useGroup } from 'soapbox/hooks'; import { useGroup } from 'soapbox/hooks/api';
import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests'; import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests';
import toast from 'soapbox/toast'; import toast from 'soapbox/toast';

View File

@ -7,7 +7,8 @@ import { connectGroupStream } from 'soapbox/actions/streaming';
import { expandGroupTimeline } from 'soapbox/actions/timelines'; import { expandGroupTimeline } from 'soapbox/actions/timelines';
import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui'; import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
import ComposeForm from 'soapbox/features/compose/components/compose-form'; import ComposeForm from 'soapbox/features/compose/components/compose-form';
import { useAppDispatch, useGroup, useOwnAccount } from 'soapbox/hooks'; import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
import { useGroup } from 'soapbox/hooks/api';
import Timeline from '../ui/components/timeline'; import Timeline from '../ui/components/timeline';

View File

@ -6,8 +6,8 @@ import { editGroup } from 'soapbox/actions/groups';
import { openModal } from 'soapbox/actions/modals'; import { openModal } from 'soapbox/actions/modals';
import List, { ListItem } from 'soapbox/components/list'; import List, { ListItem } from 'soapbox/components/list';
import { CardBody, CardHeader, CardTitle, Column, Spinner, Text } from 'soapbox/components/ui'; import { CardBody, CardHeader, CardTitle, Column, Spinner, Text } from 'soapbox/components/ui';
import { useAppDispatch, useGroup, useGroupsPath } from 'soapbox/hooks'; import { useAppDispatch, useGroupsPath } from 'soapbox/hooks';
import { useDeleteGroup } from 'soapbox/hooks/api'; import { useDeleteGroup, useGroup } from 'soapbox/hooks/api';
import { GroupRoles } from 'soapbox/schemas/group-member'; import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast'; import toast from 'soapbox/toast';

View File

@ -1,12 +1,13 @@
import React from 'react'; import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { openModal } from 'soapbox/actions/modals'; import { openModal } from 'soapbox/actions/modals';
import GroupCard from 'soapbox/components/group-card'; import GroupCard from 'soapbox/components/group-card';
import ScrollableList from 'soapbox/components/scrollable-list'; import ScrollableList from 'soapbox/components/scrollable-list';
import { Button, Stack, Text } from 'soapbox/components/ui'; import { Button, Input, Stack, Text } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useGroups, useFeatures } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector, useDebounce, useFeatures } from 'soapbox/hooks';
import { useGroups } from 'soapbox/hooks/api';
import { PERMISSION_CREATE_GROUPS, hasPermission } from 'soapbox/utils/permissions'; import { PERMISSION_CREATE_GROUPS, hasPermission } from 'soapbox/utils/permissions';
import PlaceholderGroupCard from '../placeholder/components/placeholder-group-card'; import PlaceholderGroupCard from '../placeholder/components/placeholder-group-card';
@ -16,13 +17,22 @@ import TabBar, { TabItems } from './components/tab-bar';
import type { Group as GroupEntity } from 'soapbox/types/entities'; import type { Group as GroupEntity } from 'soapbox/types/entities';
const messages = defineMessages({
placeholder: { id: 'groups.search.placeholder', defaultMessage: 'Search My Groups' },
});
const Groups: React.FC = () => { const Groups: React.FC = () => {
const debounce = useDebounce;
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const features = useFeatures(); const features = useFeatures();
const intl = useIntl();
const canCreateGroup = useAppSelector((state) => hasPermission(state, PERMISSION_CREATE_GROUPS)); const canCreateGroup = useAppSelector((state) => hasPermission(state, PERMISSION_CREATE_GROUPS));
const { groups, isLoading } = useGroups(); const [searchValue, setSearchValue] = useState<string>('');
const debouncedValue = debounce(searchValue, 300);
const { groups, isLoading } = useGroups(debouncedValue);
const createGroup = () => { const createGroup = () => {
dispatch(openModal('MANAGE_GROUP')); dispatch(openModal('MANAGE_GROUP'));
@ -76,6 +86,15 @@ const Groups: React.FC = () => {
</Button> </Button>
)} )}
{features.groupsSearch ? (
<Input
onChange={(event) => setSearchValue(event.target.value)}
placeholder={intl.formatMessage(messages.placeholder)}
theme='search'
value={searchValue}
/>
) : null}
<PendingGroupsRow /> <PendingGroupsRow />
<ScrollableList <ScrollableList

View File

@ -3,7 +3,7 @@ import React from 'react';
import { Widget } from 'soapbox/components/ui'; import { Widget } from 'soapbox/components/ui';
import GroupListItem from 'soapbox/features/groups/components/discover/group-list-item'; import GroupListItem from 'soapbox/features/groups/components/discover/group-list-item';
import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search'; import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
import { useGroups } from 'soapbox/hooks'; import { useGroups } from 'soapbox/hooks/api';
const MyGroupsPanel = () => { const MyGroupsPanel = () => {
const { groups, isFetching, isFetched, isError } = useGroups(); const { groups, isFetching, isFetched, isError } = useGroups();

View File

@ -6,15 +6,15 @@ import { useApi } from 'soapbox/hooks';
import { groupSchema, Group } from 'soapbox/schemas/group'; import { groupSchema, Group } from 'soapbox/schemas/group';
import { groupRelationshipSchema, GroupRelationship } from 'soapbox/schemas/group-relationship'; import { groupRelationshipSchema, GroupRelationship } from 'soapbox/schemas/group-relationship';
import { useFeatures } from './useFeatures'; import { useFeatures } from '../../useFeatures';
function useGroups() { function useGroups(q: string = '') {
const api = useApi(); const api = useApi();
const features = useFeatures(); const features = useFeatures();
const { entities, ...result } = useEntities<Group>( const { entities, ...result } = useEntities<Group>(
[Entities.GROUPS], [Entities.GROUPS, 'search', q],
() => api.get('/api/v1/groups'), () => api.get('/api/v1/groups', { params: { q } }),
{ enabled: features.groups, schema: groupSchema }, { enabled: features.groups, schema: groupSchema },
); );
const { relationships } = useGroupRelationships(entities.map(entity => entity.id)); const { relationships } = useGroupRelationships(entities.map(entity => entity.id));

View File

@ -5,6 +5,7 @@ export { useBlockGroupMember } from './groups/useBlockGroupMember';
export { useCancelMembershipRequest } from './groups/useCancelMembershipRequest'; export { useCancelMembershipRequest } from './groups/useCancelMembershipRequest';
export { useDeleteGroup } from './groups/useDeleteGroup'; export { useDeleteGroup } from './groups/useDeleteGroup';
export { useDemoteGroupMember } from './groups/useDemoteGroupMember'; export { useDemoteGroupMember } from './groups/useDemoteGroupMember';
export { useGroup, useGroups } from './groups/useGroups';
export { useJoinGroup } from './groups/useJoinGroup'; export { useJoinGroup } from './groups/useJoinGroup';
export { useLeaveGroup } from './groups/useLeaveGroup'; export { useLeaveGroup } from './groups/useLeaveGroup';
export { usePromoteGroupMember } from './groups/usePromoteGroupMember'; export { usePromoteGroupMember } from './groups/usePromoteGroupMember';

View File

@ -2,9 +2,9 @@ import { Entities } from 'soapbox/entity-store/entities';
import { useEntities } from 'soapbox/entity-store/hooks'; import { useEntities } from 'soapbox/entity-store/hooks';
import { Group, groupSchema } from 'soapbox/schemas'; import { Group, groupSchema } from 'soapbox/schemas';
import { useGroupRelationships } from '../api/groups/useGroups';
import { useApi } from '../useApi'; import { useApi } from '../useApi';
import { useFeatures } from '../useFeatures'; import { useFeatures } from '../useFeatures';
import { useGroupRelationships } from '../useGroups';
function usePopularGroups() { function usePopularGroups() {
const api = useApi(); const api = useApi();

View File

@ -2,9 +2,9 @@ import { Entities } from 'soapbox/entity-store/entities';
import { useEntities } from 'soapbox/entity-store/hooks'; import { useEntities } from 'soapbox/entity-store/hooks';
import { Group, groupSchema } from 'soapbox/schemas'; import { Group, groupSchema } from 'soapbox/schemas';
import { useGroupRelationships } from '../api/groups/useGroups';
import { useApi } from '../useApi'; import { useApi } from '../useApi';
import { useFeatures } from '../useFeatures'; import { useFeatures } from '../useFeatures';
import { useGroupRelationships } from '../useGroups';
function useSuggestedGroups() { function useSuggestedGroups() {
const api = useApi(); const api = useApi();

View File

@ -6,7 +6,6 @@ export { useClickOutside } from './useClickOutside';
export { useCompose } from './useCompose'; export { useCompose } from './useCompose';
export { useDebounce } from './useDebounce'; export { useDebounce } from './useDebounce';
export { useGetState } from './useGetState'; export { useGetState } from './useGetState';
export { useGroup, useGroups } from './useGroups';
export { useGroupsPath } from './useGroupsPath'; export { useGroupsPath } from './useGroupsPath';
export { useDimensions } from './useDimensions'; export { useDimensions } from './useDimensions';
export { useFeatures } from './useFeatures'; export { useFeatures } from './useFeatures';

View File

@ -1,5 +1,4 @@
import { useGroups } from 'soapbox/hooks'; import { useGroups } from './api';
import { useFeatures } from './useFeatures'; import { useFeatures } from './useFeatures';
/** /**

View File

@ -823,6 +823,7 @@
"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", "groups.popular.label": "Suggested Groups",
"groups.search.placeholder": "Search My 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}",

View File

@ -12,7 +12,8 @@ import {
SignUpPanel, SignUpPanel,
SuggestedGroupsPanel, SuggestedGroupsPanel,
} from 'soapbox/features/ui/util/async-components'; } from 'soapbox/features/ui/util/async-components';
import { useGroup, useOwnAccount } from 'soapbox/hooks'; import { useOwnAccount } from 'soapbox/hooks';
import { useGroup } from 'soapbox/hooks/api';
import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests'; import { useGroupMembershipRequests } from 'soapbox/hooks/api/groups/useGroupMembershipRequests';
import { Group } from 'soapbox/schemas'; import { Group } from 'soapbox/schemas';

View File

@ -542,6 +542,11 @@ const getInstanceFeatures = (instance: Instance) => {
*/ */
groupsPromoteToAdmin: v.software !== TRUTHSOCIAL, groupsPromoteToAdmin: v.software !== TRUTHSOCIAL,
/**
* Can search my own groups.
*/
groupsSearch: v.software === TRUTHSOCIAL,
/** /**
* Can hide follows/followers lists and counts. * Can hide follows/followers lists and counts.
* @see PATCH /api/v1/accounts/update_credentials * @see PATCH /api/v1/accounts/update_credentials