mirror of
https://github.com/etkecc/synapse-admin.git
synced 2025-02-16 11:29:48 +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" ]
|
branches: [ "main" ]
|
||||||
env:
|
env:
|
||||||
upstream_version: v0.10.3
|
upstream_version: v0.10.3
|
||||||
etke_version: etke12
|
etke_version: etke13
|
||||||
bunny_version: v0.1.0
|
bunny_version: v0.1.0
|
||||||
base_path: ./
|
base_path: ./
|
||||||
permissions:
|
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)
|
* [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)
|
* [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)
|
* [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_
|
_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",
|
title: "Raum löschen",
|
||||||
content:
|
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!",
|
"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",
|
title: "Delete room",
|
||||||
content:
|
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!",
|
"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",
|
title: "Supprimer le salon",
|
||||||
content:
|
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 !",
|
"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: {
|
erase: {
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
fields: {
|
||||||
|
block: string;
|
||||||
|
},
|
||||||
|
success: string;
|
||||||
|
failure: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -210,6 +210,11 @@ const ru: SynapseTranslationMessages = {
|
||||||
title: "Удалить комнату",
|
title: "Удалить комнату",
|
||||||
content:
|
content:
|
||||||
"Действительно удалить эту комнату? Это действие будет невозможно отменить. Все сообщения и файлы в комнате будут удалены с сервера!",
|
"Действительно удалить эту комнату? Это действие будет невозможно отменить. Все сообщения и файлы в комнате будут удалены с сервера!",
|
||||||
|
fields: {
|
||||||
|
block: "Заблокировать и запретить пользователям присоединяться к комнате",
|
||||||
|
},
|
||||||
|
success: "Комната/ы успешно удалены",
|
||||||
|
failure: "Комната/ы не могут быть удалены.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
TopToolbar,
|
TopToolbar,
|
||||||
useRecordContext,
|
useRecordContext,
|
||||||
useTranslate,
|
useTranslate,
|
||||||
|
useListContext,
|
||||||
} from "react-admin";
|
} from "react-admin";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -45,6 +46,7 @@ import {
|
||||||
RoomDirectoryPublishButton,
|
RoomDirectoryPublishButton,
|
||||||
} from "./room_directory";
|
} from "./room_directory";
|
||||||
import { DATE_FORMAT } from "../components/date";
|
import { DATE_FORMAT } from "../components/date";
|
||||||
|
import DeleteRoomButton from "../components/DeleteRoomButton";
|
||||||
|
|
||||||
const RoomPagination = () => <Pagination rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />;
|
const RoomPagination = () => <Pagination rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />;
|
||||||
|
|
||||||
|
@ -70,8 +72,8 @@ const RoomShowActions = () => {
|
||||||
return (
|
return (
|
||||||
<TopToolbar>
|
<TopToolbar>
|
||||||
{publishButton}
|
{publishButton}
|
||||||
<DeleteButton
|
<DeleteRoomButton
|
||||||
mutationMode="pessimistic"
|
selectedIds={[record.id]}
|
||||||
confirmTitle="resources.rooms.action.erase.title"
|
confirmTitle="resources.rooms.action.erase.title"
|
||||||
confirmContent="resources.rooms.action.erase.content"
|
confirmContent="resources.rooms.action.erase.content"
|
||||||
/>
|
/>
|
||||||
|
@ -207,17 +209,20 @@ export const RoomShow = (props: ShowProps) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RoomBulkActionButtons = () => (
|
const RoomBulkActionButtons = () => {
|
||||||
|
const record = useListContext();
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<RoomDirectoryBulkPublishButton />
|
<RoomDirectoryBulkPublishButton />
|
||||||
<RoomDirectoryBulkUnpublishButton />
|
<RoomDirectoryBulkUnpublishButton />
|
||||||
<BulkDeleteButton
|
<DeleteRoomButton
|
||||||
|
selectedIds={record.selectedIds}
|
||||||
confirmTitle="resources.rooms.action.erase.title"
|
confirmTitle="resources.rooms.action.erase.title"
|
||||||
confirmContent="resources.rooms.action.erase.content"
|
confirmContent="resources.rooms.action.erase.content"
|
||||||
mutationMode="pessimistic"
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const roomFilters = [<SearchInput source="search_term" alwaysOn />];
|
const roomFilters = [<SearchInput source="search_term" alwaysOn />];
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import fetchMock from "jest-fetch-mock";
|
||||||
|
|
||||||
import authProvider from "./authProvider";
|
import authProvider from "./authProvider";
|
||||||
import storage from "../storage";
|
import storage from "../storage";
|
||||||
|
import { HttpError } from "ra-core";
|
||||||
|
|
||||||
fetchMock.enableMocks();
|
fetchMock.enableMocks();
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ describe("authProvider", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should reject if error.status is 403", async () => {
|
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,
|
total: json => json.total_rooms,
|
||||||
delete: (params: DeleteParams) => ({
|
delete: (params: DeleteParams) => ({
|
||||||
endpoint: `/_synapse/admin/v2/rooms/${params.id}`,
|
endpoint: `/_synapse/admin/v2/rooms/${params.id}`,
|
||||||
body: { block: false },
|
body: { block: params.meta?.block ?? false },
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
reports: {
|
reports: {
|
||||||
|
|
Loading…
Add table
Reference in a new issue