Merge branch 'master' into french-translation
This commit is contained in:
commit
ccf53288ce
20
.github/dependabot.yml
vendored
Normal file
20
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
ignore:
|
||||
# Major updates for react-admin have breaking changes
|
||||
- dependency-name: "react-admin"
|
||||
update-types: ["version-update:semver-major"]
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
6
.github/workflows/build-test.yml
vendored
6
.github/workflows/build-test.yml
vendored
@ -10,11 +10,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 16
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
- name: Run tests
|
||||
|
10
.github/workflows/docker-release.yml
vendored
10
.github/workflows/docker-release.yml
vendored
@ -17,13 +17,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@ -43,7 +43,7 @@ jobs:
|
||||
esac
|
||||
echo "::set-output name=tag::$tag"
|
||||
- name: Build and Push Tag
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
8
.github/workflows/edge_ghpage.yml
vendored
8
.github/workflows/edge_ghpage.yml
vendored
@ -10,17 +10,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout 🛎️
|
||||
uses: actions/checkout@v2.3.1
|
||||
- uses: actions/setup-node@v2
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
- name: Install and Build 🔧
|
||||
run: |
|
||||
yarn install
|
||||
yarn build
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.5
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: build
|
||||
|
8
.github/workflows/github-release.yml
vendored
8
.github/workflows/github-release.yml
vendored
@ -13,10 +13,10 @@ jobs:
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
- run: yarn install
|
||||
- run: yarn build
|
||||
- run: |
|
||||
@ -24,7 +24,7 @@ jobs:
|
||||
mkdir -p dist
|
||||
cp -r build synapse-admin-$version
|
||||
tar chvzf dist/synapse-admin-$version.tar.gz synapse-admin-$version
|
||||
- uses: softprops/action-gh-release@b7e450da2a4b4cb4bfbae528f788167786cfcedf
|
||||
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844
|
||||
with:
|
||||
files: dist/*.tar.gz
|
||||
env:
|
||||
|
@ -6,6 +6,6 @@
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"bracketSameLine": false,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
dist: focal
|
||||
language: node_js
|
||||
node_js:
|
||||
- lts/*
|
||||
- 17
|
||||
|
||||
cache: yarn
|
||||
|
12
README.md
12
README.md
@ -1,5 +1,9 @@
|
||||
[](https://travis-ci.org/Awesome-Technologies/synapse-admin)
|
||||
[](https://github.com/Awesome-Technologies/synapse-admin/blob/master/LICENSE)
|
||||
[](https://app.travis-ci.com/github/Awesome-Technologies/synapse-admin)
|
||||
[](https://github.com/Awesome-Technologies/synapse-admin/actions/workflows/build-test.yml)
|
||||
[](https://awesome-technologies.github.io/synapse-admin/)
|
||||
[](https://hub.docker.com/r/awesometechnologies/synapse-admin)
|
||||
[](https://github.com/Awesome-Technologies/synapse-admin/releases)
|
||||
|
||||
# Synapse admin ui
|
||||
|
||||
@ -9,7 +13,7 @@ This project is built using [react-admin](https://marmelab.com/react-admin/).
|
||||
|
||||
### Supported Synapse
|
||||
|
||||
It needs at least [Synapse](https://github.com/matrix-org/synapse) v1.42.0 for all functions to work as expected!
|
||||
It needs at least [Synapse](https://github.com/matrix-org/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).
|
||||
@ -82,8 +86,8 @@ or by editing it in the [.env](.env) file. See also the
|
||||
context: https://github.com/Awesome-Technologies/synapse-admin.git
|
||||
# args:
|
||||
# - NODE_OPTIONS="--max_old_space_size=1024"
|
||||
# # see #266
|
||||
# - PUBLIC_URL="/synapse-admin"
|
||||
# # see #266, PUBLIC_URL must be without surrounding quotation marks
|
||||
# - PUBLIC_URL=/synapse-admin
|
||||
# - REACT_APP_SERVER="https://matrix.example.com"
|
||||
ports:
|
||||
- "8080:80"
|
||||
|
@ -12,10 +12,15 @@ services:
|
||||
# replace the context definition with this:
|
||||
# context: https://github.com/Awesome-Technologies/synapse-admin.git
|
||||
|
||||
# args:
|
||||
# if you're building on an architecture other than amd64, make sure
|
||||
# to define a maximum ram for node. otherwise the build will fail.
|
||||
# args:
|
||||
# - NODE_OPTIONS="--max_old_space_size=1024"
|
||||
# default is /
|
||||
# - PUBLIC_URL=/synapse-admin
|
||||
# You can use a fixed homeserver, so that the user can no longer
|
||||
# define it himself
|
||||
# - REACT_APP_SERVER="https://matrix.example.com"
|
||||
ports:
|
||||
- "8080:80"
|
||||
restart: unless-stopped
|
||||
|
15
package.json
15
package.json
@ -10,17 +10,22 @@
|
||||
"url": "https://github.com/Awesome-Technologies/synapse-admin"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^5.1.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^11.2.6",
|
||||
"@testing-library/user-event": "^13.1.8",
|
||||
"eslint": "^7.25.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"prettier": "^2.2.0",
|
||||
"ra-test": "^3.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.7.1",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@mui/icons-material": "^5.3.1",
|
||||
"@mui/material": "^5.4.0",
|
||||
"papaparse": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"ra-language-chinese": "^2.0.10",
|
||||
@ -29,7 +34,7 @@
|
||||
"react": "^17.0.0",
|
||||
"react-admin": "^3.19.7",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "^4.0.0"
|
||||
"react-scripts": "^5.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "REACT_APP_VERSION=$(git describe --tags) react-scripts start",
|
||||
|
21
src/App.js
21
src/App.js
@ -7,13 +7,15 @@ import { UserList, UserCreate, UserEdit } from "./components/users";
|
||||
import { RoomList, RoomShow } from "./components/rooms";
|
||||
import { ReportList, ReportShow } from "./components/EventReports";
|
||||
import LoginPage from "./components/LoginPage";
|
||||
import UserIcon from "@material-ui/icons/Group";
|
||||
import ConfirmationNumberIcon from "@material-ui/icons/ConfirmationNumber";
|
||||
import EqualizerIcon from "@material-ui/icons/Equalizer";
|
||||
import ConfirmationNumberIcon from "@mui/icons-material/ConfirmationNumber";
|
||||
import CloudQueueIcon from "@mui/icons-material/CloudQueue";
|
||||
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
||||
import UserIcon from "@mui/icons-material/Group";
|
||||
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 RoomIcon from "@mui/icons-material/ViewList";
|
||||
import ReportIcon from "@mui/icons-material/Warning";
|
||||
import FolderSharedIcon from "@mui/icons-material/FolderShared";
|
||||
import { DestinationList, DestinationShow } from "./components/destinations";
|
||||
import { ImportFeature } from "./components/ImportFeature";
|
||||
import {
|
||||
RegistrationTokenCreate,
|
||||
@ -74,6 +76,12 @@ const App = () => (
|
||||
list={RoomDirectoryList}
|
||||
icon={FolderSharedIcon}
|
||||
/>
|
||||
<Resource
|
||||
name="destinations"
|
||||
list={DestinationList}
|
||||
show={DestinationShow}
|
||||
icon={CloudQueueIcon}
|
||||
/>
|
||||
<Resource
|
||||
name="registration_tokens"
|
||||
list={RegistrationTokenList}
|
||||
@ -90,6 +98,7 @@ const App = () => (
|
||||
<Resource name="servernotices" />
|
||||
<Resource name="forward_extremities" />
|
||||
<Resource name="room_state" />
|
||||
<Resource name="destination_rooms" />
|
||||
</Admin>
|
||||
);
|
||||
|
||||
|
@ -12,8 +12,8 @@ import {
|
||||
TextField,
|
||||
useTranslate,
|
||||
} from "react-admin";
|
||||
import PageviewIcon from "@material-ui/icons/Pageview";
|
||||
import ViewListIcon from "@material-ui/icons/ViewList";
|
||||
import PageviewIcon from "@mui/icons-material/Pageview";
|
||||
import ViewListIcon from "@mui/icons-material/ViewList";
|
||||
|
||||
const date_format = {
|
||||
year: "numeric",
|
||||
|
@ -6,19 +6,19 @@ import {
|
||||
Title,
|
||||
} from "react-admin";
|
||||
import { parse as parseCsv, unparse as unparseCsv } from "papaparse";
|
||||
import GetAppIcon from "@material-ui/icons/GetApp";
|
||||
import GetAppIcon from "@mui/icons-material/GetApp";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
Container,
|
||||
FormControlLabel,
|
||||
NativeSelect,
|
||||
} from "@material-ui/core";
|
||||
} from "@mui/material";
|
||||
import { useTranslate } from "ra-core";
|
||||
import Container from "@material-ui/core/Container/Container";
|
||||
import { generateRandomUser } from "./users";
|
||||
|
||||
const LOGGING = true;
|
||||
|
@ -21,9 +21,9 @@ import {
|
||||
MenuItem,
|
||||
Select,
|
||||
TextField,
|
||||
} from "@material-ui/core";
|
||||
} from "@mui/material";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import LockIcon from "@material-ui/icons/Lock";
|
||||
import LockIcon from "@mui/icons-material/Lock";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
main: {
|
||||
@ -169,7 +169,7 @@ const LoginPage = ({ theme }) => {
|
||||
: typeof error === "undefined" || !error.message
|
||||
? "ra.auth.sign_in_error"
|
||||
: error.message,
|
||||
"warning"
|
||||
{ type: "warning" }
|
||||
);
|
||||
});
|
||||
};
|
||||
@ -269,7 +269,7 @@ const LoginPage = ({ theme }) => {
|
||||
autoFocus
|
||||
name="username"
|
||||
component={renderInput}
|
||||
label={translate("ra.auth.username")}
|
||||
label="ra.auth.username"
|
||||
disabled={loading || !supportPassAuth}
|
||||
onBlur={handleUsernameChange}
|
||||
resettable
|
||||
@ -280,7 +280,7 @@ const LoginPage = ({ theme }) => {
|
||||
<PasswordInput
|
||||
name="password"
|
||||
component={renderInput}
|
||||
label={translate("ra.auth.password")}
|
||||
label="ra.auth.password"
|
||||
type="password"
|
||||
disabled={loading || !supportPassAuth}
|
||||
resettable
|
||||
@ -291,7 +291,7 @@ const LoginPage = ({ theme }) => {
|
||||
<TextInput
|
||||
name="base_url"
|
||||
component={renderInput}
|
||||
label={translate("synapseadmin.auth.base_url")}
|
||||
label="synapseadmin.auth.base_url"
|
||||
disabled={cfg_base_url || loading}
|
||||
resettable
|
||||
fullWidth
|
||||
|
@ -1,10 +1,10 @@
|
||||
// in src/Menu.js
|
||||
import * as React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useMediaQuery } from "@material-ui/core";
|
||||
import { useMediaQuery } from "@mui/material";
|
||||
import { MenuItemLink, getResources } from "react-admin";
|
||||
import DefaultIcon from "@material-ui/icons/ViewList";
|
||||
import LabelIcon from "@material-ui/icons/Label";
|
||||
import DefaultIcon from "@mui/icons-material/ViewList";
|
||||
import LabelIcon from "@mui/icons-material/Label";
|
||||
|
||||
const Menu = ({ onMenuClick, logout }) => {
|
||||
const isXSmall = useMediaQuery(theme => theme.breakpoints.down("xs"));
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React, { Fragment } from "react";
|
||||
import Avatar from "@material-ui/core/Avatar";
|
||||
import { Chip } from "@material-ui/core";
|
||||
import { Avatar, Chip } from "@mui/material";
|
||||
import { connect } from "react-redux";
|
||||
import FolderSharedIcon from "@material-ui/icons/FolderShared";
|
||||
import FolderSharedIcon from "@mui/icons-material/FolderShared";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import {
|
||||
BooleanField,
|
||||
@ -19,6 +18,7 @@ import {
|
||||
useMutation,
|
||||
useNotify,
|
||||
useTranslate,
|
||||
useRecordContext,
|
||||
useRefresh,
|
||||
useUnselectAll,
|
||||
} from "react-admin";
|
||||
@ -87,7 +87,9 @@ export const RoomDirectoryBulkSaveButton = ({ selectedIds }) => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: error =>
|
||||
notify("resources.room_directory.action.send_failure", "error"),
|
||||
notify("resources.room_directory.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -103,7 +105,8 @@ export const RoomDirectoryBulkSaveButton = ({ selectedIds }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const RoomDirectorySaveButton = ({ record }) => {
|
||||
export const RoomDirectorySaveButton = props => {
|
||||
const record = useRecordContext();
|
||||
const notify = useNotify();
|
||||
const refresh = useRefresh();
|
||||
const [create, { loading }] = useCreate("room_directory");
|
||||
@ -119,7 +122,9 @@ export const RoomDirectorySaveButton = ({ record }) => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: error =>
|
||||
notify("resources.room_directory.action.send_failure", "error"),
|
||||
notify("resources.room_directory.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -177,7 +182,6 @@ export const FilterableRoomDirectoryList = ({
|
||||
...props
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const translate = useTranslate();
|
||||
const filter = roomDirectoryFilters;
|
||||
const roomIdFilter = filter && filter.room_id ? true : false;
|
||||
const topicFilter = filter && filter.topic ? true : false;
|
||||
@ -196,48 +200,48 @@ export const FilterableRoomDirectoryList = ({
|
||||
source="avatar_src"
|
||||
sortable={false}
|
||||
className={classes.small}
|
||||
label={translate("resources.rooms.fields.avatar")}
|
||||
label="resources.rooms.fields.avatar"
|
||||
/>
|
||||
<TextField
|
||||
source="name"
|
||||
sortable={false}
|
||||
label={translate("resources.rooms.fields.name")}
|
||||
label="resources.rooms.fields.name"
|
||||
/>
|
||||
{roomIdFilter && (
|
||||
<TextField
|
||||
source="room_id"
|
||||
sortable={false}
|
||||
label={translate("resources.rooms.fields.room_id")}
|
||||
label="resources.rooms.fields.room_id"
|
||||
/>
|
||||
)}
|
||||
{canonicalAliasFilter && (
|
||||
<TextField
|
||||
source="canonical_alias"
|
||||
sortable={false}
|
||||
label={translate("resources.rooms.fields.canonical_alias")}
|
||||
label="resources.rooms.fields.canonical_alias"
|
||||
/>
|
||||
)}
|
||||
{topicFilter && (
|
||||
<TextField
|
||||
source="topic"
|
||||
sortable={false}
|
||||
label={translate("resources.rooms.fields.topic")}
|
||||
label="resources.rooms.fields.topic"
|
||||
/>
|
||||
)}
|
||||
<NumberField
|
||||
source="num_joined_members"
|
||||
sortable={false}
|
||||
label={translate("resources.rooms.fields.joined_members")}
|
||||
label="resources.rooms.fields.joined_members"
|
||||
/>
|
||||
<BooleanField
|
||||
source="world_readable"
|
||||
sortable={false}
|
||||
label={translate("resources.room_directory.fields.world_readable")}
|
||||
label="resources.room_directory.fields.world_readable"
|
||||
/>
|
||||
<BooleanField
|
||||
source="guest_can_join"
|
||||
sortable={false}
|
||||
label={translate("resources.room_directory.fields.guest_can_join")}
|
||||
label="resources.room_directory.fields.guest_can_join"
|
||||
/>
|
||||
</Datagrid>
|
||||
</List>
|
||||
|
@ -9,15 +9,18 @@ import {
|
||||
useCreate,
|
||||
useMutation,
|
||||
useNotify,
|
||||
useRecordContext,
|
||||
useTranslate,
|
||||
useUnselectAll,
|
||||
} from "react-admin";
|
||||
import MessageIcon from "@material-ui/icons/Message";
|
||||
import IconCancel from "@material-ui/icons/Cancel";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import MessageIcon from "@mui/icons-material/Message";
|
||||
import IconCancel from "@mui/icons-material/Cancel";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
} from "@mui/material";
|
||||
|
||||
const ServerNoticeDialog = ({ open, loading, onClose, onSend }) => {
|
||||
const translate = useTranslate();
|
||||
@ -64,7 +67,8 @@ const ServerNoticeDialog = ({ open, loading, onClose, onSend }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const ServerNoticeButton = ({ record }) => {
|
||||
export const ServerNoticeButton = props => {
|
||||
const record = useRecordContext();
|
||||
const [open, setOpen] = useState(false);
|
||||
const notify = useNotify();
|
||||
const [create, { loading }] = useCreate("servernotices");
|
||||
@ -81,7 +85,9 @@ export const ServerNoticeButton = ({ record }) => {
|
||||
handleDialogClose();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.servernotices.action.send_failure", "error"),
|
||||
notify("resources.servernotices.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -127,7 +133,9 @@ export const ServerNoticeBulkButton = ({ selectedIds }) => {
|
||||
handleDialogClose();
|
||||
},
|
||||
onFailure: error =>
|
||||
notify("resources.servernotices.action.send_failure", "error"),
|
||||
notify("resources.servernotices.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
185
src/components/destinations.js
Normal file
185
src/components/destinations.js
Normal file
@ -0,0 +1,185 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Button,
|
||||
Datagrid,
|
||||
DateField,
|
||||
Filter,
|
||||
List,
|
||||
Pagination,
|
||||
ReferenceField,
|
||||
ReferenceManyField,
|
||||
SearchInput,
|
||||
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 => (
|
||||
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
|
||||
);
|
||||
|
||||
const date_format = {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
};
|
||||
|
||||
const destinationRowStyle = (record, index) => ({
|
||||
backgroundColor: record.retry_last_ts > 0 ? "#ffcccc" : "white",
|
||||
});
|
||||
|
||||
const DestinationFilter = ({ ...props }) => {
|
||||
return (
|
||||
<Filter {...props}>
|
||||
<SearchInput source="destination" alwaysOn />
|
||||
</Filter>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<Button
|
||||
label="resources.destinations.action.reconnect"
|
||||
onClick={handleClick}
|
||||
disabled={isLoading}
|
||||
>
|
||||
<AutorenewIcon />
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
const DestinationShowActions = props => (
|
||||
<TopToolbar>
|
||||
<DestinationReconnectButton />
|
||||
</TopToolbar>
|
||||
);
|
||||
|
||||
const DestinationTitle = props => {
|
||||
const record = useRecordContext();
|
||||
const translate = useTranslate();
|
||||
return (
|
||||
<span>
|
||||
{translate("resources.destinations.name", 1)} {record.destination}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const DestinationList = props => {
|
||||
return (
|
||||
<List
|
||||
{...props}
|
||||
filters={<DestinationFilter />}
|
||||
pagination={<DestinationPagination />}
|
||||
sort={{ field: "destination", order: "ASC" }}
|
||||
bulkActionButtons={false}
|
||||
>
|
||||
<Datagrid
|
||||
rowStyle={destinationRowStyle}
|
||||
rowClick={(id, basePath, record) => `${basePath}/${id}/show/rooms`}
|
||||
>
|
||||
<TextField source="destination" />
|
||||
<DateField source="failure_ts" showTime options={date_format} />
|
||||
<DateField source="retry_last_ts" showTime options={date_format} />
|
||||
<TextField source="retry_interval" />
|
||||
<TextField source="last_successful_stream_ordering" />
|
||||
<DestinationReconnectButton />
|
||||
</Datagrid>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
export const DestinationShow = props => {
|
||||
const translate = useTranslate();
|
||||
return (
|
||||
<Show
|
||||
actions={<DestinationShowActions />}
|
||||
title={<DestinationTitle />}
|
||||
{...props}
|
||||
>
|
||||
<TabbedShowLayout>
|
||||
<Tab label="status" icon={<ViewListIcon />}>
|
||||
<TextField source="destination" />
|
||||
<DateField source="failure_ts" showTime options={date_format} />
|
||||
<DateField source="retry_last_ts" showTime options={date_format} />
|
||||
<TextField source="retry_interval" />
|
||||
<TextField source="last_successful_stream_ordering" />
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
label={translate("resources.rooms.name", { smart_count: 2 })}
|
||||
icon={<FolderSharedIcon />}
|
||||
path="rooms"
|
||||
>
|
||||
<ReferenceManyField
|
||||
reference="destination_rooms"
|
||||
target="destination"
|
||||
addLabel={false}
|
||||
pagination={<DestinationPagination />}
|
||||
perPage={50}
|
||||
>
|
||||
<Datagrid
|
||||
style={{ width: "100%" }}
|
||||
rowClick={(id, basePath, record) => `/rooms/${id}/show`}
|
||||
>
|
||||
<TextField
|
||||
source="room_id"
|
||||
label="resources.rooms.fields.room_id"
|
||||
/>
|
||||
<TextField source="stream_ordering" sortable={false} />
|
||||
<ReferenceField
|
||||
label="resources.rooms.fields.name"
|
||||
source="id"
|
||||
reference="rooms"
|
||||
sortable={false}
|
||||
link=""
|
||||
>
|
||||
<TextField source="name" sortable={false} />
|
||||
</ReferenceField>
|
||||
</Datagrid>
|
||||
</ReferenceManyField>
|
||||
</Tab>
|
||||
</TabbedShowLayout>
|
||||
</Show>
|
||||
);
|
||||
};
|
@ -1,14 +1,15 @@
|
||||
import React, { Fragment, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
useMutation,
|
||||
useDelete,
|
||||
useNotify,
|
||||
Confirm,
|
||||
useRecordContext,
|
||||
useRefresh,
|
||||
} from "react-admin";
|
||||
import ActionDelete from "@material-ui/icons/Delete";
|
||||
import ActionDelete from "@mui/icons-material/Delete";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import { alpha } from "@material-ui/core/styles/colorManipulator";
|
||||
import { alpha } from "@mui/material/styles";
|
||||
import classnames from "classnames";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
@ -28,13 +29,13 @@ const useStyles = makeStyles(
|
||||
);
|
||||
|
||||
export const DeviceRemoveButton = props => {
|
||||
const { record } = props;
|
||||
const record = useRecordContext();
|
||||
const classes = useStyles(props);
|
||||
const [open, setOpen] = useState(false);
|
||||
const refresh = useRefresh();
|
||||
const notify = useNotify();
|
||||
|
||||
const [removeDevice, { loading }] = useMutation();
|
||||
const [removeDevice, { isLoading }] = useDelete("devices");
|
||||
|
||||
if (!record) return null;
|
||||
|
||||
@ -43,21 +44,15 @@ export const DeviceRemoveButton = props => {
|
||||
|
||||
const handleConfirm = () => {
|
||||
removeDevice(
|
||||
{
|
||||
type: "delete",
|
||||
resource: "devices",
|
||||
payload: {
|
||||
id: record.id,
|
||||
user_id: record.user_id,
|
||||
},
|
||||
},
|
||||
{ payload: { id: record.id, user_id: record.user_id } },
|
||||
{
|
||||
onSuccess: () => {
|
||||
notify("resources.devices.action.erase.success");
|
||||
refresh();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.devices.action.erase.failure", "error"),
|
||||
onFailure: () => {
|
||||
notify("resources.devices.action.erase.failure", { type: "error" });
|
||||
},
|
||||
}
|
||||
);
|
||||
setOpen(false);
|
||||
@ -74,7 +69,7 @@ export const DeviceRemoveButton = props => {
|
||||
</Button>
|
||||
<Confirm
|
||||
isOpen={open}
|
||||
loading={loading}
|
||||
loading={isLoading}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleDialogClose}
|
||||
title="resources.devices.action.erase.title"
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React, { Fragment, useState } from "react";
|
||||
import classnames from "classnames";
|
||||
import { alpha } from "@material-ui/core/styles/colorManipulator";
|
||||
import { alpha } from "@mui/material/styles";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import { Tooltip } from "@material-ui/core";
|
||||
import {
|
||||
BooleanInput,
|
||||
Button,
|
||||
@ -14,19 +13,23 @@ import {
|
||||
useCreate,
|
||||
useDelete,
|
||||
useNotify,
|
||||
useRecordContext,
|
||||
useRefresh,
|
||||
useTranslate,
|
||||
} from "react-admin";
|
||||
import BlockIcon from "@material-ui/icons/Block";
|
||||
import ClearIcon from "@material-ui/icons/Clear";
|
||||
import DeleteSweepIcon from "@material-ui/icons/DeleteSweep";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import IconCancel from "@material-ui/icons/Cancel";
|
||||
import LockIcon from "@material-ui/icons/Lock";
|
||||
import LockOpenIcon from "@material-ui/icons/LockOpen";
|
||||
import BlockIcon from "@mui/icons-material/Block";
|
||||
import ClearIcon from "@mui/icons-material/Clear";
|
||||
import DeleteSweepIcon from "@mui/icons-material/DeleteSweep";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import IconCancel from "@mui/icons-material/Cancel";
|
||||
import LockIcon from "@mui/icons-material/Lock";
|
||||
import LockOpenIcon from "@mui/icons-material/LockOpen";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
@ -127,7 +130,9 @@ export const DeleteMediaButton = props => {
|
||||
handleDialogClose();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.delete_media.action.send_failure", "error"),
|
||||
notify("resources.delete_media.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -152,7 +157,7 @@ export const DeleteMediaButton = props => {
|
||||
};
|
||||
|
||||
export const ProtectMediaButton = props => {
|
||||
const { record } = props;
|
||||
const record = useRecordContext();
|
||||
const translate = useTranslate();
|
||||
const refresh = useRefresh();
|
||||
const notify = useNotify();
|
||||
@ -170,7 +175,9 @@ export const ProtectMediaButton = props => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.protect_media.action.send_failure", "error"),
|
||||
notify("resources.protect_media.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -184,7 +191,9 @@ export const ProtectMediaButton = props => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.protect_media.action.send_failure", "error"),
|
||||
notify("resources.protect_media.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -244,7 +253,7 @@ export const ProtectMediaButton = props => {
|
||||
};
|
||||
|
||||
export const QuarantineMediaButton = props => {
|
||||
const { record } = props;
|
||||
const record = useRecordContext();
|
||||
const translate = useTranslate();
|
||||
const refresh = useRefresh();
|
||||
const notify = useNotify();
|
||||
@ -262,7 +271,9 @@ export const QuarantineMediaButton = props => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.quarantine_media.action.send_failure", "error"),
|
||||
notify("resources.quarantine_media.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -276,7 +287,9 @@ export const QuarantineMediaButton = props => {
|
||||
refresh();
|
||||
},
|
||||
onFailure: () =>
|
||||
notify("resources.quarantine_media.action.send_failure", "error"),
|
||||
notify("resources.quarantine_media.action.send_failure", {
|
||||
type: "error",
|
||||
}),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -25,15 +25,15 @@ import {
|
||||
import get from "lodash/get";
|
||||
import PropTypes from "prop-types";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import { Tooltip, Typography, Chip } from "@material-ui/core";
|
||||
import FastForwardIcon from "@material-ui/icons/FastForward";
|
||||
import HttpsIcon from "@material-ui/icons/Https";
|
||||
import NoEncryptionIcon from "@material-ui/icons/NoEncryption";
|
||||
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 EventIcon from "@material-ui/icons/Event";
|
||||
import { Tooltip, Typography, Chip } from "@mui/material";
|
||||
import FastForwardIcon from "@mui/icons-material/FastForward";
|
||||
import HttpsIcon from "@mui/icons-material/Https";
|
||||
import NoEncryptionIcon from "@mui/icons-material/NoEncryption";
|
||||
import PageviewIcon from "@mui/icons-material/Pageview";
|
||||
import UserIcon from "@mui/icons-material/Group";
|
||||
import ViewListIcon from "@mui/icons-material/ViewList";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import EventIcon from "@mui/icons-material/Event";
|
||||
import {
|
||||
RoomDirectoryBulkDeleteButton,
|
||||
RoomDirectoryBulkSaveButton,
|
||||
@ -87,7 +87,8 @@ const EncryptionField = ({ source, record = {}, emptyText }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const RoomTitle = ({ record }) => {
|
||||
const RoomTitle = props => {
|
||||
const record = useRecordContext();
|
||||
const translate = useTranslate();
|
||||
var name = "";
|
||||
if (record) {
|
||||
@ -354,7 +355,7 @@ const RoomFilter = ({ ...props }) => {
|
||||
|
||||
const RoomNameField = props => {
|
||||
const { source } = props;
|
||||
const record = useRecordContext(props);
|
||||
const record = useRecordContext();
|
||||
return (
|
||||
<span>{record[source] || record["canonical_alias"] || record["id"]}</span>
|
||||
);
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { cloneElement, Fragment } from "react";
|
||||
import Avatar from "@material-ui/core/Avatar";
|
||||
import AssignmentIndIcon from "@material-ui/icons/AssignmentInd";
|
||||
import ContactMailIcon from "@material-ui/icons/ContactMail";
|
||||
import DevicesIcon from "@material-ui/icons/Devices";
|
||||
import GetAppIcon from "@material-ui/icons/GetApp";
|
||||
import NotificationsIcon from "@material-ui/icons/Notifications";
|
||||
import PermMediaIcon from "@material-ui/icons/PermMedia";
|
||||
import PersonPinIcon from "@material-ui/icons/PersonPin";
|
||||
import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent";
|
||||
import ViewListIcon from "@material-ui/icons/ViewList";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
import AssignmentIndIcon from "@mui/icons-material/AssignmentInd";
|
||||
import ContactMailIcon from "@mui/icons-material/ContactMail";
|
||||
import DevicesIcon from "@mui/icons-material/Devices";
|
||||
import GetAppIcon from "@mui/icons-material/GetApp";
|
||||
import NotificationsIcon from "@mui/icons-material/Notifications";
|
||||
import PermMediaIcon from "@mui/icons-material/PermMedia";
|
||||
import PersonPinIcon from "@mui/icons-material/PersonPin";
|
||||
import SettingsInputComponentIcon from "@mui/icons-material/SettingsInputComponent";
|
||||
import ViewListIcon from "@mui/icons-material/ViewList";
|
||||
import {
|
||||
ArrayInput,
|
||||
ArrayField,
|
||||
@ -39,6 +39,7 @@ import {
|
||||
maxLength,
|
||||
regex,
|
||||
required,
|
||||
useRecordContext,
|
||||
useTranslate,
|
||||
Pagination,
|
||||
CreateButton,
|
||||
@ -71,6 +72,16 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
const choices_medium = [
|
||||
{ id: "email", name: "resources.users.email" },
|
||||
{ id: "msisdn", name: "resources.users.msisdn" },
|
||||
];
|
||||
|
||||
const choices_type = [
|
||||
{ id: "bot", name: "bot" },
|
||||
{ id: "support", name: "support" },
|
||||
];
|
||||
|
||||
const date_format = {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
@ -249,20 +260,31 @@ export function generateRandomUser() {
|
||||
};
|
||||
}
|
||||
|
||||
const UserEditToolbar = props => {
|
||||
const translate = useTranslate();
|
||||
return (
|
||||
const UserEditToolbar = props => (
|
||||
<Toolbar {...props}>
|
||||
<SaveButton submitOnEnter={true} disabled={props.pristine} />
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
const UserEditActions = ({ data }) => {
|
||||
const translate = useTranslate();
|
||||
var userStatus = "";
|
||||
if (data) {
|
||||
userStatus = data.deactivated;
|
||||
}
|
||||
|
||||
return (
|
||||
<TopToolbar>
|
||||
{!userStatus && <ServerNoticeButton record={data} />}
|
||||
<DeleteButton
|
||||
record={data}
|
||||
label="resources.users.action.erase"
|
||||
confirmTitle={translate("resources.users.helper.erase", {
|
||||
smart_count: 1,
|
||||
})}
|
||||
mutationMode="pessimistic"
|
||||
/>
|
||||
<ServerNoticeButton />
|
||||
</Toolbar>
|
||||
</TopToolbar>
|
||||
);
|
||||
};
|
||||
|
||||
@ -276,15 +298,19 @@ export const UserCreate = props => (
|
||||
autoComplete="new-password"
|
||||
validate={maxLength(512)}
|
||||
/>
|
||||
<SelectInput
|
||||
source="user_type"
|
||||
choices={choices_type}
|
||||
translateChoice={false}
|
||||
allowEmpty={true}
|
||||
resettable
|
||||
/>
|
||||
<BooleanInput source="admin" />
|
||||
<ArrayInput source="threepids">
|
||||
<SimpleFormIterator disableReordering>
|
||||
<SelectInput
|
||||
source="medium"
|
||||
choices={[
|
||||
{ id: "email", name: "resources.users.email" },
|
||||
{ id: "msisdn", name: "resources.users.msisdn" },
|
||||
]}
|
||||
choices={choices_medium}
|
||||
validate={required()}
|
||||
/>
|
||||
<TextInput source="address" validate={validateAddress} />
|
||||
@ -304,7 +330,8 @@ export const UserCreate = props => (
|
||||
</Create>
|
||||
);
|
||||
|
||||
const UserTitle = ({ record }) => {
|
||||
const UserTitle = props => {
|
||||
const record = useRecordContext();
|
||||
const translate = useTranslate();
|
||||
return (
|
||||
<span>
|
||||
@ -315,11 +342,12 @@ const UserTitle = ({ record }) => {
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const UserEdit = props => {
|
||||
const classes = useStyles();
|
||||
const translate = useTranslate();
|
||||
return (
|
||||
<Edit {...props} title={<UserTitle />}>
|
||||
<Edit {...props} title={<UserTitle />} actions={<UserEditActions />}>
|
||||
<TabbedForm toolbar={<UserEditToolbar />}>
|
||||
<FormTab
|
||||
label={translate("resources.users.name", { smart_count: 1 })}
|
||||
@ -332,7 +360,18 @@ export const UserEdit = props => {
|
||||
/>
|
||||
<TextInput source="id" disabled />
|
||||
<TextInput source="displayname" />
|
||||
<PasswordInput source="password" autoComplete="new-password" />
|
||||
<PasswordInput
|
||||
source="password"
|
||||
autoComplete="new-password"
|
||||
helperText="resources.users.helper.password"
|
||||
/>
|
||||
<SelectInput
|
||||
source="user_type"
|
||||
choices={choices_type}
|
||||
translateChoice={false}
|
||||
allowEmpty={true}
|
||||
resettable
|
||||
/>
|
||||
<BooleanInput source="admin" />
|
||||
<BooleanInput
|
||||
source="deactivated"
|
||||
@ -349,13 +388,7 @@ export const UserEdit = props => {
|
||||
>
|
||||
<ArrayInput source="threepids">
|
||||
<SimpleFormIterator disableReordering>
|
||||
<SelectInput
|
||||
source="medium"
|
||||
choices={[
|
||||
{ id: "email", name: "resources.users.email" },
|
||||
{ id: "msisdn", name: "resources.users.msisdn" },
|
||||
]}
|
||||
/>
|
||||
<SelectInput source="medium" choices={choices_medium} />
|
||||
<TextInput source="address" />
|
||||
</SimpleFormIterator>
|
||||
</ArrayInput>
|
||||
|
@ -121,8 +121,11 @@ const de = {
|
||||
creation_ts_ms: "Zeitpunkt der Erstellung",
|
||||
consent_version: "Zugestimmte Geschäftsbedingungen",
|
||||
auth_provider: "Provider",
|
||||
user_type: "Benutzertyp",
|
||||
},
|
||||
helper: {
|
||||
password:
|
||||
"Durch die Änderung des Passworts wird der Benutzer von allen Sitzungen abgemeldet.",
|
||||
deactivate:
|
||||
"Sie müssen ein Passwort angeben, um ein Konto wieder zu aktivieren.",
|
||||
erase: "DSGVO konformes Löschen der Benutzerdaten",
|
||||
@ -352,6 +355,18 @@ const de = {
|
||||
send_failure: "Beim Entfernen ist ein Fehler aufgetreten.",
|
||||
},
|
||||
},
|
||||
destinations: {
|
||||
name: "Föderation",
|
||||
fields: {
|
||||
destination: "Ziel",
|
||||
failure_ts: "Fehlerzeitpunkt",
|
||||
retry_last_ts: "Letzter Wiederholungsversuch",
|
||||
retry_interval: "Wiederholungsintervall",
|
||||
last_successful_stream_ordering: "letzte erfogreicher Stream",
|
||||
stream_ordering: "Stream",
|
||||
},
|
||||
action: { reconnect: "Neu verbinden" },
|
||||
},
|
||||
registration_tokens: {
|
||||
name: "Registrierungstoken",
|
||||
fields: {
|
||||
|
@ -120,8 +120,10 @@ const en = {
|
||||
creation_ts_ms: "Creation timestamp",
|
||||
consent_version: "Consent version",
|
||||
auth_provider: "Provider",
|
||||
user_type: "User type",
|
||||
},
|
||||
helper: {
|
||||
password: "Changing password will log user out of all sessions.",
|
||||
deactivate: "You must provide a password to re-activate an account.",
|
||||
erase: "Mark the user as GDPR-erased",
|
||||
},
|
||||
@ -350,6 +352,18 @@ const en = {
|
||||
send_failure: "An error has occurred.",
|
||||
},
|
||||
},
|
||||
destinations: {
|
||||
name: "Federation",
|
||||
fields: {
|
||||
destination: "Destination",
|
||||
failure_ts: "Failure timestamp",
|
||||
retry_last_ts: "Last retry timestamp",
|
||||
retry_interval: "Retry interval",
|
||||
last_successful_stream_ordering: "Last successful stream",
|
||||
stream_ordering: "Stream",
|
||||
},
|
||||
action: { reconnect: "Reconnect" },
|
||||
},
|
||||
},
|
||||
registration_tokens: {
|
||||
name: "Registration tokens",
|
||||
|
@ -41,14 +41,16 @@ const resourceMap = {
|
||||
data: "users",
|
||||
total: json => json.total,
|
||||
create: data => ({
|
||||
endpoint: `/_synapse/admin/v2/users/@${data.id}:${localStorage.getItem(
|
||||
"home_server"
|
||||
)}`,
|
||||
endpoint: `/_synapse/admin/v2/users/@${encodeURIComponent(
|
||||
data.id
|
||||
)}:${localStorage.getItem("home_server")}`,
|
||||
body: data,
|
||||
method: "PUT",
|
||||
}),
|
||||
delete: params => ({
|
||||
endpoint: `/_synapse/admin/v1/deactivate/${params.id}`,
|
||||
endpoint: `/_synapse/admin/v1/deactivate/${encodeURIComponent(
|
||||
params.id
|
||||
)}`,
|
||||
body: { erase: true },
|
||||
method: "POST",
|
||||
}),
|
||||
@ -69,7 +71,7 @@ const resourceMap = {
|
||||
return json.total_rooms;
|
||||
},
|
||||
delete: params => ({
|
||||
endpoint: `/_synapse/admin/v1/rooms/${params.id}`,
|
||||
endpoint: `/_synapse/admin/v2/rooms/${params.id}`,
|
||||
body: { block: false },
|
||||
}),
|
||||
},
|
||||
@ -92,10 +94,12 @@ const resourceMap = {
|
||||
return json.total;
|
||||
},
|
||||
reference: id => ({
|
||||
endpoint: `/_synapse/admin/v2/users/${id}/devices`,
|
||||
endpoint: `/_synapse/admin/v2/users/${encodeURIComponent(id)}/devices`,
|
||||
}),
|
||||
delete: params => ({
|
||||
endpoint: `/_synapse/admin/v2/users/${params.user_id}/devices/${params.id}`,
|
||||
endpoint: `/_synapse/admin/v2/users/${encodeURIComponent(
|
||||
params.user_id
|
||||
)}/devices/${params.id}`,
|
||||
}),
|
||||
},
|
||||
connections: {
|
||||
@ -137,7 +141,7 @@ const resourceMap = {
|
||||
id: p.pushkey,
|
||||
}),
|
||||
reference: id => ({
|
||||
endpoint: `/_synapse/admin/v1/users/${id}/pushers`,
|
||||
endpoint: `/_synapse/admin/v1/users/${encodeURIComponent(id)}/pushers`,
|
||||
}),
|
||||
data: "pushers",
|
||||
total: json => {
|
||||
@ -149,7 +153,9 @@ const resourceMap = {
|
||||
id: jr,
|
||||
}),
|
||||
reference: id => ({
|
||||
endpoint: `/_synapse/admin/v1/users/${id}/joined_rooms`,
|
||||
endpoint: `/_synapse/admin/v1/users/${encodeURIComponent(
|
||||
id
|
||||
)}/joined_rooms`,
|
||||
}),
|
||||
data: "joined_rooms",
|
||||
total: json => {
|
||||
@ -162,7 +168,7 @@ const resourceMap = {
|
||||
id: um.media_id,
|
||||
}),
|
||||
reference: id => ({
|
||||
endpoint: `/_synapse/admin/v1/users/${id}/media`,
|
||||
endpoint: `/_synapse/admin/v1/users/${encodeURIComponent(id)}/media`,
|
||||
}),
|
||||
data: "media",
|
||||
total: json => {
|
||||
@ -275,6 +281,34 @@ const resourceMap = {
|
||||
method: "PUT",
|
||||
}),
|
||||
},
|
||||
destinations: {
|
||||
path: "/_synapse/admin/v1/federation/destinations",
|
||||
map: dst => ({
|
||||
...dst,
|
||||
id: dst.destination,
|
||||
}),
|
||||
data: "destinations",
|
||||
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;
|
||||
},
|
||||
},
|
||||
registration_tokens: {
|
||||
path: "/_synapse/admin/v1/registration_tokens",
|
||||
map: rt => ({
|
||||
@ -298,7 +332,8 @@ const resourceMap = {
|
||||
|
||||
function filterNullValues(key, value) {
|
||||
// Filtering out null properties
|
||||
if (value === null) {
|
||||
// to reset user_type from user, it must be null
|
||||
if (value === null && key !== "user_type") {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
@ -315,8 +350,15 @@ function getSearchOrder(order) {
|
||||
const dataProvider = {
|
||||
getList: (resource, params) => {
|
||||
console.log("getList " + resource);
|
||||
const { user_id, name, guests, deactivated, search_term, valid } =
|
||||
params.filter;
|
||||
const {
|
||||
user_id,
|
||||
name,
|
||||
guests,
|
||||
deactivated,
|
||||
search_term,
|
||||
destination,
|
||||
valid,
|
||||
} = params.filter;
|
||||
const { page, perPage } = params.pagination;
|
||||
const { field, order } = params.sort;
|
||||
const from = (page - 1) * perPage;
|
||||
@ -326,6 +368,7 @@ const dataProvider = {
|
||||
user_id: user_id,
|
||||
search_term: search_term,
|
||||
name: name,
|
||||
destination: destination,
|
||||
guests: guests,
|
||||
deactivated: deactivated,
|
||||
valid: valid,
|
||||
@ -354,9 +397,11 @@ const dataProvider = {
|
||||
const res = resourceMap[resource];
|
||||
|
||||
const endpoint_url = homeserver + res.path;
|
||||
return jsonClient(`${endpoint_url}/${params.id}`).then(({ json }) => ({
|
||||
return jsonClient(`${endpoint_url}/${encodeURIComponent(params.id)}`).then(
|
||||
({ json }) => ({
|
||||
data: res.map(json),
|
||||
}));
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getMany: (resource, params) => {
|
||||
@ -368,7 +413,9 @@ const dataProvider = {
|
||||
|
||||
const endpoint_url = homeserver + res.path;
|
||||
return Promise.all(
|
||||
params.ids.map(id => jsonClient(`${endpoint_url}/${id}`))
|
||||
params.ids.map(id =>
|
||||
jsonClient(`${endpoint_url}/${encodeURIComponent(id)}`)
|
||||
)
|
||||
).then(responses => ({
|
||||
data: responses.map(({ json }) => res.map(json)),
|
||||
total: responses.length,
|
||||
@ -409,7 +456,7 @@ const dataProvider = {
|
||||
const res = resourceMap[resource];
|
||||
|
||||
const endpoint_url = homeserver + res.path;
|
||||
return jsonClient(`${endpoint_url}/${params.data.id}`, {
|
||||
return jsonClient(`${endpoint_url}/${encodeURIComponent(params.data.id)}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(params.data, filterNullValues),
|
||||
}).then(({ json }) => ({
|
||||
@ -426,10 +473,13 @@ const dataProvider = {
|
||||
|
||||
const endpoint_url = homeserver + res.path;
|
||||
return Promise.all(
|
||||
params.ids.map(id => jsonClient(`${endpoint_url}/${id}`), {
|
||||
params.ids.map(
|
||||
id => jsonClient(`${endpoint_url}/${encodeURIComponent(id)}`),
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(params.data, filterNullValues),
|
||||
})
|
||||
}
|
||||
)
|
||||
).then(responses => ({
|
||||
data: responses.map(({ json }) => json),
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user