Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add UI option to block deleted rooms from being rejoined
This is almost a copy of Awesome-Technologies/synapse-admin#166 PR,
authored by @jkanefendt
  • Loading branch information
beastafk committed Sep 13, 2024
commit 44dcb48f14a2bc188d4dfe8fba5d183df90bd0cb
105 changes: 105 additions & 0 deletions src/components/DeleteRoomButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
import { Fragment, useState } from "react";
import { SimpleForm, BooleanInput, useTranslate, RaRecord, useNotify, useRedirect, useDelete, NotificationType, useDeleteMany, Identifier, useUnselectAll } from "react-admin";
import ActionDelete from "@mui/icons-material/Delete";
import ActionCheck from "@mui/icons-material/CheckCircle";
import AlertError from "@mui/icons-material/ErrorOutline";

interface DeleteRoomButtonProps {
selectedIds: Identifier[];
confirmTitle: string;
confirmContent: string;
}

const resourceName = "rooms";

const DeleteRoomButton: React.FC<DeleteRoomButtonProps> = (props) => {
const translate = useTranslate();
const [open, setOpen] = useState(false);
const [block, setBlock] = useState(true);

const notify = useNotify();
const redirect = useRedirect();

const [deleteMany, { isLoading }] = useDeleteMany();
const unselectAll = useUnselectAll(resourceName);
const recordIds = props.selectedIds;

const handleDialogOpen = () => setOpen(true);
const handleDialogClose = () => setOpen(false);

const handleDelete = (values: {block: boolean}) => {
deleteMany(
resourceName,
{ ids: recordIds, meta: values },
{
onSuccess: () => {
notify("resources.rooms.action.erase.success");
handleDialogClose();
unselectAll();
redirect("/rooms");
},
onError: (error) =>
notify("resources.rooms.action.erase.failure", { type: 'error' as NotificationType }),
}
);
};

const handleConfirm = () => {
setOpen(false);
handleDelete({ block: block });
};

return (
<Fragment>
<Button
onClick={handleDialogOpen}
disabled={isLoading}
className={"ra-delete-button"}
key="button"
size="small"
sx={{
"&.MuiButton-sizeSmall": {
lineHeight: 1.5,
},
}}
color={"error"}
startIcon={<ActionDelete />}
>
{translate("ra.action.delete")}
</Button>
<Dialog open={open} onClose={handleDialogClose}>
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
<DialogContent>
<DialogContentText>{translate(props.confirmContent)}</DialogContentText>
<SimpleForm toolbar={false}>
<BooleanInput
fullWidth
source="block"
value={block}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setBlock(event.target.checked)}
label="resources.rooms.action.erase.fields.block"
defaultValue={true}
/>
</SimpleForm>
</DialogContent>
<DialogActions>
<Button disabled={false} onClick={handleDialogClose} startIcon={<AlertError />}>
{translate("ra.action.cancel")}
</Button>
<Button
disabled={false}
onClick={handleConfirm}
className={"ra-confirm RaConfirm-confirmPrimary"}
autoFocus
startIcon={<ActionCheck />}
>
{translate("ra.action.confirm")}
</Button>
</DialogActions>
</Dialog>
</Fragment>
);
};

export default DeleteRoomButton;
5 changes: 5 additions & 0 deletions src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ const de: SynapseTranslationMessages = {
title: "Raum löschen",
content:
"Sind Sie sicher dass Sie den Raum löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden. Alle Nachrichten und Medien, die der Raum beinhaltet werden vom Server gelöscht!",
fields: {
block: "Benutzer blockieren und daran hindern, dem Raum beizutreten",
},
success: "Raum/Räume erfolgreich gelöscht.",
failure: "Der/die Raum/Räume konnten nicht gelöscht werden.",
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ const en: SynapseTranslationMessages = {
title: "Delete room",
content:
"Are you sure you want to delete the room? This cannot be undone. All messages and shared media in the room will be deleted from the server!",
fields: {
block: "Block and prevent users from joining the room",
},
success: "Room/s successfully deleted.",
failure: "The room/s could not be deleted.",
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ const fr: SynapseTranslationMessages = {
title: "Supprimer le salon",
content:
"Voulez-vous vraiment supprimer le salon ? Cette opération ne peut être annulée. Tous les messages et médias partagés du salon seront supprimés du serveur !",
fields: {
block: "Bloquer et empêcher les utilisateurs de rejoindre la salle",
},
success: "Salle/s supprimées avec succès.",
failure: "La/les salle/s n'ont pas pu être supprimées.",
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ interface SynapseTranslationMessages extends TranslationMessages {
erase: {
title: string;
content: string;
fields: {
block: string;
},
success: string;
failure: string;
};
};
};
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ const ru: SynapseTranslationMessages = {
title: "Удалить комнату",
content:
"Действительно удалить эту комнату? Это действие будет невозможно отменить. Все сообщения и файлы в комнате будут удалены с сервера!",
fields: {
block: "Заблокировать и запретить пользователям присоединяться к комнате",
},
success: "Комната/ы успешно удалены",
failure: "Комната/ы не могут быть удалены.",
},
},
},
Expand Down
31 changes: 18 additions & 13 deletions src/resources/rooms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
TopToolbar,
useRecordContext,
useTranslate,
useListContext,
} from "react-admin";

import {
Expand All @@ -45,6 +46,7 @@ import {
RoomDirectoryPublishButton,
} from "./room_directory";
import { DATE_FORMAT } from "../components/date";
import DeleteRoomButton from "../components/DeleteRoomButton";

const RoomPagination = () => <Pagination rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />;

Expand All @@ -70,8 +72,8 @@ const RoomShowActions = () => {
return (
<TopToolbar>
{publishButton}
<DeleteButton
mutationMode="pessimistic"
<DeleteRoomButton
selectedIds={[record.id]}
confirmTitle="resources.rooms.action.erase.title"
confirmContent="resources.rooms.action.erase.content"
/>
Expand Down Expand Up @@ -207,17 +209,20 @@ export const RoomShow = (props: ShowProps) => {
);
};

const RoomBulkActionButtons = () => (
<>
<RoomDirectoryBulkPublishButton />
<RoomDirectoryBulkUnpublishButton />
<BulkDeleteButton
confirmTitle="resources.rooms.action.erase.title"
confirmContent="resources.rooms.action.erase.content"
mutationMode="pessimistic"
/>
</>
);
const RoomBulkActionButtons = () => {
const record = useListContext();
return (
<>
<RoomDirectoryBulkPublishButton />
<RoomDirectoryBulkUnpublishButton />
<DeleteRoomButton
selectedIds={record.selectedIds}
confirmTitle="resources.rooms.action.erase.title"
confirmContent="resources.rooms.action.erase.content"
/>
</>
);
};

const roomFilters = [<SearchInput source="search_term" alwaysOn />];

Expand Down
3 changes: 2 additions & 1 deletion src/synapse/authProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fetchMock from "jest-fetch-mock";

import authProvider from "./authProvider";
import storage from "../storage";
import { HttpError } from "ra-core";

fetchMock.enableMocks();

Expand Down Expand Up @@ -104,7 +105,7 @@ describe("authProvider", () => {
});

it("should reject if error.status is 403", async () => {
await expect(authProvider.checkError({ status: 403 })).rejects.toBeUndefined();
await expect(authProvider.checkError(new HttpError("test-error", 403, {errcode: "test-errcode", error: "test-error"}))).rejects.toBeDefined();
});
});

Expand Down
2 changes: 1 addition & 1 deletion src/synapse/dataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ const resourceMap = {
total: json => json.total_rooms,
delete: (params: DeleteParams) => ({
endpoint: `/_synapse/admin/v2/rooms/${params.id}`,
body: { block: false },
body: { block: params.meta?.block ?? false },
}),
},
reports: {
Expand Down