diff --git a/public/favicon.ico b/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..024bc75ef8673d4c4be9d578c42c05be84569963 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..a72cfc2ec3abcdf83a52fd53644a13f9844d6224 Binary files /dev/null and b/public/favicon.png differ diff --git a/public/index.html b/public/index.html index 624e8a0d931011a538149b4b305ddba45719f1d1..81367c0e66931164fd5132902ec4b76ec30599df 100644 --- a/public/index.html +++ b/public/index.html @@ -19,7 +19,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>TACS</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> diff --git a/public/wimma.png b/public/wimma.png new file mode 100644 index 0000000000000000000000000000000000000000..9e687d39389b915f8effc5121d56fd999f16205e Binary files /dev/null and b/public/wimma.png differ diff --git a/src/components/DrawTools.js b/src/components/DrawTools.js index 00ee52aa71938a5e4159edaaf65464381c1b525b..ca30541e4519e54fc2517c61ad1280c82cacb1ba 100644 --- a/src/components/DrawTools.js +++ b/src/components/DrawTools.js @@ -65,11 +65,12 @@ class DrawTools extends Component { constructor(props) { super(props); this.state = { - geoJSONAll: [] // property for all GeoJSON data in the map + geoJSONAll: [], // property for all GeoJSON data in the map + editModeActive: false }; } - _onCreated = e => { + _onCreated(e) { // check if a drawn polyline has just one point in it if (e.layerType === "polyline" && e.layer.getLatLngs().length === 1) { e.layer.remove(); @@ -117,23 +118,100 @@ class DrawTools extends Component { // turning layer data to GeoJSON this.makeGeoJSON(e.layer); - }; // end _onCreated + } // end _onCreated - makeGeoJSON = e => { + _onEditMove(e) { + console.log("_onEditMove e:"); + console.log(e); + // to be added once back-end has functionality to recognize ids + // this.props.sendGeoJSON(e.layer); + } + + _onEditResize(e) { + console.log("_onEditResize e:"); + console.log(e); + } + + _onEditVertex(e) { + console.log("_onEditVertex e:"); + console.log(e); + // to be added once back-end has functionality to recognize ids + // this.props.sendGeoJSON(e.poly); + } + + _onEditDeleteStart() { + this.setState({ editModeActive: true }); + } + + _onEditDeleteStop() { + this.setState({ editModeActive: false }); + } + + _onDeleted(e) { + console.log(e.layers._layers); + /* to be added once back-end functionality is available + for(layer in e.layers._layers) { + this.sendGeoJSON(layer.options.id); + } + */ + } + + shouldComponentUpdate() { + // disable re-rendering when edit mode is active + return !this.state.editModeActive; + } + + // turn layer to GeoJSON data and add it to an array of all GeoJSON data of the current map + makeGeoJSON(e) { let geoJSON = e.toGeoJSON(); - let newGeoJSONAll = this.state.geoJSONAll; - newGeoJSONAll.push(geoJSON); // can't do +=, need to use push function - console.log(JSON.stringify(newGeoJSONAll, null, 4)); - this.setState({ geoJSONAll: newGeoJSONAll }); - }; + console.log( + "UserMapille lähetettävä layeri: " + JSON.stringify(geoJSON, null, 4) + ); // printing GeoJSON data of the previous object create + this.props.sendGeoJSON(geoJSON); + } + + addFetchedLayerToMap(id, feature) { + if (feature.geometry.type === "Point") { + // GeoJSON saves latitude first, not longitude like usual. swapping + let position = [ + feature.geometry.coordinates[1], + feature.geometry.coordinates[0] + ]; + // keys are required to be able to edit + return <Marker key={Math.random()} position={position} id={id} />; + } else if (feature.geometry.type === "Polygon") { + // polygons have, for some reason, an extra single element array above other arrays. no other objects have this + let coords = feature.geometry.coordinates[0]; + let positions = coords.map(item => { + return [item[1], item[0]]; + }); + return <Polygon key={Math.random()} positions={positions} id={id} />; + } else if (feature.geometry.type === "LineString") { + let coords = feature.geometry.coordinates; + let positions = coords.map(item => { + return [item[1], item[0]]; + }); + return <Polyline key={Math.random()} positions={positions} id={id} />; + } + } render() { return ( - // "It's important to wrap EditControl component into FeatureGroup component from react-leaflet. The elements you draw will be added to this FeatureGroup layer, when you hit edit button only items in this layer will be edited." + // "It's important to wrap EditControl component into FeatureGroup component from react-leaflet. + // The elements you draw will be added to this FeatureGroup layer, + // when you hit edit button only items in this layer will be edited." <FeatureGroup> <EditControl position="topright" onCreated={this._onCreated} + onEditStart={this._onEditDeleteStart} + onEditStop={this._onEditDeleteStop} + onEditMove={this._onEditMove} + onEditResize={this._onEditResize} + onEditVertex={this._onEditVertex} + onDeleted={this._onDeleted} + onDeleteStart={this._onEditDeleteStart} + onDeleteStop={this._onEditDeleteStop} draw={{ circle: { repeatMode: true, // allows using the tool again after finishing the previous shape @@ -170,6 +248,16 @@ class DrawTools extends Component { circlemarker: false }} /> + + {/* iterate through every element fetched from back-end */} + {this.props.geoJSONLayer.features.map((feature, arrayIndex) => { + // first element in geoJSONLayer has an extra one element array for some reason + if (arrayIndex === 0) { + return this.addFetchedLayerToMap(feature[0], feature[1][0]); + } else { + return this.addFetchedLayerToMap(feature[0], feature[1]); + } + })} </FeatureGroup> ); } diff --git a/src/components/LoginForm.js b/src/components/LoginForm.js index 7dca5868027d18c729ad3cbb43913ec3edd63f24..91f1a5afb7d88635498b182dc62448b8e786ab37 100644 --- a/src/components/LoginForm.js +++ b/src/components/LoginForm.js @@ -90,14 +90,15 @@ export class LoginForm extends React.Component { </div> <div className='login'> <form onSubmit={this.handleLogin}> - <h1>demo login</h1> + <h1>login</h1> <br /> <input placeholder='Enter Username' name='username' value={this.state.username} onChange={this.handleChange} - id='loginUsernameInput' + autoFocus + required /> <br /> <input diff --git a/src/components/RegisterForm.js b/src/components/RegisterForm.js index a2706f12668bdfe6306cd7b2c9d6c0d405da08f1..e6da5577e2b9fa6a43f7f99b9c283f32dc4886b2 100644 --- a/src/components/RegisterForm.js +++ b/src/components/RegisterForm.js @@ -104,7 +104,8 @@ export class RegisterForm extends React.Component { name='username' value={this.state.username} onChange={this.handleChange} - id='registerUsernameInput' + autoFocus + required /> <br /> <input diff --git a/src/components/UserMap.js b/src/components/UserMap.js index 4b3e690ea038c66268066abdda38bedb7a22cdfa..2fc500b8db0a944b9b51a8559ec1b184681d0877 100644 --- a/src/components/UserMap.js +++ b/src/components/UserMap.js @@ -6,12 +6,19 @@ import DrawTools from "./DrawTools.js"; class UserMap extends Component { constructor(props) { super(props); + this.state = { ownLat: null, ownLng: null, - mapUrl: "https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg" + mapUrl: "https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg", + geoJSONLayer: { + type: "FeatureCollection", + features: [] + } }; + this.sendGeoJSON = this.sendGeoJSON.bind(this); + this.setCurrentPosition = this.setCurrentPosition.bind(this); this.watchPositionId = null; } @@ -19,6 +26,49 @@ class UserMap extends Component { this.getCurrentPosition(position => { this.setCurrentPosition(position); }); + this.fetchGeoJSON(); + } + // Sends the players drawings to the backend (and database) + sendGeoJSON(layerToDatabase) { + fetch("http://localhost:5000/draw/mapdrawing/insert-location", { + method: "PUT", + headers: { + Authorization: "Bearer " + sessionStorage.getItem("token"), + Accept: "application/json", + "Content-Type": "application/json" + }, + // need to add id once back-end is ready for it + body: JSON.stringify({ + type: "FeatureCollection", + features: layerToDatabase + }) + }); + } + // Get the drawings from the backend and add them to the state, so they can be drawn + fetchGeoJSON() { + fetch("http://localhost:5000/draw/mapdrawing/insert-location", { + method: "GET", + headers: { + Authorization: "Bearer " + sessionStorage.getItem("token"), + Accept: "application/json", + "Content-Type": "application/json" + } + }) + .then(res => res.json()) + .then(data => { + console.log(data); + let newFeatures = []; + data.map(item => { + newFeatures.push([item.id, item.features]); + }); + + this.setState({ + geoJSONLayer: { + type: "FeatureCollection", + features: [...newFeatures] + } + }); + }); } componentWillUnmount() { @@ -49,36 +99,25 @@ class UserMap extends Component { navigator.geolocation.clearWatch(this.watchPositionId); } - if(this.watchPositionId != null){navigator.geolocation.clearWatch(this.watchPositionId);} - - this.watchPositionId = navigator.geolocation.watchPosition((position) =>{ - //success - if(position != null){ - callback(position); - } - }, (error) =>{ - console.log(error); - // disable tracking - if(this.watchPositionId != null){ - navigator.geolocation.clearWatch(this.watchPositionId); - } - }, options); + this.watchPositionId = navigator.geolocation.watchPosition( + position => { + //success + if (position != null) { + callback(position); + } + }, + error => { + console.log(error); + // disable tracking + if (this.watchPositionId != null) { + navigator.geolocation.clearWatch(this.watchPositionId); + } + }, + options + ); } } - positionToGeoJSON(position) { - let geoJSON = { - type: "Feature", - properties: {}, - geometry: { - type: "Point", - coordinates: [position.coords.longitude, position.coords.latitude] - } - }; - - return JSON.stringify(geoJSON); - } - testers = asd => { console.log(asd.target.getZoom()); }; @@ -86,24 +125,23 @@ class UserMap extends Component { render() { return ( <Map - className='map' + className="map" center={this.props.position} zoom={this.props.zoom} - minZoom='7' - maxZoom='17' - zoomControl={false}> + minZoom="7" + maxZoom="17" + zoomControl={false} + > <TileLayer attribution='© <a href="https://www.maanmittauslaitos.fi/">Maanmittauslaitos</a>' url={this.props.mapUrl} /> - <ZoomControl position="topright" /> - <DrawTools position={this.props.position} /> - <Marker position={this.props.position}> - <Popup> - Se on perjantai, my dudes <br /> - </Popup> - </Marker> + <DrawTools + position={this.props.position} + sendGeoJSON={this.sendGeoJSON} + geoJSONLayer={this.state.geoJSONLayer} + /> {this.state.ownLat !== null && ( <Marker position={[this.state.ownLat, this.state.ownLng]}> <Popup> diff --git a/src/icons/color-icon-2.png b/src/icons/color-icon-2.png new file mode 100644 index 0000000000000000000000000000000000000000..6623db24a39f19eb6f46f539c0eb3d7a0e9620bf Binary files /dev/null and b/src/icons/color-icon-2.png differ diff --git a/src/icons/color-icon.png b/src/icons/color-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..28e54479f3d7fbfecc52694f51a7c6d2dbec1a34 Binary files /dev/null and b/src/icons/color-icon.png differ