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:
commit
1abcc95a0a
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
|
@ -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';
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { useGroups } from 'soapbox/hooks';
|
import { useGroups } from './api';
|
||||||
|
|
||||||
import { useFeatures } from './useFeatures';
|
import { useFeatures } from './useFeatures';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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}",
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue