mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 11:37:08 +00:00
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:
245
etc/default/templates/plan.html.njk
Normal file
245
etc/default/templates/plan.html.njk
Normal file
File diff suppressed because one or more lines are too long
83
lib/www/server/api/middleware/plan/list/html.js
Normal file
83
lib/www/server/api/middleware/plan/list/html.js
Normal 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;
|
||||
@@ -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));
|
||||
|
||||
97
lib/www/server/api/middleware/plan/list/pdf.js
Normal file
97
lib/www/server/api/middleware/plan/list/pdf.js
Normal 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;
|
||||
Reference in New Issue
Block a user