UNPKG

@opengis/fastify-table

Version:

core-plugins

156 lines (125 loc) 5.76 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(item2 => item2).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, }); 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, }; }