From 72523df008a19d6108e7fb5afc1dd2bd4b760298 Mon Sep 17 00:00:00 2001 From: mkljczk Date: Thu, 5 Dec 2024 10:49:43 +0100 Subject: [PATCH] pl-fe: migrate group members Signed-off-by: mkljczk --- packages/pl-api/lib/entities/group-member.ts | 2 +- .../hooks/groups/use-group-members.test.ts | 46 ------------------- .../src/api/hooks/groups/use-group-members.ts | 23 ---------- .../components/group-member-list-item.tsx | 16 +++---- .../src/features/group/group-members.tsx | 16 +++---- .../group/group-membership-requests.tsx | 9 +--- .../queries/accounts/use-follow-requests.ts | 4 +- .../use-event-participation-requests.ts | 4 +- .../events/use-event-participations.ts | 4 +- .../src/queries/groups/use-group-blocks.ts | 4 +- .../src/queries/groups/use-group-members.ts | 21 +++++++++ .../statuses/use-status-interactions.ts | 4 +- .../src/queries/statuses/use-status-quotes.ts | 4 +- .../utils/make-paginated-response-query.ts | 2 +- .../src/{api => queries}/utils/minify-list.ts | 0 15 files changed, 52 insertions(+), 107 deletions(-) delete mode 100644 packages/pl-fe/src/api/hooks/groups/use-group-members.test.ts delete mode 100644 packages/pl-fe/src/api/hooks/groups/use-group-members.ts create mode 100644 packages/pl-fe/src/queries/groups/use-group-members.ts rename packages/pl-fe/src/{api => queries}/utils/make-paginated-response-query.ts (94%) rename packages/pl-fe/src/{api => queries}/utils/minify-list.ts (100%) diff --git a/packages/pl-api/lib/entities/group-member.ts b/packages/pl-api/lib/entities/group-member.ts index 8919af00a..97109712f 100644 --- a/packages/pl-api/lib/entities/group-member.ts +++ b/packages/pl-api/lib/entities/group-member.ts @@ -27,4 +27,4 @@ const groupMemberSchema = v.object({ */ type GroupMember = v.InferOutput; -export { groupMemberSchema, type GroupMember, GroupRoles, type GroupRole }; +export { groupMemberSchema, type GroupMember, type GroupRoles, type GroupRole }; diff --git a/packages/pl-fe/src/api/hooks/groups/use-group-members.test.ts b/packages/pl-fe/src/api/hooks/groups/use-group-members.test.ts deleted file mode 100644 index d6dbf53dc..000000000 --- a/packages/pl-fe/src/api/hooks/groups/use-group-members.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { GroupRoles } from 'pl-api'; - -import { __stub } from 'pl-fe/api'; -import { buildGroupMember } from 'pl-fe/jest/factory'; -import { renderHook, waitFor } from 'pl-fe/jest/test-helpers'; - -import { useGroupMembers } from './use-group-members'; - -const groupMember = buildGroupMember(); -const groupId = '1'; - -describe('useGroupMembers hook', () => { - describe('with a successful request', () => { - beforeEach(() => { - __stub((mock) => { - mock.onGet(`/api/v1/groups/${groupId}/memberships?role=${GroupRoles.ADMIN}`).reply(200, [groupMember]); - }); - }); - - it('is successful', async () => { - const { result } = renderHook(() => useGroupMembers(groupId, GroupRoles.ADMIN)); - - await waitFor(() => expect(result.current.isFetching).toBe(false)); - - expect(result.current.groupMembers.length).toBe(1); - expect(result.current.groupMembers[0].id).toBe(groupMember.id); - }); - }); - - describe('with an unsuccessful query', () => { - beforeEach(() => { - __stub((mock) => { - mock.onGet(`/api/v1/groups/${groupId}/memberships?role=${GroupRoles.ADMIN}`).networkError(); - }); - }); - - it('is has error state', async() => { - const { result } = renderHook(() => useGroupMembers(groupId, GroupRoles.ADMIN)); - - await waitFor(() => expect(result.current.isFetching).toBe(false)); - - expect(result.current.groupMembers.length).toBe(0); - expect(result.current.isError).toBeTruthy(); - }); - }); -}); diff --git a/packages/pl-fe/src/api/hooks/groups/use-group-members.ts b/packages/pl-fe/src/api/hooks/groups/use-group-members.ts deleted file mode 100644 index d8e8df888..000000000 --- a/packages/pl-fe/src/api/hooks/groups/use-group-members.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Entities } from 'pl-fe/entity-store/entities'; -import { useEntities } from 'pl-fe/entity-store/hooks/use-entities'; -import { useClient } from 'pl-fe/hooks/use-client'; -import { normalizeGroupMember, type GroupMember } from 'pl-fe/normalizers/group-member'; - -import type { GroupMember as BaseGroupMember, GroupRoles } from 'pl-api'; - -const useGroupMembers = (groupId: string, role: GroupRoles) => { - const client = useClient(); - - const { entities, ...result } = useEntities( - [Entities.GROUP_MEMBERSHIPS, groupId, role], - () => client.experimental.groups.getGroupMemberships(groupId, role), - { transform: normalizeGroupMember }, - ); - - return { - ...result, - groupMembers: entities, - }; -}; - -export { useGroupMembers }; diff --git a/packages/pl-fe/src/features/group/components/group-member-list-item.tsx b/packages/pl-fe/src/features/group/components/group-member-list-item.tsx index 98e0decc8..80cd58e35 100644 --- a/packages/pl-fe/src/features/group/components/group-member-list-item.tsx +++ b/packages/pl-fe/src/features/group/components/group-member-list-item.tsx @@ -20,7 +20,7 @@ import toast from 'pl-fe/toast'; import type { Menu as IMenu } from 'pl-fe/components/dropdown-menu'; import type { Group } from 'pl-fe/normalizers/group'; -import type { GroupMember } from 'pl-fe/normalizers/group-member'; +import type { MinifiedGroupMember } from 'pl-fe/queries/groups/use-group-members'; const messages = defineMessages({ adminLimitTitle: { id: 'group.member.admin.limit.title', defaultMessage: 'Admin limit reached' }, @@ -44,7 +44,7 @@ const messages = defineMessages({ }); interface IGroupMemberListItem { - member: GroupMember; + member: MinifiedGroupMember; group: Pick; } @@ -53,11 +53,11 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { const intl = useIntl(); const { openModal } = useModalsStore(); - const { mutate: blockGroupMember } = useBlockGroupUserMutation(group.id, member.account.id); + const { mutate: blockGroupMember } = useBlockGroupUserMutation(group.id, member.account_id); const promoteGroupMember = usePromoteGroupMember(group, member); const demoteGroupMember = useDemoteGroupMember(group, member); - const { account, isLoading } = useAccount(member.account.id); + const { account, isLoading } = useAccount(member.account_id); // Current user role const isCurrentUserOwner = group.relationship?.role === GroupRoles.OWNER; @@ -102,7 +102,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { confirm: intl.formatMessage(messages.promoteConfirm), confirmationTheme: 'primary', onConfirm: () => { - promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [member.account.id] }, { + promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [member.account_id] }, { onSuccess() { toast.success( intl.formatMessage(messages.promotedToAdmin, { name: account?.acct }), @@ -114,7 +114,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { }; const handleUserAssignment = () => { - demoteGroupMember({ role: GroupRoles.USER, account_ids: [member.account.id] }, { + demoteGroupMember({ role: GroupRoles.USER, account_ids: [member.account_id] }, { onSuccess() { toast.success(intl.formatMessage(messages.demotedToUser, { name: account?.acct })); }, @@ -167,7 +167,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { return items; }, [group, account?.id]); - if (isLoading) { + if (isLoading || !account) { return ; } @@ -178,7 +178,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { data-testid='group-member-list-item' >
- +
diff --git a/packages/pl-fe/src/features/group/group-members.tsx b/packages/pl-fe/src/features/group/group-members.tsx index 05e9dc1e9..4a0dcd7dd 100644 --- a/packages/pl-fe/src/features/group/group-members.tsx +++ b/packages/pl-fe/src/features/group/group-members.tsx @@ -3,10 +3,10 @@ import { GroupRoles } from 'pl-api'; import React, { useMemo } from 'react'; import { useGroup } from 'pl-fe/api/hooks/groups/use-group'; -import { useGroupMembers } from 'pl-fe/api/hooks/groups/use-group-members'; import { useGroupMembershipRequests } from 'pl-fe/api/hooks/groups/use-group-membership-requests'; import { PendingItemsRow } from 'pl-fe/components/pending-items-row'; import ScrollableList from 'pl-fe/components/scrollable-list'; +import { useGroupMembers } from 'pl-fe/queries/groups/use-group-members'; import PlaceholderAccount from '../placeholder/components/placeholder-account'; @@ -20,17 +20,17 @@ const GroupMembers: React.FC = (props) => { const { groupId } = props.params; const { group, isFetching: isFetchingGroup } = useGroup(groupId); - const { groupMembers: owners, isFetching: isFetchingOwners } = useGroupMembers(groupId, GroupRoles.OWNER); - const { groupMembers: admins, isFetching: isFetchingAdmins } = useGroupMembers(groupId, GroupRoles.ADMIN); - const { groupMembers: users, isFetching: isFetchingUsers, fetchNextPage, hasNextPage } = useGroupMembers(groupId, GroupRoles.USER); + const { data: owners, isFetching: isFetchingOwners } = useGroupMembers(groupId, GroupRoles.OWNER); + const { data: admins, isFetching: isFetchingAdmins } = useGroupMembers(groupId, GroupRoles.ADMIN); + const { data: users, isFetching: isFetchingUsers, fetchNextPage, hasNextPage } = useGroupMembers(groupId, GroupRoles.USER); const { isFetching: isFetchingPending, count: pendingCount } = useGroupMembershipRequests(groupId); const isLoading = isFetchingGroup || isFetchingOwners || isFetchingAdmins || isFetchingUsers || isFetchingPending; const members = useMemo(() => [ - ...owners, - ...admins, - ...users, + ...(owners || []), + ...(admins || []), + ...(users || []), ], [owners, admins, users]); return ( @@ -57,7 +57,7 @@ const GroupMembers: React.FC = (props) => { ))} diff --git a/packages/pl-fe/src/features/group/group-membership-requests.tsx b/packages/pl-fe/src/features/group/group-membership-requests.tsx index 09792852c..353109aa4 100644 --- a/packages/pl-fe/src/features/group/group-membership-requests.tsx +++ b/packages/pl-fe/src/features/group/group-membership-requests.tsx @@ -1,9 +1,7 @@ -import { GroupRoles } from 'pl-api'; -import React, { useEffect } from 'react'; +import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { useGroup } from 'pl-fe/api/hooks/groups/use-group'; -import { useGroupMembers } from 'pl-fe/api/hooks/groups/use-group-members'; import { useGroupMembershipRequests } from 'pl-fe/api/hooks/groups/use-group-membership-requests'; import Account from 'pl-fe/components/account'; import { AuthorizeRejectButtons } from 'pl-fe/components/authorize-reject-buttons'; @@ -64,11 +62,6 @@ const GroupMembershipRequests: React.FC = ({ params }) const { group } = useGroup(groupId); const { accounts, authorize, reject, refetch, isLoading } = useGroupMembershipRequests(groupId); - const { invalidate } = useGroupMembers(groupId, GroupRoles.USER); - - useEffect(() => () => { - invalidate(); - }, []); if (!group || !group.relationship || isLoading) { return ( diff --git a/packages/pl-fe/src/queries/accounts/use-follow-requests.ts b/packages/pl-fe/src/queries/accounts/use-follow-requests.ts index 679664a95..a1fd1bc60 100644 --- a/packages/pl-fe/src/queries/accounts/use-follow-requests.ts +++ b/packages/pl-fe/src/queries/accounts/use-follow-requests.ts @@ -1,9 +1,9 @@ import { useMutation, type InfiniteData } from '@tanstack/react-query'; -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyAccountList } from 'pl-fe/api/utils/minify-list'; import { useClient } from 'pl-fe/hooks/use-client'; import { queryClient } from 'pl-fe/queries/client'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyAccountList } from 'pl-fe/queries/utils/minify-list'; import type { PaginatedResponse, PlApiClient } from 'pl-api'; diff --git a/packages/pl-fe/src/queries/events/use-event-participation-requests.ts b/packages/pl-fe/src/queries/events/use-event-participation-requests.ts index c974019a2..039214d8a 100644 --- a/packages/pl-fe/src/queries/events/use-event-participation-requests.ts +++ b/packages/pl-fe/src/queries/events/use-event-participation-requests.ts @@ -2,8 +2,8 @@ import { type InfiniteData, useMutation } from '@tanstack/react-query'; import { importEntities } from 'pl-fe/actions/importer'; -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyList } from 'pl-fe/api/utils/minify-list'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyList } from 'pl-fe/queries/utils/minify-list'; import { useClient } from 'pl-fe/hooks/use-client'; import { queryClient } from 'pl-fe/queries/client'; import { store } from 'pl-fe/store'; diff --git a/packages/pl-fe/src/queries/events/use-event-participations.ts b/packages/pl-fe/src/queries/events/use-event-participations.ts index 18adb8850..4b589a525 100644 --- a/packages/pl-fe/src/queries/events/use-event-participations.ts +++ b/packages/pl-fe/src/queries/events/use-event-participations.ts @@ -1,5 +1,5 @@ -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyAccountList } from 'pl-fe/api/utils/minify-list'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyAccountList } from 'pl-fe/queries/utils/minify-list'; const useEventParticipations = makePaginatedResponseQuery( (statusId: string) => ['accountsLists', 'eventParticipations', statusId], diff --git a/packages/pl-fe/src/queries/groups/use-group-blocks.ts b/packages/pl-fe/src/queries/groups/use-group-blocks.ts index f40373178..b61236967 100644 --- a/packages/pl-fe/src/queries/groups/use-group-blocks.ts +++ b/packages/pl-fe/src/queries/groups/use-group-blocks.ts @@ -1,7 +1,7 @@ import { useMutation, type InfiniteData } from '@tanstack/react-query'; -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyAccountList } from 'pl-fe/api/utils/minify-list'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyAccountList } from 'pl-fe/queries/utils/minify-list'; import { useClient } from 'pl-fe/hooks/use-client'; import { queryClient } from 'pl-fe/queries/client'; diff --git a/packages/pl-fe/src/queries/groups/use-group-members.ts b/packages/pl-fe/src/queries/groups/use-group-members.ts new file mode 100644 index 000000000..eca20278f --- /dev/null +++ b/packages/pl-fe/src/queries/groups/use-group-members.ts @@ -0,0 +1,21 @@ +import { GroupMember, GroupRole, PaginatedResponse } from 'pl-api'; + +import { importEntities } from 'pl-fe/actions/importer'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { store } from 'pl-fe/store'; + +import { minifyList } from '../utils/minify-list'; + +const minifyGroupMembersList = (response: PaginatedResponse): PaginatedResponse & { account_id: string }> => + minifyList(response, ({ account, ...groupMember }) => ({ ...groupMember, account_id: account.id }), (groupMembers) => { + store.dispatch(importEntities({ accounts: groupMembers.map(({ account }) => account) }) as any); + }); + +const useGroupMembers = makePaginatedResponseQuery( + (groupId: string, role?: GroupRole) => ['accountsLists', 'groupMembers', groupId, role], + (client, [groupId, role]) => client.experimental.groups.getGroupMemberships(groupId, role).then(minifyGroupMembersList), +); + +type MinifiedGroupMember = ReturnType['items'][0]; + +export { useGroupMembers, type MinifiedGroupMember }; diff --git a/packages/pl-fe/src/queries/statuses/use-status-interactions.ts b/packages/pl-fe/src/queries/statuses/use-status-interactions.ts index a0111b77e..2423982f5 100644 --- a/packages/pl-fe/src/queries/statuses/use-status-interactions.ts +++ b/packages/pl-fe/src/queries/statuses/use-status-interactions.ts @@ -1,8 +1,8 @@ import { useQuery } from '@tanstack/react-query'; import { importEntities } from 'pl-fe/actions/importer'; -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyAccountList } from 'pl-fe/api/utils/minify-list'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyAccountList } from 'pl-fe/queries/utils/minify-list'; import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; import { useClient } from 'pl-fe/hooks/use-client'; diff --git a/packages/pl-fe/src/queries/statuses/use-status-quotes.ts b/packages/pl-fe/src/queries/statuses/use-status-quotes.ts index 4af683f96..928c30b45 100644 --- a/packages/pl-fe/src/queries/statuses/use-status-quotes.ts +++ b/packages/pl-fe/src/queries/statuses/use-status-quotes.ts @@ -1,5 +1,5 @@ -import { makePaginatedResponseQuery } from 'pl-fe/api/utils/make-paginated-response-query'; -import { minifyStatusList } from 'pl-fe/api/utils/minify-list'; +import { makePaginatedResponseQuery } from 'pl-fe/queries/utils/make-paginated-response-query'; +import { minifyStatusList } from 'pl-fe/queries/utils/minify-list'; const useStatusQuotes = makePaginatedResponseQuery( (statusId: string) => ['statusLists', 'quotes', statusId], diff --git a/packages/pl-fe/src/api/utils/make-paginated-response-query.ts b/packages/pl-fe/src/queries/utils/make-paginated-response-query.ts similarity index 94% rename from packages/pl-fe/src/api/utils/make-paginated-response-query.ts rename to packages/pl-fe/src/queries/utils/make-paginated-response-query.ts index 26152c99c..50e475bd2 100644 --- a/packages/pl-fe/src/api/utils/make-paginated-response-query.ts +++ b/packages/pl-fe/src/queries/utils/make-paginated-response-query.ts @@ -5,7 +5,7 @@ import { useClient } from 'pl-fe/hooks/use-client'; import type { PaginatedResponse, PlApiClient } from 'pl-api'; const makePaginatedResponseQuery = , T2, T3 = Array>( - queryKey: (...params: T1) => string[], + queryKey: (...params: T1) => Array, queryFn: (client: PlApiClient, params: T1) => Promise>, select?: (data: InfiniteData>) => T3, ) => (...params: T1) => { diff --git a/packages/pl-fe/src/api/utils/minify-list.ts b/packages/pl-fe/src/queries/utils/minify-list.ts similarity index 100% rename from packages/pl-fe/src/api/utils/minify-list.ts rename to packages/pl-fe/src/queries/utils/minify-list.ts