Add exports page

This commit is contained in:
Paul Bienkowski 2022-02-22 17:52:13 +01:00
parent 8135d4ed51
commit a884ac88d8
4 changed files with 182 additions and 0 deletions

View file

@ -1,5 +1,11 @@
# Changelog
## 0.4.1 (TBD)
### Features
* Add page for exporting data through web frontend
## 0.4.0
### Improvements

View file

@ -11,6 +11,7 @@ import {useConfig} from 'config'
import styles from './App.module.less'
import {
ExportPage,
HomePage,
LoginRedirectPage,
LogoutPage,
@ -84,6 +85,10 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {
Tracks
</Link>
<Link component={MenuItemForLink} to="/export" as="a">
Export
</Link>
<Menu.Menu position="right">
{login ? (
<>
@ -127,6 +132,9 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {
<Route path={`/tracks/:slug/edit`} exact>
<TrackEditor />
</Route>
<Route path="/export" exact>
<ExportPage />
</Route>
<Route path="/redirect" exact>
<LoginRedirectPage />
</Route>

View file

@ -0,0 +1,167 @@
import React, { useState, useCallback, useMemo } from "react";
import { Source, Layer } from "react-map-gl";
import _ from "lodash";
import { Button, Form, Dropdown, Header } from "semantic-ui-react";
import { useConfig } from "config";
import { Page, Map } from "components";
const BoundingBoxSelector = React.forwardRef(
({ value, name, onChange }, ref) => {
const [pointNum, setPointNum] = useState(0);
const [point0, setPoint0] = useState(null);
const [point1, setPoint1] = useState(null);
const onClick = (e) => {
if (pointNum == 0) {
setPoint0(e.lngLat);
} else {
setPoint1(e.lngLat);
}
setPointNum(1 - pointNum);
};
React.useEffect(() => {
if (!point0 || !point1) return;
const bbox = `${point0[0]},${point0[1]},${point1[0]},${point1[1]}`;
if (bbox !== value) {
onChange(bbox);
}
}, [point0, point1]);
React.useEffect(() => {
const [p00, p01, p10, p11] = value
.split(",")
.map((v) => Number.parseFloat(v));
if (!point0 || point0[0] != p00 || point0[1] != p01)
setPoint0([p00, p01]);
if (!point1 || point1[0] != p10 || point1[1] != p11)
setPoint1([p10, p11]);
}, [value]);
return (
<div>
<Form.Input label="Bounding box" {...{ name, value, onChange }} />
<div style={{ height: 400, position: "relative", marginBottom: 16 }}>
<Map onClick={onClick}>
<Source
id="bbox"
type="geojson"
data={
point0 && point1
? {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[point0[0], point0[1]],
[point1[0], point0[1]],
[point1[0], point1[1]],
[point0[0], point1[1]],
[point0[0], point0[1]],
],
],
},
},
],
}
: {}
}
>
<Layer
id="bbox"
type="line"
paint={{
"line-width": 4,
"line-color": "#F06292",
}}
/>
</Source>
</Map>
</div>
</div>
);
}
);
const MODES = [
{
key: "events",
text: "Events",
value: "events",
},
];
const FORMATS = [
{
key: "geojson",
text: "GeoJSON",
value: "geojson",
},
{
key: "shapefile",
text: "Shapefile (ZIP)",
value: "shapefile",
},
];
export default function ExportPage() {
const [mode, setMode] = useState("events");
const [bbox, setBbox] = useState("8.294678,49.651182,9.059601,50.108249");
const [fmt, setFmt] = useState("geojson");
const config = useConfig();
const exportUrl = `${config?.apiUrl}/export/events?bbox=${bbox}&fmt=${fmt}`;
return (
<Page>
<Header as="h2">Export</Header>
<p>
This page allows you to export parts of the public dataset. Please note
the license.
</p>
<Form>
<Form.Field>
<label>Mode</label>
<Dropdown
placeholder="Select mode"
fluid
selection
options={MODES}
value={mode}
onChange={(_e, { value }) => setMode(value)}
/>
</Form.Field>
<Form.Field>
<label>Format</label>
<Dropdown
placeholder="Select format"
fluid
selection
options={FORMATS}
value={fmt}
onChange={(_e, { value }) => setFmt(value)}
/>
</Form.Field>
<BoundingBoxSelector value={bbox} onChange={setBbox} />
<Button
primary
as="a"
href={exportUrl}
target="_blank"
rel="noreferrer noopener"
>
Export
</Button>
</Form>
</Page>
);
}

View file

@ -1,3 +1,4 @@
export {default as ExportPage} from './ExportPage'
export {default as HomePage} from './HomePage'
export {default as LoginRedirectPage} from './LoginRedirectPage'
export {default as LogoutPage} from './LogoutPage'