Starting to implement a proper UI for GPX import.
This commit is contained in:
parent
3a5f5260c8
commit
31bec02496
|
@ -1,4 +1,4 @@
|
|||
import { Component } from 'solid-js';
|
||||
import { Component, createSignal, Show } from 'solid-js';
|
||||
|
||||
import CloudUploadIcon from '@suid/icons-material/CloudUpload';
|
||||
|
||||
|
@ -9,57 +9,70 @@ import css from './GpxImport.module.css';
|
|||
import { findStartTime } from '../../lib/gpx';
|
||||
import dispatch from '../../workers/dispatcher-main';
|
||||
import { intToGpxId } from '../../lib/ids';
|
||||
import Dialog from '../dialog';
|
||||
import { useI18n } from '@solid-primitives/i18n';
|
||||
import { Box, Grid, Typography } from '@suid/material';
|
||||
import GpxImportSingleFile from './GpxImportSingleFile';
|
||||
|
||||
const GpxImport: Component = () => {
|
||||
const [filesToImport, setFilesToImport] = createSignal<FileList>();
|
||||
|
||||
const [t] = useI18n();
|
||||
|
||||
const onChangeHandler = (event: any) => {
|
||||
console.log({
|
||||
caller: 'GpxImport / On change handler',
|
||||
files: event.target.files,
|
||||
});
|
||||
for (const file of event.target.files) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.readAsText(file);
|
||||
setFilesToImport(event.target.files);
|
||||
// for (const file of event.target.files) {
|
||||
// const fileReader = new FileReader();
|
||||
// fileReader.readAsText(file);
|
||||
|
||||
fileReader.addEventListener(
|
||||
'load',
|
||||
async () => {
|
||||
// this will then display a text file
|
||||
console.log({
|
||||
caller: 'GpxImport / XML',
|
||||
file,
|
||||
result: fileReader.result,
|
||||
});
|
||||
const gpx = GPX.parse(fileReader.result);
|
||||
console.log({ caller: 'GpxImport / JSON', file, gpx });
|
||||
if (gpx) {
|
||||
const startTime = new Date(findStartTime(gpx)!);
|
||||
await dispatch({
|
||||
action: 'pruneAndSaveImportedGpx',
|
||||
params: {
|
||||
id: { gpx: intToGpxId(startTime.valueOf()) },
|
||||
gpx: gpx,
|
||||
tech: {
|
||||
lastModified: new Date(file.lastModified).toISOString(),
|
||||
importDate: new Date().toISOString(),
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type,
|
||||
},
|
||||
},
|
||||
});
|
||||
console.log({ caller: 'GpxImport / JSON / done', file, gpx });
|
||||
} else {
|
||||
console.error({
|
||||
message: "can't parse GPX file",
|
||||
file,
|
||||
xml: fileReader.result,
|
||||
});
|
||||
}
|
||||
// TODO: error handling
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
// fileReader.addEventListener(
|
||||
// 'load',
|
||||
// async () => {
|
||||
// // this will then display a text file
|
||||
// console.log({
|
||||
// caller: 'GpxImport / XML',
|
||||
// file,
|
||||
// result: fileReader.result,
|
||||
// });
|
||||
// const gpx = GPX.parse(fileReader.result);
|
||||
// console.log({ caller: 'GpxImport / JSON', file, gpx });
|
||||
// if (gpx) {
|
||||
// const startTime = new Date(findStartTime(gpx)!);
|
||||
// await dispatch({
|
||||
// action: 'pruneAndSaveImportedGpx',
|
||||
// params: {
|
||||
// id: { gpx: intToGpxId(startTime.valueOf()) },
|
||||
// gpx: gpx,
|
||||
// tech: {
|
||||
// lastModified: new Date(file.lastModified).toISOString(),
|
||||
// importDate: new Date().toISOString(),
|
||||
// name: file.name,
|
||||
// size: file.size,
|
||||
// type: file.type,
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// console.log({ caller: 'GpxImport / JSON / done', file, gpx });
|
||||
// } else {
|
||||
// console.error({
|
||||
// message: "can't parse GPX file",
|
||||
// file,
|
||||
// xml: fileReader.result,
|
||||
// });
|
||||
// }
|
||||
// // TODO: error handling
|
||||
// },
|
||||
// false
|
||||
// );
|
||||
// }
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setFilesToImport(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -77,6 +90,19 @@ const GpxImport: Component = () => {
|
|||
onChange={onChangeHandler}
|
||||
/>
|
||||
</div>
|
||||
<Dialog
|
||||
open={filesToImport() !== undefined}
|
||||
title={t('gpxImport')}
|
||||
closeHandler={handleClose}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<GpxImportSingleFile gpxFile={filesToImport()[0]} />
|
||||
</Box>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import { useI18n } from '@solid-primitives/i18n';
|
||||
import { Grid, Typography } from '@suid/material';
|
||||
import { Component, createSignal, Show } from 'solid-js';
|
||||
import { findStartTime } from '../../lib/gpx';
|
||||
import GPX from '../../lib/gpx-parser-builder/src/gpx';
|
||||
|
||||
interface Props {
|
||||
gpxFile: File;
|
||||
}
|
||||
|
||||
const analyzeGpx = (gpx: Gpx | undefined) => {
|
||||
if (gpx === undefined) {
|
||||
return {};
|
||||
}
|
||||
const stats = {
|
||||
creator: gpx.$.creator,
|
||||
nbWpts: gpx.wpt ? gpx.wpt?.length : 0,
|
||||
nbRtes: gpx.rte ? gpx.rte?.length : 0,
|
||||
nbTrks: gpx.trk ? gpx.trk?.length : 0,
|
||||
};
|
||||
return stats;
|
||||
};
|
||||
|
||||
const GpxImportSingleFile: Component<Props> = ({ gpxFile }) => {
|
||||
const [t] = useI18n();
|
||||
const [gpx, setGpx] = createSignal<Gpx>();
|
||||
|
||||
const gpxReader = new FileReader();
|
||||
gpxReader.readAsText(gpxFile);
|
||||
|
||||
gpxReader.addEventListener(
|
||||
'load',
|
||||
async () => {
|
||||
// this will then display a text gpxfile
|
||||
console.log({
|
||||
caller: 'GpxImportSingleFile / XML',
|
||||
gpxFile,
|
||||
result: gpxReader.result,
|
||||
});
|
||||
const gpx = GPX.parse(gpxReader.result);
|
||||
console.log({ caller: 'GpxImportSingleFile / JSON', gpxFile, gpx });
|
||||
setGpx(gpx);
|
||||
// if (gpx) {
|
||||
// const startTime = new Date(findStartTime(gpx)!);
|
||||
// }
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
const stats = analyzeGpx(gpx());
|
||||
|
||||
return (
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant='subtitle1'>
|
||||
{t('file')}
|
||||
{gpxFile.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Show when={gpx() !== undefined}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant='body1'>
|
||||
{t('gpxStats', analyzeGpx(gpx()))}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Show>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default GpxImportSingleFile;
|
|
@ -50,7 +50,7 @@ const changeHandler = async (change: any) => {
|
|||
(doc) => {
|
||||
console.log({ caller: 'changeHandler / gpxes', doc });
|
||||
doc.push(id);
|
||||
doc.sort().reverse();
|
||||
doc.reverse().sort().reverse();
|
||||
return doc;
|
||||
},
|
||||
[]
|
||||
|
|
|
@ -20,13 +20,10 @@ export const put = async (
|
|||
db.put({ _id, _rev: current._rev, type, doc: update(current.doc) });
|
||||
} catch (error: any) {
|
||||
if (error.name === 'conflict') {
|
||||
console.log({ caller: 'db.put', _id, type, defaultDoc, error });
|
||||
await put(_id, type, update, defaultDoc);
|
||||
} else {
|
||||
console.error(
|
||||
`put(${_id}, ${JSON.stringify(
|
||||
update(current.doc)
|
||||
)}), error: ${JSON.stringify(error)}`
|
||||
);
|
||||
console.error({ caller: 'db.put', _id, type, defaultDoc, error });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,6 +20,11 @@ const dict = {
|
|||
|
||||
save: 'SAVE',
|
||||
cancel: 'CANCEL',
|
||||
|
||||
gpxImport: 'GPX import',
|
||||
file: 'File: ',
|
||||
gpxStats:
|
||||
'This file has been created with "{{creator}}" and includes {{nbWpts}} place(s), {{nbRte}} routes(s) et {{nbTrks}} track(s).',
|
||||
};
|
||||
|
||||
export default dict;
|
||||
|
|
|
@ -16,14 +16,17 @@ const dict = {
|
|||
'rte-start': 'début de route',
|
||||
'rte-finish': 'fin de route',
|
||||
|
||||
|
||||
|
||||
name: 'Nom',
|
||||
sym: 'Symbole',
|
||||
minZoom: 'Niveau de zoom minimum',
|
||||
|
||||
save: 'SAUVEGARDER',
|
||||
cancel: 'ANNULER',
|
||||
|
||||
gpxImport: 'Import de fichier(s) GPX ',
|
||||
file: 'Fichier\u00a0: ',
|
||||
gpxStats:
|
||||
'Ce fichier a été créé avec "{{creator}}" et contient {{nbWpts}} lieu(x), {{nbRtes}} itineraire(s) et {{nbTrks}} trace(s).',
|
||||
};
|
||||
|
||||
export default dict;
|
||||
|
|
|
@ -3,10 +3,16 @@ import Link from './link';
|
|||
export default class Waypoint {
|
||||
constructor(object) {
|
||||
this.$ = {};
|
||||
this.$.lat = object.$.lat === 0 || object.lat === 0 ? 0 : object.$.lat || object.lat || -1;
|
||||
this.$.lon = object.$.lon === 0 || object.lon === 0 ? 0 : object.$.lon || object.lon || -1;
|
||||
this.$.lat =
|
||||
object.$.lat === 0 || object.lat === 0
|
||||
? 0
|
||||
: object.$.lat || object.lat || -1;
|
||||
this.$.lon =
|
||||
object.$.lon === 0 || object.lon === 0
|
||||
? 0
|
||||
: object.$.lon || object.lon || -1;
|
||||
this.ele = object.ele;
|
||||
this.time = object.time ? new Date(object.time) : new Date();
|
||||
this.time = object.time ? new Date(object.time) : undefined;
|
||||
this.magvar = object.magvar;
|
||||
this.geoidheight = object.geoidheight;
|
||||
this.name = object.name;
|
||||
|
@ -26,7 +32,7 @@ export default class Waypoint {
|
|||
if (!Array.isArray(object.link)) {
|
||||
object.link = [object.link];
|
||||
}
|
||||
this.link = object.link.map(l => new Link(l));
|
||||
this.link = object.link.map((l) => new Link(l));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue