chore: initial commit
This commit is contained in:
parent
9362d44eb9
commit
7e63b3462d
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
|
||||
/*some stylesheet is required to use react-bootstrip components*/
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
import Contact from './pages/contact';
|
||||
import Home from './pages/home';
|
||||
import Map from './pages/map-page';
|
||||
import NavBar from './components/nav-bar';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
//BrowserRouter is the router implementation for HTML5 browsers
|
||||
//Link enables Routes on an anchor tag
|
||||
//Switch returns only the first matching route rather than all
|
||||
//Route is the conditionally shown component //based on matching a path to a URL
|
||||
<BrowserRouter>
|
||||
<NavBar />
|
||||
<Routes>
|
||||
<Route path="/" element={<Map />} />
|
||||
<Route path="/map" element={<Map />} />
|
||||
<Route path="/contact" element={<Contact />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 172.83 143.31" style="enable-background:new 0 0 172.83 143.31;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4E4697;}
|
||||
</style>
|
||||
<path class="st0" d="M159.98,95.78c-1.95-4.54-5.55-8.69-10.82-12.47c-1.88-1.34-4.64-2.92-8.28-4.8c4.58-2.89,7.92-5.35,9.99-7.37
|
||||
c3.94-3.77,6.51-7.74,7.72-11.91c1.23-4.21,1.18-8.44-0.14-12.8c-0.73-2.39-1.8-4.62-3.2-6.65l-1.6-2.07
|
||||
c-1.01-1.21-2.16-2.31-3.45-3.37c-4.04-3.29-9.07-5.2-15.09-5.73c-5.9-0.51-12.07,0.17-18.51,2.07c-0.05,0-0.06,0.02-0.11,0.02
|
||||
c-0.06,0.03-0.14,0.05-0.2,0.07c-3.81,1.17-7.61,2.64-11.07,4.39c-3.05,1.55-5.86,3.26-8.13,5.11l0.02,0.07h-0.02v82.31
|
||||
c5.55,3.8,12.43,7.3,21.44,9.12c7.12,1.45,13.78,1.5,19.98,0.13c5.33-1.17,9.82-3.27,13.48-6.35c0.62-0.48,1.22-1.03,1.79-1.58
|
||||
c3.28-3.24,5.55-6.89,6.83-10.96c0.29-0.86,0.52-1.73,0.71-2.64C162.38,105.2,161.92,100.33,159.98,95.78z M109.63,45.63
|
||||
c1.82-0.9,3.78-1.7,5.75-2.42c0.04-0.02,0.08-0.04,0.12-0.04l3.6-1.2c0.07-0.03,0.13-0.05,0.19-0.05
|
||||
c7.71-2.32,13.73-2.64,18.11-0.97c2.76,1.06,4.87,2.56,6.37,4.48c0.9,1.15,1.56,2.46,2,3.93c1.05,3.39,0.61,6.56-1.23,9.51
|
||||
c-0.5,0.81-1.4,2.15-2.13,2.93c-1.7,2.07-5.03,4.64-8.28,6.65c-2.34,1.45-4.91,2.64-7.57,3.36c-0.01,0.01-1.41,0.34-1.41,0.34
|
||||
c-2.18,0.63-8.53,0.69-15.52,0.66V45.63z M148.38,108.82c-0.55,2.75-1.87,5.12-3.93,7.13c-0.19,0.2-0.39,0.39-0.59,0.57
|
||||
c-2.38,2.15-5.67,3.56-9.81,4.23c-4.15,0.66-8.75,0.48-13.78-0.55c-2.7-0.55-6.72-2.19-10.64-4.08V83.79
|
||||
c3.96-0.09,7.5-0.15,10.71,0.1h0.07c0.39,0,0.77,0.01,1.16,0.04c2.67,0.17,5.38,0.86,7.98,1.89c0.01-0.01,0.02,0,0.04,0.01
|
||||
c4.37,1.72,8.56,4.3,11.54,7c2.27,1.97,4.48,4.53,5.78,6.81c0.15,0.23,0.28,0.46,0.4,0.7C148.65,102.96,149.01,105.81,148.38,108.82
|
||||
z"/>
|
||||
<ellipse transform="matrix(0.9347 -0.3553 0.3553 0.9347 0.6343 30.8075)" class="st0" cx="84.18" cy="13.68" rx="8.33" ry="8.33"/>
|
||||
<path class="st0" d="M91.15,38.16v84.61c0,5.54-3.12,10.04-6.97,10.04s-6.97-4.5-6.97-10.04V38.16c0-5.54,3.12-10.04,6.97-10.04
|
||||
S91.15,32.62,91.15,38.16z"/>
|
||||
<path class="st0" d="M23.43,49.65c-1.03,3.43-0.62,6.63,1.24,9.61c1.82,2.96,7.61,7.21,17.38,12.72
|
||||
c9.78,5.51,16.35,9.73,19.72,12.66c4.9,4.28,8.11,8.8,9.63,13.55c1.52,4.75,1.52,9.68-0.02,14.8c-1.52,5.08-4.44,9.41-8.75,13
|
||||
c-4.32,3.59-9.63,5.77-15.93,6.58c-6.3,0.81-12.93,0.14-19.88-1.98c-8.31-2.53-14.39-6.55-19.42-10.64
|
||||
c-0.05-0.04-0.1-0.08-0.15-0.12c-0.25-0.2-0.5-0.4-0.74-0.6c-3.26-2.86-4.49-6.86-2.71-9.32c1.93-2.67,6.77-2.28,10.6,0.38
|
||||
c0.38,0.3,1.87,1.47,2.52,1.94c3.71,2.71,8.45,5.56,12.7,6.85c4.91,1.5,9.47,2.11,13.66,1.82c4.19-0.29,7.58-1.4,10.17-3.34
|
||||
c2.58-1.93,4.32-4.37,5.2-7.33c0.9-2.99,0.8-5.87-0.3-8.66c-1.1-2.77-3.46-5.54-7.07-8.3c-2.32-1.79-7.63-5.1-15.94-9.93
|
||||
c-8.31-4.84-13.98-8.73-17-11.69c-3.93-3.8-6.51-7.82-7.73-12.05c-1.22-4.23-1.17-8.54,0.15-12.92c1.44-4.82,4.19-8.89,8.23-12.23
|
||||
c4.05-3.34,9.07-5.27,15.08-5.8c6.01-0.54,12.4-0.16,18.84,2.19c4.28,1.56,6.41,2.42,8.33,3.25c1.12,0.48,3.12,1.27,4.82,1.98
|
||||
c0.22,0.09,0.98,0.41,1.06,0.45c4.23,1.95,6.71,5.58,5.59,8.25c-1.09,2.57-5.18,3.34-9.37,1.83c-0.05-0.02-0.11-0.04-0.17-0.06
|
||||
c-3.65-1.15-5.71-2.17-13.07-4.42c-7.79-2.37-13.89-2.7-18.29-0.99C27.41,42.87,24.61,45.7,23.43,49.65z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -0,0 +1,35 @@
|
|||
import getIconUrl from './icon-url';
|
||||
|
||||
/*return icon object*/
|
||||
export default function getIcon(ptByIfleet){
|
||||
if(ptByIfleet===undefined || ptByIfleet===null){
|
||||
//console.log('getIcon(): ptByIfleet NOT available')
|
||||
return null;
|
||||
}
|
||||
else{
|
||||
//console.log('getIcon(): ptByIfleet available')
|
||||
const icon = new L.Icon({
|
||||
/*path to icon graphic*/
|
||||
iconUrl: getIconUrl(ptByIfleet.route_type),
|
||||
/*path to graphic used for high resolution monitors*/
|
||||
iconRetinaUrl: getIconUrl(ptByIfleet.route_type),
|
||||
popupAnchor: [-0, -0],
|
||||
/*size of the icon in width and hight*/
|
||||
iconSize: [32,32],
|
||||
/*determine how the popup is positions relative to the actual point on the map*/
|
||||
popupAnchor:[0,-10],
|
||||
/*determine how the image is positions relative to the actual point on the map*/
|
||||
iconAnchor: null,
|
||||
/*path to shadow graphic*/
|
||||
shadowUrl: null,
|
||||
/*size of the shadow in width and hight*/
|
||||
shadowSize: null,
|
||||
/*determine how the mage is positions relative to the actual point on the map*/
|
||||
shadowAnchor: null,
|
||||
className: 'marker-msg'
|
||||
});
|
||||
//console.log('getIcon(): icon available')
|
||||
return icon;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import bfly from '../../assets/Logo_SIB_electricindigo.svg';
|
||||
import bus from '../../assets/bus.svg';
|
||||
import train from '../../assets/train.svg';
|
||||
import tram from '../../assets/tram.svg';
|
||||
|
||||
/* return URL that fits GTFS route_type*/
|
||||
export default function getIconUrl(routeTypeEnum){
|
||||
//console.log('getIconUrl() routeTypeEnum: '+routeTypeEnum);
|
||||
return routeTypeEnum===0?tram:
|
||||
routeTypeEnum===1?bfly:
|
||||
routeTypeEnum===2?train:
|
||||
routeTypeEnum===3?bus:
|
||||
bfly;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import bfly from '../../assets/Logo_SIB_electricindigo.svg';
|
||||
|
||||
/*return icon object*/
|
||||
export default function getIcon(){
|
||||
//console.log('getIcon(): ptByIfleet available')
|
||||
const icon = new L.Icon({
|
||||
/*path to icon graphic*/
|
||||
iconUrl: bfly,
|
||||
/*path to graphic used for high resolution monitors*/
|
||||
iconRetinaUrl: bfly,
|
||||
popupAnchor: [-0, -0],
|
||||
/*size of the icon in width and hight*/
|
||||
iconSize: [32,32],
|
||||
/*determine how the popup is positions relative to the actual point on the map*/
|
||||
popupAnchor:[0,-10],
|
||||
/*determine how the image is positions relative to the actual point on the map*/
|
||||
iconAnchor: null,
|
||||
/*path to shadow graphic*/
|
||||
shadowUrl: null,
|
||||
/*size of the shadow in width and hight*/
|
||||
shadowSize: null,
|
||||
/*determine how the mage is positions relative to the actual point on the map*/
|
||||
shadowAnchor: null,
|
||||
className: 'marker-msg'
|
||||
});
|
||||
//console.log('getIcon(): icon available')
|
||||
return icon;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/*set up the height of*/
|
||||
.leaflet-container {
|
||||
height: 85vh;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {MapContainer,TileLayer} from 'react-leaflet';
|
||||
/*JS module import (vs cdn or style link)*/
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import './map.css';
|
||||
|
||||
import MarkerElem from './marker-elem';
|
||||
|
||||
export default function Map({elements}) {
|
||||
/*lat and lon of Braunschweig,DE*/
|
||||
const position = [52.26594, 10.52673]
|
||||
//TODO make this switch available via configuration!
|
||||
const hasGtfs = false;
|
||||
return (
|
||||
<>
|
||||
<MapContainer
|
||||
center={position}
|
||||
zoom={10}
|
||||
minZoom={2}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{
|
||||
elements.map(function(value,key) {
|
||||
//console.log(`key: ${key}, tripId: ${value.tripId}`);
|
||||
return <MarkerElem key={value.id} index={value.id} element={value}/>;
|
||||
})
|
||||
}
|
||||
</MapContainer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Map.propTypes = {
|
||||
elements: PropTypes.array
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Marker} from 'react-leaflet';
|
||||
|
||||
import PopupElem from './popup-elem';
|
||||
import getIcon from './icon';
|
||||
|
||||
export default function MarkerElemPlus({element}){
|
||||
if(element===undefined || element===null){
|
||||
console.error('element undefined or null');
|
||||
return null;
|
||||
}else{
|
||||
const markerIcon=getIcon();
|
||||
if(markerIcon===null){
|
||||
//TODO Handle issue!
|
||||
console.error('ERROR: icon null');
|
||||
return null;
|
||||
}else if(element.lat===undefined||element.lat===null){
|
||||
//TODO Handle issue!
|
||||
console.error('ERROR: element lat undefined or null');
|
||||
return null;
|
||||
}else if(element.lon===undefined||element.lon===null){
|
||||
//TODO Handle issue!
|
||||
console.error('ERROR: element lon undefined or null');
|
||||
return null;
|
||||
}else{
|
||||
return(
|
||||
<>
|
||||
<Marker
|
||||
position={[element.lat,element.lon]}
|
||||
icon={markerIcon}
|
||||
>
|
||||
<PopupElem element={element} />
|
||||
</Marker>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
MarkerElemPlus.propTypes = {
|
||||
element: PropTypes.object
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
import React, {useEffect,useState} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import MarkerElemPlus from './marker-elem-plus';
|
||||
|
||||
export default function MarkerElem({ element }){
|
||||
if(element===undefined || element===null){
|
||||
console.error('element undefined or null');
|
||||
return null;
|
||||
}else{
|
||||
return(
|
||||
<>
|
||||
<MarkerElemPlus
|
||||
element={element}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
MarkerElem.propTypes = {
|
||||
element: PropTypes.object
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Popup} from 'react-leaflet';
|
||||
|
||||
export default function PopupElem({element}){
|
||||
return (
|
||||
<>
|
||||
<Popup>
|
||||
id: {element.id} <br/>
|
||||
name: {element.name} <br/>
|
||||
lat: {element.lat} <br/>
|
||||
lon: {element.lon}
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
PopupElem.propTypes = {
|
||||
element: PropTypes.object
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import { Navbar, Nav } from 'react-bootstrap';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
|
||||
function NavigationBar () {
|
||||
return (
|
||||
<Navbar collapseOnSelect fixed="top" bg="dark" expand="xxl" variant="dark">
|
||||
//TODO make brand available through configuration
|
||||
<Navbar.Brand href="/">GOMPASS</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
<Nav className="mr-auto">
|
||||
<LinkContainer to="/map">
|
||||
<Nav.Link>Second Hand</Nav.Link>
|
||||
</LinkContainer>
|
||||
</Nav>
|
||||
<Nav className="mr-auto">
|
||||
<LinkContainer to="/contact">
|
||||
<Nav.Link>Contact</Nav.Link>
|
||||
</LinkContainer>
|
||||
</Nav>
|
||||
</Navbar.Collapse>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
export default NavigationBar;
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './app';
|
||||
//TODO remove debugging
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('development mode');
|
||||
}
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App tab="home" />
|
||||
</React.StrictMode>
|
||||
);
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import packageInfo from '../../package.json'
|
||||
const VERSION = packageInfo.version;
|
||||
const Contact = () => {
|
||||
return (
|
||||
<>
|
||||
<h2>About this website</h2>
|
||||
|
||||
<p>
|
||||
For questions about this website please do not hesitate to reach out to dialog (at) swingbe (dot) de.
|
||||
</p>
|
||||
<h2>Imprint</h2>
|
||||
<address>
|
||||
<strong>
|
||||
Stefan Begerad, Software Ingenieur Begerad
|
||||
</strong>
|
||||
<br />
|
||||
c/o WTF Kooperative eG, Hinterhaus, 3. OG
|
||||
<br />
|
||||
Forsmannstr. 14b
|
||||
<br />
|
||||
22303 Hamburg
|
||||
<br />
|
||||
Deutschland
|
||||
<br />
|
||||
</address>
|
||||
<h2>Other</h2>
|
||||
<p>
|
||||
Version: {VERSION}
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default Contact;
|
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<h1>Home</h1>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
import React, {useEffect,useState} from 'react';
|
||||
import axios from 'axios';
|
||||
import qs from 'qs';
|
||||
|
||||
import Map from '../components/map/map';
|
||||
|
||||
const data = qs.stringify(
|
||||
{
|
||||
'data': '[bbox:51.990800124058914,10.045623779296875,52.552976197007524,11.01104736328125][out:json];(node["shop"="second_hand"];way["shop"="second_hand"];relation["shop"="second_hand"];);out center;'
|
||||
}
|
||||
);
|
||||
|
||||
//TODO Make fields available via configuration!
|
||||
const interval=3600000;
|
||||
const opInstance='https://overpass-api.de/api/interpreter';
|
||||
const opInstanceZ='https://z.overpass-api.de/api/interpreter';
|
||||
const config = {
|
||||
method: 'post',
|
||||
maxBodyLength: Infinity,
|
||||
url: opInstanceZ,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
data : data
|
||||
};
|
||||
|
||||
function parseOsmElem(response){
|
||||
let elemAry=[];
|
||||
if(response.data){
|
||||
let elements=response.data.elements;
|
||||
let no=elements.length;
|
||||
//console.log('no: '+no);
|
||||
for(let i = 0; i < no; i++) {
|
||||
let elemObj={};
|
||||
elemObj.id=elements[i].id;
|
||||
elemObj.name=elements[i].tags.name;
|
||||
if(elements[i].tags.name===undefined){
|
||||
//TODO Handle issue!
|
||||
console.error('ERROR: OSM element does NOT include name tag');
|
||||
}else if(elements[i].type==='node'){
|
||||
elemObj.lat=elements[i].lat;
|
||||
elemObj.lon=elements[i].lon;
|
||||
}else if(elements[i].type==='way'){
|
||||
elemObj.lat=elements[i].center.lat;
|
||||
elemObj.lon=elements[i].center.lon;
|
||||
}else{
|
||||
console.error('ERROR: OSM element NOT supported');
|
||||
}
|
||||
//console.log('elem name: '+elemObj.name);
|
||||
//console.log('elem lat: '+elemObj.lat);
|
||||
//console.log('elem lon: '+elemObj.lon);
|
||||
elemAry.push(elemObj);
|
||||
//console.error('elemAry no: '+elemAry.length);
|
||||
}
|
||||
}else{
|
||||
console.error('ERROR: response NOT available');
|
||||
}
|
||||
return elemAry;
|
||||
};
|
||||
|
||||
export default function MapPage() {
|
||||
/*storage*/
|
||||
const [ary, setAry] = useState([]);
|
||||
const getData= async ()=>{
|
||||
//console.log('getData() start...');
|
||||
try {
|
||||
/*TODO handle errors: https://www.valentinog.com/blog/await-react/*/
|
||||
const res = await axios(config);
|
||||
let elemAry=parseOsmElem(res);
|
||||
setAry((ary) => elemAry);
|
||||
} catch (err) {
|
||||
console.error('ERROR: err.message: ' + err.message);
|
||||
}
|
||||
//console.log('getData() done.');
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
/*do not wait the interval when component loads the first time*/
|
||||
getData();
|
||||
|
||||
/*refresh data periodically*/
|
||||
const intervalCall=setInterval(()=>{
|
||||
getData();
|
||||
}, interval);
|
||||
/*TODO adjust interval, make it available via config file*/
|
||||
return ()=>{
|
||||
/*clean up*/
|
||||
clearInterval(intervalCall);
|
||||
};
|
||||
},[]);
|
||||
return (
|
||||
<>
|
||||
<Map elements={ary}/>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
//generate a HTML5 file including all webpack bundles in the body using script tags
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
//path is used to resolve properly across the OS
|
||||
const path = require('path');
|
||||
module.exports = {
|
||||
//bundle *.js from this entry point
|
||||
entry: path.resolve(__dirname, '../app/index.jsx'),
|
||||
//create output file to be linked to index.html
|
||||
output: {
|
||||
filename: '[name].bundle.js',
|
||||
path: path.resolve(__dirname, '../dist'),
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
//test all *.js using babel-loader
|
||||
//test all *.jsx (e.g. React.js) using babel-loader
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
include: path.resolve(__dirname, '../app'),
|
||||
use: ['babel-loader'],
|
||||
},
|
||||
{
|
||||
//test all *.css using style-loader and css-loader
|
||||
test: /\.css$/i,
|
||||
use: ["style-loader", "css-loader"],
|
||||
},
|
||||
{
|
||||
//test all *.svg using svg-loader
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'svg-url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['*', '.js', '.jsx'],
|
||||
},
|
||||
plugins: [
|
||||
// create a plugin instance so that you can use it several times anywhere
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Production',
|
||||
template: path.resolve(__dirname, "../public/index.html")
|
||||
}),
|
||||
],
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
//path is used to resolve properly across the OS
|
||||
const path = require('path');
|
||||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
//merge() calls in the environment-specific configuration to include commons
|
||||
module.exports = merge(common, {
|
||||
//set development mode
|
||||
mode: 'development',
|
||||
//enable strong source mapping
|
||||
devtool: 'inline-source-map',
|
||||
devServer: {
|
||||
static: path.resolve(__dirname, '../build'),
|
||||
},
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
//source maps encouraged in production
|
||||
//choose mapping with fairly quick build speed like source-map
|
||||
devtool: 'source-map',
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "gompass",
|
||||
"description": "gompass",
|
||||
"version": "0.1.0",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
"public",
|
||||
"compass",
|
||||
"gompass"
|
||||
],
|
||||
"author": "Software Ingenieur Begerad <dialog@SwIngBe.de>",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "webpack serve --config config/webpack.dev.js",
|
||||
"build": "webpack --config config/webpack.prod.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.19.1",
|
||||
"@babel/preset-env": "7.19.1",
|
||||
"@babel/preset-react": "7.18.6",
|
||||
"babel-loader": "8.2.5",
|
||||
"css-loader": "6.7.1",
|
||||
"html-webpack-plugin": "5.5.0",
|
||||
"style-loader": "3.3.1",
|
||||
"svg-url-loader": "8.0.0",
|
||||
"webpack": "5.74.0",
|
||||
"webpack-cli": "4.10.0",
|
||||
"webpack-dev-server": "4.11.0",
|
||||
"webpack-merge": "5.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "0.27.2",
|
||||
"bootstrap": "5.2.1",
|
||||
"leaflet": "1.8.0",
|
||||
"qs": "^6.11.0",
|
||||
"react": "18.2.0",
|
||||
"react-bootstrap": "2.5.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-leaflet": "4.0.2",
|
||||
"react-router-bootstrap": "0.26.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- load resources for bootstrap -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
|
||||
crossorigin="anonymous">
|
||||
<!-- avoid content hiding behind react-bootstrap navbar -->
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 100px;
|
||||
}
|
||||
</style>
|
||||
<title>Gompass</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue