feat: Add optional banner to frontend via config entry (solves #128)
This commit is contained in:
parent
99f33aa988
commit
09fe1a7ac0
|
@ -37,6 +37,7 @@ FRONTEND_CONFIG = {
|
||||||
"imprintUrl": "https://example.com/imprint",
|
"imprintUrl": "https://example.com/imprint",
|
||||||
"privacyPolicyUrl": "https://example.com/privacy",
|
"privacyPolicyUrl": "https://example.com/privacy",
|
||||||
"mapHome": {"zoom": 6, "longitude": 10.2, "latitude": 51.3},
|
"mapHome": {"zoom": 6, "longitude": 10.2, "latitude": 51.3},
|
||||||
|
"banner": {"text": "This is a test installation.", "style": "warning"},
|
||||||
}
|
}
|
||||||
|
|
||||||
# If the API should serve generated tiles, this is the path where the tiles are
|
# If the API should serve generated tiles, this is the path where the tiles are
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
@import 'styles.less';
|
@import 'styles.less';
|
||||||
|
|
||||||
:global(#root) {
|
:global(#root) {
|
||||||
padding-top: @menuHeight;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
@ -72,7 +70,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu.menu {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
> :global(.ui.container) {
|
> :global(.ui.container) {
|
||||||
height: @menuHeight;
|
height: @menuHeight;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
@ -81,7 +82,10 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: white;
|
color: white;
|
||||||
flex: 1 0 auto;
|
border-radius: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -106,3 +110,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
padding: 8px;
|
||||||
|
z-index: 100;
|
||||||
|
border-bottom: 1px solid #DDD;
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
background: #FFD54F;
|
||||||
|
border-color: #FBC02D;
|
||||||
|
color: #263238;
|
||||||
|
}
|
||||||
|
&.info {
|
||||||
|
background: #4FC3F7;
|
||||||
|
border-color: #0D47A1;
|
||||||
|
color: #0D47A1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
import {connect} from 'react-redux'
|
import {connect} from 'react-redux'
|
||||||
import {List, Grid, Container, Menu, Header, Dropdown} from 'semantic-ui-react'
|
import {List, Grid, Container, Menu, Header, Dropdown} from 'semantic-ui-react'
|
||||||
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom'
|
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom'
|
||||||
|
@ -50,6 +51,10 @@ function DropdownItemForLink({navigate, ...props}) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Banner({text, style = 'warning'}: {text: string, style: 'warning' | 'info'}) {
|
||||||
|
return <div className={classnames(styles.banner, styles[style])}>{text}</div>
|
||||||
|
}
|
||||||
|
|
||||||
const App = connect((state) => ({login: state.login}))(function App({login}) {
|
const App = connect((state) => ({login: state.login}))(function App({login}) {
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const apiVersion = useObservable(() => from(api.get('/info')).pipe(pluck('version')))
|
const apiVersion = useObservable(() => from(api.get('/info')).pipe(pluck('version')))
|
||||||
|
@ -60,7 +65,8 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {
|
||||||
|
|
||||||
return config ? (
|
return config ? (
|
||||||
<Router basename={config.basename}>
|
<Router basename={config.basename}>
|
||||||
<Menu fixed="top" className={styles.menu}>
|
{config?.banner && <Banner {...config.banner} />}
|
||||||
|
<Menu className={styles.menu}>
|
||||||
<Container>
|
<Container>
|
||||||
<Link to="/" component={MenuItemForLink} header className={styles.pageTitle}>
|
<Link to="/" component={MenuItemForLink} header className={styles.pageTitle}>
|
||||||
OpenBikeSensor
|
OpenBikeSensor
|
|
@ -3,6 +3,7 @@
|
||||||
.page {
|
.page {
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
|
|
|
@ -20,6 +20,10 @@ export interface Config {
|
||||||
obsMapSource?: MapSoure
|
obsMapSource?: MapSoure
|
||||||
imprintUrl?: string
|
imprintUrl?: string
|
||||||
privacyPolicyUrl?: string
|
privacyPolicyUrl?: string
|
||||||
|
banner?: {
|
||||||
|
text: string
|
||||||
|
style?: "warning" | "info"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadConfig(): Promise<Config> {
|
async function loadConfig(): Promise<Config> {
|
||||||
|
|
Loading…
Reference in a new issue