@opengis/bi 1.0.13 → 1.0.15
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 +50 -52
- package/config.js +12 -12
- package/dist/bi.js +1 -1
- package/dist/bi.umd.cjs +120 -134
- package/dist/{import-file-1T7kpSzt.js → import-file-CRC0sYYT.js} +11974 -11522
- package/dist/{map-component-mixin-BLM9iEWA.js → map-component-mixin-BCtWEvzv.js} +4830 -3150
- package/dist/style.css +1 -1
- package/dist/vs-calendar-5ot79n0N.js +110 -0
- package/dist/vs-funnel-bar-CLo6gXI_.js +105 -0
- package/dist/vs-heatmap-DHGA8dRk.js +97 -0
- package/dist/{vs-map-cluster-Dfe9INqE.js → vs-map-cluster-CNgX6JVF.js} +28 -25
- package/dist/vs-map-pIn5wS4G.js +74 -0
- package/dist/vs-number-DYfok8VU.js +55 -0
- package/dist/{vs-text-DcrAdQ40.js → vs-text-Dckykz09.js} +19 -13
- package/package.json +107 -72
- package/plugin.js +14 -13
- package/server/migrations/bi.dataset.sql +26 -0
- package/server/migrations/bi.sql +93 -27
- package/server/plugins/docs.js +48 -47
- package/server/plugins/hook.js +89 -86
- package/server/plugins/vite.js +69 -55
- package/server/routes/dashboard/controllers/dashboard.delete.js +38 -35
- package/server/routes/dashboard/controllers/dashboard.js +118 -80
- package/server/routes/dashboard/controllers/dashboard.list.js +30 -39
- package/server/routes/dashboard/controllers/utils/yaml.js +11 -12
- package/server/routes/dashboard/index.mjs +25 -24
- package/server/routes/data/controllers/data.js +168 -97
- package/server/routes/data/controllers/util/chartSQL.js +42 -25
- package/server/routes/data/controllers/util/normalizeData.js +59 -34
- package/server/routes/data/index.mjs +29 -26
- package/server/routes/dataset/controllers/bi.dataset.demo.add.js +97 -0
- package/server/routes/dataset/controllers/bi.dataset.import.js +67 -0
- package/server/routes/dataset/controllers/util/create.table.js +22 -0
- package/server/routes/dataset/controllers/util/prepare.data.js +49 -0
- package/server/routes/dataset/index.mjs +19 -0
- package/server/routes/db/controllers/dbTablePreview.js +63 -0
- package/server/routes/db/controllers/dbTables.js +36 -0
- package/server/routes/db/index.mjs +17 -0
- package/server/routes/edit/controllers/dashboard.add.js +26 -23
- package/server/routes/edit/controllers/dashboard.edit.js +46 -37
- package/server/routes/edit/controllers/widget.add.js +75 -49
- package/server/routes/edit/controllers/widget.del.js +69 -63
- package/server/routes/edit/controllers/widget.edit.js +52 -82
- package/server/routes/edit/index.mjs +31 -27
- package/server/routes/map/controllers/cluster.js +109 -75
- package/server/routes/map/controllers/clusterVtile.js +166 -143
- package/server/routes/map/controllers/geojson.js +127 -101
- package/server/routes/map/controllers/map.js +60 -57
- package/server/routes/map/controllers/utils/downloadClusterData.js +43 -0
- package/server/routes/map/controllers/vtile.js +183 -161
- package/server/routes/map/index.mjs +25 -25
- package/server/utils/getWidget.js +85 -56
- package/utils.js +12 -11
- package/dist/vs-calendar-WiK1hcHS.js +0 -96
- package/dist/vs-funnel-bar-CpPbYZ0_.js +0 -92
- package/dist/vs-heatmap-BG4eIROH.js +0 -83
- package/dist/vs-map-BRk6Fmks.js +0 -66
- package/dist/vs-number-CJq-vi95.js +0 -39
|
@@ -1,63 +1,69 @@
|
|
|
1
|
-
import dataDelete from '@opengis/fastify-table/
|
|
2
|
-
|
|
3
|
-
export default async function widgetDel({ pg = {}, params = {} }) {
|
|
4
|
-
const { widget: widgetName, name: dashboardName } = params;
|
|
5
|
-
|
|
6
|
-
if (!widgetName || !dashboardName) {
|
|
7
|
-
return {
|
|
8
|
-
message: 'not enough params: dashboard and widget name',
|
|
9
|
-
status: 400
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const row = await pg
|
|
15
|
-
.query(
|
|
16
|
-
`select a.widget_id, b.dashboard_id from bi.widget a, bi.dashboard b
|
|
17
|
-
where $2 in (a.widget_id, a.name) and $1 in (b.dashboard_id, b.name) order by 1,2`,
|
|
18
|
-
[dashboardName, widgetName]
|
|
19
|
-
)
|
|
20
|
-
.then((res1) => res1.rows?.[0] || {});
|
|
21
|
-
|
|
22
|
-
const { widget_id: widgetId, dashboard_id: dashboardId } = row || {};
|
|
23
|
-
|
|
24
|
-
if (!widgetId) {
|
|
25
|
-
return { message: `widget not found ${widgetName}`, status: 404 };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const res = await dataDelete({
|
|
29
|
-
table: 'bi.widget',
|
|
30
|
-
id: widgetId
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const currentDashboard = await pg
|
|
34
|
-
.query(
|
|
35
|
-
`select * from bi.dashboard
|
|
36
|
-
where $1 in (dashboard_id, name)`,
|
|
37
|
-
[dashboardName]
|
|
38
|
-
)
|
|
39
|
-
.then((res1) => res1.rows?.[0] || {});
|
|
40
|
-
|
|
41
|
-
const body = currentDashboard;
|
|
42
|
-
|
|
43
|
-
if (!currentDashboard) {
|
|
44
|
-
return { message: `dashboard not found ${dashboardName}`, status: 404 };
|
|
45
|
-
}
|
|
46
|
-
body.panels =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
|
|
63
|
-
|
|
1
|
+
import { dataDelete, dataUpdate } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function widgetDel({ pg = {}, params = {} }) {
|
|
4
|
+
const { widget: widgetName, name: dashboardName } = params;
|
|
5
|
+
|
|
6
|
+
if (!widgetName || !dashboardName) {
|
|
7
|
+
return {
|
|
8
|
+
message: 'not enough params: dashboard and widget name',
|
|
9
|
+
status: 400,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const row = await pg
|
|
15
|
+
.query(
|
|
16
|
+
`select a.widget_id, b.dashboard_id from bi.widget a, bi.dashboard b
|
|
17
|
+
where $2 in (a.widget_id, a.name) and $1 in (b.dashboard_id, b.name) order by 1,2`,
|
|
18
|
+
[dashboardName, widgetName]
|
|
19
|
+
)
|
|
20
|
+
.then((res1) => res1.rows?.[0] || {});
|
|
21
|
+
|
|
22
|
+
const { widget_id: widgetId, dashboard_id: dashboardId } = row || {};
|
|
23
|
+
|
|
24
|
+
if (!widgetId) {
|
|
25
|
+
return { message: `widget not found ${widgetName}`, status: 404 };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const res = await dataDelete({
|
|
29
|
+
table: 'bi.widget',
|
|
30
|
+
id: widgetId,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const currentDashboard = await pg
|
|
34
|
+
.query(
|
|
35
|
+
`select * from bi.dashboard
|
|
36
|
+
where $1 in (dashboard_id, name)`,
|
|
37
|
+
[dashboardName]
|
|
38
|
+
)
|
|
39
|
+
.then((res1) => res1.rows?.[0] || {});
|
|
40
|
+
|
|
41
|
+
const body = currentDashboard;
|
|
42
|
+
|
|
43
|
+
if (!currentDashboard) {
|
|
44
|
+
return { message: `dashboard not found ${dashboardName}`, status: 404 };
|
|
45
|
+
}
|
|
46
|
+
body.panels =
|
|
47
|
+
Array.isArray(body.panels) && body.panels?.length
|
|
48
|
+
? body.panels?.filter((panel) => panel.widget !== widgetName)
|
|
49
|
+
: undefined;
|
|
50
|
+
body.widgets =
|
|
51
|
+
Array.isArray(body.widgets) && body?.widgets?.length
|
|
52
|
+
? body.widgets?.filter((widget) => widget.name !== widgetName)
|
|
53
|
+
: undefined;
|
|
54
|
+
|
|
55
|
+
const res1 = await dataUpdate({
|
|
56
|
+
table: 'bi.dashboard',
|
|
57
|
+
id: dashboardId,
|
|
58
|
+
data: body,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
message: `Deleted widget ${widgetName}`,
|
|
63
|
+
status: 200,
|
|
64
|
+
rows: res1,
|
|
65
|
+
};
|
|
66
|
+
} catch (err) {
|
|
67
|
+
return { error: err.toString(), status: 500 };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,82 +1,52 @@
|
|
|
1
|
-
import dataUpdate from '@opengis/fastify-table/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
panel.col = body.col;
|
|
54
|
-
}
|
|
55
|
-
return panel;
|
|
56
|
-
})
|
|
57
|
-
: undefined;
|
|
58
|
-
bodyDashboard.widgets =
|
|
59
|
-
Array.isArray(bodyDashboard.widgets) && bodyDashboard?.widgets?.length
|
|
60
|
-
? bodyDashboard.widgets?.map((widget) => {
|
|
61
|
-
if (widget.name === widgetName) {
|
|
62
|
-
return body;
|
|
63
|
-
}
|
|
64
|
-
return widget;
|
|
65
|
-
})
|
|
66
|
-
: undefined;
|
|
67
|
-
|
|
68
|
-
const res1 = await dataUpdate({
|
|
69
|
-
table: 'bi.dashboard',
|
|
70
|
-
id: dashboardId,
|
|
71
|
-
data: bodyDashboard
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
message: `Edited widget ${widgetName}`,
|
|
76
|
-
status: 200,
|
|
77
|
-
rows: res1
|
|
78
|
-
};
|
|
79
|
-
} catch (err) {
|
|
80
|
-
return { error: err.toString(), status: 500 };
|
|
81
|
-
}
|
|
82
|
-
}
|
|
1
|
+
import { dataUpdate } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import { yamlSafe } from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
export default async function widgetEdit({ pg, body, params, }) {
|
|
6
|
+
const { widget: widgetName, name: dashboardName } = params;
|
|
7
|
+
const data = body.yml && !body.style ? yamlSafe.load(body.yml) : body;
|
|
8
|
+
|
|
9
|
+
const tableName =
|
|
10
|
+
data.data?.table || data?.table || data.table_name || body.table_name;
|
|
11
|
+
|
|
12
|
+
if (!widgetName || !dashboardName) {
|
|
13
|
+
return {
|
|
14
|
+
message: 'not enough params: dashboard and widget name',
|
|
15
|
+
status: 400,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const { widget_id: widgetId } = await pg.query(
|
|
21
|
+
`select a.widget_id , b.dashboard_id from bi.widget a, bi.dashboard b
|
|
22
|
+
where $2 in (a.widget_id, a.name) and $1 in (b.dashboard_id, b.name) order by 1,2`,
|
|
23
|
+
[dashboardName, widgetName]
|
|
24
|
+
).then((res1) => res1.rows?.[0] || {});
|
|
25
|
+
|
|
26
|
+
if (!widgetId) {
|
|
27
|
+
return { message: `widget not found ${widgetName}`, status: 404 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!tableName || !pg.pk?.[tableName]) {
|
|
31
|
+
return { message: 'bad params: table', status: 400 };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// const widgetData = { ...data, data };
|
|
37
|
+
const widgetData = body.yml && !body.style ? data : { style: data.style, data: { x: data.x, metrics: data.metrics }, controls: data.controls, type: data.type, title: data.title, table_name: data.table_name };
|
|
38
|
+
// console.log(widgetId, widgetData)
|
|
39
|
+
if (body?.yml) Object.assign(widgetData, { yml: body.yml });
|
|
40
|
+
const rows = await dataUpdate({
|
|
41
|
+
table: 'bi.widget',
|
|
42
|
+
id: widgetId,
|
|
43
|
+
data: widgetData,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
message: rows,
|
|
48
|
+
status: 200,
|
|
49
|
+
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
}
|
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export default async function route(fastify) {
|
|
22
|
-
fastify.post(`/bi-dashboard/:name`, { schema: biSchema }, widgetAdd);
|
|
23
|
-
fastify.put(`/bi-dashboard/:name/:widget`, { schema: biSchema }, widgetEdit);
|
|
24
|
-
fastify.delete(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
/* eslint-disable import/extensions */
|
|
2
|
+
import widgetAdd from './controllers/widget.add.js';
|
|
3
|
+
import widgetEdit from './controllers/widget.edit.js';
|
|
4
|
+
import widgetDel from './controllers/widget.del.js';
|
|
5
|
+
import dashboardEdit from './controllers/dashboard.edit.js';
|
|
6
|
+
import dashboardAdd from './controllers/dashboard.add.js';
|
|
7
|
+
|
|
8
|
+
const biSchema = {
|
|
9
|
+
querystring: {
|
|
10
|
+
widget: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
11
|
+
dashboard: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
12
|
+
list: { type: 'string', pattern: '^([\\d])$' },
|
|
13
|
+
sql: { type: 'string', pattern: '^([\\d])$' },
|
|
14
|
+
},
|
|
15
|
+
params: {
|
|
16
|
+
name: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
17
|
+
widget: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default async function route(fastify) {
|
|
22
|
+
fastify.post(`/bi-dashboard/:name`, { schema: biSchema }, widgetAdd);
|
|
23
|
+
fastify.put(`/bi-dashboard/:name/:widget`, { schema: biSchema }, widgetEdit);
|
|
24
|
+
fastify.delete(
|
|
25
|
+
`/bi-dashboard/:name/:widget`,
|
|
26
|
+
{ schema: biSchema },
|
|
27
|
+
widgetDel
|
|
28
|
+
);
|
|
29
|
+
fastify.post(`/bi-dashboard`, { schema: biSchema }, dashboardAdd);
|
|
30
|
+
fastify.put(`/bi-dashboard/:name`, { schema: biSchema }, dashboardEdit);
|
|
31
|
+
}
|
|
@@ -1,75 +1,109 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
1
|
+
import { getFilterSQL } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import { getWidget } from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
import downloadClusterData from './utils/downloadClusterData.js';
|
|
6
|
+
|
|
7
|
+
const clusterExists = {};
|
|
8
|
+
|
|
9
|
+
export default async function cluster({ pg, query = {}, log }) {
|
|
10
|
+
const { widget, filter, dashboard, search } = query;
|
|
11
|
+
|
|
12
|
+
if (!widget) {
|
|
13
|
+
return { message: 'not enough params: widget', status: 400 };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { data } = await getWidget({ dashboard, widget });
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const pkey = pg.pk?.[data?.table];
|
|
20
|
+
|
|
21
|
+
if (!pkey) {
|
|
22
|
+
return {
|
|
23
|
+
message: `invalid ${widget ? 'widget' : 'dashboard'}: table pk not found (${data?.table})`,
|
|
24
|
+
status: 400,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// data param
|
|
29
|
+
const {
|
|
30
|
+
table,
|
|
31
|
+
query: where = '1=1',
|
|
32
|
+
metrics = [],
|
|
33
|
+
cluster,
|
|
34
|
+
clusterTable = {},
|
|
35
|
+
} = data;
|
|
36
|
+
|
|
37
|
+
if (!cluster) {
|
|
38
|
+
return {
|
|
39
|
+
message: `invalid ${widget ? 'widget' : 'dashboard'}: cluster column not specified`,
|
|
40
|
+
status: 400,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!metrics.length) {
|
|
45
|
+
return {
|
|
46
|
+
message: `invalid ${widget ? 'widget' : 'dashboard'}: metric columns not found`,
|
|
47
|
+
status: 400,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!clusterTable?.name) {
|
|
52
|
+
Object.assign(clusterTable, {
|
|
53
|
+
name: 'bi.cluster',
|
|
54
|
+
title: 'title',
|
|
55
|
+
query: `type='${cluster}'`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (cluster && !clusterExists[cluster]) {
|
|
60
|
+
const res = await downloadClusterData({ pg, log, cluster });
|
|
61
|
+
if (res) return res;
|
|
62
|
+
clusterExists[cluster] = 1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (clusterTable?.name && !pg.pk?.[clusterTable?.name]) {
|
|
66
|
+
return {
|
|
67
|
+
message: 'invalid widget params: clusterTable pkey not found',
|
|
68
|
+
status: 404,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { bounds, extentStr } = await pg.query(`select count(*),
|
|
73
|
+
st_asgeojson(st_extent(geom))::json as bounds,
|
|
74
|
+
replace(regexp_replace(st_extent(geom)::box2d::text,'BOX\\(|\\)','','g'),' ',',') as "extentStr"
|
|
75
|
+
from ${table} where ${where || '1=1'}`).then((res) => res.rows?.[0] || {});
|
|
76
|
+
const extent = extentStr ? extentStr.split(',') : undefined;
|
|
77
|
+
|
|
78
|
+
// get sql
|
|
79
|
+
const { optimizedSQL } =
|
|
80
|
+
filter || search
|
|
81
|
+
? await getFilterSQL({ pg, table, filter, search })
|
|
82
|
+
: {};
|
|
83
|
+
|
|
84
|
+
const q = `select "${cluster}" as name, sum("${metrics[0]}")::float as metric
|
|
85
|
+
from ${optimizedSQL ? `(${optimizedSQL})` : table} q
|
|
86
|
+
left join lateral (select "${pg.pk?.[clusterTable?.name]}" as id from ${clusterTable?.name} where ${clusterTable?.title}=q."${cluster}" limit 1)b on 1=1
|
|
87
|
+
where ${where} group by ${cluster}, b.id order by sum("${metrics[0]}")::float desc`;
|
|
88
|
+
|
|
89
|
+
if (query.sql === '1') return q;
|
|
90
|
+
|
|
91
|
+
// auto Index
|
|
92
|
+
// autoIndex({ table, columns: (metrics || []).concat([cluster]) });
|
|
93
|
+
|
|
94
|
+
const { rows = [] } = await pg.query(q);
|
|
95
|
+
const vals = rows.map((el) => el.metric - 0).sort((a, b) => a - b);
|
|
96
|
+
const len = vals.length;
|
|
97
|
+
const sizes = [
|
|
98
|
+
vals[0],
|
|
99
|
+
vals[Math.floor(len / 4)],
|
|
100
|
+
vals[Math.floor(len / 2)],
|
|
101
|
+
vals[Math.floor(len * 0.75)],
|
|
102
|
+
vals[len - 1],
|
|
103
|
+
];
|
|
104
|
+
return { sizes, rows, bounds, extent, count: rows.length, total: rows?.reduce((acc, curr) => (curr.metric || 0) + acc, 0) };
|
|
105
|
+
} catch (err) {
|
|
106
|
+
log.error('bi/cluster', { error: err.toString(), query });
|
|
107
|
+
return { error: err.toString(), status: 500 };
|
|
108
|
+
}
|
|
109
|
+
}
|