diff --git a/README.md b/README.md index 26ddd69..dac34b1 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This project is built using [react-admin](https://marmelab.com/react-admin/). -It needs at least Synapse v1.49.0 for all functions to work as expected! +It needs at least Synapse v1.52.0 for all functions to work as expected! You get your server version with the request `/_synapse/admin/v1/server_version`. See also [Synapse version API](https://matrix-org.github.io/synapse/develop/admin_api/version_api.html). diff --git a/src/App.js b/src/App.js index 773291a..83071db 100644 --- a/src/App.js +++ b/src/App.js @@ -83,6 +83,7 @@ const App = () => ( + ); diff --git a/src/components/destinations.js b/src/components/destinations.js index ec926b9..542b89b 100644 --- a/src/components/destinations.js +++ b/src/components/destinations.js @@ -1,15 +1,28 @@ import React from "react"; import { + Button, Datagrid, DateField, Filter, List, Pagination, + ReferenceField, + ReferenceManyField, SearchInput, - SimpleShowLayout, Show, + Tab, + TabbedShowLayout, TextField, + TopToolbar, + useRecordContext, + useDelete, + useNotify, + useRefresh, + useTranslate, } from "react-admin"; +import AutorenewIcon from "@material-ui/icons/Autorenew"; +import FolderSharedIcon from "@material-ui/icons/FolderShared"; +import ViewListIcon from "@material-ui/icons/ViewList"; const DestinationPagination = props => ( @@ -36,6 +49,62 @@ const DestinationFilter = ({ ...props }) => { ); }; +export const DestinationReconnectButton = props => { + const record = useRecordContext(); + const refresh = useRefresh(); + const notify = useNotify(); + const [handleReconnect, { isLoading }] = useDelete("destinations"); + + // Reconnect is not required if no error has occurred. (`failure_ts`) + if (!record || !record.failure_ts) return null; + + const handleClick = e => { + // Prevents redirection to the detail page when clicking in the list + e.stopPropagation(); + + handleReconnect( + { payload: { id: record.id } }, + { + onSuccess: () => { + notify("ra.notification.updated", { + messageArgs: { smart_count: 1 }, + }); + refresh(); + }, + onFailure: () => { + notify("ra.message.error", { type: "error" }); + }, + } + ); + }; + + return ( + + ); +}; + +const DestinationShowActions = props => ( + + + +); + +const DestinationTitle = props => { + const record = useRecordContext(); + const translate = useTranslate(); + return ( + + {translate("resources.destinations.name", 1)} {record.destination} + + ); +}; + export const DestinationList = props => { return ( { sort={{ field: "destination", order: "ASC" }} bulkActionButtons={false} > - + `${basePath}/${id}/show/rooms`} + > + ); }; export const DestinationShow = props => { + const translate = useTranslate(); return ( - - - - - - - - + } + title={} + {...props} + > + + }> + + + + + + + + } + path="rooms" + > + } + perPage={50} + > + `/rooms/${id}/show`} + > + + + + + + + + + ); }; diff --git a/src/i18n/de.js b/src/i18n/de.js index 67a6b09..0fb653b 100644 --- a/src/i18n/de.js +++ b/src/i18n/de.js @@ -360,7 +360,9 @@ const de = { retry_last_ts: "Letzter Wiederholungsversuch", retry_interval: "Wiederholungsintervall", last_successful_stream_ordering: "letzte erfogreicher Stream", + stream_ordering: "Stream", }, + action: { reconnect: "Neu verbinden" }, }, }, ra: { diff --git a/src/i18n/en.js b/src/i18n/en.js index dfabda6..07c60ad 100644 --- a/src/i18n/en.js +++ b/src/i18n/en.js @@ -356,7 +356,9 @@ const en = { retry_last_ts: "Last retry timestamp", retry_interval: "Retry interval", last_successful_stream_ordering: "Last successful stream", + stream_ordering: "Stream", }, + action: { reconnect: "Reconnect" }, }, }, }; diff --git a/src/synapse/dataProvider.js b/src/synapse/dataProvider.js index 0200f9f..fe8abba 100644 --- a/src/synapse/dataProvider.js +++ b/src/synapse/dataProvider.js @@ -285,6 +285,23 @@ const resourceMap = { total: json => { return json.total; }, + delete: params => ({ + endpoint: `/_synapse/admin/v1/federation/destinations/${params.id}/reset_connection`, + method: "POST", + }), + }, + destination_rooms: { + map: dstroom => ({ + ...dstroom, + id: dstroom.room_id, + }), + reference: id => ({ + endpoint: `/_synapse/admin/v1/federation/destinations/${id}/rooms`, + }), + data: "rooms", + total: json => { + return json.total; + }, }, };