First version of the new importer (stiil needs to convert non timed tracks into routes).

This commit is contained in:
Eric van der Vlist 2022-12-13 12:41:13 +01:00
parent 102a2feddc
commit 90fb0e6944
4 changed files with 194 additions and 138 deletions

View File

@ -21,50 +21,6 @@ const GpxImport: Component = () => {
files: event.target.files,
});
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
// );
// }
};
const handleClose = (event: any, reason?: string) => {

View File

@ -12,6 +12,7 @@ import {
import { Component, createEffect, createSignal, Show } from 'solid-js';
import { findStartTime } from '../../lib/gpx';
import GPX from '../../lib/gpx-parser-builder/src/gpx';
import dispatch from '../../workers/dispatcher-main';
import GpxChooser from '../gpx-chooser';
import { currentGpxId } from '../gpx-dialog';
@ -76,8 +77,58 @@ const GpxImportSingleFile: Component<Props> = ({ gpxFile }) => {
false
);
const doImport = () => {
const doImport = async () => {
setState('importing');
// 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: gpxId(),
gpx: statsAndGpx()?.gpx,
tech: {
lastModified: new Date(gpxFile.lastModified).toISOString(),
importDate: new Date().toISOString(),
name: gpxFile.name,
size: gpxFile.size,
type: gpxFile.type,
},
},
});
console.log({
caller: 'GpxImport / JSON / done',
gpxFile,
gpx: statsAndGpx()?.gpx,
});
setState('done');
// } else {
// console.error({
// message: "can't parse GPX file",
// file,
// xml: fileReader.result,
// });
// }
// // TODO: error handling
// },
// false
// );
// }
};
const [selectedTrkTransform, setSelectedTrkTransform] = createSignal(
@ -139,7 +190,11 @@ const GpxImportSingleFile: Component<Props> = ({ gpxFile }) => {
<LinearProgress />
</Show>
<CardActions>
<GpxChooser gpxId={gpxId} setGpxId={setGpxId} disabled={state() != 'init'} />
<GpxChooser
gpxId={gpxId}
setGpxId={setGpxId}
disabled={state() != 'init'}
/>
<Button
variant='contained'
disabled={state() != 'init'}

View File

@ -1,7 +1,9 @@
import { cloneDeep } from 'lodash';
import { PureComponent } from 'react';
import { $DEVCOMP } from 'solid-js';
import { Point, Rectangle } from '../components/map/types';
import { lat2tile, lon2tile, rectanglesIntersect } from '../lib/geo';
import { findStartTime } from '../lib/gpx';
import getUri, { intToGpxId, intToTrkptId } from '../lib/ids';
import { get, getDocsByType, getFamily, put, putAll } from './lib';
@ -61,7 +63,13 @@ export const existsGpx = async (id: IdGpx) => {
}
};
const prune = (id: any, object: any, docs: any[]) => {
const prune = (
id: any,
object: any,
previousGpx: Gpx | null,
extensions: any,
docs: any[]
) => {
if (typeof object === 'object') {
for (const key in object) {
if (
@ -74,6 +82,10 @@ const prune = (id: any, object: any, docs: any[]) => {
) {
const subObjects = object[key];
let previousId = 0;
let nbPreviousObjects = 0;
if (previousGpx !== null && key in previousGpx) {
nbPreviousObjects = previousGpx[key].length;
}
for (const index in subObjects) {
const subId = { ...id };
if (key === 'trkpt') {
@ -85,7 +97,7 @@ const prune = (id: any, object: any, docs: any[]) => {
subId[key] = id;
previousId = id;
} else {
subId[key] = index;
subId[key] = index + nbPreviousObjects;
}
// console.log({
// caller: 'prune',
@ -95,113 +107,146 @@ const prune = (id: any, object: any, docs: any[]) => {
// object: object[key][index],
// time: object[key][index].time,
// });
subObjects[index].extensions = {
...extensions,
...subObjects[index].extensions,
};
docs.push({
_id: getUri(key, subId),
type: key,
doc: subObjects[index],
});
prune(subId, subObjects[index], docs);
prune(subId, subObjects[index], previousGpx, extensions, docs);
}
object[key] = undefined;
} else prune(id, object[key], docs);
} else prune(id, object[key], previousGpx, extensions, docs);
}
}
};
const extensionsFromObject = (
object: any,
extensions = {
viewport: { topLeft: <Point>{}, bottomRight: <Point>{} },
bbox: {
minLon: <number | undefined>undefined,
minLat: <number | undefined>undefined,
maxLon: <number | undefined>undefined,
maxLat: <number | undefined>undefined,
},
}
) => {
if (typeof object === 'object') {
if ('$' in object) {
const attributes = object.$;
if ('lat' in attributes) {
const lat = +attributes.lat;
if (
extensions.bbox.minLat === undefined ||
lat < extensions.bbox.minLat
) {
extensions.bbox.minLat = lat;
}
if (
extensions.bbox.maxLat === undefined ||
lat > extensions.bbox.maxLat
) {
extensions.bbox.maxLat = lat;
}
}
if ('lon' in attributes) {
const lon = +attributes.lon;
if (
extensions.bbox.minLon === undefined ||
lon < extensions.bbox.minLon
) {
extensions.bbox.minLon = lon;
}
if (
extensions.bbox.maxLon === undefined ||
lon > extensions.bbox.maxLon
) {
extensions.bbox.maxLon = lon;
}
}
}
for (const key in object) {
extensionsFromObject(object[key], extensions);
}
}
return extensions;
};
// const extensionsFromObject = (
// object: any,
// extensions = {
// viewport: { topLeft: <Point>{}, bottomRight: <Point>{} },
// bbox: {
// minLon: <number | undefined>undefined,
// minLat: <number | undefined>undefined,
// maxLon: <number | undefined>undefined,
// maxLat: <number | undefined>undefined,
// },
// }
// ) => {
// if (typeof object === 'object') {
// if ('$' in object) {
// const attributes = object.$;
// if ('lat' in attributes) {
// const lat = +attributes.lat;
// if (
// extensions.bbox.minLat === undefined ||
// lat < extensions.bbox.minLat
// ) {
// extensions.bbox.minLat = lat;
// }
// if (
// extensions.bbox.maxLat === undefined ||
// lat > extensions.bbox.maxLat
// ) {
// extensions.bbox.maxLat = lat;
// }
// }
// if ('lon' in attributes) {
// const lon = +attributes.lon;
// if (
// extensions.bbox.minLon === undefined ||
// lon < extensions.bbox.minLon
// ) {
// extensions.bbox.minLon = lon;
// }
// if (
// extensions.bbox.maxLon === undefined ||
// lon > extensions.bbox.maxLon
// ) {
// extensions.bbox.maxLon = lon;
// }
// }
// }
// for (const key in object) {
// extensionsFromObject(object[key], extensions);
// }
// }
// return extensions;
// };
const extensionsFromGpx = (gpx: Gpx) => {
const extensions = { ...gpx.extensions, ...extensionsFromObject(gpx) };
gpx.extensions = undefined;
if (
extensions.bbox.maxLat !== undefined &&
extensions.bbox.minLon !== undefined
) {
extensions.viewport.topLeft = {
x: lon2tile(extensions.bbox.minLon, 0),
y: lat2tile(extensions.bbox.maxLat, 0),
};
}
if (
extensions.bbox.minLat !== undefined &&
extensions.bbox.maxLon !== undefined
) {
extensions.viewport.bottomRight = {
x: lon2tile(extensions.bbox.maxLon, 0),
y: lat2tile(extensions.bbox.minLat, 0),
};
}
// const extensionsFromGpx = (gpx: Gpx) => {
// const extensions = { ...gpx.extensions, ...extensionsFromObject(gpx) };
// gpx.extensions = undefined;
// if (
// extensions.bbox.maxLat !== undefined &&
// extensions.bbox.minLon !== undefined
// ) {
// extensions.viewport.topLeft = {
// x: lon2tile(extensions.bbox.minLon, 0),
// y: lat2tile(extensions.bbox.maxLat, 0),
// };
// }
// if (
// extensions.bbox.minLat !== undefined &&
// extensions.bbox.maxLon !== undefined
// ) {
// extensions.viewport.bottomRight = {
// x: lon2tile(extensions.bbox.maxLon, 0),
// y: lat2tile(extensions.bbox.minLat, 0),
// };
// }
return extensions;
};
// return extensions;
// };
export const pruneAndSaveImportedGpx = async (params: any) => {
console.log({ caller: 'pruneAndSaveImportedGpx', params });
const { id, gpx, extensions } = params;
let docs: any[] = [
{ _id: getUri('gpx', id), type: 'gpx', doc: gpx },
{
_id: getUri('extensions', id),
type: 'extensions',
doc: { ...extensions, ...extensionsFromGpx(gpx) },
const { id, gpx, tech } = params;
let gpxId: IdGpx;
let docs: any[] = [];
const extensions = {
...tech,
...gpx.extensions,
gpx: {
creator: gpx?.$?.creator,
metadata: gpx.metadata,
extensions: gpx.extensions,
},
];
prune(id, gpx, docs);
};
let previousGpx: Gpx | null = null;
if (id === 'new') {
const currentDateTime = new Date().toISOString();
const startTime = new Date(findStartTime(gpx, currentDateTime));
if (gpx.metadata === undefined) {
gpx.metadata = {};
}
if (gpx.metadata.time === undefined) {
gpx.metadata.time = startTime.toISOString();
}
gpxId = { gpx: intToGpxId(startTime.valueOf()) };
docs = [
{ _id: getUri('gpx', gpxId), type: 'gpx', doc: gpx },
{
_id: getUri('extensions', gpxId),
type: 'extensions',
doc: {},
},
];
} else {
gpxId = getUri('gpx', id);
previousGpx = (await getGpx(id)) ?? null;
}
prune(gpxId, gpx, previousGpx, extensions, docs);
console.log({ caller: 'pruneAndSaveImportedGpx / pruned', docs });
try {
const result = await putAll(docs);
console.log(JSON.stringify(result));
if (id !== 'new') {
put(id, 'gpx', (doc) => doc, {});
}
} catch (err) {
console.error(`error: ${err}`);
}

View File

@ -7,7 +7,7 @@ export default class Metadata {
constructor(object) {
this.name = object.name;
this.desc = object.desc;
this.time = object.time ? new Date(object.time) : new Date();
this.time = object.time ? new Date(object.time) : undefined;
this.keywords = object.keywords;
this.extensions = object.extensions;
if (object.author) {
@ -17,7 +17,7 @@ export default class Metadata {
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));
}
if (object.bounds) {
this.bounds = new Bounds(object.bounds);
@ -25,5 +25,5 @@ export default class Metadata {
if (object.copyright) {
this.copyright = new Copyright(object.copyright);
}
}
}
}
}