@opengis/bi 1.2.30 → 1.2.32
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 +88 -86
- package/dist/{import-file-B4o9p2_2.js → import-file-D-ISqB7l.js} +1772 -1593
- package/dist/style.css +1 -1
- package/dist/{vs-funnel-bar-BOWwPnjW.js → vs-funnel-bar-aoZzvriV.js} +3 -3
- package/dist/{vs-list-D8jGusRT.js → vs-list-CBkyJSBj.js} +53 -32
- package/dist/{vs-map-BGplOwpB.js → vs-map-C3C11qmT.js} +102 -91
- package/dist/{vs-map-cluster-CHQJV2As.js → vs-map-cluster-BsPmHIMx.js} +91 -81
- package/dist/{vs-number-jPqxFQ6d.js → vs-number-d58ftpH5.js} +3 -3
- package/dist/{vs-table-BDgIvJbY.js → vs-table-BHa5Velm.js} +6 -6
- package/dist/{vs-text-DcHOffy9.js → vs-text-Bq87gMTx.js} +4 -4
- package/package.json +77 -75
- package/plugin.js +21 -22
- package/server/helpers/mdToHTML.js +17 -17
- package/server/migrations/bi.dataset.sql +46 -46
- package/server/migrations/bi.sql +115 -112
- package/server/plugins/docs.js +48 -48
- package/server/plugins/hook.js +89 -89
- package/server/plugins/vite.js +81 -81
- package/server/routes/dashboard/controllers/dashboard.import.js +103 -103
- package/server/routes/dashboard/controllers/dashboard.js +158 -157
- 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 -229
- 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 -117
- package/utils.js +12 -12
package/server/plugins/vite.js
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import config from '../../config.js';
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const rootDir = path.resolve(__dirname, '../..');
|
|
8
|
-
const distIndexPath = path.join(rootDir, 'dist', 'index.html');
|
|
9
|
-
const distAssetsDir = path.join(rootDir, 'dist', 'assets');
|
|
10
|
-
|
|
11
|
-
const { disableAuth } = config;
|
|
12
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
13
|
-
|
|
14
|
-
async function plugin(fastify) {
|
|
15
|
-
// vite server
|
|
16
|
-
if (!isProduction) {
|
|
17
|
-
const vite = await import('vite');
|
|
18
|
-
|
|
19
|
-
const viteServer = await vite.createServer({
|
|
20
|
-
server: {
|
|
21
|
-
middlewareMode: true,
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
// hot reload
|
|
25
|
-
viteServer.watcher.on('all', (d, t) => {
|
|
26
|
-
if (!t.includes('module') && !t.includes('templates')) return;
|
|
27
|
-
// console.log(d, t);
|
|
28
|
-
viteServer.ws.send({ type: 'full-reload' });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// this is middleware for vite's dev servert
|
|
32
|
-
fastify.addHook('onRequest', async (req, reply) => {
|
|
33
|
-
// const { user } = req.session?.passport || {};
|
|
34
|
-
const next = () => new Promise((resolve) => {
|
|
35
|
-
viteServer.middlewares(req.raw, reply.raw, () => resolve());
|
|
36
|
-
});
|
|
37
|
-
await next();
|
|
38
|
-
});
|
|
39
|
-
fastify.get('*', async () => {});
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// From Build
|
|
44
|
-
fastify.get('*', async (req, reply) => {
|
|
45
|
-
// console.log(disableAuth)
|
|
46
|
-
if (!req.user && !disableAuth) return reply.redirect('/login');
|
|
47
|
-
if (!fs.existsSync(distIndexPath)) {
|
|
48
|
-
return reply
|
|
49
|
-
.code(503)
|
|
50
|
-
.type('text/plain')
|
|
51
|
-
.send('index.html not found in dist. Run: npm run build-app');
|
|
52
|
-
}
|
|
53
|
-
const stream = fs.createReadStream(distIndexPath);
|
|
54
|
-
return reply
|
|
55
|
-
.headers({ 'Cache-Control': 'public, no-cache' })
|
|
56
|
-
.type('text/html')
|
|
57
|
-
.send(stream);
|
|
58
|
-
});
|
|
59
|
-
fastify.get('/assets/:file', async (req, reply) => {
|
|
60
|
-
const stream = fs.createReadStream(path.join(distAssetsDir, req.params.file));
|
|
61
|
-
const ext = path.extname(req.params.file);
|
|
62
|
-
const mime = {
|
|
63
|
-
'.js': 'text/javascript',
|
|
64
|
-
'.css': 'text/css',
|
|
65
|
-
'.woff2': 'application/font-woff',
|
|
66
|
-
'.png': 'image/png',
|
|
67
|
-
}[ext];
|
|
68
|
-
// reply.cacheControl('max-age', '1d');
|
|
69
|
-
return mime
|
|
70
|
-
? reply
|
|
71
|
-
.headers({
|
|
72
|
-
'Cache-Control': 'public, max-age=3600',
|
|
73
|
-
'Content-Encoding': 'identity',
|
|
74
|
-
})
|
|
75
|
-
.type(mime)
|
|
76
|
-
.send(stream)
|
|
77
|
-
: stream;
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export default plugin;
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import config from '../../config.js';
|
|
5
|
+
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const rootDir = path.resolve(__dirname, '../..');
|
|
8
|
+
const distIndexPath = path.join(rootDir, 'dist', 'index.html');
|
|
9
|
+
const distAssetsDir = path.join(rootDir, 'dist', 'assets');
|
|
10
|
+
|
|
11
|
+
const { disableAuth } = config;
|
|
12
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
13
|
+
|
|
14
|
+
async function plugin(fastify) {
|
|
15
|
+
// vite server
|
|
16
|
+
if (!isProduction) {
|
|
17
|
+
const vite = await import('vite');
|
|
18
|
+
|
|
19
|
+
const viteServer = await vite.createServer({
|
|
20
|
+
server: {
|
|
21
|
+
middlewareMode: true,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
// hot reload
|
|
25
|
+
viteServer.watcher.on('all', (d, t) => {
|
|
26
|
+
if (!t.includes('module') && !t.includes('templates')) return;
|
|
27
|
+
// console.log(d, t);
|
|
28
|
+
viteServer.ws.send({ type: 'full-reload' });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// this is middleware for vite's dev servert
|
|
32
|
+
fastify.addHook('onRequest', async (req, reply) => {
|
|
33
|
+
// const { user } = req.session?.passport || {};
|
|
34
|
+
const next = () => new Promise((resolve) => {
|
|
35
|
+
viteServer.middlewares(req.raw, reply.raw, () => resolve());
|
|
36
|
+
});
|
|
37
|
+
await next();
|
|
38
|
+
});
|
|
39
|
+
fastify.get('*', async () => {});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// From Build
|
|
44
|
+
fastify.get('*', async (req, reply) => {
|
|
45
|
+
// console.log(disableAuth)
|
|
46
|
+
if (!req.user && !disableAuth) return reply.redirect('/login');
|
|
47
|
+
if (!fs.existsSync(distIndexPath)) {
|
|
48
|
+
return reply
|
|
49
|
+
.code(503)
|
|
50
|
+
.type('text/plain')
|
|
51
|
+
.send('index.html not found in dist. Run: npm run build-app');
|
|
52
|
+
}
|
|
53
|
+
const stream = fs.createReadStream(distIndexPath);
|
|
54
|
+
return reply
|
|
55
|
+
.headers({ 'Cache-Control': 'public, no-cache' })
|
|
56
|
+
.type('text/html')
|
|
57
|
+
.send(stream);
|
|
58
|
+
});
|
|
59
|
+
fastify.get('/assets/:file', async (req, reply) => {
|
|
60
|
+
const stream = fs.createReadStream(path.join(distAssetsDir, req.params.file));
|
|
61
|
+
const ext = path.extname(req.params.file);
|
|
62
|
+
const mime = {
|
|
63
|
+
'.js': 'text/javascript',
|
|
64
|
+
'.css': 'text/css',
|
|
65
|
+
'.woff2': 'application/font-woff',
|
|
66
|
+
'.png': 'image/png',
|
|
67
|
+
}[ext];
|
|
68
|
+
// reply.cacheControl('max-age', '1d');
|
|
69
|
+
return mime
|
|
70
|
+
? reply
|
|
71
|
+
.headers({
|
|
72
|
+
'Cache-Control': 'public, max-age=3600',
|
|
73
|
+
'Content-Encoding': 'identity',
|
|
74
|
+
})
|
|
75
|
+
.type(mime)
|
|
76
|
+
.send(stream)
|
|
77
|
+
: stream;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default plugin;
|
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
config, logger, pgClients, getTemplate, getTemplatePath, dataInsert, dataUpdate,
|
|
5
|
-
} from '@opengis/fastify-table/utils.js';
|
|
6
|
-
|
|
7
|
-
export default async function dashboardImport({ pg = pgClients.client, query = {}, user = {} }, reply) {
|
|
8
|
-
const time = Date.now();
|
|
9
|
-
|
|
10
|
-
if (!query?.dashboard) {
|
|
11
|
-
return reply.status(400).send('not enough query params: dashboard');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const list = getTemplatePath('dashboard').filter(el => el[0] === query.dashboard);
|
|
15
|
-
|
|
16
|
-
if (!list?.length) {
|
|
17
|
-
return reply.status(404).send(`dashboard not found`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const client = await pg.connect();
|
|
21
|
-
Object.assign(client, {
|
|
22
|
-
options: pg.options,
|
|
23
|
-
pk: pg.pk,
|
|
24
|
-
pgType: pg.pgType,
|
|
25
|
-
tlist: pg.tlist,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const ids = [];
|
|
29
|
-
try {
|
|
30
|
-
await client.query('BEGIN');
|
|
31
|
-
const rows = await Promise.all(list.map(async ([filename]) => {
|
|
32
|
-
|
|
33
|
-
const obj = await getTemplate('dashboard', filename);
|
|
34
|
-
const index = obj?.find((el) => el[0] === 'index.yml')?.[1];
|
|
35
|
-
const { db = pg.options?.database, description, filters, panels, table_name, title, tags, style, grid } = index || {};
|
|
36
|
-
|
|
37
|
-
const dashboardId = await dataInsert({
|
|
38
|
-
pg,
|
|
39
|
-
table: 'bi.dashboard',
|
|
40
|
-
data: {
|
|
41
|
-
db,
|
|
42
|
-
name: filename,
|
|
43
|
-
description,
|
|
44
|
-
filters,
|
|
45
|
-
panels,
|
|
46
|
-
table_name,
|
|
47
|
-
title,
|
|
48
|
-
words: tags?.join(','),
|
|
49
|
-
style,
|
|
50
|
-
grid,
|
|
51
|
-
source: 'file',
|
|
52
|
-
},
|
|
53
|
-
uid: user?.uid,
|
|
54
|
-
}).then(el => el.rows?.[0]?.dashboard_id);
|
|
55
|
-
ids.push(dashboardId);
|
|
56
|
-
|
|
57
|
-
const widgetList = panels?.reduce((acc, curr) => {
|
|
58
|
-
curr.widgets?.forEach(item => acc.push(item));
|
|
59
|
-
if (curr.widget) acc.push(curr.widget);
|
|
60
|
-
return acc;
|
|
61
|
-
}, []).filter(el => el) || [];
|
|
62
|
-
|
|
63
|
-
const widgets = widgetList.length
|
|
64
|
-
? await Promise.all(obj.filter(el => widgetList.includes(path.parse(el[0]).name)).map(async ([widget, widgetData]) => {
|
|
65
|
-
const { ext, name } = path.parse(widget);
|
|
66
|
-
const data = ext === '.yml' ? widgetData : { type: 'text', data: { text: widgetData } };
|
|
67
|
-
Object.assign(data, { name, x: widgetData?.data?.x, table_name: widgetData?.data?.table, dashboard_id: dashboardId });
|
|
68
|
-
|
|
69
|
-
const res = await dataInsert({
|
|
70
|
-
pg: client,
|
|
71
|
-
table: 'bi.widget',
|
|
72
|
-
data,
|
|
73
|
-
uid: user?.uid,
|
|
74
|
-
}).then(el => el.rows?.[0] || {});
|
|
75
|
-
return res;
|
|
76
|
-
}))
|
|
77
|
-
: [];
|
|
78
|
-
const test = await dataUpdate({
|
|
79
|
-
pg: client,
|
|
80
|
-
table: 'bi.dashboard',
|
|
81
|
-
id: dashboardId,
|
|
82
|
-
data: {
|
|
83
|
-
widgets,
|
|
84
|
-
},
|
|
85
|
-
uid: user?.uid,
|
|
86
|
-
});
|
|
87
|
-
return { dashboardId, name: filename, widgets };
|
|
88
|
-
}));
|
|
89
|
-
|
|
90
|
-
await client.query('COMMIT');
|
|
91
|
-
return { time: Date.now() - time, rows };
|
|
92
|
-
} catch (err) {
|
|
93
|
-
await client.query('ROLLBACK');
|
|
94
|
-
if (ids.length) {
|
|
95
|
-
const { rowCount = 0 } = await pg.query('delete from bi.dashboard where dashboard_id = any($1)', [ids]);
|
|
96
|
-
console.log('ROLLBACK delete', rowCount, 'dashboard');
|
|
97
|
-
// const { rowCount: rowCount1 = 0 } = await pg.query('delete from bi.widget where dashboard_id = any($1)', [ids]);
|
|
98
|
-
// console.log('delete', rowCount1, 'widget');
|
|
99
|
-
}
|
|
100
|
-
logger.file('bi/dashboardImport/error', { error: err.toString(), stack: err.stack, ids });
|
|
101
|
-
return reply.status(500).send(config.debug ? err.toString() : 'import error');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
config, logger, pgClients, getTemplate, getTemplatePath, dataInsert, dataUpdate,
|
|
5
|
+
} from '@opengis/fastify-table/utils.js';
|
|
6
|
+
|
|
7
|
+
export default async function dashboardImport({ pg = pgClients.client, query = {}, user = {} }, reply) {
|
|
8
|
+
const time = Date.now();
|
|
9
|
+
|
|
10
|
+
if (!query?.dashboard) {
|
|
11
|
+
return reply.status(400).send('not enough query params: dashboard');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const list = getTemplatePath('dashboard').filter(el => el[0] === query.dashboard);
|
|
15
|
+
|
|
16
|
+
if (!list?.length) {
|
|
17
|
+
return reply.status(404).send(`dashboard not found`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const client = await pg.connect();
|
|
21
|
+
Object.assign(client, {
|
|
22
|
+
options: pg.options,
|
|
23
|
+
pk: pg.pk,
|
|
24
|
+
pgType: pg.pgType,
|
|
25
|
+
tlist: pg.tlist,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const ids = [];
|
|
29
|
+
try {
|
|
30
|
+
await client.query('BEGIN');
|
|
31
|
+
const rows = await Promise.all(list.map(async ([filename]) => {
|
|
32
|
+
|
|
33
|
+
const obj = await getTemplate('dashboard', filename);
|
|
34
|
+
const index = obj?.find((el) => el[0] === 'index.yml')?.[1];
|
|
35
|
+
const { db = pg.options?.database, description, filters, panels, table_name, title, tags, style, grid } = index || {};
|
|
36
|
+
|
|
37
|
+
const dashboardId = await dataInsert({
|
|
38
|
+
pg,
|
|
39
|
+
table: 'bi.dashboard',
|
|
40
|
+
data: {
|
|
41
|
+
db,
|
|
42
|
+
name: filename,
|
|
43
|
+
description,
|
|
44
|
+
filters,
|
|
45
|
+
panels,
|
|
46
|
+
table_name,
|
|
47
|
+
title,
|
|
48
|
+
words: tags?.join(','),
|
|
49
|
+
style,
|
|
50
|
+
grid,
|
|
51
|
+
source: 'file',
|
|
52
|
+
},
|
|
53
|
+
uid: user?.uid,
|
|
54
|
+
}).then(el => el.rows?.[0]?.dashboard_id);
|
|
55
|
+
ids.push(dashboardId);
|
|
56
|
+
|
|
57
|
+
const widgetList = panels?.reduce((acc, curr) => {
|
|
58
|
+
curr.widgets?.forEach(item => acc.push(item));
|
|
59
|
+
if (curr.widget) acc.push(curr.widget);
|
|
60
|
+
return acc;
|
|
61
|
+
}, []).filter(el => el) || [];
|
|
62
|
+
|
|
63
|
+
const widgets = widgetList.length
|
|
64
|
+
? await Promise.all(obj.filter(el => widgetList.includes(path.parse(el[0]).name)).map(async ([widget, widgetData]) => {
|
|
65
|
+
const { ext, name } = path.parse(widget);
|
|
66
|
+
const data = ext === '.yml' ? widgetData : { type: 'text', data: { text: widgetData } };
|
|
67
|
+
Object.assign(data, { name, x: widgetData?.data?.x, table_name: widgetData?.data?.table, dashboard_id: dashboardId });
|
|
68
|
+
|
|
69
|
+
const res = await dataInsert({
|
|
70
|
+
pg: client,
|
|
71
|
+
table: 'bi.widget',
|
|
72
|
+
data,
|
|
73
|
+
uid: user?.uid,
|
|
74
|
+
}).then(el => el.rows?.[0] || {});
|
|
75
|
+
return res;
|
|
76
|
+
}))
|
|
77
|
+
: [];
|
|
78
|
+
const test = await dataUpdate({
|
|
79
|
+
pg: client,
|
|
80
|
+
table: 'bi.dashboard',
|
|
81
|
+
id: dashboardId,
|
|
82
|
+
data: {
|
|
83
|
+
widgets,
|
|
84
|
+
},
|
|
85
|
+
uid: user?.uid,
|
|
86
|
+
});
|
|
87
|
+
return { dashboardId, name: filename, widgets };
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
await client.query('COMMIT');
|
|
91
|
+
return { time: Date.now() - time, rows };
|
|
92
|
+
} catch (err) {
|
|
93
|
+
await client.query('ROLLBACK');
|
|
94
|
+
if (ids.length) {
|
|
95
|
+
const { rowCount = 0 } = await pg.query('delete from bi.dashboard where dashboard_id = any($1)', [ids]);
|
|
96
|
+
console.log('ROLLBACK delete', rowCount, 'dashboard');
|
|
97
|
+
// const { rowCount: rowCount1 = 0 } = await pg.query('delete from bi.widget where dashboard_id = any($1)', [ids]);
|
|
98
|
+
// console.log('delete', rowCount1, 'widget');
|
|
99
|
+
}
|
|
100
|
+
logger.file('bi/dashboardImport/error', { error: err.toString(), stack: err.stack, ids });
|
|
101
|
+
return reply.status(500).send(config.debug ? err.toString() : 'import error');
|
|
102
|
+
}
|
|
103
|
+
}
|