diff --git a/maubot/management/frontend/src/components/Switch.js b/maubot/management/frontend/src/components/Switch.js
new file mode 100644
index 0000000..975b47c
--- /dev/null
+++ b/maubot/management/frontend/src/components/Switch.js
@@ -0,0 +1,54 @@
+// maubot - A plugin-based Matrix bot system.
+// Copyright (C) 2018 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+import React, { Component } from "react"
+
+class Switch extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ active: props.active,
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.setState({
+ active: nextProps.active,
+ })
+ }
+
+ toggle = () => {
+ if (this.props.onToggle) {
+ this.props.onToggle(!this.state.active)
+ } else {
+ this.setState({ active: !this.state.active })
+ }
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
+
+export default Switch
diff --git a/maubot/management/frontend/src/index.js b/maubot/management/frontend/src/index.js
index cbe10ed..12dd05c 100644
--- a/maubot/management/frontend/src/index.js
+++ b/maubot/management/frontend/src/index.js
@@ -16,6 +16,6 @@
import React from "react"
import ReactDOM from "react-dom"
import "./style/index.sass"
-import App from "./MaubotRouter"
+import App from "./pages/Main"
ReactDOM.render(, document.getElementById("root"))
diff --git a/maubot/management/frontend/src/Login.js b/maubot/management/frontend/src/pages/Login.js
similarity index 97%
rename from maubot/management/frontend/src/Login.js
rename to maubot/management/frontend/src/pages/Login.js
index e342abe..5b97f14 100644
--- a/maubot/management/frontend/src/Login.js
+++ b/maubot/management/frontend/src/pages/Login.js
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import React, { Component } from "react"
-import Spinner from "./components/Spinner"
-import api from "./api"
+import Spinner from "../components/Spinner"
+import api from "../api"
class Login extends Component {
constructor(props, context) {
diff --git a/maubot/management/frontend/src/MaubotRouter.js b/maubot/management/frontend/src/pages/Main.js
similarity index 92%
rename from maubot/management/frontend/src/MaubotRouter.js
rename to maubot/management/frontend/src/pages/Main.js
index b3c7561..efb9ac3 100644
--- a/maubot/management/frontend/src/MaubotRouter.js
+++ b/maubot/management/frontend/src/pages/Main.js
@@ -15,13 +15,13 @@
// along with this program. If not, see .
import React, { Component } from "react"
import { BrowserRouter as Router, Switch } from "react-router-dom"
-import PrivateRoute from "./components/PrivateRoute"
+import PrivateRoute from "../components/PrivateRoute"
+import Spinner from "../components/Spinner"
+import api from "../api"
import Dashboard from "./dashboard"
import Login from "./Login"
-import Spinner from "./components/Spinner"
-import api from "./api"
-class MaubotRouter extends Component {
+class Main extends Component {
constructor(props) {
super(props)
this.state = {
@@ -72,4 +72,4 @@ class MaubotRouter extends Component {
}
}
-export default MaubotRouter
+export default Main
diff --git a/maubot/management/frontend/src/pages/dashboard/Client.js b/maubot/management/frontend/src/pages/dashboard/Client.js
new file mode 100644
index 0000000..d352b31
--- /dev/null
+++ b/maubot/management/frontend/src/pages/dashboard/Client.js
@@ -0,0 +1,114 @@
+// maubot - A plugin-based Matrix bot system.
+// Copyright (C) 2018 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+import React, { Component } from "react"
+import { Link } from "react-router-dom"
+import Switch from "../../components/Switch"
+import { ReactComponent as ChevronRight } from "../../res/chevron-right.svg"
+import { ReactComponent as UploadButton } from "../../res/upload.svg"
+
+function getAvatarURL(client) {
+ const id = client.avatar_url.substr("mxc://".length)
+ return `${client.homeserver}/_matrix/media/r0/download/${id}`
+}
+
+const ClientListEntry = ({ client }) => {
+ const classes = ["client", "entry"]
+ if (!client.enabled) {
+ classes.push("disabled")
+ } else if (!client.started) {
+ classes.push("stopped")
+ }
+ return (
+
+
+ {client.displayname || client.id}
+
+
+ )
+}
+
+class Client extends Component {
+ static ListEntry = ClientListEntry
+
+ constructor(props) {
+ super(props)
+ this.state = props
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.setState(nextProps)
+ }
+
+ inputChange = event => {
+ this.setState({ [event.target.name]: event.target.value })
+ }
+
+ render() {
+ return
+
+
+
+
+
+
+
User ID
+
+
+
+
+
+
Display name
+
+
+
+
+
+
Homeserver
+
+
+
+
+
+
Access token
+
+
+
+
+
+
Sync
+
+ this.setState({ sync })}/>
+
+
+
+
Enabled
+
+ this.setState({ enabled })}/>
+
+
+
+
+
+ }
+}
+
+export default Client
diff --git a/maubot/management/frontend/src/dashboard/index.js b/maubot/management/frontend/src/pages/dashboard/index.js
similarity index 92%
rename from maubot/management/frontend/src/dashboard/index.js
rename to maubot/management/frontend/src/pages/dashboard/index.js
index 77ea69b..34dbb0c 100644
--- a/maubot/management/frontend/src/dashboard/index.js
+++ b/maubot/management/frontend/src/pages/dashboard/index.js
@@ -15,12 +15,11 @@
// along with this program. If not, see .
import React, { Component } from "react"
import { Route, Switch, Link } from "react-router-dom"
-import api from "../api"
-import { ReactComponent as Plus } from "../res/plus.svg"
+import api from "../../api"
+import { ReactComponent as Plus } from "../../res/plus.svg"
import InstanceListEntry from "./instance/ListEntry"
import InstanceView from "./instance/View"
-import ClientListEntry from "./client/ListEntry"
-import ClientView from "./client/View"
+import Client from "./Client"
import PluginListEntry from "./plugin/ListEntry"
import PluginView from "./plugin/View"
@@ -88,7 +87,7 @@ class Dashboard extends Component {