feat: connection check and welcome pop-up

This commit is contained in:
arielherself 2023-11-24 20:06:22 +08:00
parent 18be7e13ee
commit 890c3b77c3
11 changed files with 170 additions and 60 deletions

12
.idea/frontend.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/frontend.iml" filepath="$PROJECT_DIR$/.idea/frontend.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -1,27 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="3c7078e7-6f30-4d92-9696-11496f9e6dff" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/nanomap/.idea/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/.idea/jsLibraryMappings.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/.idea/modules.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/.idea/nanomap.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/.idea/vcs.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/package-lock.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/package.json" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/public/favicon.ico" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/public/index.html" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.css" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.test.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/Networking.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/SimulateClick.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/UMap.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/index.css" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/index.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/logo.svg" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/App.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Networking.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/Networking.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/SimulateClick.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/SimulateClick.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/UMap.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/UMap.js" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -34,29 +23,29 @@
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 3
}]]></component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 3
}</component>
<component name="ProjectId" id="2Yc9rUDmr9wvYpz7Xdq1eJVJoJy" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"git-widget-placeholder": "dev",
"last_opened_file_path": "/home/user/Documents/fd_data-structures/pj/nanomap-frontend",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;git-widget-placeholder&quot;: &quot;dev&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/user/Documents/fd_data-structures/pj/frontend&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="RunManager">
<configuration name="start" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
@ -83,6 +72,8 @@
<option name="presentableId" value="Default" />
<updated>1700814200305</updated>
<workItem from="1700814201341" duration="315000" />
<workItem from="1700814808669" duration="47000" />
<workItem from="1700822693197" duration="4588000" />
</task>
<servers />
</component>

BIN
misc/icon.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
public/icon.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -6,7 +6,7 @@
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="shortcut icon" href="%PUBLIC_URL%/icon.jpeg">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
@ -16,7 +16,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>nanoMap</title>
</head>
<body>
<div id="root"></div>

View File

@ -1,18 +1,110 @@
import React, { Component } from 'react';
import logo from './logo.svg';
import React, {Component, useState} from 'react';
import {Transition} from 'react-transition-group';
import './App.css';
import UMap from "./UMap";
import {
Alert,
Box,
CircularProgress,
DialogContent,
DialogTitle,
Modal,
ModalDialog,
Sheet,
Typography
} from "@mui/joy";
import {WebhookOutlined} from "@mui/icons-material";
import {post} from "./Networking";
class App extends Component {
render() {
export default function App() {
const [featureOpen, setFeatureOpen] = useState(true);
const [version, setVersion] = useState('');
const [intro, setIntro] = useState('');
const hs=setInterval(()=>{
post('handshake', []).then((response)=>{
const [version,intro]=response.split('@@');
setVersion(version);
setIntro(intro);
clearInterval(hs);
}).catch((e)=> {
console.error(e);
setVersion('');
});
}, 1000);
return (
<div className="App">
<div className="App" style={{pointerEvents: version !== '' ? 'all' : 'none'}}>
<div style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<UMap/>
<Transition in={featureOpen} timeout={400}>
{(state) => (
<Modal style={{pointerEvents: version !== '' ? 'all' : 'none'}}
keepMounted
open={!['exited', 'exiting'].includes(state)}
onClose={() => setFeatureOpen(false)}
slotProps={{
backdrop: {
sx: {
opacity: 0,
backdropFilter: 'none',
transition: `opacity 400ms, backdrop-filter 400ms`,
...{
entering: {opacity: 1, backdropFilter: 'blur(8px)'},
entered: {opacity: 1, backdropFilter: 'blur(8px)'},
}[state],
},
},
}}
sx={{
visibility: state === 'exited' ? 'hidden' : 'visible',
zIndex: 'tooltip'
}}
>
<ModalDialog
sx={{
opacity: 0,
transition: `opacity 300ms`,
...{
entering: {opacity: 1},
entered: {opacity: 1},
}[state],
}}
>
<Alert style={{display: version!==''?'none':'flex'}}
variant="soft"
color="warning"
invertedColors
startDecorator={
<CircularProgress size="lg" color="warning">
<WebhookOutlined/>
</CircularProgress>
}
sx={{alignItems: 'flex-start', gap: '1rem'}}
>
<Box sx={{flex: 1}}>
<Typography level="title-lg">Still connecting...</Typography>
<Typography level="body-md">
nanoMap requires a valid backend to work. If it takes too long, please check
your connection or see our status page.
</Typography>
</Box>
</Alert>
<Sheet style={{display: version !== '' ? 'flex' : 'none'}}>
<img src={'icon.jpeg'}
style={{height: '150px', display: 'flex', margin: 'auto', borderRadius: '50%'}}
alt={'nanoMap'}/>
</Sheet>
<DialogTitle style={{display: version !== '' ? 'flex' : 'none'}}
sx={{margin: 'auto', fontSize: '200%'}}>What's new in
nanoMap {version}</DialogTitle>
<DialogContent style={{display: version !== '' ? 'flex' : 'none'}}
sx={{margin: 'auto'}}>
<div dangerouslySetInnerHTML={{ __html: intro }} />
</DialogContent>
</ModalDialog>
</Modal>
)}
</Transition>
</div>
</div>
);
}
}
export default App;

View File

@ -13,4 +13,4 @@ export function post(method,args) {
return response_data;
};
return ft();
};
}

View File

@ -1,12 +1,12 @@
import {Button, IconButton, ButtonGroup, Menu, MenuItem, Stack} from "@mui/joy";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import React from "react";
import {Add} from "@mui/icons-material";
export default function SimulateClick() {
return (
<ButtonGroup buttonFlex={1} aria-label="flex button group" sx={{zIndex: 'modal'}}>
<Button variant={'solid'} color={'success'}>Starting</Button>
<Button variant={'solid'} color={'primary'}>Destination</Button>
<Button variant={'solid'} color={'primary'} startDecorator={<Add />}>Add</Button>
</ButtonGroup>
);
}

View File

@ -1,4 +1,5 @@
import React, {Component, useEffect, useRef, useState} from 'react';
import * as L from 'leaflet';
import SearchIcon from '@mui/icons-material/Search';
import {MapContainer, TileLayer, Marker, Popup, useMap} from 'react-leaflet';
import {useMapEvents} from 'react-leaflet/hooks';
@ -7,7 +8,6 @@ import {Autocomplete, CircularProgress, Sheet} from "@mui/joy";
import SimulateClick from "./SimulateClick";
const AppleParkLoc=[37.334835049999995,-122.01139165956805];
class Markers extends Component {
constructor(props) {
super(props);
@ -16,12 +16,10 @@ class Markers extends Component {
render() {
const mks=this.state.markers.map((p, i) => (
<Marker position={[p[0], p[1]]} opacity={1.0}><Popup>Generated
by <code>Markers()</code></Popup></Marker>
<Marker interactive={false} position={[p[0], p[1]]} opacity={1.0} />
));
const cmks=this.state.candMarkers.map((p, i) => (
<Marker interactive={false} position={[p[0], p[1]]} opacity={0.5}><Popup>Generated
by <code>Markers()</code></Popup></Marker>
<Marker interactive={false} position={[p[0], p[1]]} opacity={0.5} />
));
return mks.concat(cmks);
}
@ -71,7 +69,10 @@ function MapClickHandler({mks}) {
const lat = e.latlng.lat, lng = e.latlng.lng;
console.info(`Clicking on ${lat} ${lng}`);
mks.current.addMarker(lat, lng);
post('click', [lat, lng]);
post('click', [lat, lng]).catch((e)=>{
console.error(e);
location.reload();
});
},
// TODO
locationfound: (location) => {