@opengis/bi 1.0.21 → 1.0.22

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.
Files changed (60) hide show
  1. package/dist/bi.js +1 -1
  2. package/dist/bi.umd.cjs +101 -101
  3. package/dist/{import-file-C8BY90-b.js → import-file-r0dN1aVl.js} +19761 -18120
  4. package/dist/{map-component-mixin-CFtShPun.js → map-component-mixin-DU9YFNY4.js} +1 -1
  5. package/dist/style.css +1 -1
  6. package/dist/{vs-calendar-B9vXdsaG.js → vs-calendar-B64GoLWu.js} +1 -1
  7. package/dist/{vs-funnel-bar-Cj0O8tIf.js → vs-funnel-bar-DV5vXI3k.js} +1 -1
  8. package/dist/{vs-heatmap-C9oFph_f.js → vs-heatmap-Ox5uspv9.js} +1 -1
  9. package/dist/{vs-map-WOn0RAU7.js → vs-map-9t4WlfUa.js} +2 -2
  10. package/dist/{vs-map-cluster-RJa6sNfI.js → vs-map-cluster-DSZGPUt8.js} +2 -2
  11. package/dist/{vs-number-BG0szZL-.js → vs-number-O3_Cvwaw.js} +1 -1
  12. package/dist/vs-table-C_CsDsZN.js +68 -0
  13. package/dist/{vs-text-Kwl3-0yy.js → vs-text-I3gRlw-X.js} +2 -2
  14. package/package.json +5 -4
  15. package/plugin.js +1 -1
  16. package/server/helpers/mdToHTML.js +17 -0
  17. package/server/migrations/bi.dataset.sql +13 -0
  18. package/server/routes/dashboard/controllers/dashboard.js +3 -3
  19. package/server/routes/data/controllers/data.js +12 -13
  20. package/server/routes/data/controllers/util/chartSQL.js +6 -3
  21. package/server/routes/dataset/controllers/bi.dataset.list.js +3 -1
  22. package/server/routes/dataset/controllers/comment.js +55 -0
  23. package/server/routes/dataset/controllers/createDatasetPost.js +132 -0
  24. package/server/routes/dataset/controllers/data.js +145 -0
  25. package/server/routes/{db → dataset}/controllers/dbTablePreview.js +17 -24
  26. package/server/routes/{db → dataset}/controllers/dbTables.js +7 -11
  27. package/server/routes/dataset/controllers/delete.js +39 -0
  28. package/server/routes/dataset/controllers/{bi.dataset.edit.js → editDataset.js} +32 -26
  29. package/server/routes/dataset/controllers/export.js +213 -0
  30. package/server/routes/dataset/controllers/form.js +99 -0
  31. package/server/routes/dataset/controllers/format.js +44 -0
  32. package/server/routes/dataset/controllers/insert.js +46 -0
  33. package/server/routes/dataset/controllers/table.js +69 -0
  34. package/server/routes/dataset/controllers/update.js +42 -0
  35. package/server/routes/dataset/index.mjs +88 -43
  36. package/server/routes/dataset/utils/convertJSONToCSV.js +17 -0
  37. package/server/routes/dataset/utils/convertJSONToXls.js +49 -0
  38. package/server/routes/dataset/utils/createTableQuery.js +59 -0
  39. package/server/routes/dataset/utils/datasetForms.js +1 -0
  40. package/server/routes/dataset/utils/descriptionList.js +46 -0
  41. package/server/routes/dataset/utils/downloadRemoteFile.js +58 -0
  42. package/server/routes/dataset/utils/executeQuery.js +46 -0
  43. package/server/routes/dataset/utils/getLayersData.js +107 -0
  44. package/server/routes/dataset/utils/getTableData.js +47 -0
  45. package/server/routes/dataset/utils/insertDataQuery.js +12 -0
  46. package/server/routes/dataset/utils/metaFormat.js +24 -0
  47. package/server/routes/edit/controllers/widget.edit.js +23 -5
  48. package/server/routes/map/controllers/heatmap.js +118 -0
  49. package/server/routes/map/index.mjs +2 -0
  50. package/server/utils/getWidget.js +5 -2
  51. package/server/routes/dataset/controllers/bi.dataset.add.js +0 -86
  52. package/server/routes/dataset/controllers/bi.dataset.data.add.js +0 -49
  53. package/server/routes/dataset/controllers/bi.dataset.data.del.js +0 -54
  54. package/server/routes/dataset/controllers/bi.dataset.data.edit.js +0 -55
  55. package/server/routes/dataset/controllers/bi.dataset.data.list.js +0 -71
  56. package/server/routes/dataset/controllers/bi.dataset.del.js +0 -48
  57. package/server/routes/dataset/controllers/bi.dataset.demo.add.js +0 -97
  58. package/server/routes/dataset/controllers/util/create.table.js +0 -21
  59. package/server/routes/dataset/controllers/util/prepare.data.js +0 -49
  60. package/server/routes/db/index.mjs +0 -17
@@ -1,54 +0,0 @@
1
- import { dataDelete, getPG, initPG, pgClients } from "@opengis/fastify-table/utils.js";
2
-
3
- /**
4
- * Видалення змін до даних набору BI
5
- *
6
- * @method DELETE
7
- * @summary Внесення змін до даних набору BI
8
- * @priority 4
9
- * @alias biDatasetDataDel
10
- * @type api
11
- * @tag bi
12
- * @param {Object} params.id Dataset ID
13
- * @param {Object} params.objectId Dataset object ID
14
- * @errors 400,500
15
- * @returns {Number} status Номер помилки
16
- * @returns {String} error Опис помилки
17
- * @returns {Object} rows Масив з колонками таблиці
18
- */
19
-
20
- export default async function biDatasetDataDel(req) {
21
- const { params = {}, session = {} } = req;
22
- const { uid } = session?.passport?.user || {};
23
-
24
- if (!uid) {
25
- return { message: 'access restricted', status: 403 };
26
- }
27
-
28
- if (!params?.id) {
29
- return { message: 'not enough params: id', status: 400 };
30
- }
31
-
32
- if (!params?.objectId) {
33
- return { message: 'not enough params: objectId', status: 400 };
34
- }
35
-
36
- const { id, table, db } = await pgClients.client.query('select db, dataset_id as id, table_name as table from bi.dataset where dataset_id=$1', [params.id])
37
- .then(el => el.rows[0]);
38
-
39
- if (!id) {
40
- return { message: 'dataset not found', status: 404 };
41
- }
42
-
43
- const pg = db ? getPG({ db }) : pgClients.client;
44
- if (!pg.pk) await initPG(pg);
45
-
46
- const result = await dataDelete({
47
- pg,
48
- table,
49
- id: params.objectId,
50
- uid,
51
- });
52
-
53
- return { id, action: 'delete', result };
54
- };
@@ -1,55 +0,0 @@
1
- import { dataUpdate, getPG, initPG, pgClients } from "@opengis/fastify-table/utils.js";
2
-
3
- /**
4
- * Внесення змін до даних набору BI
5
- *
6
- * @method PUT
7
- * @summary Внесення змін до даних набору BI
8
- * @priority 4
9
- * @alias biDatasetDataEdit
10
- * @type api
11
- * @tag bi
12
- * @param {Object} params.id Dataset ID
13
- * @param {Object} params.objectId Dataset object ID
14
- * @errors 400,500
15
- * @returns {Number} status Номер помилки
16
- * @returns {String} error Опис помилки
17
- * @returns {Object} rows Масив з колонками таблиці
18
- */
19
-
20
- export default async function biDatasetDataEdit(req) {
21
- const { params = {}, session = {}, body = {} } = req;
22
- const { uid } = session?.passport?.user || {};
23
-
24
- if (!uid) {
25
- return { message: 'access restricted', status: 403 };
26
- }
27
-
28
- if (!params?.id) {
29
- return { message: 'not enough params: id', status: 400 };
30
- }
31
-
32
- if (!params?.objectId) {
33
- return { message: 'not enough params: objectId', status: 400 };
34
- }
35
-
36
- const { id, table, db } = await pgClients.client.query('select db, dataset_id as id, table_name as table from bi.dataset where dataset_id=$1', [params.id])
37
- .then(el => el.rows[0]);
38
-
39
- if (!id) {
40
- return { message: 'dataset not found', status: 404 };
41
- }
42
-
43
- const pg = db ? getPG({ db }) : pgClients.client;
44
- if (!pg.pk) await initPG(pg);
45
-
46
- const result = await dataUpdate({
47
- pg,
48
- table,
49
- data: body,
50
- id: params.objectId,
51
- uid,
52
- });
53
-
54
- return { id, action: 'update', result };
55
- };
@@ -1,71 +0,0 @@
1
- import { getMeta, getPG, initPG, pgClients } from "@opengis/fastify-table/utils.js";
2
-
3
- const maxLimit = 100;
4
-
5
- /**
6
- * Отримання даних та структури набору даних BI
7
- *
8
- * @method GET
9
- * @summary Отримання даних та структури набору даних BI
10
- * @priority 4
11
- * @alias biDatasetDataList
12
- * @type api
13
- * @tag bi
14
- * @param {Object} params.id Dataset ID
15
- * @errors 400,500
16
- * @returns {Number} status Номер помилки
17
- * @returns {String} error Опис помилки
18
- * @returns {Object} rows Масив з колонками таблиці
19
- */
20
-
21
- export default async function biDatasetDataList(req) {
22
- const { params = {}, session = {}, query = {} } = req;
23
- const { user = {} } = session?.passport || {};
24
- const { uid, user_type: userType } = user;
25
-
26
- if (!params?.id) {
27
- return { message: 'not enough params: id', status: 400 };
28
- }
29
-
30
- const { id, table, db, column_list: columnList, sql_list: sql } = await pgClients.client.query('select db, dataset_id as id, table_name as table, column_list, sql_list from bi.dataset where dataset_id=$1', [params.id])
31
- .then(el => el.rows?.[0] || {});
32
-
33
- if (!id) {
34
- return { message: 'dataset not found', status: 404 };
35
- }
36
-
37
- const pg = db ? getPG({ db }) : pgClients.client;
38
- if (!pg.pk) await initPG(pg);
39
-
40
- const q1 = `select json_object_agg(attname, pg_catalog.col_description(attrelid,attnum)) as titles from pg_catalog.pg_attribute a
41
- where attrelid=$1::regclass and attnum>0 and pg_catalog.col_description(attrelid,attnum) is not null`;
42
-
43
- const meta = await getMeta({ pg, table });
44
-
45
- if (meta?.error) return meta;
46
-
47
- const { titles = {} } = table ? await pg.query(q1, [table]) : {};
48
- const columns = columnList?.filter?.((col) => !col.disabled) || meta.columns?.map?.((col) => ({ name: col.name, type: pg.pgType[col.dataTypeID], title: titles[col.name] || col.name }));
49
-
50
- const sqlTable = sql
51
- ?.filter?.((el) => !el?.disabled && el?.sql?.replace)
52
- ?.map((el, i) => ` left join lateral (${el.sql.replace('{{uid}}', uid || '')}) ${el.name || `t${i}`} on 1=1 `)
53
- ?.join('') || '';
54
-
55
- const limit = Math.min(maxLimit, +(query.limit || 20));
56
- const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
57
- const orderBy = columns.find((col) => col.name ==='cdate')?.name || columns.find((col) => col.type ==='date')?.name;
58
-
59
- const q = table && pg.pk[table]
60
- ? `select ${columns.map((col) => `"${col.name}"`).filter((col) => col.name !== 'id').join(',')}, ${pg.pk[table]} as id from ( select * from ${table} ${sqlTable} ${orderBy ? `order by ${orderBy} desc` : ''} offset ${offset} limit ${limit} )q`
61
- : undefined;
62
-
63
- if (query.sql && userType?.includes?.('admin')) return q;
64
-
65
- const { rows = [] } = q ? await pg.query(q) : {};
66
-
67
- const { totals = {} } = await pg.query(`select json_object_agg(oid::regclass, reltuples) as totals from pg_class`)
68
- .then(el => el.rows?.[0] || {});
69
-
70
- return { total: totals[table] || 0, count: rows?.length, sql, rows, columns };
71
- };
@@ -1,48 +0,0 @@
1
- import { dataDelete, pgClients, getPG, initPG } from "@opengis/fastify-table/utils.js";
2
-
3
- /**
4
- * Видалення набору даних BI
5
- *
6
- * @method DELETE
7
- * @summary Видалення нового набору даних BI
8
- * @priority 4
9
- * @alias biDatasetDel
10
- * @type api
11
- * @tag bi
12
- * @param {Object} params.id dataset ID
13
- * @errors 400,500
14
- * @returns {Number} status Номер помилки
15
- * @returns {String} error Опис помилки
16
- * @returns {Object} rows Масив з колонками таблиці
17
- */
18
-
19
- export default async function biDatasetDel(req) {
20
- const { params = {}, session = {} } = req;
21
- const { uid } = session?.passport?.user || {};
22
-
23
- if (!uid) {
24
- return { message: 'access restricted', status: 403 };
25
- }
26
-
27
- const dataset = await pgClients.client.query('select db, dataset_id as id, table_name as table from bi.dataset where dataset_id=$1', [params.id])
28
- .then(el => el.rows[0]);
29
-
30
- if (!dataset.id) {
31
- return { message: 'dataset not found', status: 404 };
32
- }
33
-
34
- await dataDelete({
35
- table: 'bi.dataset',
36
- id: dataset.id,
37
- uid,
38
- });
39
-
40
- const pg = dataset.db ? getPG({ db: dataset.db }) : pgClients.client;
41
- if (!pg.pk) await initPG(pg);
42
-
43
- if (dataset.table && dataset.table?.split?.('.')?.shift() === 'bi_data') {
44
- await pg.query(`drop table if exists ${dataset.table}`);
45
- }
46
-
47
- return { message: { id: dataset.id, action: 'delete', table: dataset.table }, status: 200 };
48
- };
@@ -1,97 +0,0 @@
1
- import path from 'node:path';
2
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
3
-
4
- import { getPG } from '@opengis/fastify-table/utils.js';
5
-
6
- const host = 'https://cdn.softpro.ua/demo/bi';
7
-
8
-
9
- const root = process.cwd();
10
- const send = (msg) => console.log(msg)
11
- async function downloadFile(fileName) {
12
- const pg = getPG();
13
- send(`${fileName} - checking if already downloaded...`);
14
-
15
- const demoPath = path.join(root, '/log/temp/', fileName);
16
- // const fileExists = await isFileExists(demoPath);
17
-
18
- // send(`${host}/${fileName}` + demoPath)
19
- const response = await fetch(`${host}/${fileName}`);
20
- const body = await response.text();
21
- //send(body)
22
- if (response?.status !== 200) {
23
- return { [fileName]: { result: 'file not found', status: 404 } };
24
- }
25
-
26
- await mkdir(path.dirname(demoPath), { recursive: true });
27
-
28
- await writeFile(demoPath, body, 'utf8');
29
-
30
- await pg.query(`drop table if exists ${path.parse(fileName).name}`);
31
- const { exists } = await pg.query(`select to_regclass($1) is not null as exists`, [path.parse(fileName).name])
32
- .then((res1) => res1.rows?.[0] || {});
33
-
34
-
35
- if (exists) {
36
- send(`${fileName} - dataset table already exists!`);
37
- return { [fileName]: { result: 'dataset table already exists', status: 200 } };
38
- }
39
-
40
- const sql = await readFile(demoPath, 'utf8');
41
- await pg.query(sql);
42
- return { [fileName]: { result: 'success', status: 200 } };
43
- }
44
-
45
- /**
46
- * Імпорт demo даних dashboard
47
- *
48
- * @method GET
49
- * @summary Імпорт demo даних dashboard
50
- * @priority 4
51
- * @type api
52
- * @tag bi
53
- * @errors 400,500
54
- * @returns {Number} status Номер помилки
55
- * @returns {String} error Опис помилки
56
- * @returns {Object} rows Масив з колонками таблиці
57
- */
58
-
59
- const demoList = {
60
- 'demo.orders.sql': 'Статистика продажів (demo)',
61
- 'demo.cleaned_sales_data.sql': 'Статистика продажів (demo 2)',
62
- 'demo.video_game_sales.sql': 'Статистика продажів відеоігор (demo)',
63
- };
64
-
65
- export default async function biDatasetDemoAdd(req) {
66
- const { pg, query = {} } = req;
67
- // const send = () => { }; // eventStream?
68
-
69
-
70
-
71
- const sqlList = [];
72
-
73
- const tables = Object.keys(demoList)?.map((el) => {
74
- const table = path.parse(el).name;
75
- sqlList.push(`insert into bi.dataset(dataset_id,name,table_name,source_type)
76
- select '${el}', '${demoList?.[el]}', '${table}', 'demo' on conflict(dataset_id) do update set
77
- name=excluded.name, table_name=excluded.table_name
78
- returning dataset_id as id`);
79
- return table;
80
- });
81
-
82
- const { count } = await pg.query(`select count(*) from pg_catalog.pg_tables where schemaname||'.'||tablename = any($1)`, [tables]).then((res1) => res1.rows?.[0] || {});
83
-
84
- if (count === '3' && !query.nocache) {
85
- const result = await pg.query(sqlList.join(';\n'));
86
- const ids = (Array.isArray(result) ? result : [result]).filter((el) => el).map((el) => el?.rows?.[0]?.id);
87
- return { message: { ids, message: 'all datasets already downloaded' }, status: 200 };
88
- }
89
-
90
- const res = {};
91
- const resultAll = await Promise.all(Object.keys(demoList).map(async (fileName) => await downloadFile(fileName))).catch(err => console.log(err));
92
-
93
- const result = await pg.query(sqlList.join(';\n'));
94
- const ids = (Array.isArray(result) ? result : [result]).filter((el) => el).map((el) => el?.rows?.[0]?.id);
95
- return { message: { ids, message: res, resultAll }, status: 200 };
96
-
97
- };
@@ -1,21 +0,0 @@
1
- export default function createTableFunc({
2
- table, pkey, columns, name,
3
- }) {
4
- const columnType1 = {
5
- text: 'text', select: 'text', date: 'date', 'yes/no': 'boolean', badge: 'text', number: 'numeric', tags: 'text[]', geom: 'geom',
6
- };
7
-
8
- const createQuery = `create table if not exists ${table} (
9
- ${pkey} text not null default public.uuid_generate_v4(),
10
- geom public.geometry, ${columns ? `
11
- ${columns?.map((el) => `${el.name} ${columnType1[el.format] || 'text'}`).join(', ')},` : ''}
12
- cdate timestamp without time zone not null default now(),
13
- editor_date timestamp without time zone,
14
- uid text,
15
- editor_id text,
16
- files json,
17
- constraint ${table.replace(/\./g, '_')}_constraint_pkey PRIMARY KEY (${pkey}) )`;
18
-
19
- const commentQuery = columns?.filter((el) => el.ua)?.map((el) => `comment on column ${table}.${el.name} is '${el.ua}'`).join(';');
20
- return [createQuery, commentQuery, (name ? `comment on table ${table} is '${name}'` : undefined)].filter((el) => el).join(';');
21
- };
@@ -1,49 +0,0 @@
1
- import path from 'node:path';
2
-
3
- import { config, getFolder, isFileExists } from '@opengis/fastify-table/utils.js';
4
-
5
- import { file2json } from '@opengis/fastify-file/utils.js';
6
-
7
- function getFileColumns({ data }) {
8
- if (data?.features) {
9
- return Object.keys(data?.features[0]?.properties); // geojson / shapefile
10
- }
11
- if (Array.isArray(data)) {
12
- return Object.keys(data[0])?.filter((el) => el); // csv / xls
13
- }
14
- return Object.values(data[Object.keys(data)?.[0]]?.[0]); // else?
15
- }
16
-
17
- export default async function prepareData({
18
- table, file_path: filePath, data: data1,
19
- }) {
20
- const rootDir = getFolder(config);
21
- const fullPath = path.join(rootDir, filePath || '');
22
- const fileExists = data1 ? false : await isFileExists(fullPath);
23
- if (!fileExists && !data1) {
24
- return { message: `file not found: ${filePath}`, status: 404 };
25
- }
26
-
27
- const data11 = fileExists ? await file2json({ filepath: fullPath }) : data1;
28
- const data = (['.xls', '.xlsx'].includes(path.extname(fullPath)) && !Array.isArray(data11)) ? data11[Object.keys(data11)[0]] : data11;
29
-
30
- /* generate column list based on input data */
31
- const columns = getFileColumns({ data })
32
- ?.filter((el) => !['editor_date', 'cdate', 'uid', 'editor_id', 'files'].includes(el.toLowerCase()))
33
- ?.map((el, index) => ({ name: `col_${index}`, ua: el, format: 'text' }));
34
-
35
- const columnList1 = columns?.map((el) => el.name)?.join(',');
36
- const columns1 = ','.concat(columns?.map((el) => `features->'properties'->>'${el?.ua}'`)?.join(','));
37
- const columns2 = columns?.map((el) => `d->>'${el.ua}'`).join(',');
38
- const q1 = data?.features ? `(SELECT json_array_elements('${JSON.stringify(data.features).replace(/'/g, "''")}'::json) AS features)q` : null;
39
- const q2 = !data?.features ? `( SELECT json_array_elements('${JSON.stringify(Array.isArray(data)
40
- ? data
41
- : data[Object?.keys(data)?.[0]])
42
- .replace(/'/g, "''")
43
- .replace(/\\"/g, '`')}'::json) AS d )q`
44
- : null;
45
- const insertData = data?.features
46
- ? `INSERT into ${table} (geom ${','.concat(columnList1)}) SELECT public.ST_GeomFromGeoJSON((features->>'geometry')::json) AS geom ${columns1} FROM ${q1}`
47
- : `INSERT into ${table} (${columnList1}) SELECT ${columns2} FROM ${q2}`;
48
- return { columns, insertData };
49
- };
@@ -1,17 +0,0 @@
1
- import dbTables from './controllers/dbTables.js';
2
- import dbTablePreview from './controllers/dbTablePreview.js';
3
-
4
- export default async function route(fastify, opts) {
5
- fastify.route({
6
- method: 'GET',
7
- url: '/db-tables',
8
- schema: {},
9
- handler: dbTables,
10
- });
11
- fastify.route({
12
- method: 'GET',
13
- url: '/db-tables/:name',
14
- schema: {},
15
- handler: dbTablePreview,
16
- });
17
- }