mirror of
https://github.com/etkecc/synapse-admin.git
synced 2024-11-21 15:25:22 +03:00
Add UI option to block deleted rooms from being rejoined (#26)
Add UI option to block deleted rooms from being rejoined This is almost a copy of https://github.com/Awesome-Technologies/synapse-admin/pull/166 PR, authored by @jkanefendt
This commit is contained in:
parent
0bf3440fc8
commit
7de9166648
11 changed files with 153 additions and 16 deletions
2
.github/workflows/workflow.yml
vendored
2
.github/workflows/workflow.yml
vendored
|
@ -4,7 +4,7 @@ on:
|
|||
branches: [ "main" ]
|
||||
env:
|
||||
upstream_version: v0.10.3
|
||||
etke_version: etke12
|
||||
etke_version: etke13
|
||||
bunny_version: v0.1.0
|
||||
base_path: ./
|
||||
permissions:
|
||||
|
|
|
@ -35,6 +35,7 @@ The following changes are already implemented:
|
|||
* [Fix base_url being undefined on unsuccessful login](https://github.com/etkecc/synapse-admin/pull/18)
|
||||
* [Put the version into manifest.json](https://github.com/Awesome-Technologies/synapse-admin/issues/507) (CI only)
|
||||
* [Federation page improvements](https://github.com/Awesome-Technologies/synapse-admin/pull/583) (using theme colors)
|
||||
* [Add UI option to block deleted rooms from being rejoined](https://github.com/etkecc/synapse-admin/pull/26)
|
||||
|
||||
_the list will be updated as new changes are added_
|
||||
|
||||
|
|
105
src/components/DeleteRoomButton.tsx
Normal file
105
src/components/DeleteRoomButton.tsx
Normal file
|
@ -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;
|
|
@ -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.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
5
src/i18n/index.d.ts
vendored
5
src/i18n/index.d.ts
vendored
|
@ -192,6 +192,11 @@ interface SynapseTranslationMessages extends TranslationMessages {
|
|||
erase: {
|
||||
title: string;
|
||||
content: string;
|
||||
fields: {
|
||||
block: string;
|
||||
},
|
||||
success: string;
|
||||
failure: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -210,6 +210,11 @@ const ru: SynapseTranslationMessages = {
|
|||
title: "Удалить комнату",
|
||||
content:
|
||||
"Действительно удалить эту комнату? Это действие будет невозможно отменить. Все сообщения и файлы в комнате будут удалены с сервера!",
|
||||
fields: {
|
||||
block: "Заблокировать и запретить пользователям присоединяться к комнате",
|
||||
},
|
||||
success: "Комната/ы успешно удалены",
|
||||
failure: "Комната/ы не могут быть удалены.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
TopToolbar,
|
||||
useRecordContext,
|
||||
useTranslate,
|
||||
useListContext,
|
||||
} from "react-admin";
|
||||
|
||||
import {
|
||||
|
@ -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]} />;
|
||||
|
||||
|
@ -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"
|
||||
/>
|
||||
|
@ -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 />];
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Reference in a new issue