import React, {useContext} from "react";
import {
APIButton,
ErrorMessage,
HandPointMessage,
humanFileSize,
IframeViewer,
InfoMessage,
InfoPopup,
PageContainer,
TabLinks,
useTitle,
WROLModeMessage
} from "./Common";
import {Route, Routes} from "react-router";
import {getMapImportStatus, importMapFiles} from "../api";
import {
Checkbox,
Divider,
Icon as SIcon,
Loader as SLoader,
TableCell,
TableFooter,
TableHeaderCell,
TableRow
} from "semantic-ui-react";
import {SortableTable} from "./SortableTable";
import Message from "semantic-ui-react/dist/commonjs/collections/Message";
import {Header, Loader, Segment} from "./Theme";
import {StatusContext} from "../contexts/contexts";
import _ from "lodash";
import {MAP_VIEWER_URI} from "./Vars";
function DockerMapImportWarning() {
const {status} = useContext(StatusContext);
if (status['dockerized']) {
return
Maps are not fully supported in a Docker container!
Only one PBF can be imported and displayed in the docker container.
To import a map file, run the following docker-compose commands:
docker-compose stop map
docker-compose rm map
docker-compose run --rm -v /absolute/path/to/map.osm.pbf:/data.osm.pbf
-v openstreetmap-data:/var/lib/postgresql/12/main map import
Be sure to change /absolute/path/to/map.osm.pbf!
After you have imported a new PBF file, you need to clear the rendered tile cache:
docker volume rm openstreetmap-rendered-tiles
docker volume create openstreetmap-rendered-tiles
Start your map container:
docker-compose up -d map
You can merge multiple PBF files using osmium (the merged file can then be imported):
osmium merge file1.osm.pbf file2.osm.pbf -o merged.osm.pbf
;
}
return <>>;
}
function DownloadMessage() {
return
Where do I get map files?
You can download map files from
https://download.geofabrik.de/
Download only the areas you need. Large regions like all of Asia, or the entire
planet are most likely too large and won't render quickly. It is recommend to only
import files less than 1GB on a Raspberry Pi.
Only *.osm.pbf files are supported!
Place downloaded map files into map/pbf so they can be imported here.
}
const ViewerMessage = () => {
return
You can view the Map at {MAP_VIEWER_URI}
}
function SlowImportMessage() {
const {status} = useContext(StatusContext);
if (status && status['cpu_stats'] && status['cpu_stats']['temperature'] >= 80) {
return
CPU temperature is too high
Any import may take much more time because the CPU is throttled.
If your import takes more time than estimated, you will need an aftermarket cooler.
}
return <>>
}
class ManageMap extends React.Component {
constructor(props) {
super(props);
this.state = {
files: null,
pending: null,
import_running: false,
selectedPaths: [],
dockerized: null,
}
}
async componentDidMount() {
await this.fetchImportStatus();
this.intervalId = setInterval(this.fetchImportStatus, 1000 * 30);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
fetchImportStatus = async () => {
try {
const importStatus = await getMapImportStatus();
this.setState({
files: importStatus['files'],
pending: importStatus['pending'],
import_running: importStatus['import_running'],
dockerized: importStatus['dockerized'],
});
} catch (e) {
console.error(e);
this.setState({files: undefined});
}
}
import = async (e) => {
if (e) {
e.preventDefault();
}
this.setState({'ready': false});
const {files, selectedPaths} = this.state;
if (_.isEmpty(selectedPaths)) {
// No files are selected, import all.
let paths = [];
for (let i = 0; i < files.length; i++) {
paths = paths.concat([files[i].path]);
}
await importMapFiles(paths);
} else {
await importMapFiles(selectedPaths);
}
await this.fetchImportStatus();
}
handleCheckbox = (checked, pbf) => {
let {selectedPaths} = this.state;
if (checked === true) {
selectedPaths = selectedPaths.concat([pbf.path]);
} else {
const index = selectedPaths.indexOf(pbf.path);
if (index > -1) {
selectedPaths.splice(index, 1);
}
}
this.setState({selectedPaths});
}
render() {
const {files, selectedPaths, import_running, pending, dockerized} = this.state;
const importingMessage = pending ?
pending.length > 1 ? 'Importing...' : `Importing ${pending[0]}`
: null;
let disabled = dockerized || _.isEmpty(files) || import_running;
let importButton =
{!_.isEmpty(selectedPaths) ? 'Import Selected' : 'Import All'}
;
let spaceInfoPopup = ;
let timeInfoPopup = ;
const tableHeaders = [
{key: 'select', text: '', sortBy: null},
{key: 'path', text: 'PBF File', sortBy: i => i.path.toLowerCase()},
{key: 'imported', text: 'Imported', sortBy: i => i.imported ? 1 : 0},
{key: 'size', text: 'Size', sortBy: i => i.size || 0},
{key: 'space', text: <>Space Required {spaceInfoPopup}>, sortBy: i => i.size || 0},
{key: 'time', text: <>Time to Import {timeInfoPopup}>, sortBy: i => i.seconds_to_import || 0},
];
const rowFunc = (pbf) => {
let ref = React.createRef();
const {size, path, imported, time_to_import} = pbf;
let sizeCells = (<>
{humanFileSize(size)}
{humanFileSize(size * 25)}
{time_to_import}
>);
return
this.handleCheckbox(data.checked, pbf)}
/>
{path}
{pending && pending.indexOf(path) >= 0 ?
:
imported ? 'yes' : 'no'}
{size !== null ? sizeCells : }
;
};
const emptyRow =
No PBF map files were found in map/pbf
;
const footer =
{importButton}
;
// Handle error state (files === undefined)
if (files === undefined) {
return
Could not fetch map files
;
}
return
{importingMessage}
}
}
function MapPage() {
const fallback =
Failed to fetch Map service.
You may need to give permission to access the page: {MAP_VIEWER_URI}
Map startup is delayed on boot, if you have just started your WROLPi try again in a few minutes.
If the above does not work, try starting the service:
sudo systemctl start renderd
sudo systemctl start apache2
Check the logs
journalctl -u renderd
sudo tail -f /var/log/apache2/*log
;
return
}
export function MapRoute() {
useTitle('Map');
const links = [
{text: 'Map', to: '/map', key: 'map', end: true},
{text: 'Manage', to: '/map/manage', key: 'manage'},
];
return
}/>
}/>
}