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 ReactDOM from "react-dom"
|
||||
import "./style/index.sass"
|
||||
import App from "./MaubotRouter"
|
||||
import App from "./pages/Main"
|
||||
|
||||
ReactDOM.render(<App/>, document.getElementById("root"))
|
||||
|
@ -14,8 +14,8 @@
|
||||
// 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 Spinner from "./components/Spinner"
|
||||
import api from "./api"
|
||||
import Spinner from "../components/Spinner"
|
||||
import api from "../api"
|
||||
|
||||
class Login extends Component {
|
||||
constructor(props, context) {
|
@ -15,13 +15,13 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
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
|
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/>.
|
||||
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 {
|
||||
<h2>Clients</h2>
|
||||
<Link to="/new/client"><Plus/></Link>
|
||||
</div>
|
||||
{this.renderList("client", ClientListEntry)}
|
||||
{this.renderList("client", Client.ListEntry)}
|
||||
</div>
|
||||
<div className="plugins list">
|
||||
<div className="title">
|
||||
@ -98,16 +97,16 @@ class Dashboard extends Component {
|
||||
{this.renderList("plugin", PluginListEntry)}
|
||||
</div>
|
||||
</nav>
|
||||
<main className="dashboard">
|
||||
<main className="view">
|
||||
<Switch>
|
||||
<Route path="/" exact render={() => "Hello, World!"}/>
|
||||
<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="/instance/:id" render={({ match }) =>
|
||||
this.renderView("instance", InstanceView, match.params.id)}/>
|
||||
<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 }) =>
|
||||
this.renderView("plugin", PluginView, match.params.id)}/>
|
||||
<Route render={() => "Not found :("}/>
|
@ -15,7 +15,7 @@
|
||||
// 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"
|
||||
import { ReactComponent as ChevronRight } from "../../../res/chevron-right.svg"
|
||||
|
||||
const InstanceListEntry = ({ instance }) => (
|
||||
<Link className="instance entry" to={`/instance/${instance.id}`}>
|
@ -15,7 +15,7 @@
|
||||
// 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"
|
||||
import { ReactComponent as ChevronRight } from "../../../res/chevron-right.svg"
|
||||
|
||||
const PluginListEntry = ({ plugin }) => (
|
||||
<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
|
||||
padding: 0
|
||||
font-size: 16px
|
||||
background-color: $background-color
|
||||
|
||||
#root
|
||||
position: fixed
|
||||
@ -33,6 +32,10 @@ body
|
||||
bottom: 0
|
||||
left: 0
|
||||
right: 0
|
||||
background-color: $background-dark
|
||||
|
||||
> *
|
||||
background-color: $background
|
||||
|
||||
.maubot-loading
|
||||
margin-top: 10rem
|
||||
|
@ -19,7 +19,7 @@
|
||||
padding: $padding
|
||||
width: $width
|
||||
height: $height
|
||||
background-color: $background-color
|
||||
background-color: $background
|
||||
border: none
|
||||
border-radius: .25rem
|
||||
color: $inverted-text-color
|
||||
@ -28,7 +28,7 @@
|
||||
cursor: pointer
|
||||
|
||||
&:hover
|
||||
background-color: darken($background-color, 10%)
|
||||
background-color: darken($background, 10%)
|
||||
|
||||
=link-button()
|
||||
display: inline-block
|
||||
@ -81,7 +81,7 @@
|
||||
=input($width: null, $height: null, $vertical-padding: .375rem, $horizontal-padding: 1rem, $font-size: 1rem)
|
||||
font-family: $font-stack
|
||||
border: 1px solid $border-color
|
||||
background-color: $background-color
|
||||
background-color: $background
|
||||
color: $text-color
|
||||
width: $width
|
||||
height: $height
|
||||
|
@ -13,6 +13,7 @@
|
||||
//
|
||||
// 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/>.
|
||||
|
||||
$primary: #00C853
|
||||
$primary-dark: #009624
|
||||
$primary-light: #5EFC82
|
||||
@ -25,6 +26,7 @@ $error-light: #F05545
|
||||
|
||||
$border-color: #DDD
|
||||
$text-color: #212121
|
||||
$background-color: #FAFAFA
|
||||
$inverted-text-color: $background-color
|
||||
$background: #FAFAFA
|
||||
$background-dark: #E7E7E7
|
||||
$inverted-text-color: $background
|
||||
$font-stack: sans-serif
|
||||
|
@ -14,10 +14,10 @@
|
||||
// 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 lib/spinner
|
||||
|
||||
@import base/vars
|
||||
@import base/body
|
||||
@import base/elements
|
||||
@import lib/switch
|
||||
|
||||
@import pages/login
|
||||
@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
|
||||
display: grid
|
||||
height: 100%
|
||||
max-width: 60rem
|
||||
margin: auto
|
||||
box-shadow: 0 .5rem .5rem rgba(0, 0, 0, 0.5)
|
||||
|
||||
> a.title
|
||||
grid-area: title
|
||||
@ -31,9 +34,7 @@
|
||||
color: $text-color
|
||||
text-decoration: none
|
||||
|
||||
z-index: 1
|
||||
|
||||
background-color: $background-color
|
||||
background-color: white
|
||||
border-right: 1px solid $primary
|
||||
border-bottom: 1px solid $border-color
|
||||
|
||||
@ -47,12 +48,14 @@
|
||||
align-items: center
|
||||
justify-content: center
|
||||
background-color: $primary
|
||||
width: 110%
|
||||
margin: 0 -5%
|
||||
box-shadow: 0 .25rem .25rem rgba(0, 0, 0, .25)
|
||||
box-shadow: 0 .25rem .25rem rgba(0, 0, 0, .2)
|
||||
|
||||
|
||||
@import "sidebar"
|
||||
|
||||
> main.dashboard
|
||||
> main.view
|
||||
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
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import React, { Component } from "react"
|
||||
|
||||
class ClientView extends Component {
|
||||
render() {
|
||||
return <div>{this.props.displayname}</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default ClientView
|
||||
> .instance
|
||||
margin: 1rem
|
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
|
||||
grid-area: sidebar
|
||||
background-color: $background-color
|
||||
background-color: white
|
||||
|
||||
border-right: 1px solid $border-color
|
||||
padding: .5rem
|
||||
|
||||
overflow-y: auto
|
||||
|
||||
div.list
|
||||
margin-bottom: 1.5rem
|
||||
&:not(:last-of-type)
|
||||
margin-bottom: 1.5rem
|
||||
|
||||
div.title
|
||||
h2
|
||||
|
Loading…
Reference in New Issue
Block a user