@opengis/bi 1.2.32 → 1.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -92
- package/dist/bi.js +1 -1
- package/dist/bi.umd.cjs +68 -68
- package/dist/{import-file-D-ISqB7l.js → import-file-BwxPX622.js} +1132 -1079
- package/dist/style.css +1 -1
- package/dist/{vs-funnel-bar-aoZzvriV.js → vs-funnel-bar-BV18EA4K.js} +3 -3
- package/dist/{vs-list-CBkyJSBj.js → vs-list-WrrWQ5KF.js} +32 -53
- package/dist/{vs-map-C3C11qmT.js → vs-map-CYd9vdrd.js} +3 -3
- package/dist/{vs-map-cluster-BsPmHIMx.js → vs-map-cluster-5TnGPuBH.js} +3 -3
- package/dist/{vs-number-d58ftpH5.js → vs-number-DUeRr7uz.js} +3 -3
- package/dist/{vs-table-BHa5Velm.js → vs-table-CZJnXfUv.js} +6 -6
- package/dist/{vs-text-Bq87gMTx.js → vs-text-D3nCPkgk.js} +4 -4
- package/package.json +77 -77
- package/plugin.js +21 -21
- package/server/helpers/mdToHTML.js +17 -17
- package/server/migrations/bi.dataset.sql +46 -46
- package/server/migrations/bi.sql +114 -114
- package/server/plugins/docs.js +48 -48
- package/server/plugins/hook.js +89 -89
- package/server/routes/dashboard/controllers/dashboard.import.js +103 -103
- package/server/routes/dashboard/controllers/dashboard.js +158 -158
- package/server/routes/dashboard/controllers/dashboard.list.js +60 -60
- package/server/routes/dashboard/controllers/utils/yaml.js +11 -11
- package/server/routes/dashboard/index.mjs +26 -26
- package/server/routes/data/controllers/data.js +230 -230
- package/server/routes/data/controllers/util/chartSQL.js +49 -49
- package/server/routes/data/controllers/util/normalizeData.js +65 -65
- package/server/routes/data/index.mjs +38 -38
- package/server/routes/dataset/controllers/bi.dataset.list.js +29 -29
- package/server/routes/dataset/controllers/bi.db.list.js +19 -19
- package/server/routes/dataset/controllers/comment.js +55 -55
- package/server/routes/dataset/controllers/createDatasetPost.js +134 -134
- package/server/routes/dataset/controllers/data.js +149 -149
- package/server/routes/dataset/controllers/dbTablePreview.js +58 -58
- package/server/routes/dataset/controllers/dbTables.js +34 -34
- package/server/routes/dataset/controllers/delete.js +40 -40
- package/server/routes/dataset/controllers/deleteDataset.js +52 -52
- package/server/routes/dataset/controllers/editDataset.js +90 -90
- package/server/routes/dataset/controllers/export.js +214 -214
- package/server/routes/dataset/controllers/form.js +99 -99
- package/server/routes/dataset/controllers/format.js +46 -46
- package/server/routes/dataset/controllers/insert.js +47 -47
- package/server/routes/dataset/controllers/table.js +68 -68
- package/server/routes/dataset/controllers/update.js +43 -43
- package/server/routes/dataset/index.mjs +132 -132
- package/server/routes/dataset/utils/convertJSONToCSV.js +17 -17
- package/server/routes/dataset/utils/convertJSONToXls.js +47 -47
- package/server/routes/dataset/utils/createTableQuery.js +59 -59
- package/server/routes/dataset/utils/datasetForms.js +1 -1
- package/server/routes/dataset/utils/descriptionList.js +45 -45
- package/server/routes/dataset/utils/downloadRemoteFile.js +58 -58
- package/server/routes/dataset/utils/executeQuery.js +46 -46
- package/server/routes/dataset/utils/getLayersData.js +106 -106
- package/server/routes/dataset/utils/getTableData.js +46 -46
- package/server/routes/dataset/utils/insertDataQuery.js +12 -12
- package/server/routes/dataset/utils/metaFormat.js +24 -24
- package/server/routes/edit/controllers/dashboard.add.js +36 -36
- package/server/routes/edit/controllers/dashboard.delete.js +39 -39
- package/server/routes/edit/controllers/dashboard.edit.js +61 -61
- package/server/routes/edit/controllers/widget.add.js +78 -78
- package/server/routes/edit/controllers/widget.del.js +58 -58
- package/server/routes/edit/controllers/widget.edit.js +115 -115
- package/server/routes/edit/index.mjs +33 -33
- package/server/routes/map/controllers/cluster.js +125 -125
- package/server/routes/map/controllers/clusterVtile.js +166 -166
- package/server/routes/map/controllers/geojson.js +127 -127
- package/server/routes/map/controllers/heatmap.js +118 -118
- package/server/routes/map/controllers/map.js +69 -69
- package/server/routes/map/controllers/utils/downloadClusterData.js +44 -44
- package/server/routes/map/controllers/vtile.js +183 -183
- package/server/routes/map/index.mjs +32 -32
- package/server/templates/page/login.html +58 -58
- package/server/utils/getWidget.js +118 -118
- package/utils.js +12 -12
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import descriptionList from "./descriptionList.js";
|
|
2
|
-
import metaFormat from "./metaFormat.js";
|
|
3
|
-
|
|
4
|
-
async function getDataByLatLng({ pg, layer, table, id, lat, lng, time = [] }) {
|
|
5
|
-
// const rclient = getRedis();
|
|
6
|
-
// const redisKey = `${pg.options.database}:gis-format:${layer}:${lat}:${lng}`;
|
|
7
|
-
// const cacheData = await rclient.get(redisKey);
|
|
8
|
-
// if (cacheData && !config.local) return JSON.parse(cacheData);
|
|
9
|
-
|
|
10
|
-
const { rows: styles = [] } = await pg.query(`select style_id as id, dataset
|
|
11
|
-
from gis.style where style_id=any($1::text[])
|
|
12
|
-
union all
|
|
13
|
-
select dataset_id as id, json_build_array(json_build_object('pk', pk, 'table', table_name, 'query', query, 'card', setting->>'card', 'columns', column_list)) as dataset
|
|
14
|
-
from bi.dataset a where dataset_id=any($1::text[])`, [layer.split(',')]);
|
|
15
|
-
time.push(Date.now());
|
|
16
|
-
|
|
17
|
-
if (!styles?.length) {
|
|
18
|
-
return { message: `style not found: ${layer}`, status: 400 };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { srids } = await pg.queryCache?.('select json_agg(srid) as srids from spatial_ref_sys').then((res1) => res1.rows?.[0] || {}) || {};
|
|
22
|
-
|
|
23
|
-
const layers = styles.reduce((acc, curr) => {
|
|
24
|
-
curr.dataset?.filter((el) => el.table && (el.pk || pg.pk?.[el.table]))
|
|
25
|
-
?.forEach((el) => acc.push({
|
|
26
|
-
layer: curr.id,
|
|
27
|
-
pk: el.pk || pg.pk?.[el.table],
|
|
28
|
-
key: el.key,
|
|
29
|
-
table: el.table,
|
|
30
|
-
query: el.query,
|
|
31
|
-
template: el.card,
|
|
32
|
-
column_list: el.column_list,
|
|
33
|
-
columns: el.columns || el.column_list?.map((el) => el.name)?.join(','),
|
|
34
|
-
srid: el.srid || '4326',
|
|
35
|
-
geom: el.geom || 'geom',
|
|
36
|
-
step: srids?.includes(el.srid - 0) && el.srid !== '4326' ? 10 : 0.0002,
|
|
37
|
-
}));
|
|
38
|
-
return acc;
|
|
39
|
-
}, [])
|
|
40
|
-
.filter((el) => el.pk && el.layer)
|
|
41
|
-
.filter((el) => table ? el.table === table : true);
|
|
42
|
-
|
|
43
|
-
if (!layers.length) {
|
|
44
|
-
return { message: 'data not found', status: 404 };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const point = `srid=4326;point(${lng} ${lat})`;
|
|
48
|
-
|
|
49
|
-
// ${el.columns?.split?.filter?.((el) => el) ? `,${el.columns?.split?.filter?.((el) => el) || ''}` : ''}
|
|
50
|
-
|
|
51
|
-
const q = layers.map((el) => `select ${el.pk}, '${el.layer}' as layer,
|
|
52
|
-
row_to_json(t) as data,
|
|
53
|
-
st_asgeojson(${el.geom})::json as geom from ${el.table} t
|
|
54
|
-
where ${el.query || '1=1'} and ${id ? `${el.pk}::text='${id.replace(/'/g, "''")}'` : '1=1'}
|
|
55
|
-
and case
|
|
56
|
-
when ST_GeometryType(geom) in ('ST_Polygon','ST_MultiPolygon')
|
|
57
|
-
then st_intersects(geom,st_buffer('${point}',${el.step}))
|
|
58
|
-
|
|
59
|
-
when ST_GeometryType(geom) in ('ST_Line','ST_MultiLineString')
|
|
60
|
-
then st_distance(geom,'${point}') < ${el.step}
|
|
61
|
-
else false end`).join(' union all ');
|
|
62
|
-
|
|
63
|
-
// if (config.local && config.debug) console.log(q);
|
|
64
|
-
const { rows: objects = [] } = await pg.query(q) || {};
|
|
65
|
-
time.push(Date.now());
|
|
66
|
-
|
|
67
|
-
const rows = objects.map((row) => {
|
|
68
|
-
const layerData = layers.find((el) => el.layer === row?.layer) || {};
|
|
69
|
-
const rowData = layerData?.columns?.split?.filter?.((el) => el) ? layerData?.columns?.split?.filter?.((el) => el).reduce((acc, curr) => Object.assign(acc, { [curr]: row.data?.[curr] }), {}) : row.data;
|
|
70
|
-
return {
|
|
71
|
-
...rowData,
|
|
72
|
-
...row,
|
|
73
|
-
...layerData,
|
|
74
|
-
data: undefined,
|
|
75
|
-
id: layerData.pk ? row?.[layerData.pk] : undefined,
|
|
76
|
-
geom: row.geom,
|
|
77
|
-
};
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const { pk, layer: layerId, card, template } = rows[0] || {};
|
|
81
|
-
|
|
82
|
-
const dataset = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
|
|
83
|
-
|
|
84
|
-
const columnList = (dataset.column_list || dataset.columns)?.reduce?.((acc, curr) => Object.assign(acc, { [curr.name]: curr.title || curr.ua || curr.name }), {}) || {};
|
|
85
|
-
|
|
86
|
-
const columns = card
|
|
87
|
-
? Object.keys(card).map(el => `${el}| ${card[el]}`).join('|')
|
|
88
|
-
: Object.keys(columnList)?.map((key) => `${columnList[key]}| ${key}`).join('|');
|
|
89
|
-
|
|
90
|
-
const html = columns && rows?.[0] ? await descriptionList(rows[0], { hash: { columns } }) : undefined;
|
|
91
|
-
time.push(Date.now());
|
|
92
|
-
|
|
93
|
-
await Promise.all(rows.map(async () => {
|
|
94
|
-
const layerData = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
|
|
95
|
-
const columns = layerData.column_list || layerData.columns;
|
|
96
|
-
if (columns?.length && Array.isArray(columns)) {
|
|
97
|
-
await metaFormat({ rows, columns });
|
|
98
|
-
}
|
|
99
|
-
}));
|
|
100
|
-
time.push(Date.now());
|
|
101
|
-
|
|
102
|
-
const resp = { id: rows?.[0]?.[pk], layers: layerId, template, data: rows?.[0], rows, html };
|
|
103
|
-
|
|
104
|
-
// await rclient.set(redisKey, JSON.stringify(resp), 'EX', 5 * 60);
|
|
105
|
-
return resp;
|
|
106
|
-
}
|
|
1
|
+
import descriptionList from "./descriptionList.js";
|
|
2
|
+
import metaFormat from "./metaFormat.js";
|
|
3
|
+
|
|
4
|
+
async function getDataByLatLng({ pg, layer, table, id, lat, lng, time = [] }) {
|
|
5
|
+
// const rclient = getRedis();
|
|
6
|
+
// const redisKey = `${pg.options.database}:gis-format:${layer}:${lat}:${lng}`;
|
|
7
|
+
// const cacheData = await rclient.get(redisKey);
|
|
8
|
+
// if (cacheData && !config.local) return JSON.parse(cacheData);
|
|
9
|
+
|
|
10
|
+
const { rows: styles = [] } = await pg.query(`select style_id as id, dataset
|
|
11
|
+
from gis.style where style_id=any($1::text[])
|
|
12
|
+
union all
|
|
13
|
+
select dataset_id as id, json_build_array(json_build_object('pk', pk, 'table', table_name, 'query', query, 'card', setting->>'card', 'columns', column_list)) as dataset
|
|
14
|
+
from bi.dataset a where dataset_id=any($1::text[])`, [layer.split(',')]);
|
|
15
|
+
time.push(Date.now());
|
|
16
|
+
|
|
17
|
+
if (!styles?.length) {
|
|
18
|
+
return { message: `style not found: ${layer}`, status: 400 };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { srids } = await pg.queryCache?.('select json_agg(srid) as srids from spatial_ref_sys').then((res1) => res1.rows?.[0] || {}) || {};
|
|
22
|
+
|
|
23
|
+
const layers = styles.reduce((acc, curr) => {
|
|
24
|
+
curr.dataset?.filter((el) => el.table && (el.pk || pg.pk?.[el.table]))
|
|
25
|
+
?.forEach((el) => acc.push({
|
|
26
|
+
layer: curr.id,
|
|
27
|
+
pk: el.pk || pg.pk?.[el.table],
|
|
28
|
+
key: el.key,
|
|
29
|
+
table: el.table,
|
|
30
|
+
query: el.query,
|
|
31
|
+
template: el.card,
|
|
32
|
+
column_list: el.column_list,
|
|
33
|
+
columns: el.columns || el.column_list?.map((el) => el.name)?.join(','),
|
|
34
|
+
srid: el.srid || '4326',
|
|
35
|
+
geom: el.geom || 'geom',
|
|
36
|
+
step: srids?.includes(el.srid - 0) && el.srid !== '4326' ? 10 : 0.0002,
|
|
37
|
+
}));
|
|
38
|
+
return acc;
|
|
39
|
+
}, [])
|
|
40
|
+
.filter((el) => el.pk && el.layer)
|
|
41
|
+
.filter((el) => table ? el.table === table : true);
|
|
42
|
+
|
|
43
|
+
if (!layers.length) {
|
|
44
|
+
return { message: 'data not found', status: 404 };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const point = `srid=4326;point(${lng} ${lat})`;
|
|
48
|
+
|
|
49
|
+
// ${el.columns?.split?.filter?.((el) => el) ? `,${el.columns?.split?.filter?.((el) => el) || ''}` : ''}
|
|
50
|
+
|
|
51
|
+
const q = layers.map((el) => `select ${el.pk}, '${el.layer}' as layer,
|
|
52
|
+
row_to_json(t) as data,
|
|
53
|
+
st_asgeojson(${el.geom})::json as geom from ${el.table} t
|
|
54
|
+
where ${el.query || '1=1'} and ${id ? `${el.pk}::text='${id.replace(/'/g, "''")}'` : '1=1'}
|
|
55
|
+
and case
|
|
56
|
+
when ST_GeometryType(geom) in ('ST_Polygon','ST_MultiPolygon')
|
|
57
|
+
then st_intersects(geom,st_buffer('${point}',${el.step}))
|
|
58
|
+
|
|
59
|
+
when ST_GeometryType(geom) in ('ST_Line','ST_MultiLineString')
|
|
60
|
+
then st_distance(geom,'${point}') < ${el.step}
|
|
61
|
+
else false end`).join(' union all ');
|
|
62
|
+
|
|
63
|
+
// if (config.local && config.debug) console.log(q);
|
|
64
|
+
const { rows: objects = [] } = await pg.query(q) || {};
|
|
65
|
+
time.push(Date.now());
|
|
66
|
+
|
|
67
|
+
const rows = objects.map((row) => {
|
|
68
|
+
const layerData = layers.find((el) => el.layer === row?.layer) || {};
|
|
69
|
+
const rowData = layerData?.columns?.split?.filter?.((el) => el) ? layerData?.columns?.split?.filter?.((el) => el).reduce((acc, curr) => Object.assign(acc, { [curr]: row.data?.[curr] }), {}) : row.data;
|
|
70
|
+
return {
|
|
71
|
+
...rowData,
|
|
72
|
+
...row,
|
|
73
|
+
...layerData,
|
|
74
|
+
data: undefined,
|
|
75
|
+
id: layerData.pk ? row?.[layerData.pk] : undefined,
|
|
76
|
+
geom: row.geom,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const { pk, layer: layerId, card, template } = rows[0] || {};
|
|
81
|
+
|
|
82
|
+
const dataset = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
|
|
83
|
+
|
|
84
|
+
const columnList = (dataset.column_list || dataset.columns)?.reduce?.((acc, curr) => Object.assign(acc, { [curr.name]: curr.title || curr.ua || curr.name }), {}) || {};
|
|
85
|
+
|
|
86
|
+
const columns = card
|
|
87
|
+
? Object.keys(card).map(el => `${el}| ${card[el]}`).join('|')
|
|
88
|
+
: Object.keys(columnList)?.map((key) => `${columnList[key]}| ${key}`).join('|');
|
|
89
|
+
|
|
90
|
+
const html = columns && rows?.[0] ? await descriptionList(rows[0], { hash: { columns } }) : undefined;
|
|
91
|
+
time.push(Date.now());
|
|
92
|
+
|
|
93
|
+
await Promise.all(rows.map(async () => {
|
|
94
|
+
const layerData = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
|
|
95
|
+
const columns = layerData.column_list || layerData.columns;
|
|
96
|
+
if (columns?.length && Array.isArray(columns)) {
|
|
97
|
+
await metaFormat({ rows, columns });
|
|
98
|
+
}
|
|
99
|
+
}));
|
|
100
|
+
time.push(Date.now());
|
|
101
|
+
|
|
102
|
+
const resp = { id: rows?.[0]?.[pk], layers: layerId, template, data: rows?.[0], rows, html };
|
|
103
|
+
|
|
104
|
+
// await rclient.set(redisKey, JSON.stringify(resp), 'EX', 5 * 60);
|
|
105
|
+
return resp;
|
|
106
|
+
}
|
|
107
107
|
export default getDataByLatLng
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { handlebars } from "@opengis/fastify-table/utils.js";
|
|
2
|
-
|
|
3
|
-
import descriptionList from "./descriptionList.js";
|
|
4
|
-
// import metaFormat from "./metaFormat.js";
|
|
5
|
-
|
|
6
|
-
async function getDataById({ pg, table, id, time = [] }) {
|
|
7
|
-
const dataset = await pg.query(`select dataset_id as id, pk, query, table_name, column_list, setting
|
|
8
|
-
from bi.dataset where dataset_id=$1`, [table]).then((res) => res.rows[0] || {});
|
|
9
|
-
time.push(Date.now());
|
|
10
|
-
|
|
11
|
-
if (!dataset?.id) {
|
|
12
|
-
return { message: `dataset not found: ${table}`, status: 400 };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (!dataset?.table_name) {
|
|
16
|
-
return { message: 'invalid dataset: empty params table', status: 400 };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const pk = dataset.pk || pg.pk?.[dataset.table_name];
|
|
20
|
-
|
|
21
|
-
const { rows = [] } = pk ? await pg.query(`select *, ${pk}, geom::json from ${dataset.table_name} where ${dataset.query || '1=1'} and ${pk}=$1`, [id]) || {} : {};
|
|
22
|
-
if (pk) rows.forEach((row) => Object.assign(row, { id: row?.[pk] }));
|
|
23
|
-
time.push(Date.now());
|
|
24
|
-
|
|
25
|
-
// sql columns
|
|
26
|
-
const sql = `select attname as name, pg_catalog.col_description(attrelid,attnum) as title, atttypid::regtype as type from pg_catalog.pg_attribute a
|
|
27
|
-
where attrelid='${dataset.table_name}'::regclass and attnum>0
|
|
28
|
-
and attname not in ('editor_id','editor_date','cdate','geom','id','uid','cdate')
|
|
29
|
-
and atttypid::regtype not in ('json','geometry')`;
|
|
30
|
-
|
|
31
|
-
// card or auto
|
|
32
|
-
const type = dataset.setting?.card_type || 'auto';
|
|
33
|
-
const list = dataset.setting?.card_list || [];
|
|
34
|
-
const { rows: all } = await pg.query(sql).then(el => el);
|
|
35
|
-
const columns = all.filter(el => type === 'list' ? list.includes(el.name) : true)
|
|
36
|
-
.map(el => `${el.title || el.name}| ${el.name}`).join('|')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const { body } = type === 'html' && dataset?.setting?.card ? await pg.query(`select body->>'body' as body from admin.doc_template where title=$1`, [dataset?.setting?.card]).then(el => el.rows[0] || {}) : {}
|
|
40
|
-
|
|
41
|
-
const html = body ? await handlebars.compile(body)(rows[0]) : await descriptionList(rows[0], { hash: { columns } });
|
|
42
|
-
time.push(Date.now());
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return { id: rows?.[0]?.id, template: dataset?.setting?.card, rows, html, body };
|
|
46
|
-
}
|
|
1
|
+
import { handlebars } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
import descriptionList from "./descriptionList.js";
|
|
4
|
+
// import metaFormat from "./metaFormat.js";
|
|
5
|
+
|
|
6
|
+
async function getDataById({ pg, table, id, time = [] }) {
|
|
7
|
+
const dataset = await pg.query(`select dataset_id as id, pk, query, table_name, column_list, setting
|
|
8
|
+
from bi.dataset where dataset_id=$1`, [table]).then((res) => res.rows[0] || {});
|
|
9
|
+
time.push(Date.now());
|
|
10
|
+
|
|
11
|
+
if (!dataset?.id) {
|
|
12
|
+
return { message: `dataset not found: ${table}`, status: 400 };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!dataset?.table_name) {
|
|
16
|
+
return { message: 'invalid dataset: empty params table', status: 400 };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const pk = dataset.pk || pg.pk?.[dataset.table_name];
|
|
20
|
+
|
|
21
|
+
const { rows = [] } = pk ? await pg.query(`select *, ${pk}, geom::json from ${dataset.table_name} where ${dataset.query || '1=1'} and ${pk}=$1`, [id]) || {} : {};
|
|
22
|
+
if (pk) rows.forEach((row) => Object.assign(row, { id: row?.[pk] }));
|
|
23
|
+
time.push(Date.now());
|
|
24
|
+
|
|
25
|
+
// sql columns
|
|
26
|
+
const sql = `select attname as name, pg_catalog.col_description(attrelid,attnum) as title, atttypid::regtype as type from pg_catalog.pg_attribute a
|
|
27
|
+
where attrelid='${dataset.table_name}'::regclass and attnum>0
|
|
28
|
+
and attname not in ('editor_id','editor_date','cdate','geom','id','uid','cdate')
|
|
29
|
+
and atttypid::regtype not in ('json','geometry')`;
|
|
30
|
+
|
|
31
|
+
// card or auto
|
|
32
|
+
const type = dataset.setting?.card_type || 'auto';
|
|
33
|
+
const list = dataset.setting?.card_list || [];
|
|
34
|
+
const { rows: all } = await pg.query(sql).then(el => el);
|
|
35
|
+
const columns = all.filter(el => type === 'list' ? list.includes(el.name) : true)
|
|
36
|
+
.map(el => `${el.title || el.name}| ${el.name}`).join('|')
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const { body } = type === 'html' && dataset?.setting?.card ? await pg.query(`select body->>'body' as body from admin.doc_template where title=$1`, [dataset?.setting?.card]).then(el => el.rows[0] || {}) : {}
|
|
40
|
+
|
|
41
|
+
const html = body ? await handlebars.compile(body)(rows[0]) : await descriptionList(rows[0], { hash: { columns } });
|
|
42
|
+
time.push(Date.now());
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
return { id: rows?.[0]?.id, template: dataset?.setting?.card, rows, html, body };
|
|
46
|
+
}
|
|
47
47
|
export default getDataById
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export default function insertDataQuery(columns, data, table) {
|
|
2
|
-
const columnList = columns?.map((el) => el.name)?.join(',');
|
|
3
|
-
const features = data?.features || [];
|
|
4
|
-
if (!features?.length) return null;
|
|
5
|
-
|
|
6
|
-
const insertData = `INSERT into ${table} (geom ${columns?.length ? ','.concat(columnList) : ''}) SELECT public.ST_GeomFromGeoJSON((features->>'geometry')::json) AS geom
|
|
7
|
-
${columns?.length ? ','.concat(columns?.map((el) => `features->'properties'->>'${el.title}'`)?.join(',')) : ''} FROM
|
|
8
|
-
(SELECT json_array_elements('${JSON.stringify(features).replace(/'/g, "''")}'::json) AS features)q`;
|
|
9
|
-
|
|
10
|
-
// console.log(insertData);
|
|
11
|
-
return insertData;
|
|
12
|
-
}
|
|
1
|
+
export default function insertDataQuery(columns, data, table) {
|
|
2
|
+
const columnList = columns?.map((el) => el.name)?.join(',');
|
|
3
|
+
const features = data?.features || [];
|
|
4
|
+
if (!features?.length) return null;
|
|
5
|
+
|
|
6
|
+
const insertData = `INSERT into ${table} (geom ${columns?.length ? ','.concat(columnList) : ''}) SELECT public.ST_GeomFromGeoJSON((features->>'geometry')::json) AS geom
|
|
7
|
+
${columns?.length ? ','.concat(columns?.map((el) => `features->'properties'->>'${el.title}'`)?.join(',')) : ''} FROM
|
|
8
|
+
(SELECT json_array_elements('${JSON.stringify(features).replace(/'/g, "''")}'::json) AS features)q`;
|
|
9
|
+
|
|
10
|
+
// console.log(insertData);
|
|
11
|
+
return insertData;
|
|
12
|
+
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { getSelectVal } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
export default async function metaFormat({ rows, columns }) {
|
|
4
|
-
const selectCols = columns?.filter?.((el) => el.data);
|
|
5
|
-
if (!selectCols?.length) return rows;
|
|
6
|
-
|
|
7
|
-
await Promise.all(selectCols.map(async (attr) => {
|
|
8
|
-
const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => (typeof el === 'boolean' ? true : el));
|
|
9
|
-
if (!values.length) return null;
|
|
10
|
-
|
|
11
|
-
const cls = await getSelectVal({ name: attr.data, values });
|
|
12
|
-
if (!cls) return null;
|
|
13
|
-
|
|
14
|
-
rows.forEach(el => {
|
|
15
|
-
const val = el[attr.name]?.map?.(c => cls[c.toString()] || cls[c] || c) || cls[el[attr.name]?.toString()] || cls[el[attr.name]] || el[attr.name];
|
|
16
|
-
if (!val) return;
|
|
17
|
-
Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return null;
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
return rows;
|
|
24
|
-
}
|
|
1
|
+
import { getSelectVal } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function metaFormat({ rows, columns }) {
|
|
4
|
+
const selectCols = columns?.filter?.((el) => el.data);
|
|
5
|
+
if (!selectCols?.length) return rows;
|
|
6
|
+
|
|
7
|
+
await Promise.all(selectCols.map(async (attr) => {
|
|
8
|
+
const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => (typeof el === 'boolean' ? true : el));
|
|
9
|
+
if (!values.length) return null;
|
|
10
|
+
|
|
11
|
+
const cls = await getSelectVal({ name: attr.data, values });
|
|
12
|
+
if (!cls) return null;
|
|
13
|
+
|
|
14
|
+
rows.forEach(el => {
|
|
15
|
+
const val = el[attr.name]?.map?.(c => cls[c.toString()] || cls[c] || c) || cls[el[attr.name]?.toString()] || cls[el[attr.name]] || el[attr.name];
|
|
16
|
+
if (!val) return;
|
|
17
|
+
Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
return rows;
|
|
24
|
+
}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { pgClients, dataInsert, getPGAsync } from "@opengis/fastify-table/utils.js";
|
|
2
|
-
|
|
3
|
-
export default async function dashboardAdd(req, reply) {
|
|
4
|
-
const {
|
|
5
|
-
pg = pgClients.client,
|
|
6
|
-
body = {},
|
|
7
|
-
} = req;
|
|
8
|
-
const time = Date.now();
|
|
9
|
-
|
|
10
|
-
if (body?.db) {
|
|
11
|
-
try {
|
|
12
|
-
const pg1 = await getPGAsync(body.db);
|
|
13
|
-
await pg1.query('select 1');
|
|
14
|
-
} catch (err) {
|
|
15
|
-
return reply.status(400).send('Некоректна база даних');
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const res = await dataInsert({
|
|
20
|
-
pg,
|
|
21
|
-
table: 'bi.dashboard',
|
|
22
|
-
data: body,
|
|
23
|
-
}).then(el => el.rows?.[0] || {});
|
|
24
|
-
|
|
25
|
-
if (res.dashboard_id && body.dataset) {
|
|
26
|
-
await pg.query(`update bi.dataset set dashboard_list=coalesce(dashboard_list, '{}'::text[]) || array[$1]
|
|
27
|
-
where dataset_id=$2`, [res.dashboard_id, body.dataset]);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
time: Date.now() - time,
|
|
32
|
-
id: res.dashboard_id,
|
|
33
|
-
title: res.title,
|
|
34
|
-
name: res.name,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
1
|
+
import { pgClients, dataInsert, getPGAsync } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default async function dashboardAdd(req, reply) {
|
|
4
|
+
const {
|
|
5
|
+
pg = pgClients.client,
|
|
6
|
+
body = {},
|
|
7
|
+
} = req;
|
|
8
|
+
const time = Date.now();
|
|
9
|
+
|
|
10
|
+
if (body?.db) {
|
|
11
|
+
try {
|
|
12
|
+
const pg1 = await getPGAsync(body.db);
|
|
13
|
+
await pg1.query('select 1');
|
|
14
|
+
} catch (err) {
|
|
15
|
+
return reply.status(400).send('Некоректна база даних');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const res = await dataInsert({
|
|
20
|
+
pg,
|
|
21
|
+
table: 'bi.dashboard',
|
|
22
|
+
data: body,
|
|
23
|
+
}).then(el => el.rows?.[0] || {});
|
|
24
|
+
|
|
25
|
+
if (res.dashboard_id && body.dataset) {
|
|
26
|
+
await pg.query(`update bi.dataset set dashboard_list=coalesce(dashboard_list, '{}'::text[]) || array[$1]
|
|
27
|
+
where dataset_id=$2`, [res.dashboard_id, body.dataset]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
time: Date.now() - time,
|
|
32
|
+
id: res.dashboard_id,
|
|
33
|
+
title: res.title,
|
|
34
|
+
name: res.name,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
3
|
-
|
|
4
|
-
import { pgClients, dataDelete } from '@opengis/fastify-table/utils.js';
|
|
5
|
-
|
|
6
|
-
const cwd = process.cwd();
|
|
7
|
-
const dashboardDir = path.join(cwd, 'server/templates/dashboard');
|
|
8
|
-
|
|
9
|
-
export default async function dashboardDelete({ pg = pgClients.client, params = {}, user }, reply) {
|
|
10
|
-
if (!params?.id) {
|
|
11
|
-
return reply.status(400).send('not enough params: id');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const dirContent = existsSync(dashboardDir)
|
|
15
|
-
? readdirSync(dashboardDir)
|
|
16
|
-
: [];
|
|
17
|
-
|
|
18
|
-
if (dirContent.includes(params.id)) {
|
|
19
|
-
return reply.status(403).send(`access restricted: ${params.id}`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const { rowCount = 0 } = pg.pk?.['bi.dashboard']
|
|
23
|
-
? await pg.query('select * from bi.dashboard where $1 in (dashboard_id,name)', [params.id])
|
|
24
|
-
: {};
|
|
25
|
-
|
|
26
|
-
if (rowCount === 0) {
|
|
27
|
-
return reply.status(404).send(`not found ${params.id}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
await pg.query(`delete from bi.widget where $1 in (dashboard_id)`, [params.id]);
|
|
31
|
-
await dataDelete({
|
|
32
|
-
pg,
|
|
33
|
-
table: 'bi.dashboard',
|
|
34
|
-
id: params.id,
|
|
35
|
-
uid: user?.uid,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return reply.status(200).send('successfully deleted');
|
|
39
|
-
}
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
3
|
+
|
|
4
|
+
import { pgClients, dataDelete } from '@opengis/fastify-table/utils.js';
|
|
5
|
+
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const dashboardDir = path.join(cwd, 'server/templates/dashboard');
|
|
8
|
+
|
|
9
|
+
export default async function dashboardDelete({ pg = pgClients.client, params = {}, user }, reply) {
|
|
10
|
+
if (!params?.id) {
|
|
11
|
+
return reply.status(400).send('not enough params: id');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const dirContent = existsSync(dashboardDir)
|
|
15
|
+
? readdirSync(dashboardDir)
|
|
16
|
+
: [];
|
|
17
|
+
|
|
18
|
+
if (dirContent.includes(params.id)) {
|
|
19
|
+
return reply.status(403).send(`access restricted: ${params.id}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { rowCount = 0 } = pg.pk?.['bi.dashboard']
|
|
23
|
+
? await pg.query('select * from bi.dashboard where $1 in (dashboard_id,name)', [params.id])
|
|
24
|
+
: {};
|
|
25
|
+
|
|
26
|
+
if (rowCount === 0) {
|
|
27
|
+
return reply.status(404).send(`not found ${params.id}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await pg.query(`delete from bi.widget where $1 in (dashboard_id)`, [params.id]);
|
|
31
|
+
await dataDelete({
|
|
32
|
+
pg,
|
|
33
|
+
table: 'bi.dashboard',
|
|
34
|
+
id: params.id,
|
|
35
|
+
uid: user?.uid,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return reply.status(200).send('successfully deleted');
|
|
39
|
+
}
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import { dataUpdate, pgClients, getPGAsync } from "@opengis/fastify-table/utils.js";
|
|
2
|
-
|
|
3
|
-
export default async function dashboardEdit({
|
|
4
|
-
pg = pgClients.client, params = {}, body = {},
|
|
5
|
-
}, reply) {
|
|
6
|
-
const { name: dashboardName } = params;
|
|
7
|
-
const { panels, widgets, table_name: tableName } = body;
|
|
8
|
-
|
|
9
|
-
if (body?.db) {
|
|
10
|
-
try {
|
|
11
|
-
const pg1 = await getPGAsync(body.db);
|
|
12
|
-
await pg1.query('select 1');
|
|
13
|
-
} catch (err) {
|
|
14
|
-
return reply.status(400).send('Некоректна база даних');
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!dashboardName) {
|
|
19
|
-
return reply.status(400).send('not enough params: name');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!tableName) {
|
|
23
|
-
return reply.status(400).send('not enough params: table_name');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const row = await pg.query('select dashboard_id, widgets, panels from bi.dashboard where $1 in (dashboard_id, name)', [dashboardName])
|
|
27
|
-
.then(el => el.rows?.[0] || {});
|
|
28
|
-
const { dashboard_id: dashboardId } = row;
|
|
29
|
-
|
|
30
|
-
if (!dashboardId) {
|
|
31
|
-
return reply.status(400).send('dashboard not found');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (panels?.length && !widgets?.length) {
|
|
35
|
-
(row.widgets || []).forEach((el) => {
|
|
36
|
-
const { title } = panels?.find?.(item => item.widget === el.name) || {};
|
|
37
|
-
if (el.data) {
|
|
38
|
-
// console.log('el.title', el.title, 'title', title);
|
|
39
|
-
el.data.title = title;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
Object.assign(body, { widgets: row.widgets });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const res = await dataUpdate({
|
|
46
|
-
pg,
|
|
47
|
-
table: 'bi.dashboard',
|
|
48
|
-
id: dashboardId,
|
|
49
|
-
data: body,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (!Object.keys(res)?.length) {
|
|
53
|
-
return reply.status(404).send('not found data');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
message: `updated ${dashboardName}`,
|
|
58
|
-
status: 200,
|
|
59
|
-
rows: res,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
1
|
+
import { dataUpdate, pgClients, getPGAsync } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default async function dashboardEdit({
|
|
4
|
+
pg = pgClients.client, params = {}, body = {},
|
|
5
|
+
}, reply) {
|
|
6
|
+
const { name: dashboardName } = params;
|
|
7
|
+
const { panels, widgets, table_name: tableName } = body;
|
|
8
|
+
|
|
9
|
+
if (body?.db) {
|
|
10
|
+
try {
|
|
11
|
+
const pg1 = await getPGAsync(body.db);
|
|
12
|
+
await pg1.query('select 1');
|
|
13
|
+
} catch (err) {
|
|
14
|
+
return reply.status(400).send('Некоректна база даних');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!dashboardName) {
|
|
19
|
+
return reply.status(400).send('not enough params: name');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!tableName) {
|
|
23
|
+
return reply.status(400).send('not enough params: table_name');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const row = await pg.query('select dashboard_id, widgets, panels from bi.dashboard where $1 in (dashboard_id, name)', [dashboardName])
|
|
27
|
+
.then(el => el.rows?.[0] || {});
|
|
28
|
+
const { dashboard_id: dashboardId } = row;
|
|
29
|
+
|
|
30
|
+
if (!dashboardId) {
|
|
31
|
+
return reply.status(400).send('dashboard not found');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (panels?.length && !widgets?.length) {
|
|
35
|
+
(row.widgets || []).forEach((el) => {
|
|
36
|
+
const { title } = panels?.find?.(item => item.widget === el.name) || {};
|
|
37
|
+
if (el.data) {
|
|
38
|
+
// console.log('el.title', el.title, 'title', title);
|
|
39
|
+
el.data.title = title;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.assign(body, { widgets: row.widgets });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const res = await dataUpdate({
|
|
46
|
+
pg,
|
|
47
|
+
table: 'bi.dashboard',
|
|
48
|
+
id: dashboardId,
|
|
49
|
+
data: body,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!Object.keys(res)?.length) {
|
|
53
|
+
return reply.status(404).send('not found data');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
message: `updated ${dashboardName}`,
|
|
58
|
+
status: 200,
|
|
59
|
+
rows: res,
|
|
60
|
+
};
|
|
61
|
+
}
|