Add hook to delete Group

develop^2
Chewbacca 2023-03-20 15:40:21 -04:00
rodzic be7a462fc4
commit ad98bf45cc
5 zmienionych plików z 67 dodań i 22 usunięć

Wyświetl plik

@ -30,7 +30,7 @@ interface EntityActionEndpoints {
}
interface EntityCallbacks<TEntity extends Entity = Entity> {
onSuccess?(entity: TEntity): void
onSuccess?(entity?: TEntity): void
}
function useEntityActions<TEntity extends Entity = Entity, P = any>(
@ -70,14 +70,20 @@ function useEntityActions<TEntity extends Entity = Entity, P = any>(
});
}
function deleteEntity(entityId: string): Promise<DeleteEntityResult> {
function deleteEntity(entityId: string, callbacks: EntityCallbacks = {}): Promise<DeleteEntityResult> {
if (!endpoints.delete) return Promise.reject(endpoints);
// Get the entity before deleting, so we can reverse the action if the API request fails.
const entity = getState().entities[entityType]?.store[entityId];
// Optimistically delete the entity from the _store_ but keep the lists in tact.
dispatch(deleteEntities([entityId], entityType, { preserveLists: true }));
setIsLoading(true);
return api.delete(endpoints.delete.replaceAll(':id', entityId)).then((response) => {
if (callbacks.onSuccess) {
callbacks.onSuccess();
}
// Success - finish deleting entity from the state.
dispatch(deleteEntities([entityId], entityType));
@ -90,12 +96,14 @@ function useEntityActions<TEntity extends Entity = Entity, P = any>(
dispatch(importEntities([entity], entityType));
}
throw e;
}).finally(() => {
setIsLoading(false);
});
}
return {
createEntity: createEntity,
deleteEntity: endpoints.delete ? deleteEntity : undefined,
createEntity,
deleteEntity,
isLoading,
};
}

Wyświetl plik

@ -7,8 +7,10 @@ import { deleteEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
import { useAppDispatch } from 'soapbox/hooks';
import { useCancelMembershipRequest, useJoinGroup, useLeaveGroup } from 'soapbox/hooks/api';
import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast';
import { Group } from 'soapbox/types/entities';
import type { Group } from 'soapbox/types/entities';
interface IGroupActionButton {
group: Group
@ -33,7 +35,7 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
const isRequested = group.relationship?.requested;
const isNonMember = !group.relationship?.member && !isRequested;
const isAdmin = group.relationship?.role === 'owner';
const isOwner = group.relationship?.role === GroupRoles.OWNER;
const isBlocked = group.relationship?.blocked_by;
const onJoinGroup = () => joinGroup.mutate({}, {
@ -68,6 +70,17 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
return null;
}
if (isOwner) {
return (
<Button
theme='secondary'
to={`/groups/${group.id}/manage`}
>
<FormattedMessage id='group.manage' defaultMessage='Manage Group' />
</Button>
);
}
if (isNonMember) {
return (
<Button
@ -94,17 +107,6 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
);
}
if (isAdmin) {
return (
<Button
theme='secondary'
to={`/groups/${group.id}/manage`}
>
<FormattedMessage id='group.manage' defaultMessage='Manage Group' />
</Button>
);
}
return (
<Button
theme='secondary'

Wyświetl plik

@ -2,11 +2,14 @@ import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useHistory } from 'react-router-dom';
import { deleteGroup, editGroup } from 'soapbox/actions/groups';
import { editGroup } from 'soapbox/actions/groups';
import { openModal } from 'soapbox/actions/modals';
import List, { ListItem } from 'soapbox/components/list';
import { CardBody, CardHeader, CardTitle, Column, Spinner, Text } from 'soapbox/components/ui';
import { useAppDispatch, useGroup } from 'soapbox/hooks';
import { useAppDispatch, useGroup, useGroupsPath } from 'soapbox/hooks';
import { useDeleteGroup } from 'soapbox/hooks/api';
import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast';
import ColumnForbidden from '../ui/components/column-forbidden';
@ -23,6 +26,7 @@ const messages = defineMessages({
deleteMessage: { id: 'confirmations.delete_group.message', defaultMessage: 'Are you sure you want to delete this group? This is a permanent action that cannot be undone.' },
members: { id: 'group.tabs.members', defaultMessage: 'Members' },
other: { id: 'settings.other', defaultMessage: 'Other options' },
deleteSuccess: { id: 'group.delete.success', defaultMessage: 'Group successfully deleted' },
});
interface IManageGroup {
@ -34,9 +38,14 @@ const ManageGroup: React.FC<IManageGroup> = ({ params }) => {
const intl = useIntl();
const history = useHistory();
const dispatch = useAppDispatch();
const groupsPath = useGroupsPath();
const { group } = useGroup(id);
const deleteGroup = useDeleteGroup();
const isOwner = group?.relationship?.role === GroupRoles.OWNER;
if (!group || !group.relationship) {
return (
<Column label={intl.formatMessage(messages.heading)}>
@ -58,7 +67,14 @@ const ManageGroup: React.FC<IManageGroup> = ({ params }) => {
heading: intl.formatMessage(messages.deleteHeading),
message: intl.formatMessage(messages.deleteMessage),
confirm: intl.formatMessage(messages.deleteConfirm),
onConfirm: () => dispatch(deleteGroup(id)),
onConfirm: () => {
deleteGroup.mutate(group.id, {
onSuccess() {
toast.success(intl.formatMessage(messages.deleteSuccess));
history.push(groupsPath);
},
});
},
}));
const navigateToPending = () => history.push(`/groups/${id}/manage/requests`);
@ -67,7 +83,7 @@ const ManageGroup: React.FC<IManageGroup> = ({ params }) => {
return (
<Column label={intl.formatMessage(messages.heading)} backHref={`/groups/${id}`}>
<CardBody className='space-y-4'>
{group.relationship.role === 'owner' && (
{isOwner && (
<>
<CardHeader>
<CardTitle title={intl.formatMessage(messages.editGroup)} />
@ -90,7 +106,7 @@ const ManageGroup: React.FC<IManageGroup> = ({ params }) => {
<ListItem label={intl.formatMessage(messages.blockedMembers)} onClick={navigateToBlocks} />
</List>
{group.relationship.role === 'owner' && (
{isOwner && (
<>
<CardHeader>
<CardTitle title={intl.formatMessage(messages.other)} />

Wyświetl plik

@ -0,0 +1,18 @@
import { Entities } from 'soapbox/entity-store/entities';
import { useEntityActions } from 'soapbox/entity-store/hooks';
import type { Group } from 'soapbox/schemas';
function useDeleteGroup() {
const { deleteEntity, isLoading } = useEntityActions<Group>(
[Entities.GROUPS],
{ delete: '/api/v1/groups/:id' },
);
return {
mutate: deleteEntity,
isLoading,
};
}
export { useDeleteGroup };

Wyświetl plik

@ -3,6 +3,7 @@
*/
export { useBlockGroupMember } from './groups/useBlockGroupMember';
export { useCancelMembershipRequest } from './groups/useCancelMembershipRequest';
export { useDeleteGroup } from './groups/useDeleteGroup';
export { useDemoteGroupMember } from './groups/useDemoteGroupMember';
export { useJoinGroup } from './groups/useJoinGroup';
export { useLeaveGroup } from './groups/useLeaveGroup';