First version of the new importer (stiil needs to convert non timed tracks into routes).
This commit is contained in:
parent
102a2feddc
commit
90fb0e6944
|
@ -21,50 +21,6 @@ const GpxImport: Component = () => {
|
||||||
files: event.target.files,
|
files: event.target.files,
|
||||||
});
|
});
|
||||||
setFilesToImport(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) => {
|
const handleClose = (event: any, reason?: string) => {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Component, createEffect, createSignal, Show } from 'solid-js';
|
import { Component, createEffect, createSignal, Show } from 'solid-js';
|
||||||
import { findStartTime } from '../../lib/gpx';
|
import { findStartTime } from '../../lib/gpx';
|
||||||
import GPX from '../../lib/gpx-parser-builder/src/gpx';
|
import GPX from '../../lib/gpx-parser-builder/src/gpx';
|
||||||
|
import dispatch from '../../workers/dispatcher-main';
|
||||||
import GpxChooser from '../gpx-chooser';
|
import GpxChooser from '../gpx-chooser';
|
||||||
import { currentGpxId } from '../gpx-dialog';
|
import { currentGpxId } from '../gpx-dialog';
|
||||||
|
|
||||||
|
@ -76,8 +77,58 @@ const GpxImportSingleFile: Component<Props> = ({ gpxFile }) => {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
const doImport = () => {
|
const doImport = async () => {
|
||||||
setState('importing');
|
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(
|
const [selectedTrkTransform, setSelectedTrkTransform] = createSignal(
|
||||||
|
@ -139,7 +190,11 @@ const GpxImportSingleFile: Component<Props> = ({ gpxFile }) => {
|
||||||
<LinearProgress />
|
<LinearProgress />
|
||||||
</Show>
|
</Show>
|
||||||
<CardActions>
|
<CardActions>
|
||||||
<GpxChooser gpxId={gpxId} setGpxId={setGpxId} disabled={state() != 'init'} />
|
<GpxChooser
|
||||||
|
gpxId={gpxId}
|
||||||
|
setGpxId={setGpxId}
|
||||||
|
disabled={state() != 'init'}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
variant='contained'
|
variant='contained'
|
||||||
disabled={state() != 'init'}
|
disabled={state() != 'init'}
|
||||||
|
|
215
src/db/gpx.ts
215
src/db/gpx.ts
|
@ -1,7 +1,9 @@
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
import { $DEVCOMP } from 'solid-js';
|
||||||
import { Point, Rectangle } from '../components/map/types';
|
import { Point, Rectangle } from '../components/map/types';
|
||||||
import { lat2tile, lon2tile, rectanglesIntersect } from '../lib/geo';
|
import { lat2tile, lon2tile, rectanglesIntersect } from '../lib/geo';
|
||||||
|
import { findStartTime } from '../lib/gpx';
|
||||||
import getUri, { intToGpxId, intToTrkptId } from '../lib/ids';
|
import getUri, { intToGpxId, intToTrkptId } from '../lib/ids';
|
||||||
import { get, getDocsByType, getFamily, put, putAll } from './lib';
|
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') {
|
if (typeof object === 'object') {
|
||||||
for (const key in object) {
|
for (const key in object) {
|
||||||
if (
|
if (
|
||||||
|
@ -74,6 +82,10 @@ const prune = (id: any, object: any, docs: any[]) => {
|
||||||
) {
|
) {
|
||||||
const subObjects = object[key];
|
const subObjects = object[key];
|
||||||
let previousId = 0;
|
let previousId = 0;
|
||||||
|
let nbPreviousObjects = 0;
|
||||||
|
if (previousGpx !== null && key in previousGpx) {
|
||||||
|
nbPreviousObjects = previousGpx[key].length;
|
||||||
|
}
|
||||||
for (const index in subObjects) {
|
for (const index in subObjects) {
|
||||||
const subId = { ...id };
|
const subId = { ...id };
|
||||||
if (key === 'trkpt') {
|
if (key === 'trkpt') {
|
||||||
|
@ -85,7 +97,7 @@ const prune = (id: any, object: any, docs: any[]) => {
|
||||||
subId[key] = id;
|
subId[key] = id;
|
||||||
previousId = id;
|
previousId = id;
|
||||||
} else {
|
} else {
|
||||||
subId[key] = index;
|
subId[key] = index + nbPreviousObjects;
|
||||||
}
|
}
|
||||||
// console.log({
|
// console.log({
|
||||||
// caller: 'prune',
|
// caller: 'prune',
|
||||||
|
@ -95,113 +107,146 @@ const prune = (id: any, object: any, docs: any[]) => {
|
||||||
// object: object[key][index],
|
// object: object[key][index],
|
||||||
// time: object[key][index].time,
|
// time: object[key][index].time,
|
||||||
// });
|
// });
|
||||||
|
subObjects[index].extensions = {
|
||||||
|
...extensions,
|
||||||
|
...subObjects[index].extensions,
|
||||||
|
};
|
||||||
docs.push({
|
docs.push({
|
||||||
_id: getUri(key, subId),
|
_id: getUri(key, subId),
|
||||||
type: key,
|
type: key,
|
||||||
doc: subObjects[index],
|
doc: subObjects[index],
|
||||||
});
|
});
|
||||||
prune(subId, subObjects[index], docs);
|
prune(subId, subObjects[index], previousGpx, extensions, docs);
|
||||||
}
|
}
|
||||||
object[key] = undefined;
|
object[key] = undefined;
|
||||||
} else prune(id, object[key], docs);
|
} else prune(id, object[key], previousGpx, extensions, docs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const extensionsFromObject = (
|
// const extensionsFromObject = (
|
||||||
object: any,
|
// object: any,
|
||||||
extensions = {
|
// extensions = {
|
||||||
viewport: { topLeft: <Point>{}, bottomRight: <Point>{} },
|
// viewport: { topLeft: <Point>{}, bottomRight: <Point>{} },
|
||||||
bbox: {
|
// bbox: {
|
||||||
minLon: <number | undefined>undefined,
|
// minLon: <number | undefined>undefined,
|
||||||
minLat: <number | undefined>undefined,
|
// minLat: <number | undefined>undefined,
|
||||||
maxLon: <number | undefined>undefined,
|
// maxLon: <number | undefined>undefined,
|
||||||
maxLat: <number | undefined>undefined,
|
// maxLat: <number | undefined>undefined,
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
) => {
|
// ) => {
|
||||||
if (typeof object === 'object') {
|
// if (typeof object === 'object') {
|
||||||
if ('$' in object) {
|
// if ('$' in object) {
|
||||||
const attributes = object.$;
|
// const attributes = object.$;
|
||||||
if ('lat' in attributes) {
|
// if ('lat' in attributes) {
|
||||||
const lat = +attributes.lat;
|
// const lat = +attributes.lat;
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.minLat === undefined ||
|
// extensions.bbox.minLat === undefined ||
|
||||||
lat < extensions.bbox.minLat
|
// lat < extensions.bbox.minLat
|
||||||
) {
|
// ) {
|
||||||
extensions.bbox.minLat = lat;
|
// extensions.bbox.minLat = lat;
|
||||||
}
|
// }
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.maxLat === undefined ||
|
// extensions.bbox.maxLat === undefined ||
|
||||||
lat > extensions.bbox.maxLat
|
// lat > extensions.bbox.maxLat
|
||||||
) {
|
// ) {
|
||||||
extensions.bbox.maxLat = lat;
|
// extensions.bbox.maxLat = lat;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if ('lon' in attributes) {
|
// if ('lon' in attributes) {
|
||||||
const lon = +attributes.lon;
|
// const lon = +attributes.lon;
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.minLon === undefined ||
|
// extensions.bbox.minLon === undefined ||
|
||||||
lon < extensions.bbox.minLon
|
// lon < extensions.bbox.minLon
|
||||||
) {
|
// ) {
|
||||||
extensions.bbox.minLon = lon;
|
// extensions.bbox.minLon = lon;
|
||||||
}
|
// }
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.maxLon === undefined ||
|
// extensions.bbox.maxLon === undefined ||
|
||||||
lon > extensions.bbox.maxLon
|
// lon > extensions.bbox.maxLon
|
||||||
) {
|
// ) {
|
||||||
extensions.bbox.maxLon = lon;
|
// extensions.bbox.maxLon = lon;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for (const key in object) {
|
// for (const key in object) {
|
||||||
extensionsFromObject(object[key], extensions);
|
// extensionsFromObject(object[key], extensions);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return extensions;
|
// return extensions;
|
||||||
};
|
// };
|
||||||
|
|
||||||
const extensionsFromGpx = (gpx: Gpx) => {
|
// const extensionsFromGpx = (gpx: Gpx) => {
|
||||||
const extensions = { ...gpx.extensions, ...extensionsFromObject(gpx) };
|
// const extensions = { ...gpx.extensions, ...extensionsFromObject(gpx) };
|
||||||
gpx.extensions = undefined;
|
// gpx.extensions = undefined;
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.maxLat !== undefined &&
|
// extensions.bbox.maxLat !== undefined &&
|
||||||
extensions.bbox.minLon !== undefined
|
// extensions.bbox.minLon !== undefined
|
||||||
) {
|
// ) {
|
||||||
extensions.viewport.topLeft = {
|
// extensions.viewport.topLeft = {
|
||||||
x: lon2tile(extensions.bbox.minLon, 0),
|
// x: lon2tile(extensions.bbox.minLon, 0),
|
||||||
y: lat2tile(extensions.bbox.maxLat, 0),
|
// y: lat2tile(extensions.bbox.maxLat, 0),
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
if (
|
// if (
|
||||||
extensions.bbox.minLat !== undefined &&
|
// extensions.bbox.minLat !== undefined &&
|
||||||
extensions.bbox.maxLon !== undefined
|
// extensions.bbox.maxLon !== undefined
|
||||||
) {
|
// ) {
|
||||||
extensions.viewport.bottomRight = {
|
// extensions.viewport.bottomRight = {
|
||||||
x: lon2tile(extensions.bbox.maxLon, 0),
|
// x: lon2tile(extensions.bbox.maxLon, 0),
|
||||||
y: lat2tile(extensions.bbox.minLat, 0),
|
// y: lat2tile(extensions.bbox.minLat, 0),
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
return extensions;
|
// return extensions;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const pruneAndSaveImportedGpx = async (params: any) => {
|
export const pruneAndSaveImportedGpx = async (params: any) => {
|
||||||
console.log({ caller: 'pruneAndSaveImportedGpx', params });
|
console.log({ caller: 'pruneAndSaveImportedGpx', params });
|
||||||
const { id, gpx, extensions } = params;
|
const { id, gpx, tech } = params;
|
||||||
let docs: any[] = [
|
let gpxId: IdGpx;
|
||||||
{ _id: getUri('gpx', id), type: 'gpx', doc: gpx },
|
let docs: any[] = [];
|
||||||
|
const extensions = {
|
||||||
|
...tech,
|
||||||
|
...gpx.extensions,
|
||||||
|
gpx: {
|
||||||
|
creator: gpx?.$?.creator,
|
||||||
|
metadata: gpx.metadata,
|
||||||
|
extensions: gpx.extensions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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', id),
|
_id: getUri('extensions', gpxId),
|
||||||
type: 'extensions',
|
type: 'extensions',
|
||||||
doc: { ...extensions, ...extensionsFromGpx(gpx) },
|
doc: {},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
prune(id, gpx, docs);
|
} else {
|
||||||
|
gpxId = getUri('gpx', id);
|
||||||
|
previousGpx = (await getGpx(id)) ?? null;
|
||||||
|
}
|
||||||
|
prune(gpxId, gpx, previousGpx, extensions, docs);
|
||||||
console.log({ caller: 'pruneAndSaveImportedGpx / pruned', docs });
|
console.log({ caller: 'pruneAndSaveImportedGpx / pruned', docs });
|
||||||
try {
|
try {
|
||||||
const result = await putAll(docs);
|
const result = await putAll(docs);
|
||||||
console.log(JSON.stringify(result));
|
console.log(JSON.stringify(result));
|
||||||
|
if (id !== 'new') {
|
||||||
|
put(id, 'gpx', (doc) => doc, {});
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`error: ${err}`);
|
console.error(`error: ${err}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default class Metadata {
|
||||||
constructor(object) {
|
constructor(object) {
|
||||||
this.name = object.name;
|
this.name = object.name;
|
||||||
this.desc = object.desc;
|
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.keywords = object.keywords;
|
||||||
this.extensions = object.extensions;
|
this.extensions = object.extensions;
|
||||||
if (object.author) {
|
if (object.author) {
|
||||||
|
@ -17,7 +17,7 @@ export default class Metadata {
|
||||||
if (!Array.isArray(object.link)) {
|
if (!Array.isArray(object.link)) {
|
||||||
object.link = [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) {
|
if (object.bounds) {
|
||||||
this.bounds = new Bounds(object.bounds);
|
this.bounds = new Bounds(object.bounds);
|
||||||
|
|
Loading…
Reference in New Issue