@opengis/bi 1.0.24 → 1.0.26
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 +37 -75
- package/dist/bi.js +1 -1
- package/dist/bi.umd.cjs +135 -161
- package/dist/{import-file-ChpPHgUN.js → import-file-EpXoz6mK.js} +18923 -19115
- package/dist/{map-component-mixin-C0Z88c8b.js → map-component-mixin-CiEzcAge.js} +5729 -5730
- package/dist/style.css +1 -1
- package/dist/vs-donut-UOFHF75N.js +148 -0
- package/dist/{vs-funnel-bar-Ba0HB6U8.js → vs-funnel-bar-C1_Ov3Jr.js} +5 -5
- package/dist/{vs-map-T9bTjwSG.js → vs-map-D60SRZV8.js} +4 -4
- package/dist/{vs-map-cluster-CQik8xir.js → vs-map-cluster-C5DVVsK7.js} +3 -3
- package/dist/{vs-number-DhACUDku.js → vs-number-Dj0hzedH.js} +3 -3
- package/dist/{vs-table-Df4lMM4d.js → vs-table-DLFJjeka.js} +11 -11
- package/dist/{vs-text-D9iYudVA.js → vs-text-A-jj2xDe.js} +30 -37
- package/package.json +4 -4
- package/server/routes/dashboard/controllers/dashboard.import.js +17 -5
- package/server/routes/dashboard/controllers/dashboard.js +39 -28
- package/server/routes/dashboard/controllers/dashboard.list.js +13 -10
- package/server/routes/data/controllers/data.js +13 -6
- package/server/routes/data/controllers/util/chartSQL.js +2 -1
- package/server/routes/data/controllers/util/normalizeData.js +7 -5
- package/server/routes/dataset/controllers/bi.dataset.list.js +1 -3
- package/server/routes/dataset/controllers/createDatasetPost.js +8 -5
- package/server/routes/dataset/controllers/dbTablePreview.js +3 -1
- package/server/routes/dataset/controllers/dbTables.js +3 -1
- package/server/routes/dataset/controllers/delete.js +1 -0
- package/server/routes/dataset/controllers/deleteDataset.js +1 -0
- package/server/routes/dataset/controllers/editDataset.js +1 -0
- package/server/routes/dataset/controllers/format.js +3 -1
- package/server/routes/dataset/controllers/insert.js +1 -0
- package/server/routes/dataset/controllers/update.js +1 -0
- package/server/routes/dataset/utils/createTableQuery.js +1 -1
- package/server/routes/dataset/utils/executeQuery.js +2 -2
- package/server/routes/edit/controllers/dashboard.add.js +16 -5
- package/server/routes/edit/controllers/dashboard.delete.js +11 -8
- package/server/routes/edit/controllers/dashboard.edit.js +20 -18
- package/server/routes/edit/controllers/widget.add.js +8 -8
- package/server/routes/edit/controllers/widget.del.js +4 -2
- package/server/routes/edit/controllers/widget.edit.js +25 -7
- package/server/routes/map/controllers/cluster.js +3 -2
- package/server/routes/map/controllers/clusterVtile.js +1 -1
- package/server/routes/map/controllers/geojson.js +2 -2
- package/server/routes/map/controllers/heatmap.js +2 -2
- package/server/routes/map/controllers/map.js +3 -2
- package/server/routes/map/controllers/vtile.js +1 -1
- package/server/templates/page/login.html +59 -0
- package/server/utils/getWidget.js +31 -18
- package/dist/vs-calendar-B4_gYR3Q.js +0 -116
- package/dist/vs-donut-BF1K_2LP.js +0 -150
- package/dist/vs-heatmap-Bzwa1rgF.js +0 -97
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { dataInsert, dataUpdate } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
import { dataInsert, dataUpdate, pgClients } from "@opengis/fastify-table/utils.js";
|
|
3
3
|
|
|
4
4
|
/* eslint-disable import/extensions */
|
|
5
5
|
import { yamlSafe } from '../../../../utils.js';
|
|
@@ -10,14 +10,14 @@ function generateUniqueName(prefix = 'bar') {
|
|
|
10
10
|
return `${prefix}_${randomPart}_${timestamp}`;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export default async function widgetAdd({ pg, params = {}, body = {} }) {
|
|
13
|
+
export default async function widgetAdd({ pg = pgClients.client, params = {}, body = {} }) {
|
|
14
14
|
const { name: dashboardName } = params;
|
|
15
15
|
if (!dashboardName) {
|
|
16
16
|
return { message: 'not enough params: id', status: 400 };
|
|
17
17
|
}
|
|
18
18
|
const data = body.yml ? yamlSafe.load(body.yml) : body;
|
|
19
19
|
|
|
20
|
-
const row = await pg.query(`select dashboard_id, widgets, panels, table_name from bi.dashboard
|
|
20
|
+
const row = await pg.query(`select dashboard_id, widgets, panels, table_name, db from bi.dashboard
|
|
21
21
|
where $1 in (dashboard_id,name)`, [dashboardName]).then(el => el.rows?.[0] || {});
|
|
22
22
|
|
|
23
23
|
const tableName = data.data?.table
|
|
@@ -25,24 +25,23 @@ export default async function widgetAdd({ pg, params = {}, body = {} }) {
|
|
|
25
25
|
|| data.table_name
|
|
26
26
|
|| row.table_name;
|
|
27
27
|
|
|
28
|
-
if (!tableName || !pg.pk?.[tableName]) {
|
|
28
|
+
if (!tableName || !(pg.pk?.[tableName] || pgClients[data.db || row.db || 'client']?.pk?.[tableName])) {
|
|
29
29
|
return { message: 'bad params: table', status: 400 };
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const { dashboard_id: dashboardId } = row;
|
|
33
33
|
|
|
34
|
+
const metric = data.data?.metrics || data.data?.metric || data?.metrics || data?.metric;
|
|
34
35
|
Object.assign(data, {
|
|
35
36
|
name: generateUniqueName(data.type),
|
|
36
37
|
table_name: tableName,
|
|
37
|
-
metrics:
|
|
38
|
-
(data.data?.metrics || data?.metrics)?.[0] ||
|
|
39
|
-
data.data?.metrics ||
|
|
40
|
-
data?.metrics,
|
|
38
|
+
metrics: Array.isArray(metric) ? metric[0] : metric,
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
data.widget_id = createHash('md5').update([data?.name, dashboardId].join()).digest('hex').substr(0, 10);
|
|
44
42
|
|
|
45
43
|
const res = await dataUpdate({
|
|
44
|
+
pg,
|
|
46
45
|
table: 'bi.dashboard',
|
|
47
46
|
id: dashboardId,
|
|
48
47
|
data: {
|
|
@@ -57,6 +56,7 @@ export default async function widgetAdd({ pg, params = {}, body = {} }) {
|
|
|
57
56
|
if (body?.yml) Object.assign(widgetData, { yml: body.yml });
|
|
58
57
|
|
|
59
58
|
await dataInsert({
|
|
59
|
+
pg,
|
|
60
60
|
table: 'bi.widget',
|
|
61
61
|
data: widgetData,
|
|
62
62
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { dataDelete, dataUpdate } from '@opengis/fastify-table/utils.js';
|
|
1
|
+
import { dataDelete, dataUpdate, pgClients } from '@opengis/fastify-table/utils.js';
|
|
2
2
|
|
|
3
|
-
export default async function widgetDel({ pg =
|
|
3
|
+
export default async function widgetDel({ pg = pgClients.client, params = {} }) {
|
|
4
4
|
const { widget: widgetName, name: dashboardName } = params;
|
|
5
5
|
|
|
6
6
|
if (!widgetName || !dashboardName) {
|
|
@@ -21,6 +21,7 @@ export default async function widgetDel({ pg = {}, params = {} }) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
await dataDelete({
|
|
24
|
+
pg,
|
|
24
25
|
table: 'bi.widget',
|
|
25
26
|
id: widgetId,
|
|
26
27
|
});
|
|
@@ -43,6 +44,7 @@ export default async function widgetDel({ pg = {}, params = {} }) {
|
|
|
43
44
|
: undefined;
|
|
44
45
|
|
|
45
46
|
const res1 = await dataUpdate({
|
|
47
|
+
pg,
|
|
46
48
|
table: 'bi.dashboard',
|
|
47
49
|
id: dashboardId,
|
|
48
50
|
data: body,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { dataUpdate } from '@opengis/fastify-table/utils.js';
|
|
1
|
+
import { dataUpdate, pgClients } from '@opengis/fastify-table/utils.js';
|
|
2
2
|
|
|
3
3
|
import { getWidget, yamlSafe } from '../../../../utils.js';
|
|
4
4
|
|
|
5
|
-
export default async function widgetEdit({ pg, body, params
|
|
5
|
+
export default async function widgetEdit({ pg = pgClients.client, body, params }) {
|
|
6
6
|
const { widget: widgetName, name: dashboardName } = params;
|
|
7
7
|
const data = body.yml && !body.style ? yamlSafe.load(body.yml) : body;
|
|
8
8
|
const yml = body.yml ?? yamlSafe.dump(body.data);
|
|
@@ -21,19 +21,25 @@ export default async function widgetEdit({ pg, body, params, }) {
|
|
|
21
21
|
[dashboardName, widgetName]).then(res1 => res1.rows?.[0] || {});
|
|
22
22
|
|
|
23
23
|
// get Data
|
|
24
|
-
const templateData = await getWidget({ dashboard: dashboardName, widget: widgetName });
|
|
24
|
+
const templateData = await getWidget({ pg, dashboard: dashboardName, widget: widgetName });
|
|
25
25
|
if (!templateData) {
|
|
26
26
|
return { message: `widget not found ${widgetName}`, status: 404 };
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
if (data?.data) {
|
|
30
|
+
Object.assign(data, {
|
|
31
|
+
data: Object.keys(data.data || {})
|
|
32
|
+
?.reduce?.((acc, curr) => ({ ...acc, [curr]: data.data[curr] === 'null' ? null : data.data[curr] }), {})
|
|
33
|
+
});
|
|
34
|
+
}
|
|
29
35
|
const widgetData = ['style', 'data', 'type', 'title', 'controls']
|
|
30
36
|
.filter(el => data[el])
|
|
31
37
|
.reduce((p, el) => ({ ...p, [el]: data[el] }), {});
|
|
32
38
|
|
|
33
39
|
//console.log(templateData)
|
|
34
40
|
// get table
|
|
35
|
-
const tableName =
|
|
36
|
-
if (!tableName || !pg.pk?.[tableName]) {
|
|
41
|
+
const tableName = body.table || widgetData.data?.table_name || widgetData.data?.table || widgetData?.table_name || templateData.table;
|
|
42
|
+
if (!tableName || !(pg.pk?.[tableName] || pgClients[widgetData?.data?.db || templateData?.db || 'client']?.pk?.[tableName])) {
|
|
37
43
|
return { message: 'bad params: table ' + tableName, status: 400 };
|
|
38
44
|
}
|
|
39
45
|
|
|
@@ -41,15 +47,20 @@ export default async function widgetEdit({ pg, body, params, }) {
|
|
|
41
47
|
Object.assign(widgetData, { yml })
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
Object.assign(widgetData, { table_name: tableName });
|
|
50
|
+
Object.assign(widgetData, { table_name: tableName, data: { ...widgetData?.data || {}, table_name: tableName } });
|
|
45
51
|
console.log(widgetData);
|
|
46
52
|
const rows = await dataUpdate({
|
|
53
|
+
pg,
|
|
47
54
|
table: 'bi.widget',
|
|
48
55
|
id: widgetId,
|
|
49
56
|
data: widgetData,
|
|
50
57
|
});
|
|
51
58
|
|
|
52
|
-
const idx = widgets?.findIndex?.(el => el.name === widgetName) || -1;
|
|
59
|
+
const idx = widgets?.findIndex?.(el => el.name === widgetName)?.toString?.() || -1;
|
|
60
|
+
if (widgetData.hasOwnProperty('table_name') && idx > -1) {
|
|
61
|
+
widgets[idx].table_name = tableName;
|
|
62
|
+
widgets[idx].table = tableName;
|
|
63
|
+
}
|
|
53
64
|
if (widgetData.hasOwnProperty('data') && idx > -1) {
|
|
54
65
|
widgets[idx].data = widgetData.data
|
|
55
66
|
}
|
|
@@ -59,8 +70,15 @@ export default async function widgetEdit({ pg, body, params, }) {
|
|
|
59
70
|
if (widgetData.hasOwnProperty('style') && idx > -1) {
|
|
60
71
|
widgets[idx].style = widgetData.style;
|
|
61
72
|
}
|
|
73
|
+
if (widgetData.hasOwnProperty('type') && idx > -1) {
|
|
74
|
+
widgets[idx].type = widgetData.type;
|
|
75
|
+
}
|
|
76
|
+
if (widgetData.data?.type === 'text' && idx > -1) {
|
|
77
|
+
widgets[idx].data.text = widgetData.data?.text;
|
|
78
|
+
}
|
|
62
79
|
|
|
63
80
|
await dataUpdate({
|
|
81
|
+
pg,
|
|
64
82
|
table: 'bi.dashboard',
|
|
65
83
|
id: dashboardId,
|
|
66
84
|
data: { widgets },
|
|
@@ -6,14 +6,15 @@ import downloadClusterData from './utils/downloadClusterData.js';
|
|
|
6
6
|
|
|
7
7
|
const clusterExists = {};
|
|
8
8
|
|
|
9
|
-
export default async function cluster(
|
|
9
|
+
export default async function cluster(req) {
|
|
10
|
+
const { query = {} } = req;
|
|
10
11
|
const { widget, filter, dashboard, search } = query;
|
|
11
12
|
|
|
12
13
|
if (!widget) {
|
|
13
14
|
return { message: 'not enough params: widget', status: 400 };
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const { pg = pgClients.client, data } = await getWidget({ dashboard, widget });
|
|
17
|
+
const { pg = req.pg || pgClients.client, data } = await getWidget({ pg: req.pg, dashboard, widget });
|
|
17
18
|
|
|
18
19
|
const pkey = pg.pk?.[data?.table];
|
|
19
20
|
|
|
@@ -30,7 +30,7 @@ export default async function clusterVtile(req, reply) {
|
|
|
30
30
|
return { message: 'not enough params: widget', status: 400 };
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const { pg = pgClients.client, data } = await getWidget({ dashboard, widget });
|
|
33
|
+
const { pg = req.pg || pgClients.client, data } = await getWidget({ pg: req.pg, dashboard, widget });
|
|
34
34
|
|
|
35
35
|
const headers = {
|
|
36
36
|
'Content-Type': 'application/x-protobuf',
|
|
@@ -35,10 +35,10 @@ export default async function geojson(req, reply) {
|
|
|
35
35
|
return { message: 'not enough params: widget', status: 400 };
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const data = await getWidget({ dashboard, widget });
|
|
38
|
+
const data = await getWidget({ pg: req.pg, dashboard, widget });
|
|
39
39
|
if (data.status) return data;
|
|
40
40
|
|
|
41
|
-
const pg = data.pg || pgClients.client;
|
|
41
|
+
const pg = data.pg || req.pg || pgClients.client;
|
|
42
42
|
const hash = [pointZoom, filter].filter((el) => el).join();
|
|
43
43
|
|
|
44
44
|
const root = getFolder(req);
|
|
@@ -23,7 +23,7 @@ export default async function heatmap(req, reply) {
|
|
|
23
23
|
return { message: 'not enough params: dashboard / widget', status: 400 };
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const { data } = await getWidget({ widget, dashboard });
|
|
26
|
+
const { data } = await getWidget({ pg: req.pg, widget, dashboard });
|
|
27
27
|
|
|
28
28
|
if (!data?.table) {
|
|
29
29
|
return { message: 'widget not found: ' + widget, status: 400 };
|
|
@@ -48,7 +48,7 @@ export default async function heatmap(req, reply) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const pg = data.pg || pgClients.client;
|
|
51
|
+
const pg = data.pg || req.pg || pgClients.client;
|
|
52
52
|
|
|
53
53
|
if (!pg.pk?.[data.table]) {
|
|
54
54
|
return { message: `table not found: ${data.table}`, status: 404 };
|
|
@@ -2,10 +2,11 @@ import { pgClients, getFilterSQL } from '@opengis/fastify-table/utils.js';
|
|
|
2
2
|
|
|
3
3
|
import { getWidget } from '../../../../utils.js';
|
|
4
4
|
|
|
5
|
-
export default async function map(
|
|
5
|
+
export default async function map(req) {
|
|
6
|
+
const { query = {} } = req;
|
|
6
7
|
const { dashboard, widget } = query;
|
|
7
8
|
|
|
8
|
-
const { pg = pgClients.client, data, type, layers } = await getWidget({ dashboard, widget });
|
|
9
|
+
const { pg = req.pg || pgClients.client, data, type, layers } = await getWidget({ pg: req.pg, dashboard, widget });
|
|
9
10
|
|
|
10
11
|
if (!['map'].includes(type)) {
|
|
11
12
|
return { message: 'access restricted: invalid widget type', status: 403 };
|
|
@@ -59,7 +59,7 @@ export default async function vtile(req, reply) {
|
|
|
59
59
|
return { message: 'not enough params: xyz', status: 400 };
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const { pg = pgClients.client, data } = await getWidget({ widget, dashboard });
|
|
62
|
+
const { pg = req.pg || pgClients.client, data } = await getWidget({ pg: req.pg, widget, dashboard });
|
|
63
63
|
|
|
64
64
|
const headers = {
|
|
65
65
|
'Content-Type': 'application/x-protobuf',
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" dir="">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<!-- scripts -->
|
|
6
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body class="bg-[#f3f4f6] flex items-center flex-1 w-full h-[100vh] overflow-x-hidden min-h-full ">
|
|
10
|
+
<main class="w-full">
|
|
11
|
+
<div class="flex w-full max-w-sm mx-auto overflow-hidden bg-white rounded-lg shadow-lg dark:bg-gray-800 lg:max-w-4xl">
|
|
12
|
+
<div class="hidden bg-left bg-cover lg:block lg:w-1/2" style="background-image: url('https://media.istockphoto.com/id/1296381479/vector/set-of-simple-infographic-graphs-and-charts-data-visualization-statistics-and-business.jpg?s=612x612&w=0&k=20&c=JpEoP-6w16OwVC49Sq2PEI8-dHF1CZnm7rHyL5DoxqA=');"></div>
|
|
13
|
+
|
|
14
|
+
<div class="w-full px-6 py-8 md:px-8 lg:w-1/2">
|
|
15
|
+
<div class="flex justify-center mx-auto">
|
|
16
|
+
<img width="300" height="100" src="https://cdn.softpro.ua/data/icons/logo-softpro.png" alt="logo">
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<p class="mt-3 mb-[32px] text-xl text-center text-gray-600 dark:text-gray-200">
|
|
20
|
+
Аналітичний модуль
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<form action="/api/login" method="get" >
|
|
24
|
+
<div class="mt-4">
|
|
25
|
+
<label class="block mb-2 text-sm font-medium text-gray-600 dark:text-gray-200" for="LoggingEmailAddress">Електронна пошта</label>
|
|
26
|
+
<input name="username" id="LoggingEmailAddress" class="block w-full px-4 py-2 text-gray-700 bg-white border rounded-lg dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring focus:ring-blue-300" type="text">
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="mt-4">
|
|
30
|
+
<div class="flex justify-between">
|
|
31
|
+
<label class="block mb-2 text-sm font-medium text-gray-600 dark:text-gray-200" for="loggingPassword">Пароль</label>
|
|
32
|
+
<!-- <a class="text-xs text-gray-500 dark:text-gray-300 hover:underline">Forget Password?</a> -->
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<input id="loggingPassword" name="password" class="block w-full px-4 py-2 text-gray-700 bg-white border rounded-lg dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring focus:ring-blue-300" type="password">
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="mt-6">
|
|
39
|
+
<button type="submit" class="w-full px-6 py-3 text-sm font-medium tracking-wide text-white capitalize transition-colors duration-300 transform bg-gray-800 rounded-lg hover:bg-gray-700 focus:outline-none focus:ring focus:ring-gray-300 focus:ring-opacity-50">
|
|
40
|
+
Увійти
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
</form>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</main>
|
|
48
|
+
|
|
49
|
+
</body>
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
<script>
|
|
53
|
+
const error = location.search.includes('wrong_pass')
|
|
54
|
+
if (error) {
|
|
55
|
+
document.getElementById('login_error').innerHTML = 'Не вірний користувач або пароль';
|
|
56
|
+
}
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
</html>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getTemplate, getPGAsync, pgClients } from '@opengis/fastify-table/utils.js';
|
|
1
|
+
import { getTemplate, getPGAsync, pgClients, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
2
|
|
|
3
3
|
import mdToHTML from '../helpers/mdToHTML.js';
|
|
4
4
|
|
|
5
|
-
async function getWidget({ dashboard, widget }) {
|
|
5
|
+
async function getWidget({ pg: pg1 = pgClients.client, dashboard, widget }) {
|
|
6
6
|
if (!dashboard && !widget) {
|
|
7
7
|
return { message: `not enough params: dashboard / widget`, status: 400 };
|
|
8
8
|
}
|
|
@@ -10,20 +10,21 @@ async function getWidget({ dashboard, widget }) {
|
|
|
10
10
|
? await getTemplate('dashboard', dashboard)
|
|
11
11
|
: null;
|
|
12
12
|
|
|
13
|
+
const dashboardData1 = await pg1.query(`select db, table_name, widgets as "dashboardWidgets" from bi.dashboard where dashboard_id=$1`, [dashboard])
|
|
14
|
+
.then(el => el.rows?.[0] || {});
|
|
15
|
+
const { dashboardWidgets = [] } = dashboardData1;
|
|
16
|
+
const dashboardDb = typeof dashboardData1?.db === 'string' && dashboardData1?.db?.startsWith('{') ? JSON.parse(dashboardData1?.db) : dashboardData1?.db;
|
|
17
|
+
|
|
13
18
|
const dashboardIndex = dashboardData?.find((el) => el[0] == 'index.yml')?.[1]; // dashboardData?.find((el) => el[2] == 'index')?.[1]
|
|
14
|
-
const pg = dashboardIndex?.db ? await getPGAsync(dashboardIndex?.db) :
|
|
19
|
+
const pg = dashboardDb || dashboardIndex?.db ? await getPGAsync(dashboardDb || dashboardIndex?.db) : pg1;
|
|
15
20
|
|
|
16
21
|
const { id, tableName } =
|
|
17
|
-
!dashboardData && pg.pk['bi.dashboard'] && dashboard
|
|
18
|
-
? await
|
|
19
|
-
.query(
|
|
20
|
-
`select dashboard_id as id, table_name as "tableName" from bi.dashboard where $1 in (dashboard_id, name)`,
|
|
21
|
-
[dashboard]
|
|
22
|
-
)
|
|
22
|
+
!dashboardData && !dashboardData1 && pg.pk['bi.dashboard'] && dashboard
|
|
23
|
+
? await pg1.query(`select dashboard_id as id, table_name as "tableName" from bi.dashboard where $1 in (dashboard_id, name)`, [dashboard])
|
|
23
24
|
.then(el => el.rows?.[0] || {})
|
|
24
25
|
: {};
|
|
25
26
|
|
|
26
|
-
if (!dashboardData && dashboard && !id) {
|
|
27
|
+
if (!dashboardData && !dashboardData1 && dashboard && !id) {
|
|
27
28
|
return { message: `dashboard not found: ${dashboard}`, status: 404 };
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -33,12 +34,15 @@ async function getWidget({ dashboard, widget }) {
|
|
|
33
34
|
|
|
34
35
|
const widgetData = dashboard
|
|
35
36
|
? dashboardData?.find((el) => el[2] === (widget || 'index'))?.[1]
|
|
37
|
+
|| dashboardWidgets?.find(el => el.name === widget)
|
|
36
38
|
: await getTemplate('widget', widget);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
|
|
40
|
+
if (typeof widgetData === 'string' || (widgetData?.type === 'text' && typeof widgetData?.data?.text === 'string')) {
|
|
41
|
+
const html = mdToHTML(widgetData?.data?.text || widgetData);
|
|
39
42
|
return { source: html, status: 200 };
|
|
40
43
|
}
|
|
41
|
-
|
|
44
|
+
|
|
45
|
+
if (!id && !dashboardData && !dashboardData1 && !widgetData) {
|
|
42
46
|
return { message: `not found ${widget} ${dashboard}`, status: 404 };
|
|
43
47
|
}
|
|
44
48
|
|
|
@@ -67,15 +71,24 @@ async function getWidget({ dashboard, widget }) {
|
|
|
67
71
|
tableName ||
|
|
68
72
|
widgetData?.table_name ||
|
|
69
73
|
dashboardIndex?.table ||
|
|
70
|
-
dashboardIndex?.table_name
|
|
71
|
-
|
|
74
|
+
dashboardIndex?.table_name ||
|
|
75
|
+
dashboardData1?.table_name,
|
|
76
|
+
db: dashboardDb?.db || dashboardDb || dashboardIndex?.db || widgetData?.db || pg?.options?.database,
|
|
72
77
|
});
|
|
73
78
|
const main = { ...(dashboardIndex || {}), ...widgetData, ...data, ...data?.data || {} };
|
|
74
|
-
const
|
|
79
|
+
const widgetDb = widgetData?.db ? await getPGAsync(widgetData?.db) : pg;
|
|
75
80
|
|
|
76
81
|
if (!main?.table) {
|
|
77
82
|
return {
|
|
78
|
-
message: /* json.error || */ `invalid ${widget ? 'widget' : 'dashboard'}:
|
|
83
|
+
message: /* json.error || */ `invalid ${widget ? 'widget' : 'dashboard'}: empty table`,
|
|
84
|
+
status: 404,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const { pk, view } = await getMeta({ pg: widgetDb, table: main?.table });
|
|
89
|
+
if (!pk && !view) {
|
|
90
|
+
return {
|
|
91
|
+
message: /* json.error || */ `invalid ${widget ? 'widget' : 'dashboard'}: table not found (${main?.table})`,
|
|
79
92
|
status: 404,
|
|
80
93
|
};
|
|
81
94
|
}
|
|
@@ -84,6 +97,6 @@ async function getWidget({ dashboard, widget }) {
|
|
|
84
97
|
(el, i) => `left join lateral(${el})t${i + 1} on 1=1`
|
|
85
98
|
);
|
|
86
99
|
|
|
87
|
-
return { ...main, pg:
|
|
100
|
+
return { ...main, pg: widgetDb, tableSQL, data, type, text, controls, style, options, yml };
|
|
88
101
|
}
|
|
89
102
|
export default getWidget;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { _ as l, c, i as h, t as p, h as d } from "./import-file-ChpPHgUN.js";
|
|
2
|
-
import { openBlock as u, createElementBlock as m } from "vue";
|
|
3
|
-
const D = {
|
|
4
|
-
name: "VsCalendar",
|
|
5
|
-
mixins: [c],
|
|
6
|
-
data() {
|
|
7
|
-
return {
|
|
8
|
-
chartInstance: null,
|
|
9
|
-
label: null,
|
|
10
|
-
uniqueID: null
|
|
11
|
-
};
|
|
12
|
-
},
|
|
13
|
-
computed: {
|
|
14
|
-
calendarRange() {
|
|
15
|
-
return this.getCalendarRange();
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
async mounted() {
|
|
19
|
-
this.uniqueID = this.widget, await this.$nextTick(), await this.getData(), this.initChart();
|
|
20
|
-
},
|
|
21
|
-
methods: {
|
|
22
|
-
onChangedData() {
|
|
23
|
-
try {
|
|
24
|
-
if (this.sourceData) {
|
|
25
|
-
const { series: t, xs: a, ys: e } = this.prepareData();
|
|
26
|
-
t && (this == null || this.initChart(t, a, e));
|
|
27
|
-
}
|
|
28
|
-
} catch (t) {
|
|
29
|
-
console.error(t);
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
prepareData() {
|
|
33
|
-
try {
|
|
34
|
-
return this.sourceData.map((a) => {
|
|
35
|
-
var e, r, n;
|
|
36
|
-
return [
|
|
37
|
-
(n = (r = a == null ? void 0 : a[(e = this.dimensions) == null ? void 0 : e[0]]) == null ? void 0 : r.split("T")) == null ? void 0 : n[0],
|
|
38
|
-
Number(a[this.dimensions[1]])
|
|
39
|
-
];
|
|
40
|
-
});
|
|
41
|
-
} catch (t) {
|
|
42
|
-
console.error(t);
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
getCalendarRange() {
|
|
46
|
-
const t = this.sourceData.map(
|
|
47
|
-
(r) => {
|
|
48
|
-
var n, s;
|
|
49
|
-
return new Date((s = r == null ? void 0 : r[(n = this.dimensions) == null ? void 0 : n[0]]) == null ? void 0 : s.split("T")[0]);
|
|
50
|
-
}
|
|
51
|
-
), a = new Date(Math.min(...t)), e = new Date(Math.max(...t));
|
|
52
|
-
return [
|
|
53
|
-
a.getFullYear().toString(),
|
|
54
|
-
e.getFullYear().toString()
|
|
55
|
-
];
|
|
56
|
-
},
|
|
57
|
-
async initChart() {
|
|
58
|
-
var t, a, e, r;
|
|
59
|
-
try {
|
|
60
|
-
const n = this.$refs.chart, s = h(n), o = {
|
|
61
|
-
tooltip: {
|
|
62
|
-
...p(
|
|
63
|
-
(t = this.styleData) == null ? void 0 : t.tooltip,
|
|
64
|
-
(a = this.styleData) == null ? void 0 : a.show_tooltip
|
|
65
|
-
),
|
|
66
|
-
trigger: "item",
|
|
67
|
-
formatter: (i) => d(i)
|
|
68
|
-
},
|
|
69
|
-
visualMap: {
|
|
70
|
-
min: Math.min(...(e = this.prepareData()) == null ? void 0 : e.map((i) => i[1])),
|
|
71
|
-
max: Math.max(...(r = this.prepareData()) == null ? void 0 : r.map((i) => i[1])),
|
|
72
|
-
type: "piecewise",
|
|
73
|
-
orient: "horizontal",
|
|
74
|
-
left: "center",
|
|
75
|
-
top: 65
|
|
76
|
-
},
|
|
77
|
-
calendar: {
|
|
78
|
-
top: 120,
|
|
79
|
-
left: 30,
|
|
80
|
-
right: 30,
|
|
81
|
-
cellSize: ["auto", 20],
|
|
82
|
-
range: this.calendarRange,
|
|
83
|
-
itemStyle: {
|
|
84
|
-
borderWidth: 0.5
|
|
85
|
-
},
|
|
86
|
-
yearLabel: { show: !1 }
|
|
87
|
-
},
|
|
88
|
-
series: {
|
|
89
|
-
name: "calendar",
|
|
90
|
-
type: "heatmap",
|
|
91
|
-
coordinateSystem: "calendar",
|
|
92
|
-
data: this.prepareData(),
|
|
93
|
-
itemStyle: {
|
|
94
|
-
borderWidth: 0.5
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
s.setOption(o), s.resize(), window.addEventListener("resize", () => {
|
|
99
|
-
s.resize();
|
|
100
|
-
});
|
|
101
|
-
} catch (n) {
|
|
102
|
-
console.error(n);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}, f = {
|
|
107
|
-
ref: "chart",
|
|
108
|
-
class: "h-full w-full min-h-[200px] pb-2"
|
|
109
|
-
};
|
|
110
|
-
function g(t, a, e, r, n, s) {
|
|
111
|
-
return u(), m("div", f, null, 512);
|
|
112
|
-
}
|
|
113
|
-
const x = /* @__PURE__ */ l(D, [["render", g]]);
|
|
114
|
-
export {
|
|
115
|
-
x as default
|
|
116
|
-
};
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { _ as y, c as g, a as c, P as h, b as l, i as b } from "./import-file-ChpPHgUN.js";
|
|
2
|
-
import { openBlock as x, createElementBlock as I } from "vue";
|
|
3
|
-
const w = {
|
|
4
|
-
name: "VsPie",
|
|
5
|
-
props: ["currentWidget"],
|
|
6
|
-
mixins: [g],
|
|
7
|
-
data() {
|
|
8
|
-
return {
|
|
9
|
-
chartInstance: null,
|
|
10
|
-
uniqueID: null,
|
|
11
|
-
resizeObserver: null
|
|
12
|
-
};
|
|
13
|
-
},
|
|
14
|
-
async mounted() {
|
|
15
|
-
var e, a;
|
|
16
|
-
this.uniqueID = this.widget, await this.$nextTick(), await this.getData();
|
|
17
|
-
const { series: t } = this.prepareData();
|
|
18
|
-
t && this.initChart(t);
|
|
19
|
-
const r = (e = this.$refs) == null ? void 0 : e.chart;
|
|
20
|
-
r && (this.resizeObserver = new ResizeObserver(() => {
|
|
21
|
-
var s;
|
|
22
|
-
this.chartInstance && ((s = this.chartInstance) == null || s.resize());
|
|
23
|
-
}), (a = this.resizeObserver) == null || a.observe(r));
|
|
24
|
-
},
|
|
25
|
-
beforeUnmount() {
|
|
26
|
-
var t;
|
|
27
|
-
(t = this.resizeObserver) == null || t.disconnect();
|
|
28
|
-
},
|
|
29
|
-
methods: {
|
|
30
|
-
onChangedData() {
|
|
31
|
-
try {
|
|
32
|
-
if (this.sourceData) {
|
|
33
|
-
const { series: t, xs: r, ys: e } = this.prepareData();
|
|
34
|
-
t && (this == null || this.initChart(t, r, e));
|
|
35
|
-
}
|
|
36
|
-
} catch (t) {
|
|
37
|
-
console.error(t);
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
buildTooltipForDonut(t, r) {
|
|
41
|
-
const { name: e, value: a, percent: s } = t;
|
|
42
|
-
return `
|
|
43
|
-
<div style="background-color:${r[0]};font-size: 12px; font-family: Helvetica, Arial, sans-serif;color:#ffff; padding:5px; border-radius:5px; ![box-shadow:none]">
|
|
44
|
-
${e == null ? void 0 : e.replace("null", "Не визначено")}: ${c(a)} (${s}%)
|
|
45
|
-
</div>`;
|
|
46
|
-
},
|
|
47
|
-
prepareData() {
|
|
48
|
-
var t, r, e, a;
|
|
49
|
-
try {
|
|
50
|
-
const s = Array.from(
|
|
51
|
-
new Set(this.sourceData.map((i) => i[this.dimensions[0]]))
|
|
52
|
-
), n = Array.from(
|
|
53
|
-
new Set(this.sourceData.map((i) => i[this.dimensions[1]]))
|
|
54
|
-
), d = parseInt(
|
|
55
|
-
(t = this.sourceData) == null ? void 0 : t.reduce((i, o) => i += parseFloat(o == null ? void 0 : o.metric), 0)
|
|
56
|
-
), u = s.map((i, o) => {
|
|
57
|
-
const D = (n[o] / d * 100).toFixed(2);
|
|
58
|
-
return {
|
|
59
|
-
name: `${i} (${D}%)`,
|
|
60
|
-
value: n[o]
|
|
61
|
-
};
|
|
62
|
-
}), p = ((r = this.styleData) == null ? void 0 : r.innerRadius) || "80%", m = ((e = this.styleData) == null ? void 0 : e.outerRadius) || "100%", f = [p, m];
|
|
63
|
-
return this.styleData.legend = h.getLegendOpions({
|
|
64
|
-
borderRadius: 10,
|
|
65
|
-
height: "100%",
|
|
66
|
-
padding: 10,
|
|
67
|
-
bottom: "0",
|
|
68
|
-
type: "scroll",
|
|
69
|
-
itemWidth: 14,
|
|
70
|
-
itemHeight: 14,
|
|
71
|
-
formatter: (i) => i == null ? void 0 : i.replace("null", "Не визначено"),
|
|
72
|
-
...this.styleData.legend
|
|
73
|
-
}), this.styleData.label = h.getLabelOptions(
|
|
74
|
-
this.styleData.label
|
|
75
|
-
), this.styleData.show_legend = ((a = this.styleData) == null ? void 0 : a.show_legend) || !0, { series: [
|
|
76
|
-
{
|
|
77
|
-
name: this.titleCharts ? this.titleCharts : this.dimensions[0],
|
|
78
|
-
type: "pie",
|
|
79
|
-
radius: f,
|
|
80
|
-
center: ["50%", "60%"],
|
|
81
|
-
height: "75%",
|
|
82
|
-
...l(this.styleData),
|
|
83
|
-
data: u
|
|
84
|
-
}
|
|
85
|
-
] };
|
|
86
|
-
} catch (s) {
|
|
87
|
-
return console.error(s), null;
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
async initChart(t) {
|
|
91
|
-
var r;
|
|
92
|
-
try {
|
|
93
|
-
const e = document.getElementById(this.uniqueID);
|
|
94
|
-
this.chartInstance = b(e);
|
|
95
|
-
const a = {
|
|
96
|
-
tooltip: {
|
|
97
|
-
trigger: "item",
|
|
98
|
-
formatter: (s) => this.buildTooltipForDonut(s, [s.color]),
|
|
99
|
-
borderWidth: 0,
|
|
100
|
-
appendToBody: !0,
|
|
101
|
-
borderColor: "transparent",
|
|
102
|
-
textStyle: {
|
|
103
|
-
color: "#000"
|
|
104
|
-
},
|
|
105
|
-
padding: [15, 15],
|
|
106
|
-
shadowColor: "transparent",
|
|
107
|
-
backgroundColor: "transparent"
|
|
108
|
-
},
|
|
109
|
-
series: t,
|
|
110
|
-
...l({
|
|
111
|
-
...this.styleData
|
|
112
|
-
}),
|
|
113
|
-
title: {
|
|
114
|
-
text: c(
|
|
115
|
-
parseInt(
|
|
116
|
-
(r = this.sourceData) == null ? void 0 : r.reduce(
|
|
117
|
-
(s, n) => s += parseFloat(n == null ? void 0 : n.metric),
|
|
118
|
-
0
|
|
119
|
-
)
|
|
120
|
-
)
|
|
121
|
-
),
|
|
122
|
-
left: "center",
|
|
123
|
-
top: "41%",
|
|
124
|
-
textStyle: {
|
|
125
|
-
color: "black",
|
|
126
|
-
fontWeight: 400,
|
|
127
|
-
fontSize: "22px"
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
this.chartInstance.setOption(a), this.$emit("update:currentWidget", this.chartInstance), this.chartInstance.resize(), window.addEventListener("resize", () => {
|
|
132
|
-
this.chartInstance.resize();
|
|
133
|
-
});
|
|
134
|
-
} catch (e) {
|
|
135
|
-
console.error(e);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}, _ = ["id"];
|
|
140
|
-
function $(t, r, e, a, s, n) {
|
|
141
|
-
return x(), I("div", {
|
|
142
|
-
id: s.uniqueID,
|
|
143
|
-
ref: "chart",
|
|
144
|
-
class: "h-full min-h-[200px] flex items-center"
|
|
145
|
-
}, null, 8, _);
|
|
146
|
-
}
|
|
147
|
-
const O = /* @__PURE__ */ y(w, [["render", $]]);
|
|
148
|
-
export {
|
|
149
|
-
O as default
|
|
150
|
-
};
|