@opengis/fastify-table
Version:
core-plugins
163 lines (162 loc) • 6.13 kB
JavaScript
/* eslint-disable no-param-reassign */
import path from "node:path";
import { config, getAccess, handlebars, setOpt, setToken, getTemplate, handlebarsSync, applyHook, getData, } from "../../../../utils.js";
import conditions from "./utils/conditions.js";
const components = {
"vs-widget-file": "select 'vs-widget-file' as component, count(*) from crm.files where entity_id=$1 and file_status<>3",
"vs-widget-comments": "select 'vs-widget-comments' as component, count(*) from crm.communications where entity_id=$1",
};
export default async function getCardData(req, reply) {
const { pg, headers, params = {}, user = {} } = req;
const { table, id } = params;
const { uid } = user;
const res = await applyHook("cardData", { table, id, user });
if (res)
return res;
const time = Date.now();
const template = await getTemplate("card", table);
const access = (await getAccess({ table, user }, pg));
if (!access?.actions?.length) {
return reply.status(403).send("access restricted");
}
const tableTemplate = await getTemplate("table", table);
const index = template?.find((el) => el[0] === "index.yml")?.[1] || {};
const result = index.table && index.query
? await pg.query(`select * from ${index.table} where ${handlebarsSync.compile(index.query)({ uid, user })}`)
: await getData({
pg,
table,
id,
user,
headers,
}, reply);
if (result?.message)
return result?.message;
if (!result?.rows?.length) {
return reply.status(403).send("access restricted: empty rows");
}
const { rows = [] } = result;
const panels = (index.table && index.query ? index.panels : result?.panels) || [];
if (index.table && index.query) {
// conditions
panels
.filter((panel) => panel.items)
.forEach((el) => {
el.items = el.items?.filter?.((item) => conditions(item.conditions, rows[0]));
});
// title, count
await Promise.all(panels
.filter((el) => el.items)
.map(async (el) => {
const filtered = el.items.filter((item) => item.count?.toLowerCase?.().includes("select"));
const data = await Promise.all(filtered.map(async (el1) => pg.query(el1.count).then((item) => item.rows?.[0] || {})));
filtered.forEach((item1, i) => {
Object.assign(item1, data[i] || {}, data[i].count ? {} : { count: undefined });
});
const q = el.items
.map((item2) => item2.component ? components?.[item2.component] : null)
.filter(Boolean)
.join(" union all ");
const counts = q && id
? await pg
.query(q, [id])
.then((e) => e.rows.reduce((acc, curr) => Object.assign(acc, { [curr.component]: curr.count }), {}))
: {};
el.items
?.filter?.((item) => item.component)
?.forEach((item) => Object.assign(item, { count: counts?.[item.component] }));
}));
}
// tokens result
const tokens = {};
if (!config.security?.disableToken &&
index?.tokens &&
typeof index?.tokens === "object" &&
!Array.isArray(index?.tokens)) {
Object.keys(index.tokens || {})
.filter((key) => index?.tokens[key]?.public ||
access.actions?.includes?.("edit") ||
access.actions?.includes?.("add") ||
!index?.tokens[key]?.table)
.forEach((key) => {
const item = index?.tokens[key];
Object.keys(item)
.filter((el) => item[el]?.includes?.("{{"))
.forEach((el) => {
item[el] = handlebarsSync.compile(item[el])({
user,
uid,
id,
data: rows[0],
});
});
const token = item.form && item.table
? setToken({
ids: [JSON.stringify(item)],
uid,
array: 1,
})[0]
: setOpt(item, uid);
tokens[key] = token;
});
}
// vue result
const vue = template
?.filter((el) => el[0].endsWith(".vue"))
.reduce((acc, curr) => Object.assign(acc, {
[path.parse(curr[0]).name]: curr[1]
.match(/<template[^>]*>([\s\S]*?)<\/template>/)[1]
.trim(),
}), {});
// data result
const data = {};
const route = await pg
.query("select route_id as path, title from admin.routes where enabled and alias=$1 limit 1", [table])
.then((el) => el.rows?.[0] || {});
Object.assign(route, { tableTitle: tableTemplate?.title });
if (index?.data && index?.data?.[0]?.name) {
await Promise.all(index.data
.filter((el) => el?.name && el?.sql)
.map(async (el) => {
const q = handlebarsSync.compile(el.sql)({
data: rows[0],
user,
uid,
id,
});
const { rows: sqlData } = await pg.query(q);
data[el.name] = sqlData;
}));
}
// html result
const html = {};
if (template) {
await Promise.all(template
.filter((el) => el[0].includes(".hbs"))
.map(async (el) => {
const htmlContent = await handlebars.compile(el[1])({
...rows[0],
user,
data,
tokens,
actions: access.actions,
});
const name = el[0].substring(0, el[0].lastIndexOf("."));
html[name] = htmlContent;
}));
}
return {
time: Date.now() - time,
...index,
panels,
tokens,
vue,
data,
route,
html,
rows,
columns: tableTemplate?.columns || tableTemplate?.colModel,
table: undefined,
query: undefined,
};
}