dyomedea/src/db/rte.ts

137 lines
3.4 KiB
TypeScript

import { cloneDeep, debounce, memoize, property, wrap } from 'lodash';
import getUri from '../lib/ids';
import { putNewGpx } from './gpx';
import { getFamily, put } from './lib';
export const emptyRte: Rte = {
name: undefined,
cmt: undefined,
desc: undefined,
src: undefined,
link: undefined,
number: 0,
type: undefined,
extensions: undefined,
rtept: undefined,
};
export const putNewRte = async (id?: IdRte | IdGpx) => {
let finalId = { ...id };
if (!('rte' in finalId)) {
const gpxId = await putNewGpx(id);
finalId = { ...gpxId, rte: 0 };
}
const uri = getUri('rte', finalId);
await put(
uri,
'rte',
(rte) => {
return rte;
},
emptyRte
);
return finalId as IdRte;
};
// See https://stackoverflow.com/questions/28787436/debounce-a-function-with-argument
export const debounceByParam = (
targetFunc: (params: any) => any,
resolver: (params: any) => any,
...debounceParams: any
) =>
wrap(
memoize(() => debounce(targetFunc, ...debounceParams), resolver),
(getMemoizedFunc, ...params) => getMemoizedFunc(...params)(...params)
);
export const compactRteOrTrkseg = async (params: any) => {
const { getDocs } = params;
const { docs, rte, trkseg } = await getDocs(params);
if (docs.rows.length > 1) {
const compactedDocs = docs.rows.map((row: any) => {
if (['rte', 'trkseg'].includes(row.doc.type)) {
return { ...row.doc, doc: rte || trkseg };
}
return { ...row.doc, doc: undefined, _deleted: true };
});
console.log({
caller: 'compactRteOrTrkseg',
params,
compactedDocs,
firstDoc: compactedDocs[0].doc,
firstDocWpt: compactedDocs[0].doc.trkpt[0],
date: new Date().toISOString(),
});
await db.bulkDocs(compactedDocs);
}
};
export const compactRteOrTrksegDebounced = debounceByParam(
compactRteOrTrkseg,
property('id'),
60 * 60 * 1000 * (1 + Math.random())
);
export const getRteDocs: ({
id,
}: {
id: string;
}) => Promise<{ docs: any; rte: Rte }> = async (params) => {
const { id } = params;
const docs = await getFamily(id, { include_docs: true });
let rte: Rte;
if (docs.rows.length === 1) {
rte = docs.rows[0].doc.doc;
} else {
rte = cloneDeep(docs.rows[0].doc.doc);
if (!rte.rtept) {
rte.rtept = [];
}
docs.rows.slice(1).forEach((row: any) => {
rte.rtept.push(row.doc.doc);
});
}
// console.log({
// caller: 'getRteDocs',
// id,
// docs,
// nbRteptIn: docs.rows[0].doc.doc.rtept?.length,
// nbRteptTotal: rte?.rtept?.length,
// });
return { docs, rte };
};
export const getRte = async (params: any) => {
const { id } = params;
const { docs, rte } = await getRteDocs(params);
if (docs.rows.length > 1) {
console.log({
caller: 'getRte compactRteOrTrksegDebounced required',
id,
});
compactRteOrTrksegDebounced({ id, getDocs: getRteDocs });
}
return rte;
};
export const putRte = async (params: any) => {
const { id, rte } = params;
await put(id, 'rte', (doc) => rte, rte);
return rte;
};
export const deleteRte = async (params: any) => {
const { id } = params;
const docs = await getFamily(id, { include_docs: false });
console.log({ caller: 'deleteRte' }, id, docs);
const deletedDocs = docs.rows.reverse().map((doc: any) => ({
_deleted: true,
_id: doc.id,
_rev: doc.value.rev,
}));
console.log({ caller: 'deleteRte' }, id, docs, deletedDocs);
await db.bulkDocs(deletedDocs);
return id;
};