@opengis/bi
Version:
BI data visualization module
150 lines (121 loc) • 5.29 kB
JavaScript
import {
config, pgClients, getMeta, getFilterSQL, setToken, getToken,
} from '@opengis/fastify-table/utils.js';
import metaFormat from '../utils/metaFormat.js';
import datasetFormData from './table.js';
import datasetFormBody from './form.js';
const maxLimit = 100;
export default async function datasetData(req, reply) {
const {
pg = pgClients.client, params = {}, query = {}, user = {},
} = req;
const time = Date.now();
const { uid, user_type: userType = 'regular' } = user;
if (!uid) {
// return { message: 'access restricted', status: 403 };
}
if (!params?.id) {
return { message: 'not enough params: id', status: 404 };
}
const tokenData = await getToken({
uid: user?.uid,
token: params.id,
mode: 'w',
json: 1,
});
if (tokenData?.dataset && tokenData?.id) {
return datasetFormData(req, reply);
}
const dataset = await pg.query(`select dataset_id as id, table_name as table, column_list as columns, filter_list as filters,
sql_list as sql, style, form_setting, pk, access_level, dashboard_list from bi.dataset where dataset_id=$1`, [params.id]).then(el => el.rows[0] || {});
if (!dataset?.id) {
return { message: 'dataset not found', status: 404 };
}
const tlist = await pg.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist
from pg_class where relkind in ('r','v')`).then(el => el.rows[0]?.tlist || []);
if (!dataset.table || !tlist.includes(dataset.table.replace(/"/g, '')) || (!pg.pk?.[dataset.table.replace(/"/g, '')] && !dataset.pk)) {
return { message: `table not found: ${dataset.table}`, status: 404 };
}
const { pk = dataset.pk, columns: dbColumns = [] } = await getMeta(dataset.table) || {};
const cols = dataset.columns?.filter((el) => el.name !== 'geom')?.map((el) => el.name || el)?.join(',');
const limit = Math.min(maxLimit, +(query.limit || 20));
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
const checkFilter = [query.filter, query.search].filter((el) => el).length;
const fData = checkFilter ? await getFilterSQL({
table: dataset.table,
filter: query.filter,
search: query.search,
json: 1,
}) : {};
const where = [dataset.query, fData.q].filter((el) => el);
const sqlTable = dataset.sql
?.filter?.((el) => !el?.disabled && el?.sql?.replace)
?.map((el, i) => ` left join lateral (${el.sql.replace('{{uid}}', uid || '')}) ${el.name || `t${i}`} on 1=1 `)
?.join('') || '';
const columnList = dbColumns.map((el) => el.name || el).join(',');
const order = columnList.includes('cdate') ? (`order by cdate ${query.desc ? 'desc' : ''}`) : '';
const q = `select
${cols || '*'}
${pk ? `,"${pk}" as id` : ''}
${dbColumns.find((el) => el.name === 'files' && pg.pgType[el.dataTypeID] === 'text') ? ',files' : ''}
${dbColumns.find((el) => el.name === 'geom' && pg.pgType[el.dataTypeID] === 'geometry') ? ',st_asgeojson(geom)::json as geom' : ''}
from (select * from ${dataset.table} where ${sqlTable ? 'true' : (where.join(' and ') || 'true')} ${order}) t
${sqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`.replace(/{{uid}}/g, uid || '');
if (query.sql === '1' && (config.debug || userType.includes('admin'))) { return q; }
// console.log(pg.options.database, q);
const { rows = [] } = await pg.query(q);
const qCount = `select
count(*)::int as total,
count(*) FILTER(WHERE ${[fData.q].filter(el => el).join(' and ') || 'true'})::int as filtered
from ${dataset.table} t ${sqlTable}
where ${[dataset.query].filter(el => el).join(' and ') || 'true'} `.replace(/{{uid}}/g, uid || '');
const { total, filtered } = await pg.queryCache(qCount).then(el => el?.rows?.[0] || {});
await metaFormat({ rows, columns: dataset.columns });
if (rows?.length && uid) {
rows.filter((row) => row[pk] || row.id).forEach((row) => Object.assign(row, {
token: setToken({
ids: [JSON.stringify({
id: row[pk] || row.id,
table: dataset.table,
form: `${params.id}.form`,
dataset: params.id,
})],
uid,
array: 1,
})[0],
}));
}
const res = {
time: Date.now() - time,
access: dataset.access_level,
card: dataset.card,
actions: ['add', 'edit', 'del', 'get'],
total,
filtered,
count: rows.length,
pk,
table: dataset.table,
form: `${params.id}.form`,
dashboardList: dataset.dashboard_list,
rows,
columns: dataset.columns || dbColumns.map(col => ({ name: col.name, type: pg.pgType[col.dataTypeID], title: col.name })),
filters: dataset.filters,
};
if (uid) {
const addTokens = setToken({
ids: [JSON.stringify({
table: dataset.table,
form: `${params.id}.form`,
dataset: dataset.id,
})],
uid,
array: 1,
});
Object.assign(res, {
addToken: addTokens[0],
});
Object.assign(req, { params: { id: addTokens[0] } });
await datasetFormBody(req); // for inline edit
}
return res;
}