Add initial parts of client view
This commit is contained in:
parent
3e661aa887
commit
ed16ee8860
54
maubot/management/frontend/src/components/Switch.js
Normal file
54
maubot/management/frontend/src/components/Switch.js
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
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 (
|
||||||
|
<div className="switch" data-active={this.state.active} onClick={this.toggle}>
|
||||||
|
<div className="box">
|
||||||
|
<span className="text">
|
||||||
|
<span className="on">{this.props.onText || "On"}</span>
|
||||||
|
<span className="off">{this.props.offText || "Off"}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Switch
|
@ -1,30 +0,0 @@
|
|||||||
// 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 <https://www.gnu.org/licenses/>.
|
|
||||||
import React from "react"
|
|
||||||
import { Link } from "react-router-dom"
|
|
||||||
import { ReactComponent as ChevronRight } from "../../res/chevron-right.svg"
|
|
||||||
|
|
||||||
const ClientListEntry = ({ client }) => (
|
|
||||||
<Link className="client entry" to={`/client/${client.id}`}>
|
|
||||||
<img className="avatar"
|
|
||||||
src={`${client.homeserver}/_matrix/media/r0/download/${client.avatar_url.substr("mxc://".length)}`}
|
|
||||||
alt={client.id.substr(1, 1)}/>
|
|
||||||
<span className="displayname">{client.displayname || client.id}</span>
|
|
||||||
<ChevronRight/>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ClientListEntry
|
|
@ -16,6 +16,6 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import ReactDOM from "react-dom"
|
import ReactDOM from "react-dom"
|
||||||
import "./style/index.sass"
|
import "./style/index.sass"
|
||||||
import App from "./MaubotRouter"
|
import App from "./pages/Main"
|
||||||
|
|
||||||
ReactDOM.render(<App/>, document.getElementById("root"))
|
ReactDOM.render(<App/>, document.getElementById("root"))
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import Spinner from "./components/Spinner"
|
import Spinner from "../components/Spinner"
|
||||||
import api from "./api"
|
import api from "../api"
|
||||||
|
|
||||||
class Login extends Component {
|
class Login extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
@ -15,13 +15,13 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { BrowserRouter as Router, Switch } from "react-router-dom"
|
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 Dashboard from "./dashboard"
|
||||||
import Login from "./Login"
|
import Login from "./Login"
|
||||||
import Spinner from "./components/Spinner"
|
|
||||||
import api from "./api"
|
|
||||||
|
|
||||||
class MaubotRouter extends Component {
|
class Main extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -72,4 +72,4 @@ class MaubotRouter extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MaubotRouter
|
export default Main
|
114
maubot/management/frontend/src/pages/dashboard/Client.js
Normal file
114
maubot/management/frontend/src/pages/dashboard/Client.js
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
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 (
|
||||||
|
<Link className={classes.join(" ")} to={`/client/${client.id}`}>
|
||||||
|
<img className="avatar" src={getAvatarURL(client)} alt={client.id.substr(1, 1)}/>
|
||||||
|
<span className="displayname">{client.displayname || client.id}</span>
|
||||||
|
<ChevronRight/>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <div className="client">
|
||||||
|
<div className="avatar-container">
|
||||||
|
<img className="avatar" src={getAvatarURL(this.state)} alt="Avatar"/>
|
||||||
|
<UploadButton className="upload"/>
|
||||||
|
</div>
|
||||||
|
<div className="info-container">
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">User ID</div>
|
||||||
|
<div className="value">
|
||||||
|
<input type="text" disabled value={this.props.id}
|
||||||
|
onChange={this.inputChange}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">Display name</div>
|
||||||
|
<div className="value">
|
||||||
|
<input type="text" name="displayname" value={this.state.displayname}
|
||||||
|
onChange={this.inputChange}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">Homeserver</div>
|
||||||
|
<div className="value">
|
||||||
|
<input type="text" name="homeserver" value={this.state.homeserver}
|
||||||
|
onChange={this.inputChange}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">Access token</div>
|
||||||
|
<div className="value">
|
||||||
|
<input type="text" name="access_token" value={this.state.access_token}
|
||||||
|
onChange={this.inputChange}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">Sync</div>
|
||||||
|
<div className="value">
|
||||||
|
<Switch active={this.state.sync}
|
||||||
|
onToggle={sync => this.setState({ sync })}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="key">Enabled</div>
|
||||||
|
<div className="value">
|
||||||
|
<Switch active={this.state.enabled}
|
||||||
|
onToggle={enabled => this.setState({ enabled })}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Client
|
@ -15,12 +15,11 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { Route, Switch, Link } from "react-router-dom"
|
import { Route, Switch, Link } from "react-router-dom"
|
||||||
import api from "../api"
|
import api from "../../api"
|
||||||
import { ReactComponent as Plus } from "../res/plus.svg"
|
import { ReactComponent as Plus } from "../../res/plus.svg"
|
||||||
import InstanceListEntry from "./instance/ListEntry"
|
import InstanceListEntry from "./instance/ListEntry"
|
||||||
import InstanceView from "./instance/View"
|
import InstanceView from "./instance/View"
|
||||||
import ClientListEntry from "./client/ListEntry"
|
import Client from "./Client"
|
||||||
import ClientView from "./client/View"
|
|
||||||
import PluginListEntry from "./plugin/ListEntry"
|
import PluginListEntry from "./plugin/ListEntry"
|
||||||
import PluginView from "./plugin/View"
|
import PluginView from "./plugin/View"
|
||||||
|
|
||||||
@ -88,7 +87,7 @@ class Dashboard extends Component {
|
|||||||
<h2>Clients</h2>
|
<h2>Clients</h2>
|
||||||
<Link to="/new/client"><Plus/></Link>
|
<Link to="/new/client"><Plus/></Link>
|
||||||
</div>
|
</div>
|
||||||
{this.renderList("client", ClientListEntry)}
|
{this.renderList("client", Client.ListEntry)}
|
||||||
</div>
|
</div>
|
||||||
<div className="plugins list">
|
<div className="plugins list">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
@ -98,16 +97,16 @@ class Dashboard extends Component {
|
|||||||
{this.renderList("plugin", PluginListEntry)}
|
{this.renderList("plugin", PluginListEntry)}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<main className="dashboard">
|
<main className="view">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact render={() => "Hello, World!"}/>
|
<Route path="/" exact render={() => "Hello, World!"}/>
|
||||||
<Route path="/new/instance" render={() => <InstanceView/>}/>
|
<Route path="/new/instance" render={() => <InstanceView/>}/>
|
||||||
<Route path="/new/client" render={() => <ClientView/>}/>
|
<Route path="/new/client" render={() => <Client/>}/>
|
||||||
<Route path="/new/plugin" render={() => <PluginView/>}/>
|
<Route path="/new/plugin" render={() => <PluginView/>}/>
|
||||||
<Route path="/instance/:id" render={({ match }) =>
|
<Route path="/instance/:id" render={({ match }) =>
|
||||||
this.renderView("instance", InstanceView, match.params.id)}/>
|
this.renderView("instance", InstanceView, match.params.id)}/>
|
||||||
<Route path="/client/:id" render={({ match }) =>
|
<Route path="/client/:id" render={({ match }) =>
|
||||||
this.renderView("client", ClientView, match.params.id)}/>
|
this.renderView("client", Client, match.params.id)}/>
|
||||||
<Route path="/plugin/:id" render={({ match }) =>
|
<Route path="/plugin/:id" render={({ match }) =>
|
||||||
this.renderView("plugin", PluginView, match.params.id)}/>
|
this.renderView("plugin", PluginView, match.params.id)}/>
|
||||||
<Route render={() => "Not found :("}/>
|
<Route render={() => "Not found :("}/>
|
@ -15,7 +15,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import { ReactComponent as ChevronRight } from "../../res/chevron-right.svg"
|
import { ReactComponent as ChevronRight } from "../../../res/chevron-right.svg"
|
||||||
|
|
||||||
const InstanceListEntry = ({ instance }) => (
|
const InstanceListEntry = ({ instance }) => (
|
||||||
<Link className="instance entry" to={`/instance/${instance.id}`}>
|
<Link className="instance entry" to={`/instance/${instance.id}`}>
|
@ -15,7 +15,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import { ReactComponent as ChevronRight } from "../../res/chevron-right.svg"
|
import { ReactComponent as ChevronRight } from "../../../res/chevron-right.svg"
|
||||||
|
|
||||||
const PluginListEntry = ({ plugin }) => (
|
const PluginListEntry = ({ plugin }) => (
|
||||||
<Link className="plugin entry" to={`/plugin/${plugin.id}`}>
|
<Link className="plugin entry" to={`/plugin/${plugin.id}`}>
|
5
maubot/management/frontend/src/res/upload.svg
Normal file
5
maubot/management/frontend/src/res/upload.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path fill="#000000" d="M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 365 B |
@ -18,7 +18,6 @@ body
|
|||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
font-size: 16px
|
font-size: 16px
|
||||||
background-color: $background-color
|
|
||||||
|
|
||||||
#root
|
#root
|
||||||
position: fixed
|
position: fixed
|
||||||
@ -33,6 +32,10 @@ body
|
|||||||
bottom: 0
|
bottom: 0
|
||||||
left: 0
|
left: 0
|
||||||
right: 0
|
right: 0
|
||||||
|
background-color: $background-dark
|
||||||
|
|
||||||
|
> *
|
||||||
|
background-color: $background
|
||||||
|
|
||||||
.maubot-loading
|
.maubot-loading
|
||||||
margin-top: 10rem
|
margin-top: 10rem
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
padding: $padding
|
padding: $padding
|
||||||
width: $width
|
width: $width
|
||||||
height: $height
|
height: $height
|
||||||
background-color: $background-color
|
background-color: $background
|
||||||
border: none
|
border: none
|
||||||
border-radius: .25rem
|
border-radius: .25rem
|
||||||
color: $inverted-text-color
|
color: $inverted-text-color
|
||||||
@ -28,7 +28,7 @@
|
|||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color: darken($background-color, 10%)
|
background-color: darken($background, 10%)
|
||||||
|
|
||||||
=link-button()
|
=link-button()
|
||||||
display: inline-block
|
display: inline-block
|
||||||
@ -81,7 +81,7 @@
|
|||||||
=input($width: null, $height: null, $vertical-padding: .375rem, $horizontal-padding: 1rem, $font-size: 1rem)
|
=input($width: null, $height: null, $vertical-padding: .375rem, $horizontal-padding: 1rem, $font-size: 1rem)
|
||||||
font-family: $font-stack
|
font-family: $font-stack
|
||||||
border: 1px solid $border-color
|
border: 1px solid $border-color
|
||||||
background-color: $background-color
|
background-color: $background
|
||||||
color: $text-color
|
color: $text-color
|
||||||
width: $width
|
width: $width
|
||||||
height: $height
|
height: $height
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
$primary: #00C853
|
$primary: #00C853
|
||||||
$primary-dark: #009624
|
$primary-dark: #009624
|
||||||
$primary-light: #5EFC82
|
$primary-light: #5EFC82
|
||||||
@ -25,6 +26,7 @@ $error-light: #F05545
|
|||||||
|
|
||||||
$border-color: #DDD
|
$border-color: #DDD
|
||||||
$text-color: #212121
|
$text-color: #212121
|
||||||
$background-color: #FAFAFA
|
$background: #FAFAFA
|
||||||
$inverted-text-color: $background-color
|
$background-dark: #E7E7E7
|
||||||
|
$inverted-text-color: $background
|
||||||
$font-stack: sans-serif
|
$font-stack: sans-serif
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
@import lib/spinner
|
@import lib/spinner
|
||||||
|
|
||||||
@import base/vars
|
@import base/vars
|
||||||
@import base/body
|
@import base/body
|
||||||
@import base/elements
|
@import base/elements
|
||||||
|
@import lib/switch
|
||||||
|
|
||||||
@import pages/login
|
@import pages/login
|
||||||
@import pages/dashboard
|
@import pages/dashboard
|
||||||
|
79
maubot/management/frontend/src/style/lib/switch.sass
Normal file
79
maubot/management/frontend/src/style/lib/switch.sass
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
.switch
|
||||||
|
display: flex
|
||||||
|
|
||||||
|
width: 100%
|
||||||
|
height: 2rem
|
||||||
|
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
border: 1px solid $primary
|
||||||
|
border-radius: .25rem
|
||||||
|
background-color: $background
|
||||||
|
|
||||||
|
box-sizing: border-box
|
||||||
|
|
||||||
|
> .box
|
||||||
|
box-sizing: border-box
|
||||||
|
width: 50%
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
transition: .5s
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
color: $inverted-text-color
|
||||||
|
border-radius: .15rem 0 0 .15rem
|
||||||
|
background-color: $primary
|
||||||
|
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
> .text
|
||||||
|
box-sizing: border-box
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
text-align: center
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
color: $inverted-text-color
|
||||||
|
font-size: 1rem
|
||||||
|
|
||||||
|
user-select: none
|
||||||
|
|
||||||
|
.on
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.off
|
||||||
|
display: inline
|
||||||
|
|
||||||
|
|
||||||
|
&[data-active=true]
|
||||||
|
> .box
|
||||||
|
transform: translateX(100%)
|
||||||
|
|
||||||
|
border-radius: 0 .15rem .15rem 0
|
||||||
|
background-color: $primary
|
||||||
|
|
||||||
|
.on
|
||||||
|
display: inline
|
||||||
|
|
||||||
|
.off
|
||||||
|
display: none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
109
maubot/management/frontend/src/style/pages/client.sass
Normal file
109
maubot/management/frontend/src/style/pages/client.sass
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
> .client
|
||||||
|
margin: 1rem
|
||||||
|
|
||||||
|
div.avatar-container
|
||||||
|
position: relative
|
||||||
|
display: inline-block
|
||||||
|
width: 8rem
|
||||||
|
height: 8rem
|
||||||
|
border-radius: 100%
|
||||||
|
cursor: pointer
|
||||||
|
vertical-align: top
|
||||||
|
|
||||||
|
> img.avatar
|
||||||
|
display: block
|
||||||
|
max-width: 8rem
|
||||||
|
max-height: 8rem
|
||||||
|
border-radius: 100%
|
||||||
|
position: absolute
|
||||||
|
left: 50%
|
||||||
|
top: 50%
|
||||||
|
-webkit-transform: translateY(-50%) translateX(-50%)
|
||||||
|
|
||||||
|
> svg.upload
|
||||||
|
position: absolute
|
||||||
|
display: block
|
||||||
|
visibility: hidden
|
||||||
|
|
||||||
|
width: 6rem
|
||||||
|
height: 6rem
|
||||||
|
|
||||||
|
padding: 1rem
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
> img.avatar
|
||||||
|
opacity: .25
|
||||||
|
|
||||||
|
> svg.upload
|
||||||
|
visibility: visible
|
||||||
|
|
||||||
|
div.info-container
|
||||||
|
display: inline-table
|
||||||
|
vertical-align: top
|
||||||
|
|
||||||
|
margin: 1rem 2rem
|
||||||
|
|
||||||
|
> .row
|
||||||
|
display: table-row
|
||||||
|
|
||||||
|
> .key, > .value
|
||||||
|
display: table-cell
|
||||||
|
padding-bottom: .5rem
|
||||||
|
|
||||||
|
> .key
|
||||||
|
width: 6.5rem
|
||||||
|
|
||||||
|
> .value
|
||||||
|
margin: .5rem
|
||||||
|
|
||||||
|
> .value > .switch
|
||||||
|
width: auto
|
||||||
|
height: 2rem
|
||||||
|
|
||||||
|
> .value > input
|
||||||
|
border: none
|
||||||
|
height: 2rem
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
box-sizing: border-box
|
||||||
|
|
||||||
|
padding: .375rem 0
|
||||||
|
background-color: $background
|
||||||
|
|
||||||
|
font-size: 1rem
|
||||||
|
|
||||||
|
border-bottom: 1px solid transparent
|
||||||
|
|
||||||
|
&:hover:not(:disabled)
|
||||||
|
border-bottom: 1px solid $primary
|
||||||
|
|
||||||
|
&:focus:not(:disabled)
|
||||||
|
border-bottom: 2px solid $primary
|
||||||
|
|
||||||
|
//> .client
|
||||||
|
display: table
|
||||||
|
|
||||||
|
> .field
|
||||||
|
display: table-row
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
> .name, > .value
|
||||||
|
display: table-cell
|
||||||
|
width: 50%
|
||||||
|
text-align: center
|
@ -18,6 +18,9 @@
|
|||||||
.dashboard
|
.dashboard
|
||||||
display: grid
|
display: grid
|
||||||
height: 100%
|
height: 100%
|
||||||
|
max-width: 60rem
|
||||||
|
margin: auto
|
||||||
|
box-shadow: 0 .5rem .5rem rgba(0, 0, 0, 0.5)
|
||||||
|
|
||||||
> a.title
|
> a.title
|
||||||
grid-area: title
|
grid-area: title
|
||||||
@ -31,9 +34,7 @@
|
|||||||
color: $text-color
|
color: $text-color
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
|
|
||||||
z-index: 1
|
background-color: white
|
||||||
|
|
||||||
background-color: $background-color
|
|
||||||
border-right: 1px solid $primary
|
border-right: 1px solid $primary
|
||||||
border-bottom: 1px solid $border-color
|
border-bottom: 1px solid $border-color
|
||||||
|
|
||||||
@ -47,12 +48,14 @@
|
|||||||
align-items: center
|
align-items: center
|
||||||
justify-content: center
|
justify-content: center
|
||||||
background-color: $primary
|
background-color: $primary
|
||||||
width: 110%
|
box-shadow: 0 .25rem .25rem rgba(0, 0, 0, .2)
|
||||||
margin: 0 -5%
|
|
||||||
box-shadow: 0 .25rem .25rem rgba(0, 0, 0, .25)
|
|
||||||
|
|
||||||
|
|
||||||
@import "sidebar"
|
@import "sidebar"
|
||||||
|
|
||||||
> main.dashboard
|
> main.view
|
||||||
grid-area: main
|
grid-area: main
|
||||||
|
|
||||||
|
@import "client"
|
||||||
|
@import "instance"
|
||||||
|
@import "plugin"
|
||||||
|
@ -13,12 +13,6 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React, { Component } from "react"
|
|
||||||
|
|
||||||
class ClientView extends Component {
|
> .instance
|
||||||
render() {
|
margin: 1rem
|
||||||
return <div>{this.props.displayname}</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ClientView
|
|
18
maubot/management/frontend/src/style/pages/plugin.sass
Normal file
18
maubot/management/frontend/src/style/pages/plugin.sass
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
> .plugin
|
||||||
|
margin: 1rem
|
@ -16,13 +16,16 @@
|
|||||||
|
|
||||||
> .sidebar
|
> .sidebar
|
||||||
grid-area: sidebar
|
grid-area: sidebar
|
||||||
background-color: $background-color
|
background-color: white
|
||||||
|
|
||||||
border-right: 1px solid $border-color
|
border-right: 1px solid $border-color
|
||||||
padding: .5rem
|
padding: .5rem
|
||||||
|
|
||||||
|
overflow-y: auto
|
||||||
|
|
||||||
div.list
|
div.list
|
||||||
margin-bottom: 1.5rem
|
&:not(:last-of-type)
|
||||||
|
margin-bottom: 1.5rem
|
||||||
|
|
||||||
div.title
|
div.title
|
||||||
h2
|
h2
|
||||||
|
Loading…
Reference in New Issue
Block a user