chore: auto format frontend code with prettier

This commit is contained in:
Paul Bienkowski 2021-12-06 08:47:47 +01:00
parent 3db5132199
commit ee13e8e2f5
23 changed files with 153 additions and 103 deletions

View file

@ -5,7 +5,9 @@
flex-direction: column; flex-direction: column;
justify-content: stretch; justify-content: stretch;
html, body, & { html,
body,
& {
min-height: 100%; min-height: 100%;
} }
} }
@ -18,14 +20,20 @@
background: @obsColorB4; background: @obsColorB4;
color: @obsColorW; color: @obsColorW;
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
&:global(.ui.header) { &:global(.ui.header) {
color: inherit; color: inherit;
} }
} }
a { a {
&, &:hover { &,
&:hover {
color: inherit; color: inherit;
} }
@ -65,7 +73,8 @@
font-weight: 600; font-weight: 600;
font-size: 18pt; font-size: 18pt;
&, &:hover { &,
&:hover {
color: @obsColorB4; color: @obsColorB4;
} }
} }
@ -114,16 +123,16 @@
.banner { .banner {
padding: 8px; padding: 8px;
z-index: 100; z-index: 100;
border-bottom: 1px solid #DDD; border-bottom: 1px solid #ddd;
&.warning { &.warning {
background: #FFD54F; background: #ffd54f;
border-color: #FBC02D; border-color: #fbc02d;
color: #263238; color: #263238;
} }
&.info { &.info {
background: #4FC3F7; background: #4fc3f7;
border-color: #0D47A1; border-color: #0d47a1;
color: #0D47A1; color: #0d47a1;
} }
} }

View file

@ -51,7 +51,7 @@ function DropdownItemForLink({navigate, ...props}) {
) )
} }
function Banner({text, style = 'warning'}: {text: string, style: 'warning' | 'info'}) { function Banner({text, style = 'warning'}: {text: string; style: 'warning' | 'info'}) {
return <div className={classnames(styles.banner, styles[style])}>{text}</div> return <div className={classnames(styles.banner, styles[style])}>{text}</div>
} }

View file

@ -47,7 +47,7 @@ class API {
async makeLoginUrl() { async makeLoginUrl() {
const config = await configPromise const config = await configPromise
const url = new URL(config.loginUrl || (config.apiUrl + '/login')) const url = new URL(config.loginUrl || config.apiUrl + '/login')
url.searchParams.append('next', window.location.href) // bring us back to the current page url.searchParams.append('next', window.location.href) // bring us back to the current page
return url.toString() return url.toString()
} }

View file

@ -26,13 +26,13 @@ export default function Avatar({user, className}) {
} }
if (!username) { if (!username) {
return <div className={classnames(className, "avatar", "empty-avatar")} /> return <div className={classnames(className, 'avatar', 'empty-avatar')} />
} }
const color = getColor(username) const color = getColor(username)
return ( return (
<div className={classnames(className, "avatar", "text-avatar")} style={{background: color}}> <div className={classnames(className, 'avatar', 'text-avatar')} style={{background: color}}>
{username && <span>{username[0]}</span>} {username && <span>{username[0]}</span>}
</div> </div>
) )

View file

@ -16,12 +16,10 @@
} }
} }
.avatar.empty-avatar { .avatar.empty-avatar {
background: #AAA; background: #aaa;
} }
.avatar.text-avatar, .avatar.text-avatar,
.avatar.empty-avatar { .avatar.empty-avatar {
// border-radius: 0.25rem; // border-radius: 0.25rem;
@ -40,4 +38,3 @@
height: 64px; height: 64px;
} }
} }

View file

@ -13,18 +13,18 @@ export default function ColorMapLegend({map}: {map: ColorMap}) {
<defs> <defs>
<linearGradient id="gradient" x1="0" x2="1" y1="0" y2="0"> <linearGradient id="gradient" x1="0" x2="1" y1="0" y2="0">
{map.map(([value, color]) => ( {map.map(([value, color]) => (
<stop key={value} offset={normalizeValue(value) * 100 + '%'} stop-color={color} /> <stop key={value} offset={normalizeValue(value) * 100 + '%'} stopColor={color} />
))} ))}
</linearGradient> </linearGradient>
</defs> </defs>
<rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(#gradient)" /> <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(#gradient)" />
</svg> </svg>
{map.map(([value]) => <span className={styles.tick} key={value} {map.map(([value]) => (
style={{left: normalizeValue(value)*100 + '%'}} <span className={styles.tick} key={value} style={{left: normalizeValue(value) * 100 + '%'}}>
> {value.toFixed(2)}
{value.toFixed(2)} </span>
</span>)} ))}
</div> </div>
) )
} }

View file

@ -1,18 +1,25 @@
import React from 'react' import React from 'react'
import {Button} from 'semantic-ui-react' import {Button} from 'semantic-ui-react'
import api from 'api' import api from 'api'
export default function LoginButton(props) { export default function LoginButton(props) {
const [busy, setBusy] = React.useState(false) const [busy, setBusy] = React.useState(false)
const onClick = React.useCallback(async (e) => { const onClick = React.useCallback(
e.preventDefault() async (e) => {
setBusy(true) e.preventDefault()
const url = await api.makeLoginUrl() setBusy(true)
window.location.href = url const url = await api.makeLoginUrl()
setBusy(false) window.location.href = url
}, [setBusy]) setBusy(false)
},
[setBusy]
)
return <Button onClick={busy ? null : onClick} loading={busy} {...props}>Login</Button> return (
<Button onClick={busy ? null : onClick} loading={busy} {...props}>
Login
</Button>
)
} }

View file

@ -12,7 +12,11 @@ import {baseMapStyles} from '../../mapstyles'
import styles from './styles.module.less' import styles from './styles.module.less'
interface Viewport {longitude: number; latitude: number; zoom: number} interface Viewport {
longitude: number
latitude: number
zoom: number
}
const EMPTY_VIEWPORT: Viewport = {longitude: 0, latitude: 0, zoom: 0} const EMPTY_VIEWPORT: Viewport = {longitude: 0, latitude: 0, zoom: 0}
export const withBaseMapStyle = connect((state) => ({baseMapStyle: state.mapConfig?.baseMap?.style ?? 'positron'})) export const withBaseMapStyle = connect((state) => ({baseMapStyle: state.mapConfig?.baseMap?.style ?? 'positron'}))
@ -32,7 +36,7 @@ function buildHash(v: Viewport): string {
return `${v.zoom.toFixed(2)}/${v.latitude}/${v.longitude}` return `${v.zoom.toFixed(2)}/${v.latitude}/${v.longitude}`
} }
function useViewportFromUrl(): [Viewport|null, (v: Viewport) => void] { function useViewportFromUrl(): [Viewport | null, (v: Viewport) => void] {
const history = useHistory() const history = useHistory()
const location = useLocation() const location = useLocation()
const value = useMemo(() => parseHash(location.hash), [location.hash]) const value = useMemo(() => parseHash(location.hash), [location.hash])

View file

@ -4,9 +4,26 @@ import {Container} from 'semantic-ui-react'
import styles from './Page.module.less' import styles from './Page.module.less'
export default function Page({small, children, fullScreen, stage}: {small?: boolean, children: ReactNode, fullScreen?: boolean,stage?: ReactNode}) { export default function Page({
small,
children,
fullScreen,
stage,
}: {
small?: boolean
children: ReactNode
fullScreen?: boolean
stage?: ReactNode
}) {
return ( return (
<main className={classnames(styles.page, small && styles.small, fullScreen && styles.fullScreen,stage && styles.hasStage)}> <main
className={classnames(
styles.page,
small && styles.small,
fullScreen && styles.fullScreen,
stage && styles.hasStage
)}
>
{stage} {stage}
{fullScreen ? children : <Container>{children}</Container>} {fullScreen ? children : <Container>{children}</Container>}
</main> </main>

View file

@ -1,14 +1,16 @@
import React from 'react' import React from 'react'
export type MapSoure = { export type MapSoure =
type: 'vector' | {
url: string, type: 'vector'
} | { url: string
type: 'vector', }
tiles: string[], | {
minzoom: number, type: 'vector'
maxzoom: number, tiles: string[]
} minzoom: number
maxzoom: number
}
export interface Config { export interface Config {
apiUrl: string apiUrl: string
@ -22,7 +24,7 @@ export interface Config {
privacyPolicyUrl?: string privacyPolicyUrl?: string
banner?: { banner?: {
text: string text: string
style?: "warning" | "info" style?: 'warning' | 'info'
} }
} }

View file

@ -8,18 +8,17 @@ import viridisBase from 'colormap/res/res/viridis'
export {bright, positron} export {bright, positron}
export const baseMapStyles = {bright, positron} export const baseMapStyles = {bright, positron}
function simplifyColormap(colormap, maxCount = 16) { function simplifyColormap(colormap, maxCount = 16) {
const result = [] const result = []
const step = Math.ceil(colormap.length / maxCount) const step = Math.ceil(colormap.length / maxCount)
for (let i = 0; i < colormap.length; i+= step) { for (let i = 0; i < colormap.length; i += step) {
result.push(colormap[i]) result.push(colormap[i])
} }
return result return result
} }
function rgbArrayToColor(arr) { function rgbArrayToColor(arr) {
return ['rgb', ...arr.map(v => Math.round(v*255))] return ['rgb', ...arr.map((v) => Math.round(v * 255))]
} }
export function colormapToScale(colormap, value, min, max) { export function colormapToScale(colormap, value, min, max) {
@ -27,24 +26,19 @@ export function colormapToScale(colormap, value, min, max) {
'interpolate-hcl', 'interpolate-hcl',
['linear'], ['linear'],
value, value,
...colormap.flatMap((v, i, a) => [ ...colormap.flatMap((v, i, a) => [(i / (a.length - 1)) * (max - min) + min, v]),
(i / (a.length - 1)) * (max - min) + min,
v,
])
] ]
} }
export const viridis = simplifyColormap(viridisBase.map(rgbArrayToColor), 20); export const viridis = simplifyColormap(viridisBase.map(rgbArrayToColor), 20)
export const grayscale = ['#FFFFFF', '#000000'] export const grayscale = ['#FFFFFF', '#000000']
export const reds = [['rgba', 255, 0, 0, 0], ['rgba', 255, 0, 0, 1]] export const reds = [
['rgba', 255, 0, 0, 0],
['rgba', 255, 0, 0, 1],
]
export function colorByCount(attribute = 'event_count', maxCount, colormap = viridis) { export function colorByCount(attribute = 'event_count', maxCount, colormap = viridis) {
return colormapToScale( return colormapToScale(colormap, ['case', ['to-boolean', ['get', attribute]], ['get', attribute], 0], 0, maxCount)
colormap,
['case', ['to-boolean', ['get', attribute]], ['get', attribute], 0],
0,
maxCount
)
} }
export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC') { export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC') {
@ -68,13 +62,12 @@ export function colorByDistance(attribute = 'distance_overtaker_mean', fallback
] ]
} }
export const trackLayer = { export const trackLayer = {
type: 'line', type: 'line',
paint: { paint: {
'line-width': ['interpolate', ['linear'], ['zoom'], 14, 2, 17, 5], 'line-width': ['interpolate', ['linear'], ['zoom'], 14, 2, 17, 5],
'line-color': '#F06292', 'line-color': '#F06292',
} },
} }
export const basemap = positron export const basemap = positron

View file

@ -1,4 +1,4 @@
@import "styles.less"; @import 'styles.less';
.welcomeMap { .welcomeMap {
height: 60rem; height: 60rem;

View file

@ -5,9 +5,7 @@ import {Redirect} from 'react-router-dom'
import api from 'api' import api from 'api'
const LogoutPage = connect( const LogoutPage = connect((state) => ({loggedIn: Boolean(state.login)}))(function LogoutPage({loggedIn}) {
(state) => ({loggedIn: Boolean(state.login)}),
)(function LogoutPage({loggedIn}) {
React.useEffect(() => { React.useEffect(() => {
// no await, just trigger it // no await, just trigger it
if (loggedIn) { if (loggedIn) {

View file

@ -107,16 +107,18 @@ function LayerSidebar({
<Header as="h4">Event points</Header> <Header as="h4">Event points</Header>
</label> </label>
</List.Item> </List.Item>
{showEvents && <><List.Item> {showEvents && (
<ColorMapLegend map={_.chunk(colorByDistance('distance_overtaker')[3].slice(3), 2)} /> <>
</List.Item> <List.Item>
</>} <ColorMapLegend map={_.chunk(colorByDistance('distance_overtaker')[3].slice(3), 2)} />
</List.Item>
</>
)}
</List> </List>
</div> </div>
) )
} }
export default connect( export default connect(
(state) => ({ (state) => ({
mapConfig: _.merge( mapConfig: _.merge(

View file

@ -88,7 +88,7 @@ const getEventsTextLayer = () => ({
'text-keep-upright': false, 'text-keep-upright': false,
'text-anchor': 'left', 'text-anchor': 'left',
'text-radial-offset': 1, 'text-radial-offset': 1,
'text-rotate': ['-', 90, ['*', ['get', 'course'], 180/Math.PI]], 'text-rotate': ['-', 90, ['*', ['get', 'course'], 180 / Math.PI]],
'text-rotation-alignment': 'map', 'text-rotation-alignment': 'map',
}, },
paint: { paint: {

View file

@ -2,7 +2,7 @@
.mapContainer { .mapContainer {
height: calc(100vh - @menuHeight); height: calc(100vh - @menuHeight);
background: #F0F0F3; background: #f0f0f3;
position: relative; position: relative;
display: flex; display: flex;
align-items: stretch; align-items: stretch;
@ -28,4 +28,3 @@
overflow: auto; overflow: auto;
margin: 20px; margin: 20px;
} }

View file

@ -54,7 +54,13 @@ const SettingsPage = connect((state) => ({login: state.login}), {setLogin})(func
<Form onSubmit={handleSubmit(onSave)} loading={loading}> <Form onSubmit={handleSubmit(onSave)} loading={loading}>
<Ref innerRef={findInput(register)}> <Ref innerRef={findInput(register)}>
<Form.Input error={errors?.username} label="Username" name="username" defaultValue={login.username} disabled /> <Form.Input
error={errors?.username}
label="Username"
name="username"
defaultValue={login.username}
disabled
/>
</Ref> </Ref>
<Form.Field error={errors?.bio}> <Form.Field error={errors?.bio}>
<label>Bio</label> <label>Bio</label>
@ -148,7 +154,7 @@ function ApiKeyDialog({login, onGenerateNewKey}) {
<CopyInput label="Personal API Key" value={login.apiKey} /> <CopyInput label="Personal API Key" value={login.apiKey} />
</Ref> </Ref>
) : ( ) : (
<Message warning content='You have no API Key, please generate one below.' /> <Message warning content="You have no API Key, please generate one below." />
) )
) : ( ) : (
<Button onClick={onClick}> <Button onClick={onClick}>

View file

@ -1,7 +1,20 @@
import React from 'react' import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import {connect} from 'react-redux' import {connect} from 'react-redux'
import {Divider, Message, Confirm, Grid, Button, Icon, Popup, Form, Ref, TextArea, Checkbox, Header} from 'semantic-ui-react' import {
Divider,
Message,
Confirm,
Grid,
Button,
Icon,
Popup,
Form,
Ref,
TextArea,
Checkbox,
Header,
} from 'semantic-ui-react'
import {useHistory, useParams, Link} from 'react-router-dom' import {useHistory, useParams, Link} from 'react-router-dom'
import {concat, of, from} from 'rxjs' import {concat, of, from} from 'rxjs'
import {pluck, distinctUntilChanged, map, switchMap} from 'rxjs/operators' import {pluck, distinctUntilChanged, map, switchMap} from 'rxjs/operators'

View file

@ -20,10 +20,7 @@ export default function TrackDetails({track, isAuthor}) {
{track.originalFileName != null && ( {track.originalFileName != null && (
<List.Item> <List.Item>
{isAuthor && ( {isAuthor && <div style={{float: 'right'}}></div>}
<div style={{float: 'right'}}>
</div>
)}
<List.Header>Original Filename</List.Header> <List.Header>Original Filename</List.Header>
<code>{track.originalFileName}</code> <code>{track.originalFileName}</code>
@ -72,7 +69,6 @@ export default function TrackDetails({track, isAuthor}) {
</List.Item> </List.Item>
)} )}
{track?.processingStatus != null && track?.processingStatus != 'error' && ( {track?.processingStatus != null && track?.processingStatus != 'error' && (
<List.Item> <List.Item>
<List.Header>Processing</List.Header> <List.Header>Processing</List.Header>

View file

@ -1,4 +1,4 @@
@import "styles.less"; @import 'styles.less';
.stage { .stage {
position: relative; position: relative;

View file

@ -26,9 +26,15 @@ function TracksPageTabs() {
return ( return (
<Menu pointing secondary> <Menu pointing secondary>
<Menu.Item name="/tracks" active={!isOwnTracksPage} {...{onClick}}>Tracks</Menu.Item> <Menu.Item name="/tracks" active={!isOwnTracksPage} {...{onClick}}>
Tracks
</Menu.Item>
<Menu.Item name="/my/tracks" active={isOwnTracksPage} {...{onClick}} /> <Menu.Item name="/my/tracks" active={isOwnTracksPage} {...{onClick}} />
<Menu.Item name="/upload" position='right' {...{onClick}}><Button color='green' compact size='small'>Upload</Button></Menu.Item> <Menu.Item name="/upload" position="right" {...{onClick}}>
<Button color="green" compact size="small">
Upload
</Button>
</Menu.Item>
</Menu> </Menu>
) )
} }
@ -131,7 +137,8 @@ export function TrackListItem({track, privateTracks = false}) {
)} )}
<span style={{marginLeft: '1em'}}> <span style={{marginLeft: '1em'}}>
<Icon color={COLOR_BY_STATUS[track.processingStatus]} name="bolt" fitted /> Processing {track.processingStatus} <Icon color={COLOR_BY_STATUS[track.processingStatus]} name="bolt" fitted /> Processing{' '}
{track.processingStatus}
</span> </span>
</Item.Extra> </Item.Extra>
)} )}

View file

@ -1,15 +1,15 @@
@obsColorB4: #114594; @obsColorB4: #114594;
@obsColorG1: #76520E; @obsColorG1: #76520e;
@obsColorW: #FFFFFF; @obsColorW: #ffffff;
@obsColorB1: #122037; @obsColorB1: #122037;
@obsColorG6: #EFB509; @obsColorG6: #efb509;
@obsColorS: #000000; @obsColorS: #000000;
@primaryColor: @obsColorB4; @primaryColor: @obsColorB4;
@secondaryColor: @obsColorG1; @secondaryColor: @obsColorG1;
@borderColor: #E0E0E0; @borderColor: #e0e0e0;
@menuHeight: 50px; @menuHeight: 50px;
@mobile: ~"screen and (max-width: 767px)"; @mobile: ~'screen and (max-width: 767px)';
@desktop: ~"screen and (min-width: 768px)"; @desktop: ~'screen and (min-width: 768px)';

View file

@ -7,9 +7,9 @@ export type UserProfile = {
} }
export type TrackData = { export type TrackData = {
track: Feature<LineString>, track: Feature<LineString>
measurements: FeatureCollection, measurements: FeatureCollection
overtakingEvents: FeatureCollection, overtakingEvents: FeatureCollection
} }
export type Track = { export type Track = {
@ -30,12 +30,12 @@ export type Track = {
} }
export type TrackPoint = { export type TrackPoint = {
type: 'Feature', type: 'Feature'
geometry: Point, geometry: Point
properties: { properties: {
distanceOvertaker: null | number, distanceOvertaker: null | number
distanceStationary: null | number, distanceStationary: null | number
}, }
} }
export type TrackComment = { export type TrackComment = {