Fetch account and relationship with entity store
This commit is contained in:
parent
c045a6630d
commit
a486b317d4
|
@ -3,4 +3,5 @@ export enum Entities {
|
||||||
GROUPS = 'Groups',
|
GROUPS = 'Groups',
|
||||||
GROUP_RELATIONSHIPS = 'GroupRelationships',
|
GROUP_RELATIONSHIPS = 'GroupRelationships',
|
||||||
GROUP_MEMBERSHIPS = 'GroupMemberships',
|
GROUP_MEMBERSHIPS = 'GroupMemberships',
|
||||||
|
RELATIONSHIPS = 'Relationships'
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ function useEntity<TEntity extends Entity>(
|
||||||
entityFn: EntityFn<void>,
|
entityFn: EntityFn<void>,
|
||||||
opts: UseEntityOpts<TEntity> = {},
|
opts: UseEntityOpts<TEntity> = {},
|
||||||
) {
|
) {
|
||||||
const [isFetching, setPromise] = useLoading();
|
const [isFetching, setPromise] = useLoading(true);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [entityType, entityId] = path;
|
const [entityType, entityId] = path;
|
||||||
|
|
|
@ -9,13 +9,14 @@ import DropdownMenu from 'soapbox/components/dropdown-menu/dropdown-menu';
|
||||||
import { HStack } from 'soapbox/components/ui';
|
import { HStack } from 'soapbox/components/ui';
|
||||||
import { deleteEntities } from 'soapbox/entity-store/actions';
|
import { deleteEntities } from 'soapbox/entity-store/actions';
|
||||||
import { Entities } from 'soapbox/entity-store/entities';
|
import { Entities } from 'soapbox/entity-store/entities';
|
||||||
import { useAccount, useAppDispatch, useFeatures } from 'soapbox/hooks';
|
import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder-account';
|
||||||
import { useBlockGroupMember, useDemoteGroupMember, usePromoteGroupMember } from 'soapbox/hooks/api';
|
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
|
||||||
|
import { useAccount, useBlockGroupMember, useDemoteGroupMember, usePromoteGroupMember } 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';
|
||||||
|
|
||||||
import type { Menu as IMenu } from 'soapbox/components/dropdown-menu';
|
import type { Menu as IMenu } from 'soapbox/components/dropdown-menu';
|
||||||
import type { Account as AccountEntity, Group, GroupMember } from 'soapbox/types/entities';
|
import type { Group, GroupMember } from 'soapbox/types/entities';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
blockConfirm: { id: 'confirmations.block_from_group.confirm', defaultMessage: 'Ban' },
|
blockConfirm: { id: 'confirmations.block_from_group.confirm', defaultMessage: 'Ban' },
|
||||||
|
@ -51,7 +52,7 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
const promoteGroupMember = usePromoteGroupMember(group, member);
|
const promoteGroupMember = usePromoteGroupMember(group, member);
|
||||||
const demoteGroupMember = useDemoteGroupMember(group, member);
|
const demoteGroupMember = useDemoteGroupMember(group, member);
|
||||||
|
|
||||||
const account = useAccount(member.account.id) as AccountEntity;
|
const { account, isLoading } = useAccount(member.account.id);
|
||||||
|
|
||||||
// Current user role
|
// Current user role
|
||||||
const isCurrentUserOwner = group.relationship?.role === GroupRoles.OWNER;
|
const isCurrentUserOwner = group.relationship?.role === GroupRoles.OWNER;
|
||||||
|
@ -64,10 +65,10 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
|
|
||||||
const handleKickFromGroup = () => {
|
const handleKickFromGroup = () => {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
message: intl.formatMessage(messages.kickFromGroupMessage, { name: account.username }),
|
message: intl.formatMessage(messages.kickFromGroupMessage, { name: account?.username }),
|
||||||
confirm: intl.formatMessage(messages.kickConfirm),
|
confirm: intl.formatMessage(messages.kickConfirm),
|
||||||
onConfirm: () => dispatch(groupKick(group.id, account.id)).then(() =>
|
onConfirm: () => dispatch(groupKick(group.id, account?.id as string)).then(() =>
|
||||||
toast.success(intl.formatMessage(messages.kicked, { name: account.acct })),
|
toast.success(intl.formatMessage(messages.kicked, { name: account?.acct })),
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
@ -75,13 +76,13 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
const handleBlockFromGroup = () => {
|
const handleBlockFromGroup = () => {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
heading: intl.formatMessage(messages.blockFromGroupHeading),
|
heading: intl.formatMessage(messages.blockFromGroupHeading),
|
||||||
message: intl.formatMessage(messages.blockFromGroupMessage, { name: account.username }),
|
message: intl.formatMessage(messages.blockFromGroupMessage, { name: account?.username }),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
confirm: intl.formatMessage(messages.blockConfirm),
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
blockGroupMember({ account_ids: [member.account.id] }, {
|
blockGroupMember({ account_ids: [member.account.id] }, {
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
dispatch(deleteEntities([member.id], Entities.GROUP_MEMBERSHIPS));
|
dispatch(deleteEntities([member.id], Entities.GROUP_MEMBERSHIPS));
|
||||||
toast.success(intl.formatMessage(messages.blocked, { name: account.acct }));
|
toast.success(intl.formatMessage(messages.blocked, { name: account?.acct }));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -91,14 +92,14 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
const handleAdminAssignment = () => {
|
const handleAdminAssignment = () => {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
heading: intl.formatMessage(messages.promoteConfirm),
|
heading: intl.formatMessage(messages.promoteConfirm),
|
||||||
message: intl.formatMessage(messages.promoteConfirmMessage, { name: account.username }),
|
message: intl.formatMessage(messages.promoteConfirmMessage, { name: account?.username }),
|
||||||
confirm: intl.formatMessage(messages.promoteConfirm),
|
confirm: intl.formatMessage(messages.promoteConfirm),
|
||||||
confirmationTheme: 'primary',
|
confirmationTheme: 'primary',
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [account.id] }, {
|
promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [account?.id] }, {
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
toast.success(
|
toast.success(
|
||||||
intl.formatMessage(messages.promotedToAdmin, { name: account.acct }),
|
intl.formatMessage(messages.promotedToAdmin, { name: account?.acct }),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -107,9 +108,9 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUserAssignment = () => {
|
const handleUserAssignment = () => {
|
||||||
demoteGroupMember({ role: GroupRoles.USER, account_ids: [account.id] }, {
|
demoteGroupMember({ role: GroupRoles.USER, account_ids: [account?.id] }, {
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
toast.success(intl.formatMessage(messages.demotedToUser, { name: account.acct }));
|
toast.success(intl.formatMessage(messages.demotedToUser, { name: account?.acct }));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -160,7 +161,11 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}, [group, account]);
|
}, [group, account?.id]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <PlaceholderAccount />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack alignItems='center' justifyContent='between'>
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
|
|
|
@ -53,11 +53,11 @@ const GroupMembers: React.FC<IGroupMembers> = (props) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{members.map((member) => (
|
{members.map((member, idx) => (
|
||||||
<GroupMemberListItem
|
<GroupMemberListItem
|
||||||
group={group as Group}
|
group={group as Group}
|
||||||
member={member}
|
member={member}
|
||||||
key={member.account.id}
|
key={idx}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
|
|
@ -18,4 +18,4 @@ const PlaceholderAccount: React.FC = () => (
|
||||||
</HStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default PlaceholderAccount;
|
export default React.memo(PlaceholderAccount);
|
||||||
|
|
|
@ -21,4 +21,4 @@ const PlaceholderDisplayName: React.FC<IPlaceholderDisplayName> = ({ minLength,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PlaceholderDisplayName;
|
export default React.memo(PlaceholderDisplayName);
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/**
|
||||||
|
* Accounts
|
||||||
|
*/
|
||||||
|
export { useAccount } from './useAccount';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups
|
* Groups
|
||||||
*/
|
*/
|
||||||
|
@ -12,3 +17,8 @@ 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';
|
||||||
export { useUpdateGroup } from './groups/useUpdateGroup';
|
export { useUpdateGroup } from './groups/useUpdateGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relationships
|
||||||
|
*/
|
||||||
|
export { useRelationships } from './useRelationships';
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Entities } from 'soapbox/entity-store/entities';
|
||||||
|
import { useEntity } from 'soapbox/entity-store/hooks';
|
||||||
|
import { type Account, accountSchema } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
import { useApi } from '../useApi';
|
||||||
|
|
||||||
|
import { useRelationships } from './useRelationships';
|
||||||
|
|
||||||
|
function useAccount(id: string) {
|
||||||
|
const api = useApi();
|
||||||
|
|
||||||
|
const { entity: account, ...result } = useEntity<Account>(
|
||||||
|
[Entities.ACCOUNTS, id],
|
||||||
|
() => api.get(`/api/v1/accounts/${id}`),
|
||||||
|
{ schema: accountSchema },
|
||||||
|
);
|
||||||
|
const { relationships, isLoading } = useRelationships([account?.id as string]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
isLoading: result.isLoading || isLoading,
|
||||||
|
account: account ? { ...account, relationship: relationships[0] || null } : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useAccount };
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Entities } from 'soapbox/entity-store/entities';
|
||||||
|
import { useEntities } from 'soapbox/entity-store/hooks';
|
||||||
|
import { type Relationship, relationshipSchema } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
import { useApi } from '../useApi';
|
||||||
|
|
||||||
|
function useRelationships(ids: string[]) {
|
||||||
|
const api = useApi();
|
||||||
|
|
||||||
|
const { entities: relationships, ...result } = useEntities<Relationship>(
|
||||||
|
[Entities.RELATIONSHIPS],
|
||||||
|
() => api.get(`/api/v1/accounts/relationships?${ids.map(id => `id[]=${id}`).join('&')}`),
|
||||||
|
{ schema: relationshipSchema, enabled: ids.filter(Boolean).length > 0 },
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
relationships,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useRelationships };
|
|
@ -1,7 +1,7 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
function useLoading() {
|
function useLoading(initialState: boolean = false) {
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(initialState);
|
||||||
|
|
||||||
function setPromise<T>(promise: Promise<T>) {
|
function setPromise<T>(promise: Promise<T>) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
Loading…
Reference in New Issue