Translate region frontend
This commit is contained in:
parent
e0070fc794
commit
6d71b88010
6 changed files with 95 additions and 68 deletions
|
@ -1,46 +1,36 @@
|
||||||
import React, { useState, useCallback } from "react";
|
import React, {useState, useCallback} from 'react'
|
||||||
import { pickBy } from "lodash";
|
import {pickBy} from 'lodash'
|
||||||
import {
|
import {Loader, Statistic, Pagination, Segment, Header, Menu, Table, Icon} from 'semantic-ui-react'
|
||||||
Loader,
|
import {useObservable} from 'rxjs-hooks'
|
||||||
Statistic,
|
import {of, from, concat, combineLatest} from 'rxjs'
|
||||||
Pagination,
|
import {map, switchMap, distinctUntilChanged} from 'rxjs/operators'
|
||||||
Segment,
|
import {Duration, DateTime} from 'luxon'
|
||||||
Header,
|
|
||||||
Menu,
|
|
||||||
Table,
|
|
||||||
Icon,
|
|
||||||
} from "semantic-ui-react";
|
|
||||||
import { useObservable } from "rxjs-hooks";
|
|
||||||
import { of, from, concat, combineLatest } from "rxjs";
|
|
||||||
import { map, switchMap, distinctUntilChanged } from "rxjs/operators";
|
|
||||||
import { Duration, DateTime } from "luxon";
|
|
||||||
|
|
||||||
import api from "api";
|
import api from 'api'
|
||||||
|
import {useTranslation} from 'react-i18next'
|
||||||
|
|
||||||
function formatDuration(seconds) {
|
function formatDuration(seconds) {
|
||||||
return (
|
return (
|
||||||
Duration.fromMillis((seconds ?? 0) * 1000)
|
Duration.fromMillis((seconds ?? 0) * 1000)
|
||||||
.as("hours")
|
.as('hours')
|
||||||
.toFixed(1) + " h"
|
.toFixed(1) + ' h'
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Stats() {
|
export default function Stats() {
|
||||||
const [page, setPage] = useState(1);
|
const {t} = useTranslation()
|
||||||
const PER_PAGE = 10;
|
const [page, setPage] = useState(1)
|
||||||
|
const PER_PAGE = 10
|
||||||
const stats = useObservable(
|
const stats = useObservable(
|
||||||
() =>
|
() => of(null).pipe(switchMap(() => concat(of(null), from(api.get('/stats/regions'))))),
|
||||||
of(null).pipe(
|
|
||||||
switchMap(() => concat(of(null), from(api.get("/stats/regions"))))
|
|
||||||
),
|
|
||||||
null
|
null
|
||||||
);
|
)
|
||||||
|
|
||||||
const pageCount = stats ? Math.ceil(stats.length / PER_PAGE) : 1;
|
const pageCount = stats ? Math.ceil(stats.length / PER_PAGE) : 1
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header as="h2">Top Regions</Header>
|
<Header as="h2">{t('RegionStats.title')}</Header>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Loader active={stats == null} />
|
<Loader active={stats == null} />
|
||||||
|
@ -48,36 +38,36 @@ export default function Stats() {
|
||||||
<Table celled>
|
<Table celled>
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.HeaderCell>Region name</Table.HeaderCell>
|
<Table.HeaderCell> {t('RegionStats.regionName')}</Table.HeaderCell>
|
||||||
<Table.HeaderCell>Event count</Table.HeaderCell>
|
<Table.HeaderCell>{t('RegionStats.eventCount')}</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
|
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{stats
|
{stats?.slice((page - 1) * PER_PAGE, page * PER_PAGE)?.map((area) => (
|
||||||
?.slice((page - 1) * PER_PAGE, page * PER_PAGE)
|
<Table.Row key={area.id}>
|
||||||
?.map((area) => (
|
<Table.Cell>{area.name}</Table.Cell>
|
||||||
<Table.Row key={area.id}>
|
<Table.Cell>{area.overtaking_event_count}</Table.Cell>
|
||||||
<Table.Cell>{area.name}</Table.Cell>
|
</Table.Row>
|
||||||
<Table.Cell>{area.overtaking_event_count}</Table.Cell>
|
))}
|
||||||
</Table.Row>
|
|
||||||
))}
|
|
||||||
</Table.Body>
|
</Table.Body>
|
||||||
|
|
||||||
{pageCount > 1 && <Table.Footer>
|
{pageCount > 1 && (
|
||||||
<Table.Row>
|
<Table.Footer>
|
||||||
<Table.HeaderCell colSpan="2">
|
<Table.Row>
|
||||||
<Pagination
|
<Table.HeaderCell colSpan="2">
|
||||||
floated="right"
|
<Pagination
|
||||||
activePage={page}
|
floated="right"
|
||||||
totalPages={pageCount}
|
activePage={page}
|
||||||
onPageChange={(e, data) => setPage(data.activePage as number)}
|
totalPages={pageCount}
|
||||||
/>
|
onPageChange={(e, data) => setPage(data.activePage as number)}
|
||||||
</Table.HeaderCell>
|
/>
|
||||||
</Table.Row>
|
</Table.HeaderCell>
|
||||||
</Table.Footer>}
|
</Table.Row>
|
||||||
|
</Table.Footer>
|
||||||
|
)}
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,12 +72,12 @@ function LayerSidebar({
|
||||||
onChange={() => setMapConfigFlag('obsRegions.show', !showRegions)}
|
onChange={() => setMapConfigFlag('obsRegions.show', !showRegions)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="obsRegions.show">
|
<label htmlFor="obsRegions.show">
|
||||||
<Header as="h4">Regions</Header>
|
<Header as="h4">{t('MapPage.sidebar.obsRegions.title')}</Header>
|
||||||
</label>
|
</label>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
{showRegions && (
|
{showRegions && (
|
||||||
<>
|
<>
|
||||||
<List.Item>Color regions based on event count</List.Item>
|
<List.Item>{t('MapPage.sidebar.obsRegions.colorByEventCount')}</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<ColorMapLegend
|
<ColorMapLegend
|
||||||
twoTicks
|
twoTicks
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import React, { useState, useCallback } from "react";
|
import React from 'react'
|
||||||
import { createPortal } from "react-dom";
|
import {createPortal} from 'react-dom'
|
||||||
import _ from "lodash";
|
import {useTranslation} from 'react-i18next'
|
||||||
import { List, Header, Icon, Button } from "semantic-ui-react";
|
import {List, Header, Icon, Button} from 'semantic-ui-react'
|
||||||
|
|
||||||
import styles from "./styles.module.less";
|
import styles from './styles.module.less'
|
||||||
|
|
||||||
export default function RegionInfo({ region, mapInfoPortal, onClose }) {
|
export default function RegionInfo({region, mapInfoPortal, onClose}) {
|
||||||
|
const {t} = useTranslation()
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<div className={styles.closeHeader}>
|
<div className={styles.closeHeader}>
|
||||||
<Header as="h3">{region.properties.name || "Unnamed region"}</Header>
|
<Header as="h3">{region.properties.name || t('MapPage.regionInfo.unnamedRegion')}</Header>
|
||||||
<Button primary icon onClick={onClose}>
|
<Button primary icon onClick={onClose}>
|
||||||
<Icon name="close" />
|
<Icon name="close" />
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -17,17 +18,14 @@ export default function RegionInfo({ region, mapInfoPortal, onClose }) {
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Header>Number of events</List.Header>
|
<List.Header>{t('MapPage.regionInfo.eventCount')}</List.Header>
|
||||||
<List.Content>{region.properties.overtaking_event_count ?? 0}</List.Content>
|
<List.Content>{region.properties.overtaking_event_count ?? 0}</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
</List>
|
</List>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
|
|
||||||
return content && mapInfoPortal
|
return content && mapInfoPortal
|
||||||
? createPortal(
|
? createPortal(<div className={styles.mapInfoBox}>{content}</div>, mapInfoPortal)
|
||||||
<div className={styles.mapInfoBox}>{content}</div>,
|
: null
|
||||||
mapInfoPortal
|
|
||||||
)
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,10 @@ MapPage:
|
||||||
obsEvents:
|
obsEvents:
|
||||||
title: Überholvorgänge
|
title: Überholvorgänge
|
||||||
|
|
||||||
|
obsRegions:
|
||||||
|
title: Regionen
|
||||||
|
colorByEventCount: Regionen eingefärbt nach Anzahl Überholungen
|
||||||
|
|
||||||
filters:
|
filters:
|
||||||
title: Filter
|
title: Filter
|
||||||
needsLogin: Filter sind ohne Login nicht verfügbar.
|
needsLogin: Filter sind ohne Login nicht verfügbar.
|
||||||
|
@ -203,6 +207,10 @@ MapPage:
|
||||||
west: westwärts
|
west: westwärts
|
||||||
northWest: nordwestwärts
|
northWest: nordwestwärts
|
||||||
|
|
||||||
|
regionInfo:
|
||||||
|
unnamedRegion: Unbenannte Region
|
||||||
|
eventCount: Anzahl Überholungen
|
||||||
|
|
||||||
SettingsPage:
|
SettingsPage:
|
||||||
title: Einstellungen
|
title: Einstellungen
|
||||||
|
|
||||||
|
@ -343,3 +351,8 @@ TrackEditor:
|
||||||
vorhanden bleiben.
|
vorhanden bleiben.
|
||||||
|
|
||||||
**Nutze diese Funktion mit Bedacht und auf dein eigenes Risiko.**
|
**Nutze diese Funktion mit Bedacht und auf dein eigenes Risiko.**
|
||||||
|
|
||||||
|
RegionStats:
|
||||||
|
title: Top-Regionen
|
||||||
|
regionName: Region
|
||||||
|
eventCount: Anzahl Überholungen
|
||||||
|
|
|
@ -164,6 +164,10 @@ MapPage:
|
||||||
obsEvents:
|
obsEvents:
|
||||||
title: Event points
|
title: Event points
|
||||||
|
|
||||||
|
obsRegions:
|
||||||
|
title: Regions
|
||||||
|
colorByEventCount: Color regions are based on event count
|
||||||
|
|
||||||
filters:
|
filters:
|
||||||
title: Filters
|
title: Filters
|
||||||
needsLogin: No filters available without login.
|
needsLogin: No filters available without login.
|
||||||
|
@ -208,6 +212,10 @@ MapPage:
|
||||||
west: west bound
|
west: west bound
|
||||||
northWest: north-west bound
|
northWest: north-west bound
|
||||||
|
|
||||||
|
regionInfo:
|
||||||
|
unnamedRegion: Unnamed region
|
||||||
|
eventCount: Event count
|
||||||
|
|
||||||
SettingsPage:
|
SettingsPage:
|
||||||
title: Settings
|
title: Settings
|
||||||
|
|
||||||
|
@ -342,3 +350,8 @@ TrackEditor:
|
||||||
later.
|
later.
|
||||||
|
|
||||||
**Use at your own risk.**
|
**Use at your own risk.**
|
||||||
|
|
||||||
|
RegionStats:
|
||||||
|
title: Top regions
|
||||||
|
regionName: Region name
|
||||||
|
eventCount: Event count
|
||||||
|
|
|
@ -164,6 +164,10 @@ MapPage:
|
||||||
obsEvents:
|
obsEvents:
|
||||||
title: Points d'événement
|
title: Points d'événement
|
||||||
|
|
||||||
|
obsRegions:
|
||||||
|
title: Régions
|
||||||
|
colorByEventCount: Couleurs des régions sont basées sur le nombre d'événements
|
||||||
|
|
||||||
filters:
|
filters:
|
||||||
title: Filtres
|
title: Filtres
|
||||||
needsLogin: Aucun filtre disponible sans être connecté.
|
needsLogin: Aucun filtre disponible sans être connecté.
|
||||||
|
@ -208,6 +212,10 @@ MapPage:
|
||||||
west: Ouest
|
west: Ouest
|
||||||
northWest: Nord-Ouest
|
northWest: Nord-Ouest
|
||||||
|
|
||||||
|
regionInfo:
|
||||||
|
unnamedRegion: Région sans nom
|
||||||
|
eventCount: Nombre de dépassements
|
||||||
|
|
||||||
SettingsPage:
|
SettingsPage:
|
||||||
title: Paramètres
|
title: Paramètres
|
||||||
|
|
||||||
|
@ -343,3 +351,8 @@ TrackEditor:
|
||||||
ou les rendez anonymes plus tard.
|
ou les rendez anonymes plus tard.
|
||||||
|
|
||||||
**Utilisation à vos risques et périls.**
|
**Utilisation à vos risques et périls.**
|
||||||
|
|
||||||
|
RegionStats:
|
||||||
|
title: Top régions
|
||||||
|
regionName: Nom de la région
|
||||||
|
eventCount: Nombre de dépassements
|
||||||
|
|
Loading…
Add table
Reference in a new issue