Add HTML & PDF planner output options.

Coupled with a suitable Nunjucks template, this is effectively the
24-hour (or whatever period of time) lookahead.
This commit is contained in:
D. Berge
2021-05-31 02:20:50 +02:00
parent 5795c1f87d
commit 594233c965
4 changed files with 429 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,83 @@
// const { configuration } = require('../../../../lib/db');
const { plan, gis, info } = require('../../../../lib/db');
const leafletMap = require('../../../../lib/map');
const render = require('../../../../lib/render');
// FIXME Refactor when able
const defaultTemplatePath = require('path').resolve(__dirname, "../../../../../../../etc/default/templates/plan.html.njk");
const html = async function (req, res, next) {
try {
const planInfo = await info.get(req.params.project, "plan", req.query);
const lines = await plan.list(req.params.project, req.query);
const preplotGeoJSON = await gis.project.preplot.lines(req.params.project, {class: "V", ...req.query});
const linesGeoJSON = lines.filter(plan => plan.geometry).map(plan => {
const feature = {
type: "Feature",
geometry: plan.geometry,
properties: plan
};
delete feature.properties.geometry;
return feature;
});
// const template = (await configuration.get(req.params.project, "sse/templates/0/template")) || defaultTemplatePath;
const template = defaultTemplatePath;
const mapConfig = {
size: { width: 500, height: 500 },
layers: [
{
features: preplotGeoJSON,
options: {
style (feature) {
return {
opacity: feature.properties.ntba ? 0.2 : 0.5,
color: "gray",
weight: 1
}
}
}
},
{
features: linesGeoJSON,
options: {
style (feature) {
return {
color: "magenta",
weight: 2
}
}
}
}
]
}
const map = leafletMap(mapConfig);
const data = {
projectId: req.params.project,
info: planInfo,
lines,
map: await map.getImageData()
}
const response = await render(data, template);
if ("download" in req.query || "d" in req.query) {
const extension = "html";
const filename = `${req.params.project.toUpperCase()}-Plan.${extension}`;
res.set("Content-Disposition", `attachment; filename="${filename}"`);
}
res.status(200).send(response);
next();
} catch (err) {
if (err.message.startsWith("template")) {
next({message: err.message});
} else {
next(err);
}
}
};
module.exports = html;

View File

@@ -1,11 +1,15 @@
const json = require('./json');
const geojson = require('./geojson');
const html = require('./html');
const pdf = require('./pdf');
module.exports = async function (req, res, next) {
try {
const handlers = {
"application/json": json,
"application/geo+json": geojson,
"text/html": html,
"application/pdf": pdf
};
const mimetype = (handlers[req.query.mime] && req.query.mime) || req.accepts(Object.keys(handlers));

View File

@@ -0,0 +1,97 @@
const fs = require('fs/promises');
const Path = require('path');
const crypto = require('crypto');
const { configuration } = require('../../../../lib/db');
const { plan, gis, info } = require('../../../../lib/db');
const leafletMap = require('../../../../lib/map');
const render = require('../../../../lib/render');
const { url2pdf } = require('../../../../lib/selenium');
// FIXME Refactor when able
const defaultTemplatePath = require('path').resolve(__dirname, "../../../../../../../etc/default/templates/plan.html.njk");
function tmpname (tmpdir="/dev/shm") {
return Path.join(tmpdir, crypto.randomBytes(16).toString('hex')+".tmp");
}
const pdf = async function (req, res, next) {
const fname = tmpname();
try {
const planInfo = await info.get(req.params.project, "plan", req.query);
const lines = await plan.list(req.params.project, req.query);
const preplotGeoJSON = await gis.project.preplot.lines(req.params.project, {class: "V", ...req.query});
const linesGeoJSON = lines.filter(plan => plan.geometry).map(plan => {
const feature = {
type: "Feature",
geometry: plan.geometry,
properties: plan
};
delete feature.properties.geometry;
return feature;
});
// const template = (await configuration.get(req.params.project, "sse/templates/0/template")) || defaultTemplatePath;
const template = defaultTemplatePath;
const mapConfig = {
size: { width: 500, height: 500 },
layers: [
{
features: preplotGeoJSON,
options: {
style (feature) {
return {
opacity: feature.properties.ntba ? 0.2 : 0.5,
color: "gray",
weight: 1
}
}
}
},
{
features: linesGeoJSON,
options: {
style (feature) {
return {
color: "magenta",
weight: 2
}
}
}
}
]
}
const map = leafletMap(mapConfig);
const data = {
projectId: req.params.project,
info: planInfo,
lines,
map: await map.getImageData()
}
const html = await render(data, template);
await fs.writeFile(fname, html);
const pdf = Buffer.from(await url2pdf("file://"+fname), "base64");
if ("download" in req.query || "d" in req.query) {
const extension = "pdf";
const filename = `${req.params.project.toUpperCase()}-Plan.${extension}`;
res.set("Content-Disposition", `attachment; filename="${filename}"`);
}
res.status(200).send(pdf);
next();
} catch (err) {
if (err.message.startsWith("template")) {
next({message: err.message});
} else {
next(err);
}
} finally {
await fs.unlink(fname);
}
};
module.exports = pdf;