From 2ab434397069e7995fabe8ffc536d818aacd0523 Mon Sep 17 00:00:00 2001
From: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>
Date: Tue, 4 May 2021 13:52:43 +0200
Subject: [PATCH] Add the lists of public rooms on the server (#105)
* Add room directory and the switches to rooms settings
* Fix react admin version
---
src/App.js | 7 +
src/components/RoomDirectory.js | 252 ++++++++++++++++++++++++++++++++
src/components/rooms.js | 43 ++++--
src/components/users.js | 31 ++--
src/i18n/de.js | 33 ++++-
src/i18n/en.js | 31 +++-
src/synapse/dataProvider.js | 24 +++
7 files changed, 381 insertions(+), 40 deletions(-)
create mode 100644 src/components/RoomDirectory.js
diff --git a/src/App.js b/src/App.js
index 3afdff8..2ab6161 100644
--- a/src/App.js
+++ b/src/App.js
@@ -12,7 +12,9 @@ import EqualizerIcon from "@material-ui/icons/Equalizer";
import { UserMediaStatsList } from "./components/statistics";
import RoomIcon from "@material-ui/icons/ViewList";
import ReportIcon from "@material-ui/icons/Warning";
+import FolderSharedIcon from "@material-ui/icons/FolderShared";
import { ImportFeature } from "./components/ImportFeature";
+import { RoomDirectoryList } from "./components/RoomDirectory";
import { Route } from "react-router-dom";
import germanMessages from "./i18n/de";
import englishMessages from "./i18n/en";
@@ -57,6 +59,11 @@ const App = () => (
show={ReportShow}
icon={ReportIcon}
/>
+
diff --git a/src/components/RoomDirectory.js b/src/components/RoomDirectory.js
new file mode 100644
index 0000000..654c824
--- /dev/null
+++ b/src/components/RoomDirectory.js
@@ -0,0 +1,252 @@
+import React, { Fragment } from "react";
+import Avatar from "@material-ui/core/Avatar";
+import { Chip } from "@material-ui/core";
+import { connect } from "react-redux";
+import FolderSharedIcon from "@material-ui/icons/FolderShared";
+import { makeStyles } from "@material-ui/core/styles";
+import {
+ BooleanField,
+ BulkDeleteButton,
+ Button,
+ Datagrid,
+ DeleteButton,
+ Filter,
+ List,
+ NumberField,
+ Pagination,
+ TextField,
+ useCreate,
+ useMutation,
+ useNotify,
+ useTranslate,
+ useRefresh,
+ useUnselectAll,
+} from "react-admin";
+
+const useStyles = makeStyles({
+ small: {
+ height: "40px",
+ width: "40px",
+ },
+});
+
+const RoomDirectoryPagination = props => (
+
+);
+
+export const RoomDirectoryDeleteButton = props => {
+ const translate = useTranslate();
+
+ return (
+ }
+ />
+ );
+};
+
+export const RoomDirectoryBulkDeleteButton = props => (
+ }
+ />
+);
+
+export const RoomDirectoryBulkSaveButton = ({ selectedIds }) => {
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const unselectAll = useUnselectAll();
+ const [createMany, { loading }] = useMutation();
+
+ const handleSend = values => {
+ createMany(
+ {
+ type: "createMany",
+ resource: "room_directory",
+ payload: { ids: selectedIds, data: {} },
+ },
+ {
+ onSuccess: ({ data }) => {
+ notify("resources.room_directory.action.send_success");
+ unselectAll("rooms");
+ refresh();
+ },
+ onFailure: error =>
+ notify("resources.room_directory.action.send_failure", "error"),
+ }
+ );
+ };
+
+ return (
+
+ );
+};
+
+export const RoomDirectorySaveButton = ({ record }) => {
+ const notify = useNotify();
+ const refresh = useRefresh();
+ const [create, { loading }] = useCreate("room_directory");
+
+ const handleSend = values => {
+ create(
+ {
+ payload: { data: { id: record.id } },
+ },
+ {
+ onSuccess: ({ data }) => {
+ notify("resources.room_directory.action.send_success");
+ refresh();
+ },
+ onFailure: error =>
+ notify("resources.room_directory.action.send_failure", "error"),
+ }
+ );
+ };
+
+ return (
+
+ );
+};
+
+const RoomDirectoryBulkActionButtons = props => (
+
+
+
+);
+
+const AvatarField = ({ source, className, record = {} }) => (
+
+);
+
+const RoomDirectoryFilter = ({ ...props }) => {
+ const translate = useTranslate();
+ return (
+
+
+
+
+
+ );
+};
+
+export const FilterableRoomDirectoryList = ({ ...props }) => {
+ const classes = useStyles();
+ const translate = useTranslate();
+ const filter = props.roomDirectoryFilters;
+ const roomIdFilter = filter && filter.room_id ? true : false;
+ const topicFilter = filter && filter.topic ? true : false;
+ const canonicalAliasFilter = filter && filter.canonical_alias ? true : false;
+
+ return (
+
}
+ bulkActionButtons={}
+ filters={}
+ perPage={100}
+ >
+
+
+
+ {roomIdFilter && (
+
+ )}
+ {canonicalAliasFilter && (
+
+ )}
+ {topicFilter && (
+
+ )}
+
+
+
+
+
+ );
+};
+
+function mapStateToProps(state) {
+ return {
+ roomDirectoryFilters:
+ state.admin.resources.room_directory.list.params.displayedFilters,
+ };
+}
+
+export const RoomDirectoryList = connect(mapStateToProps)(
+ FilterableRoomDirectoryList
+);
diff --git a/src/components/rooms.js b/src/components/rooms.js
index e1a44e6..0c2c514 100644
--- a/src/components/rooms.js
+++ b/src/components/rooms.js
@@ -2,7 +2,7 @@ import React, { Fragment } from "react";
import { connect } from "react-redux";
import {
BooleanField,
- BulkDeleteWithConfirmButton,
+ BulkDeleteButton,
Datagrid,
DeleteButton,
Filter,
@@ -27,6 +27,12 @@ import PageviewIcon from "@material-ui/icons/Pageview";
import UserIcon from "@material-ui/icons/Group";
import ViewListIcon from "@material-ui/icons/ViewList";
import VisibilityIcon from "@material-ui/icons/Visibility";
+import {
+ RoomDirectoryBulkDeleteButton,
+ RoomDirectoryBulkSaveButton,
+ RoomDirectoryDeleteButton,
+ RoomDirectorySaveButton,
+} from "./RoomDirectory";
const RoomPagination = props => (
@@ -73,16 +79,26 @@ const RoomTitle = ({ record }) => {
};
const RoomShowActions = ({ basePath, data, resource }) => {
- const translate = useTranslate();
+ var roomDirectoryStatus = "";
+ if (data) {
+ roomDirectoryStatus = data.public;
+ }
+
return (
+ {roomDirectoryStatus === false && (
+
+ )}
+ {roomDirectoryStatus === true && (
+
+ )}
);
@@ -205,7 +221,14 @@ export const RoomShow = props => {
const RoomBulkActionButtons = props => (
-
+
+
+
);
@@ -249,7 +272,6 @@ const FilterableRoomList = ({ ...props }) => {
const stateEventsFilter = filter && filter.state_events ? true : false;
const versionFilter = filter && filter.version ? true : false;
const federateableFilter = filter && filter.federatable ? true : false;
- const translate = useTranslate();
return (
{
pagination={}
sort={{ field: "name", order: "ASC" }}
filters={}
- bulkActionButtons={
-
- }
+ bulkActionButtons={}
>
(
);
-const UserBulkActionButtons = props => {
- const translate = useTranslate();
- return (
-
-
-
-
- );
-};
+const UserBulkActionButtons = props => (
+
+
+
+
+);
const AvatarField = ({ source, className, record = {} }) => (
@@ -238,7 +236,10 @@ const UserEditToolbar = props => {
@@ -453,7 +454,7 @@ export const UserEdit = props => {
-
+
diff --git a/src/i18n/de.js b/src/i18n/de.js
index f75f2b0..a1a57e3 100644
--- a/src/i18n/de.js
+++ b/src/i18n/de.js
@@ -23,11 +23,6 @@ export default {
detail: "Details",
permission: "Berechtigungen",
},
- delete: {
- title: "Raum löschen",
- message:
- "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!",
- },
},
reports: { tabs: { basic: "Allgemein", detail: "Details" } },
},
@@ -149,11 +144,13 @@ export default {
is_encrypted: "Verschlüsselt",
encryption: "Verschlüsselungs-Algorithmus",
federatable: "Föderierbar",
- public: "Öffentlich",
+ public: "Sichtbar im Raumverzeichnis",
creator: "Ersteller",
join_rules: "Beitrittsregeln",
guest_access: "Gastzugriff",
history_visibility: "Historie-Sichtbarkeit",
+ topic: "Thema",
+ avatar: "Avatar",
},
enums: {
join_rules: {
@@ -174,6 +171,13 @@ export default {
},
unencrypted: "Nicht verschlüsselt",
},
+ action: {
+ erase: {
+ 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!",
+ },
+ },
},
reports: {
name: "Ereignisbericht |||| Ereignisberichte",
@@ -291,6 +295,23 @@ export default {
media_length: "Größe der Dateien",
},
},
+ room_directory: {
+ name: "Raumverzeichnis",
+ fields: {
+ world_readable: "Gastbenutzer dürfen ohne Beitritt lesen",
+ guest_can_join: "Gastbenutzer dürfen beitreten",
+ },
+ action: {
+ title:
+ "Raum aus Verzeichnis löschen |||| %{smart_count} Räume aus Verzeichnis löschen",
+ content:
+ "Möchten Sie den Raum wirklich aus dem Raumverzeichnis löschen? |||| Möchten Sie die %{smart_count} Räume wirklich aus dem Raumverzeichnis löschen?",
+ erase: "Lösche aus Verzeichnis",
+ create: "Eintragen ins Verzeichnis",
+ send_success: "Raum erfolgreich eingetragen.",
+ send_failure: "Beim Entfernen ist ein Fehler aufgetreten.",
+ },
+ },
},
ra: {
...germanMessages.ra,
diff --git a/src/i18n/en.js b/src/i18n/en.js
index 50cba01..ec7f9b4 100644
--- a/src/i18n/en.js
+++ b/src/i18n/en.js
@@ -22,11 +22,6 @@ export default {
detail: "Details",
permission: "Permissions",
},
- delete: {
- title: "Delete room",
- message:
- "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!",
- },
},
reports: { tabs: { basic: "Basic", detail: "Details" } },
},
@@ -147,11 +142,13 @@ export default {
is_encrypted: "Encrypted",
encryption: "Encryption",
federatable: "Federatable",
- public: "Public",
+ public: "Visible in room directory",
creator: "Creator",
join_rules: "Join rules",
guest_access: "Guest access",
history_visibility: "History visibility",
+ topic: "Topic",
+ avatar: "Avatar",
},
enums: {
join_rules: {
@@ -172,6 +169,11 @@ export default {
},
unencrypted: "Unencrypted",
},
+ erase: {
+ 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!",
+ },
},
reports: {
name: "Reported event |||| Reported events",
@@ -289,5 +291,22 @@ export default {
media_length: "Media length",
},
},
+ room_directory: {
+ name: "Room directory",
+ fields: {
+ world_readable: "guest users may view without joining",
+ guest_can_join: "guest users may join",
+ },
+ action: {
+ title:
+ "Delete room from directory |||| Delete %{smart_count} rooms from directory",
+ content:
+ "Are you sure you want to remove this room from directory? |||| Are you sure you want to remove these %{smart_count} rooms from directory",
+ erase: "Delete from room directory",
+ create: "Publish in room directory",
+ send_success: "Room successfully published.",
+ send_failure: "An error has occurred.",
+ },
+ },
},
};
diff --git a/src/synapse/dataProvider.js b/src/synapse/dataProvider.js
index 2dae5dc..245852c 100644
--- a/src/synapse/dataProvider.js
+++ b/src/synapse/dataProvider.js
@@ -195,6 +195,30 @@ const resourceMap = {
return json.total;
},
},
+ room_directory: {
+ path: "/_matrix/client/r0/publicRooms",
+ map: rd => ({
+ ...rd,
+ id: rd.room_id,
+ public: !!rd.public,
+ guest_access: !!rd.guest_access,
+ avatar_src: mxcUrlToHttp(rd.avatar_url),
+ }),
+ data: "chunk",
+ total: json => {
+ return json.total_room_count_estimate;
+ },
+ create: params => ({
+ endpoint: `/_matrix/client/r0/directory/list/room/${params.id}`,
+ body: { visibility: "public" },
+ method: "PUT",
+ }),
+ delete: params => ({
+ endpoint: `/_matrix/client/r0/directory/list/room/${params.id}`,
+ body: { visibility: "private" },
+ method: "PUT",
+ }),
+ },
};
function filterNullValues(key, value) {