UNPKG

@opengis/fastify-table

Version:

core-plugins

163 lines (162 loc) 6.13 kB
/* 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, }; }