Skip to content

Commit

Permalink
Merge pull request #15 from aloxe/tiles-attribution
Browse files Browse the repository at this point in the history
Dropfile and upload geojson
  • Loading branch information
aloxe authored Jun 18, 2024
2 parents 8ace4ac + 74c0f22 commit 0c2394c
Show file tree
Hide file tree
Showing 20 changed files with 1,235 additions and 600 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-dropzone": "^14.2.3",
"react-router-dom": "^6.23.1",
"@mapbox/togeojson": "^0.16.2",
"turf-line-distance": "^3.0.12"
Expand Down
12 changes: 12 additions & 0 deletions public/datavelo/api/login.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
$login = $_POST["login"];
$line = fgets(fopen('../../../../homes/psswd', 'r'));

if ($login == $line) {
$data = array('status' => 201, 'message' => '🐝 login ok');
} else {
$data = array("status"=> '0', "message"=> '🕸️ not logged');
}

echo json_encode($data);
?>
18 changes: 18 additions & 0 deletions public/datavelo/api/renamegpx.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
$json = json_decode(file_get_contents("php://input"));
if (isset($json->name))
$name = $json->name;
if (isset($json->slug))
$slug = $json->slug;

$path = '../gpx/'.$name;
$newpath = '../gpx/'.$slug.'.gpx';

if (rename($path, $newpath)) {
$data = array('status' => 201, 'message' => '🐝 File renamed « '.$newpath.' »');
} else {
$data = array("status"=> '0', "message"=> '🐛 File NOT renamed '.$path.''.$newpath);
}

echo json_encode($data);
?>
26 changes: 26 additions & 0 deletions public/datavelo/api/uploadfile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
$name = $_FILES['file']['name'];

if (substr($name, -4, 4) == ".gpx") {
// temporarly follow naming scheme on gpx
if (substr($name, -7, 1) == ".") {
$cc = substr($name, -7, 3);
$root = substr($name, 0, -7);
} else {
$cc = ".xx";
$root = substr($name, 0, -4);
}
$newname = $root.'-php'.$cc.'.gpx';
$newpath = '../gpx/'.$newname;

if (move_uploaded_file( $_FILES['file']['tmp_name'], $newpath)) {
$data = array('status' => 201, 'message' => '🐝 File written ('.$name.')', 'name' => $newname);
} else {
$data = array("status"=> '0', "message"=> '🐛 File NOT saved '.$newname);
}
} else {
$data = array("status"=> '0', "message"=> '🐛 File NOT saved (not a gpx)');
}

echo json_encode($data);
?>
30 changes: 30 additions & 0 deletions public/datavelo/api/uploadjson.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
$json = json_decode(file_get_contents("php://input"));

if (isset($json->slug))
$slug = $json->slug;
if (isset($json->title))
$title = $json->title;
if (isset($json->type))
$type = $json->type;

if (isset($type) && isset($slug)) {
if ($type == "FeatureCollection") {
$filename = "../json/".$slug.".json";
$encodedJSON = json_encode($json, JSON_PRETTY_PRINT);
$fp = fopen($filename, "w") or die("Données non écrites");
$write = fwrite($fp, $encodedJSON);

$data = array('status' => 201, 'message' => '🐝 File written', 'title' => $title, 'filename' => $filename);

fclose($fp);
chmod($filename, 0777);
} else {
$data = array("status"=> '0', "message"=> '🐛 File NOT written (wrong type) '.$slug);
}
} else {
$data = array("status"=> '0', "message"=> '🐛 File NOT written '.$slug);
}

echo json_encode($data);
?>
94 changes: 94 additions & 0 deletions src/components/FileUpload.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
.upload {
position: absolute;
top: 0;
width: 75vw;
max-height: 80vh;
padding: 1em;
}

.upload .footer {
position: fixed;
bottom: 10px;
left: 10px;
width: 200px;
}

.dropzone {
height: 100px;
margin: 0 auto;
background-color: azure;
border: 2px dotted skyblue;
}

.dropzone:hover {
background-color: whitesmoke;
border: 2px solid skyblue;
}

.selected-file {
margin-top: 40px;
font-weight: 500;
}

.progress {
margin: 2px auto;
margin-top: -5px;
width: calc(100% + 1px);
background: aliceblue;
justify-content: flex-start;
align-items: center;
position: relative;
padding: 0;
display: flex;
height: 7px;
}

.progress-value {
animation: load 1s normal forwards;
background: skyblue;
height: 7px;
font-size: xx-small;
color: white;
}

@keyframes load {
0% { width: 0; }
100% { width: 100%; }
}

.card {
margin: 0 auto;
padding: 5px;
background-color: rgba(255,255,255,0.7);
}

form {
margin: 5px auto 10px;
text-align: left;
}

form label{
text-align: left;
display: inline-flex;
flex-direction: column;
font-size: x-small;
padding-right: 20px;
}

form input.date {
width: 80px;
}
form input.title {
width: 50vw;
min-width: 250px;
}
form input.countries {
width: 50px;
}

form + div {
padding: 10px 0;
text-align: left;
width: 80%;
margin: 0 auto;
}
180 changes: 180 additions & 0 deletions src/components/FileUpload.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { useEffect, useState } from "react";
import Dropzone from "react-dropzone";
import {getDistance, loadGeoJsonFromGpx, renameGpx, uploadFile, uploadJson } from "../helpers/gpxUtil";
import { colorRainbow, toSlug } from "../helpers/strings";
import Login from "./Login";
import './FileUpload.css'


const FileUpload = ({ isLogged, setIsLogged, setGeojsonList }) => {
const [currentGpx, setCurrentGpx] = useState(undefined);
const [currentName, setCurrentName] = useState(undefined);
const [currentGeoJson, setCurrentGeoJson] = useState(undefined);
const [progress, setProgress] = useState(0);
const [message, setMessage] = useState("")
const [form, setForm] = useState({
date: '',
title: '',
countries: [],
});

useEffect(() => {
const getGeoJsonAwaited = async (name) => {
const geojson = await loadGeoJsonFromGpx(name);
geojson.features.map((feature, i) => feature.properties.color = colorRainbow[i])
geojson.color = "rainbow"
setCurrentGeoJson(geojson);
setGeojsonList([geojson])
}
if (currentName) {
getGeoJsonAwaited(currentName)
}
}, [currentName]);

useEffect(() => {
if (currentGeoJson) {
setForm({
date: currentGeoJson.date,
title: currentGeoJson.title,
countries: currentGeoJson.countries
})
}
}, [currentGeoJson]);

useEffect(() => {
const uploadgpx = async () => {
setProgress(0);
const fileName = await uploadFile(currentGpx, (event) => {
setProgress(Math.round((100 * event.loaded) / event.total));
})
if (fileName) {
setCurrentName(fileName)
setMessage(`💾 ${fileName} téléversé`)
} else {
setMessage('💢💢💢 PAS SAUVÉ')
}
};

if (currentGpx) {
uploadgpx();
}
}, [currentGpx]);

const onDrop = (files) => {
if (files.length > 0) {
setCurrentGpx(files[0]);
}
};

const uploadjson = async () => {
currentGeoJson.date = form.date;
currentGeoJson.title = form.title;
currentGeoJson.countries = form.countries;
currentGeoJson.distance = getDistance(currentGeoJson)
currentGeoJson.slug = `${currentGeoJson.date}-${toSlug(currentGeoJson.title)}.${currentGeoJson.countries.toString().replace(',','.')}`
await renameGpx(currentName, currentGeoJson.slug)
const saved = await uploadJson(currentGeoJson)
if (saved.status === 201) {
setMessage(`💾 ${saved.filename}`)
} else {
setMessage(`💢💢💢 ${saved.filename} PAS SAUVÉ`)
}
setCurrentGpx(null)
setCurrentName("")
setCurrentGeoJson(null)
};

const updateName = async (e) => {
const i = e.target.name;
let newFeatures = currentGeoJson.features
newFeatures[i].properties.name = e.target.value;
setCurrentGeoJson({...currentGeoJson, features: newFeatures})
}

return (
<div className="upload">

{isLogged && <Dropzone onDrop={onDrop} multiple={false}>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps({ className: "dropzone" })}>
<input {...getInputProps()} />
{currentGpx && currentGpx.name ? (
<div className="selected-file">
{currentGpx.name}
</div>
) : (
<div className="selected-file">
Upload GPX
</div>
)}
{message && (
<div className="message">
{message}
</div>)}
</div>
</section>
)}
</Dropzone>}

{currentGpx && (<div className="progress centered">
<div className="progress-value " style={{width: `${progress}%`}} >{progress}%</div>
</div>)}

{currentGeoJson && <div className="card">
<form>
<label>Date:
<input type="text" className="date" name="date" value={form.date} onChange={e => {
setForm({
...form,
date: e.target.value
});
}}/>
</label>
<label>Title:
<input type="text" className="title" name="title" value={form.title} onChange={e => {
setForm({
...form,
title: e.target.value
});
}}/>
</label>
<label>
Countries:
<input type="text" className="countries" name="countries" value={form.countries.toString()} onChange={e => {
setForm({
...form,
countries: e.target.value.split(',')
});
}}/>
</label>
<div></div>
</form>
<div><b>Filename:</b> {`${form.date}-${form.title && toSlug(form.title.trim())}${form.countries.map(cc=>`.${cc}`).join('')}.json`}
</div>
{<form>
{currentGeoJson.features.length > 1 && currentGeoJson.features.map((feat,i) => {
return (<label key={i}><div><span style={{color: feat.properties.color ?? "indogo"}}></span> {feat.properties.time}:</div>
<input type="text" name={i} value={feat.properties.name} onChange={updateName} />
</label>)
})}
</form>}
<aside className="selected-file-wrapper">
<button
className="btn btn-success"
disabled={!currentGeoJson}
onClick={uploadjson}
>
Upload GeoJson
</button>
</aside>
</div>}
<div className='footer'>
<Login isLogged={isLogged} setIsLogged={setIsLogged} />
</div>
</div>

);
};

export default FileUpload;
Loading

0 comments on commit 0c2394c

Please sign in to comment.