From 9279f600fe8a0b5d87abf3dabace25d8f2ea6d1a Mon Sep 17 00:00:00 2001 From: Jussi Surma-Aho <L4929@student.jamk.fi> Date: Fri, 5 Jul 2019 18:40:32 +0300 Subject: [PATCH] Edited and deleted elements now also get updated in the database. When editing or deleting a single element, it won't update in the map; need to fix --- src/App.js | 1 + src/components/DrawTools.js | 130 +++++++++++++++++++++--------------- src/components/GameList.js | 4 +- src/components/UserMap.js | 84 ++++++++++++----------- 4 files changed, 123 insertions(+), 96 deletions(-) diff --git a/src/App.js b/src/App.js index d849a33..b2d8e87 100644 --- a/src/App.js +++ b/src/App.js @@ -35,6 +35,7 @@ class App extends Component { }); }; + // function to be sent to Header -> GameList to get changed game ID handleGameChange = gameId => { this.setState({ currentGameId: gameId diff --git a/src/components/DrawTools.js b/src/components/DrawTools.js index b6b576b..a9d70f7 100644 --- a/src/components/DrawTools.js +++ b/src/components/DrawTools.js @@ -12,6 +12,7 @@ import { Tooltip } from "react-leaflet"; +// an empty icon for textboxes let noIcon = L.divIcon({ className: "", iconSize: [20, 20], @@ -81,7 +82,6 @@ class DrawTools extends Component { } _onCreated = e => { - console.log(e.layer); // check if a drawn polyline has just one point in it if (e.layerType === "polyline" && e.layer.getLatLngs().length === 1) { e.layer.remove(); @@ -121,12 +121,18 @@ class DrawTools extends Component { // manually removing it so that the placeholder text can show if ( tooltip.innerHTML === - '<div placeholder="Click out to save" contenteditable="true"><br></div>' || + '<div placeholder="Click out to save" contenteditable="true" id ="' + + e.layer._leaflet_id + + "><br></div>" || tooltip.innerHTML === - '<div placeholder="Click out to save" contenteditable="true"><div><br></div></div>' + '<div placeholder="Click out to save" contenteditable="true" id ="' + + e.layer._leaflet_id + + "><div><br></div></div>" ) { tooltip.innerHTML = - '<div placeholder="Click out to save" contenteditable="true"></div>'; + '<div placeholder="Click out to save" contenteditable="true" id ="' + + e.layer._leaflet_id + + "></div>"; } }); @@ -134,59 +140,46 @@ class DrawTools extends Component { // getting element by ID and adding an event listener to the element document .getElementById(e.layer._leaflet_id) - .addEventListener("blur", this.makeGeoJSON.bind(this, e)); // can't put this.makeGeoJSON(e) straight, as it calls the function + .addEventListener( + "blur", + this.makeGeoJSON.bind(this, e.layerType, e.layer) + ); // can't put this.makeGeoJSON(e) straight, as it calls the function document.getElementById(e.layer._leaflet_id).focus(); console.log(e.layer); - return; + return; // only sending the textbox to database until text has been written } // end if (e.layerType === "textbox") - // turning layer data to GeoJSON - this.makeGeoJSON(e); + this.makeGeoJSON(e.layerType, e.layer); }; // end _onCreated - // turn layer to GeoJSON data and add it to an array of all GeoJSON data of the current map - makeGeoJSON = e => { - let geoJSON = e.layer.toGeoJSON(); + // turn layer to GeoJSON data + makeGeoJSON = (layerType, layer) => { + // setting the format in which the data will be sent + let geoJSON = { + data: layer.toGeoJSON(), + mapDrawingId: layer.options.id + }; - if (e.layerType === "textbox") { - if (e.layer._tooltip._content.innerText) { - geoJSON.properties.text = e.layer._tooltip._content.innerText; + // setting properties + if (layerType === "textbox") { + if (layer._tooltip._content.innerText) { + geoJSON.data.properties.text = layer._tooltip._content.innerText; } else { return; } - } else if (e.layerType === "circle") { - geoJSON.properties.radius = e.layer.options.radius; - } else if (e.layerType === "rectangle") { - geoJSON.properties.rectangle = true; + } else if (layerType === "circle") { + geoJSON.data.properties.radius = layer._mRadius; // layer.options.radius doesn't update for some reason; need to use _mRadius instead + } else if (layerType === "rectangle") { + // rectangle is a simple true/false property to recognize a rectangle + // so that Polygons with this property can be inserted into map with rectangle functionalities instead of Polygon's + geoJSON.data.properties.rectangle = true; } + geoJSON.data.properties.color = layer.options.color; - geoJSON.properties.color = e.layer.options.color; - - console.log( - "UserMapille lähetettävä layeri: " + JSON.stringify(geoJSON, null, 4) - ); // printing GeoJSON data of the previous object create - e.layer.options.id = this.props.sendGeoJSON(geoJSON); - }; - - _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); + // send item to database, and receive an ID for the layer + this.props.sendGeoJSON(geoJSON, false); }; _onEditDeleteStart = () => { @@ -197,13 +190,44 @@ class DrawTools extends Component { this.setState({ editModeActive: false }); }; + _onEdited = e => { + // layers are saved in a rather curious format. they're not in an array, so need to make an array first + let editedLayers = e.layers; + let idsToEdit = []; + editedLayers.eachLayer(function(layer) { + idsToEdit.push(layer); + }); + + idsToEdit.map(layer => { + // checking the contents of the layer to determine its type, as it's not explicitly stated + if (layer.options.bounds) { + this.makeGeoJSON("rectangle", layer); + } else if (layer.options.radius) { + this.makeGeoJSON("circle", layer); + } else if (layer.options.text) { + this.makeGeoJSON("textbox", layer); + } else { + this.makeGeoJSON(null, layer); + } + }); + }; + _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); - } - */ + // layers are saved in a rather curious format. they're not in an array, so need to make an array first + let deletedLayers = e.layers; + let idsToDelete = []; + deletedLayers.eachLayer(function(layer) { + idsToDelete.push(layer); + }); + + idsToDelete.map(layer => { + let geoJSON = { + data: layer.toGeoJSON(), + mapDrawingId: layer.options.id + }; + + this.props.sendGeoJSON(geoJSON, true); + }); }; shouldComponentUpdate() { @@ -220,11 +244,9 @@ class DrawTools extends Component { <EditControl position="topright" onCreated={this._onCreated} + onEdited={this._onEdited} onEditStart={this._onEditDeleteStart} onEditStop={this._onEditDeleteStop} - onEditMove={this._onEditMove} - onEditResize={this._onEditResize} - onEditVertex={this._onEditVertex} onDeleted={this._onDeleted} onDeleteStart={this._onEditDeleteStart} onDeleteStop={this._onEditDeleteStop} @@ -273,8 +295,6 @@ class DrawTools extends Component { let color = feature.data.properties.color; let radius = feature.data.properties.radius; let text = feature.data.properties.text; - // rectangle is a simple true/false property to recognize a rectangle - // so that Polygons with this property can be inserted into map with rectangle functionalities let rectangle = feature.data.properties.rectangle; if (type === "Point") { @@ -318,6 +338,7 @@ class DrawTools extends Component { </Marker> ); } else { + // unknown if color changes anything. need to test return ( <Marker key={Math.random()} @@ -328,6 +349,7 @@ class DrawTools extends Component { ); } } else if (rectangle) { + // instead of an array of four coordinates, rectangles only have two corners let bounds = coords[0].map(coord => { return [coord[1], coord[0]]; }); diff --git a/src/components/GameList.js b/src/components/GameList.js index d5d94d7..acaca0c 100644 --- a/src/components/GameList.js +++ b/src/components/GameList.js @@ -39,12 +39,10 @@ class GameList extends React.Component { selectedGame: e.target.value }, () => { + // taking the changed gameID to UserMap.js (GameList.js -> Header.js -> App.js -> UserMap.js) this.props.handleGameChange(this.state.selectedGame); } ); - - // taking the initialized gameID to UserMap.js (GameList.js -> Header.js -> App.js -> UserMap.js) - // this.state.selectedGame gives belated response, for some reason }; handleEditClick = e => { diff --git a/src/components/UserMap.js b/src/components/UserMap.js index b39fff5..2ef9072 100644 --- a/src/components/UserMap.js +++ b/src/components/UserMap.js @@ -28,18 +28,8 @@ class UserMap extends Component { }); } - /* - shouldComponentUpdate(nextProps, nextState) { - if (nextProps.currentGameId !== this.props.currentGameId) { - // this.fetchGeoJSON(); - } - this.fetchGeoJSON(); - return true; - } - */ - componentDidUpdate() { - // console.log(this.props.currentGameId); + // check if game ID has changed and fetch that game's drawings if (this.state.currentGameId !== this.props.currentGameId) { this.setState({ currentGameId: this.props.currentGameId @@ -49,33 +39,49 @@ class UserMap extends Component { } // Sends the players drawings to the backend (and database) - sendGeoJSON(layerToDatabase) { - fetch("http://localhost:5000/draw/mapdrawing/" + this.props.currentGameId, { - method: "PUT", - headers: { - Authorization: "Bearer " + sessionStorage.getItem("token"), - Accept: "application/json", - "Content-Type": "application/json" - }, - body: JSON.stringify({ - type: "FeatureCollection", - drawingIsActive: true, - data: layerToDatabase - }) - }) - .then(res => { - console.log(res); - res.json(); - }) - .then(data => { - console.log(data); - console.log(data.mapDrawingId); - return data.mapDrawingId; - }) - .catch(error => { - console.log(error); - return; - }); + sendGeoJSON(layerToDatabase, isDeleted) { + // isDeleted is used to determine the drawing's drawingIsActive status + // otherwise the fetch functions are the same in both if and else. any smarter way to do this? + if (isDeleted === true) { + fetch( + "http://localhost:5000/draw/mapdrawing/" + this.props.currentGameId, + { + method: "PUT", + headers: { + Authorization: "Bearer " + sessionStorage.getItem("token"), + Accept: "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify({ + type: "FeatureCollection", + drawingIsActive: false, + mapDrawingId: layerToDatabase.mapDrawingId, + data: layerToDatabase.data + }) + } + ); + } else { + fetch( + "http://localhost:5000/draw/mapdrawing/" + this.props.currentGameId, + { + method: "PUT", + headers: { + Authorization: "Bearer " + sessionStorage.getItem("token"), + Accept: "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify({ + type: "FeatureCollection", + drawingIsActive: true, + mapDrawingId: layerToDatabase.mapDrawingId, + data: layerToDatabase.data + }) + } + ); + } + + // get the layers again to stop updating with old objects + this.fetchGeoJSON(); } // Get the drawings from the backend and add them to the state, so they can be drawn @@ -101,11 +107,11 @@ class UserMap extends Component { features: [...newFeatures] } }); - console.log(this.state.geoJSONLayer); }) .catch(error => { console.log(error); }); + console.log(this.state.geoJSONLayer); } componentWillUnmount() { -- GitLab