@opengis/bi 1.0.41 → 1.0.42
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/dist/bi.js +1 -1
- package/dist/bi.umd.cjs +57 -57
- package/dist/{import-file-CcioJxEB.js → import-file-XtDaxS3X.js} +5855 -5812
- package/dist/{vs-donut-D-QP9o_T.js → vs-donut-DsuDQZ3C.js} +1 -1
- package/dist/{vs-funnel-bar-Bmk_YjfV.js → vs-funnel-bar-CQAgEcLe.js} +1 -1
- package/dist/{vs-list-ONirzMum.js → vs-list-C-gFvDvr.js} +1 -1
- package/dist/{vs-map-cluster-D3AbUEU0.js → vs-map-cluster-B9kG91Ge.js} +59 -56
- package/dist/{vs-map-CnK-QncQ.js → vs-map-uUiqdNLp.js} +3 -3
- package/dist/{vs-number-BwR2niBA.js → vs-number-BuOWTFVp.js} +1 -1
- package/dist/{vs-table-BgSOqPFX.js → vs-table-BG9nb7R0.js} +1 -1
- package/dist/{vs-text-L2QtfpkN.js → vs-text-BEb3W2ua.js} +1 -1
- package/package.json +1 -1
- package/server/routes/dashboard/controllers/dashboard.js +16 -6
- package/server/routes/data/controllers/data.js +6 -5
- package/server/routes/data/controllers/util/normalizeData.js +1 -1
- package/server/routes/edit/controllers/widget.add.js +9 -2
- package/server/routes/edit/controllers/widget.edit.js +12 -2
- package/server/routes/map/controllers/map.js +2 -2
- package/server/utils/getWidget.js +18 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as y, c as D, i as g, a as c, b as h, P as l } from "./import-file-
|
|
1
|
+
import { _ as y, c as D, i as g, a as c, b as h, P as l } from "./import-file-XtDaxS3X.js";
|
|
2
2
|
import { createElementBlock as b, openBlock as x } from "vue";
|
|
3
3
|
const _ = {
|
|
4
4
|
name: "VsPie",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as n, c, i as h, b as o, d as l, a as d } from "./import-file-
|
|
1
|
+
import { _ as n, c, i as h, b as o, d as l, a as d } from "./import-file-XtDaxS3X.js";
|
|
2
2
|
import { createElementBlock as p, openBlock as u } from "vue";
|
|
3
3
|
const m = {
|
|
4
4
|
name: "VsFunnelBar",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as Qs,
|
|
1
|
+
import { _ as Qs, h as Vp, j as Np } from "./import-file-XtDaxS3X.js";
|
|
2
2
|
import { createElementBlock as br, openBlock as wr, createElementVNode as Vt, createStaticVNode as jp, withDirectives as Up, toDisplayString as rh, vShow as $p, Fragment as ju, renderList as Uu, normalizeClass as qp, resolveComponent as Zp, createVNode as Gp } from "vue";
|
|
3
3
|
const Hp = {}, Xp = {
|
|
4
4
|
class: "shrink-0 size-3",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as
|
|
2
|
-
import { _ as V, V as
|
|
3
|
-
import { createElementBlock as h, createCommentVNode as S, openBlock as p, createElementVNode as l, normalizeClass as I, Fragment as
|
|
4
|
-
const
|
|
5
|
-
components: { legendIcon:
|
|
1
|
+
import { c as A, l as P, p as O, b as Z, V as q, a as K, d as W, e as D, m as T } from "./vs-list-C-gFvDvr.js";
|
|
2
|
+
import { _ as V, V as J, c as Q, e as N, I as U, g as X } from "./import-file-XtDaxS3X.js";
|
|
3
|
+
import { createElementBlock as h, createCommentVNode as S, openBlock as p, createElementVNode as l, normalizeClass as I, Fragment as F, renderList as G, toDisplayString as R, normalizeStyle as Y, resolveComponent as u, withDirectives as z, createBlock as M, resolveDynamicComponent as j, createVNode as w, vShow as C } from "vue";
|
|
4
|
+
const $ = {
|
|
5
|
+
components: { legendIcon: P, closeIcon: A },
|
|
6
6
|
props: {
|
|
7
7
|
mapId: { type: String },
|
|
8
8
|
colors: { type: Array },
|
|
@@ -17,7 +17,7 @@ const j = {
|
|
|
17
17
|
data() {
|
|
18
18
|
return {
|
|
19
19
|
isOpenLegend: !1,
|
|
20
|
-
palette:
|
|
20
|
+
palette: O
|
|
21
21
|
// palette: ['#69D2E7', 'yellow', '#FE4365'],
|
|
22
22
|
};
|
|
23
23
|
},
|
|
@@ -45,37 +45,37 @@ const j = {
|
|
|
45
45
|
return (t + 1) / this.sortedSizes.length;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
},
|
|
48
|
+
}, ee = {
|
|
49
49
|
key: 0,
|
|
50
50
|
class: "absolute flex items-end w-fit bottom-[10px] max-w-[80%] left-[50%] translate-x-[-50%] bg-[rgba(255,255,255,0.7)] p-[10px] rounded"
|
|
51
|
-
},
|
|
52
|
-
function
|
|
51
|
+
}, te = { class: "w-[80px] mr-[10px]" }, se = ["title"], oe = { class: "text-[10px] mb-[2px] text-[#1F2937] font-normal leading-[1.2]" };
|
|
52
|
+
function re(t, s, n, a, e, o) {
|
|
53
53
|
var d;
|
|
54
|
-
return (d = n.sizes) != null && d.length ? (p(), h("div",
|
|
55
|
-
l("div",
|
|
54
|
+
return (d = n.sizes) != null && d.length ? (p(), h("div", ee, [
|
|
55
|
+
l("div", te, [
|
|
56
56
|
s[0] || (s[0] = l("p", { class: "text-[10px] mb-[2px] text-[#1F2937] leading-[1.2]" }, " Дані відсутні ", -1)),
|
|
57
57
|
l("div", {
|
|
58
58
|
class: I([o.sizeClass(t.index), "w-full border border-gray-500"])
|
|
59
59
|
}, null, 2)
|
|
60
60
|
]),
|
|
61
|
-
o.sortedSizes.length ? (p(!0), h(
|
|
62
|
-
var
|
|
61
|
+
o.sortedSizes.length ? (p(!0), h(F, { key: 0 }, G(o.sortedSizes, (c, i) => {
|
|
62
|
+
var x, v, _, m, g, y, f, b;
|
|
63
63
|
return p(), h("div", {
|
|
64
64
|
class: "w-[80px]",
|
|
65
|
-
title: i === ((
|
|
65
|
+
title: i === ((x = o.sortedSizes) == null ? void 0 : x.length) - 1 ? ">" + c : i == ((v = o.sortedSizes) == null ? void 0 : v.length) - 1 ? ">" + o.sortedSizes[((_ = o.sortedSizes) == null ? void 0 : _.length) - 1] : c + "-" + o.sortedSizes[i + 1]
|
|
66
66
|
}, [
|
|
67
|
-
l("p",
|
|
67
|
+
l("p", oe, R(i === ((m = o.sortedSizes) == null ? void 0 : m.length) - 1 ? ">" + parseInt(c) : i == ((g = o.sortedSizes) == null ? void 0 : g.length) - 1 ? ">" + parseInt(o.sortedSizes[((y = o.sortedSizes) == null ? void 0 : y.length) - 1]) : parseInt(c) + "-" + parseInt(o.sortedSizes[i + 1])), 1),
|
|
68
68
|
l("div", {
|
|
69
69
|
class: I([o.sizeClass(i), "w-full border border-r-0 border-gray-500"]),
|
|
70
|
-
style:
|
|
70
|
+
style: Y({
|
|
71
71
|
backgroundColor: ((b = (f = e.palette) == null ? void 0 : f[n.color]) == null ? void 0 : b[i]) || n.color
|
|
72
72
|
})
|
|
73
73
|
}, null, 6)
|
|
74
|
-
], 8,
|
|
74
|
+
], 8, se);
|
|
75
75
|
}), 256)) : S("", !0)
|
|
76
76
|
])) : S("", !0);
|
|
77
77
|
}
|
|
78
|
-
const
|
|
78
|
+
const ae = /* @__PURE__ */ V($, [["render", re]]), ne = {}, le = {
|
|
79
79
|
xmlns: "http://www.w3.org/2000/svg",
|
|
80
80
|
width: "24",
|
|
81
81
|
height: "24",
|
|
@@ -87,8 +87,8 @@ const re = /* @__PURE__ */ V(j, [["render", oe]]), ae = {}, ne = {
|
|
|
87
87
|
"stroke-linejoin": "round",
|
|
88
88
|
class: "icon icon-tabler icons-tabler-outline icon-tabler-map"
|
|
89
89
|
};
|
|
90
|
-
function
|
|
91
|
-
return p(), h("svg",
|
|
90
|
+
function ie(t, s) {
|
|
91
|
+
return p(), h("svg", le, s[0] || (s[0] = [
|
|
92
92
|
l("path", {
|
|
93
93
|
stroke: "none",
|
|
94
94
|
d: "M0 0h24v24H0z",
|
|
@@ -99,24 +99,25 @@ function le(t, s) {
|
|
|
99
99
|
l("path", { d: "M15 7v13" }, null, -1)
|
|
100
100
|
]));
|
|
101
101
|
}
|
|
102
|
-
const
|
|
103
|
-
mixins: [
|
|
102
|
+
const pe = /* @__PURE__ */ V(ne, [["render", ie]]), ce = {
|
|
103
|
+
mixins: [Q, D],
|
|
104
104
|
components: {
|
|
105
|
-
VsMapSetting:
|
|
106
|
-
VsClusterLegend:
|
|
107
|
-
VsMapGoHome:
|
|
108
|
-
VsList:
|
|
109
|
-
VsMapSlotLayers:
|
|
110
|
-
VsListbar
|
|
105
|
+
VsMapSetting: W,
|
|
106
|
+
VsClusterLegend: ae,
|
|
107
|
+
VsMapGoHome: K,
|
|
108
|
+
VsList: q,
|
|
109
|
+
VsMapSlotLayers: Z,
|
|
110
|
+
// VsListbar,
|
|
111
|
+
VsBar: J
|
|
111
112
|
},
|
|
112
113
|
data() {
|
|
113
114
|
return {
|
|
114
115
|
baseColor: "pink",
|
|
115
116
|
kattotg: "",
|
|
116
117
|
options: [
|
|
117
|
-
{ id: "map", text: "Карта", component:
|
|
118
|
-
{ id: "table", text: "Таблиця", component:
|
|
119
|
-
{ id: "chart", text: "Віджет", component:
|
|
118
|
+
{ id: "map", text: "Карта", component: pe },
|
|
119
|
+
{ id: "table", text: "Таблиця", component: U },
|
|
120
|
+
{ id: "chart", text: "Віджет", component: X }
|
|
120
121
|
],
|
|
121
122
|
activeTab: "map",
|
|
122
123
|
mapId: `map-${Math.floor(Math.random() * 1e3)}`,
|
|
@@ -141,17 +142,19 @@ const ie = /* @__PURE__ */ V(ae, [["render", le]]), pe = {
|
|
|
141
142
|
},
|
|
142
143
|
methods: {
|
|
143
144
|
async getMapData() {
|
|
144
|
-
const t = await
|
|
145
|
-
`/
|
|
145
|
+
const t = await N.get(
|
|
146
|
+
`/bi-cluster?widget=${this.widget}&dashboard=${this.dashboard}`
|
|
147
|
+
), { data: s } = await N.get(
|
|
148
|
+
`/bi-data?dashboard=${this.dashboard}&widget=${this.widget}`
|
|
146
149
|
);
|
|
147
|
-
this.data =
|
|
150
|
+
console.log(s), this.data = t.data;
|
|
148
151
|
},
|
|
149
152
|
async loadHandler() {
|
|
150
153
|
var a, e, o, d;
|
|
151
154
|
this.baseColor = ((a = this.data.style) == null ? void 0 : a.color) || "blue";
|
|
152
155
|
const t = ["case"];
|
|
153
156
|
(d = (o = (e = this.data) == null ? void 0 : e.sizes) == null ? void 0 : o.reverse()) == null || d.forEach((c, i) => {
|
|
154
|
-
t.push([">", ["get", "metric"], c]), t.push(
|
|
157
|
+
t.push([">", ["get", "metric"], c]), t.push(O[this.baseColor][i]), i++;
|
|
155
158
|
}), t.push("gray");
|
|
156
159
|
const s = {
|
|
157
160
|
type: "polygon",
|
|
@@ -231,23 +234,23 @@ const ie = /* @__PURE__ */ V(ae, [["render", le]]), pe = {
|
|
|
231
234
|
}
|
|
232
235
|
}
|
|
233
236
|
}
|
|
234
|
-
},
|
|
237
|
+
}, de = { class: "h-full" }, he = { class: "flex items-start justify-between mb-[6px] w-full" }, ue = { class: "text-gray-800 font-[600]" }, me = { class: "flex gap-2" }, ge = ["onClick"], ye = ["id"], fe = ["id"], be = { class: "absolute flex flex-col right-[10px] top-[105px] gap-1" }, xe = { class: "h-[calc(250px)]" };
|
|
235
238
|
function ve(t, s, n, a, e, o) {
|
|
236
239
|
var m, g, y, f, b, k, L, E, B, H;
|
|
237
|
-
const d = u("VsMapSetting"), c = u("VsMapSlotLayers"), i = u("VsMapGoHome"),
|
|
238
|
-
return p(), h("div",
|
|
239
|
-
l("div",
|
|
240
|
-
l("h3",
|
|
241
|
-
l("div",
|
|
242
|
-
(p(!0), h(
|
|
243
|
-
class: I(["p-1 text-gray-700 border rounded
|
|
244
|
-
onClick: (
|
|
240
|
+
const d = u("VsMapSetting"), c = u("VsMapSlotLayers"), i = u("VsMapGoHome"), x = u("VsClusterLegend"), v = u("VsList"), _ = u("VsBar");
|
|
241
|
+
return p(), h("div", de, [
|
|
242
|
+
l("div", he, [
|
|
243
|
+
l("h3", ue, R(t.title), 1),
|
|
244
|
+
l("div", me, [
|
|
245
|
+
(p(!0), h(F, null, G(e.options, (r) => (p(), h("button", {
|
|
246
|
+
class: I(["p-1 text-gray-700 border rounded", [e.activeTab === (r == null ? void 0 : r.id) ? "ring-2 ring-blue-500" : ""]]),
|
|
247
|
+
onClick: (_e) => e.activeTab = r == null ? void 0 : r.id
|
|
245
248
|
}, [
|
|
246
|
-
(p(), M(
|
|
247
|
-
height: "
|
|
248
|
-
width: "
|
|
249
|
+
(p(), M(j(r == null ? void 0 : r.component), {
|
|
250
|
+
height: "16",
|
|
251
|
+
width: "16"
|
|
249
252
|
}))
|
|
250
|
-
], 10,
|
|
253
|
+
], 10, ge))), 256))
|
|
251
254
|
])
|
|
252
255
|
]),
|
|
253
256
|
z(l("div", {
|
|
@@ -257,20 +260,20 @@ function ve(t, s, n, a, e, o) {
|
|
|
257
260
|
l("div", {
|
|
258
261
|
id: e.mapId,
|
|
259
262
|
class: "h-[calc(100%-40px)] w-full flex items-end min-h-[250px]"
|
|
260
|
-
}, null, 8,
|
|
263
|
+
}, null, 8, fe),
|
|
261
264
|
e.showSetting ? (p(), M(d, {
|
|
262
265
|
key: 0,
|
|
263
266
|
map: e.map,
|
|
264
267
|
coordinates: e.coordinatesByMouse
|
|
265
268
|
}, null, 8, ["map", "coordinates"])) : S("", !0),
|
|
266
269
|
w(c, { map: e.map }, null, 8, ["map"]),
|
|
267
|
-
l("div",
|
|
270
|
+
l("div", be, [
|
|
268
271
|
w(i, {
|
|
269
272
|
map: e.map,
|
|
270
273
|
bbox: (m = e.data) == null ? void 0 : m.bounds
|
|
271
274
|
}, null, 8, ["map", "bbox"])
|
|
272
275
|
]),
|
|
273
|
-
w(
|
|
276
|
+
w(x, {
|
|
274
277
|
mapId: e.mapId,
|
|
275
278
|
colors: (g = e.data) == null ? void 0 : g.colors,
|
|
276
279
|
sizes: (y = e.data) == null ? void 0 : y.sizes,
|
|
@@ -278,10 +281,10 @@ function ve(t, s, n, a, e, o) {
|
|
|
278
281
|
changeOpacityItem: "true",
|
|
279
282
|
cluster: "true"
|
|
280
283
|
}, null, 8, ["mapId", "colors", "sizes", "color"])
|
|
281
|
-
], 8,
|
|
284
|
+
], 8, ye), [
|
|
282
285
|
[C, e.activeTab == "map"]
|
|
283
286
|
]),
|
|
284
|
-
z(w(
|
|
287
|
+
z(w(v, {
|
|
285
288
|
mapId: e.mapId,
|
|
286
289
|
source: (f = e.data) == null ? void 0 : f.rows,
|
|
287
290
|
total: ((b = e.data) == null ? void 0 : b.total) || 0,
|
|
@@ -290,7 +293,7 @@ function ve(t, s, n, a, e, o) {
|
|
|
290
293
|
}, null, 8, ["mapId", "source", "total", "count"]), [
|
|
291
294
|
[C, e.activeTab == "table"]
|
|
292
295
|
]),
|
|
293
|
-
z(l("div",
|
|
296
|
+
z(l("div", xe, [
|
|
294
297
|
(E = (L = e.data) == null ? void 0 : L.rows) != null && E.length ? (p(), M(_, {
|
|
295
298
|
key: 0,
|
|
296
299
|
source: (H = (B = e.data) == null ? void 0 : B.rows) == null ? void 0 : H.map((r) => ({
|
|
@@ -303,7 +306,7 @@ function ve(t, s, n, a, e, o) {
|
|
|
303
306
|
])
|
|
304
307
|
]);
|
|
305
308
|
}
|
|
306
|
-
const
|
|
309
|
+
const Me = /* @__PURE__ */ V(ce, [["render", ve]]);
|
|
307
310
|
export {
|
|
308
|
-
|
|
311
|
+
Me as default
|
|
309
312
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as L, l as $, p as B, V as H, a as O, b as T, d as F, m as S, e as N } from "./vs-list-
|
|
2
|
-
import { _ as C, c as R } from "./import-file-
|
|
1
|
+
import { c as L, l as $, p as B, V as H, a as O, b as T, d as F, m as S, e as N } from "./vs-list-C-gFvDvr.js";
|
|
2
|
+
import { _ as C, c as R } from "./import-file-XtDaxS3X.js";
|
|
3
3
|
import { resolveComponent as u, createElementBlock as d, openBlock as n, Fragment as w, createElementVNode as a, createBlock as E, createCommentVNode as c, createVNode as f, Teleport as A, toDisplayString as b, renderList as k, normalizeStyle as I, normalizeClass as V } from "vue";
|
|
4
4
|
const G = {
|
|
5
5
|
components: { legendIcon: $, closeIcon: L },
|
|
@@ -98,7 +98,7 @@ function ee(e, t, s, o, r, l) {
|
|
|
98
98
|
backgroundColor: i.color
|
|
99
99
|
})
|
|
100
100
|
}, null, 4)) : c("", !0),
|
|
101
|
-
a("p", K, b(i.val), 1)
|
|
101
|
+
a("p", K, b(i.text || i.val), 1)
|
|
102
102
|
]))), 128))
|
|
103
103
|
])
|
|
104
104
|
])) : c("", !0),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as m, c as f, d as _, a as b } from "./import-file-
|
|
1
|
+
import { _ as m, c as f, d as _, a as b } from "./import-file-XtDaxS3X.js";
|
|
2
2
|
import { createElementBlock as a, openBlock as r, createElementVNode as s, Fragment as n, renderList as c, toDisplayString as d } from "vue";
|
|
3
3
|
const x = {
|
|
4
4
|
name: "VsTable",
|
package/package.json
CHANGED
|
@@ -31,6 +31,7 @@ export default async function dashboard({
|
|
|
31
31
|
} catch (err) {
|
|
32
32
|
data.error = err.toString();
|
|
33
33
|
}
|
|
34
|
+
|
|
34
35
|
data.type = 'bd';
|
|
35
36
|
const { table_name: table } = data;
|
|
36
37
|
|
|
@@ -38,7 +39,16 @@ export default async function dashboard({
|
|
|
38
39
|
return { message: 'not enough params: table required', status: 400 };
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
+
const loadTemplate = pg.pk?.['admin.doc_template'] ? await pg.query(
|
|
43
|
+
'select body from admin.doc_template where doc_type=5 and title=$1',
|
|
44
|
+
[table]
|
|
45
|
+
).then(el => el.rows?.[0]?.body) : null;
|
|
46
|
+
|
|
47
|
+
const sqlList = loadTemplate?.sql ? loadTemplate?.sql
|
|
48
|
+
?.filter?.(el => !el.disabled && el?.sql?.replace)
|
|
49
|
+
?.map?.((el, i) => `left join lateral (${el.sql.replace(/limit 1/ig, '')}) t${i} on 1=1`)?.join?.(' ') : '';
|
|
50
|
+
|
|
51
|
+
const { fields = [] } = table && pg.pk?.[loadTemplate?.table || table] ? await pg.query(`select * from ${loadTemplate?.table || table} t ${sqlList || ''} limit 0`) : {};
|
|
42
52
|
|
|
43
53
|
data?.widgets?.forEach?.(el => {
|
|
44
54
|
const { style, data = {}, type, title, x, metrics } = el;
|
|
@@ -51,11 +61,10 @@ export default async function dashboard({
|
|
|
51
61
|
Object.assign(el, { title, type });
|
|
52
62
|
});
|
|
53
63
|
|
|
54
|
-
const meta = table ? await getMeta({ pg, table }) : {};
|
|
64
|
+
const meta = table ? await getMeta({ pg, table: loadTemplate?.table || table }) : {};
|
|
65
|
+
const columnIndexes = meta?.columns?.reduce((acc, curr, idx) => Object.assign(acc, { [curr.name]: idx }), {}) || [];
|
|
55
66
|
|
|
56
|
-
const columns = meta?.columns
|
|
57
|
-
?.filter(el => fields.map(field => field.name).includes(el.name))
|
|
58
|
-
?.map(el => ({ name: el.name, title: el.title, type: pg.pgType?.[el.dataTypeID] }));
|
|
67
|
+
const columns = fields?.map(el => ({ name: el.name, title: meta?.columns[columnIndexes[el.name]]?.title || el.name, type: pg.pgType?.[el.dataTypeID] }));
|
|
59
68
|
|
|
60
69
|
return {
|
|
61
70
|
...data || {},
|
|
@@ -63,8 +72,9 @@ export default async function dashboard({
|
|
|
63
72
|
panels: data?.panels?.filter?.(el => el?.widget) || [],
|
|
64
73
|
geom: !meta?.geom,
|
|
65
74
|
error:
|
|
66
|
-
table && !pg.pk?.[table] ? `table pkey not found: ${table}` : undefined,
|
|
75
|
+
table && !pg.pk?.[loadTemplate?.table || table] ? `table pkey not found: ${loadTemplate?.table || table}` : undefined,
|
|
67
76
|
table_name: table,
|
|
77
|
+
templateTable: loadTemplate?.table,
|
|
68
78
|
time: Date.now() - time,
|
|
69
79
|
columns,
|
|
70
80
|
};
|
|
@@ -34,7 +34,7 @@ export default async function dataAPI(req, reply) {
|
|
|
34
34
|
const pg = widgetData.pg || req.pg || pgClients.client;
|
|
35
35
|
|
|
36
36
|
const { fields: cols } = await pg.query(
|
|
37
|
-
`select * from ${data.table} limit 0`
|
|
37
|
+
`select * from ${data.table} t ${widgetData.tableSQL || data.tableSQL || ''} limit 0`
|
|
38
38
|
);
|
|
39
39
|
const columnTypes = cols.map((el) => ({
|
|
40
40
|
name: el.name,
|
|
@@ -65,8 +65,8 @@ export default async function dataAPI(req, reply) {
|
|
|
65
65
|
return { message: `table not found: ${data.table} (${pg.options?.database})`, status: 404 };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const columnList = columns.map(col => col.name);
|
|
69
|
-
const groupbyColumnNotExists = groupby?.split?.(',')?.filter?.(el => !
|
|
68
|
+
// const columnList = columns.map(col => col.name);
|
|
69
|
+
const groupbyColumnNotExists = groupby?.split?.(',')?.filter?.(el => !columnTypes.map(el => el.name).includes(el.trim()));
|
|
70
70
|
|
|
71
71
|
if (groupby && groupbyColumnNotExists?.length) {
|
|
72
72
|
return { message: `groupby column not found: ${groupbyColumnNotExists} (${data.table}/${pg.options?.database})`, status: 404 };
|
|
@@ -83,7 +83,7 @@ export default async function dataAPI(req, reply) {
|
|
|
83
83
|
|
|
84
84
|
if (query.sql === '2') return { x, metric, table, tableSQL, data, groupData };
|
|
85
85
|
|
|
86
|
-
const order = data.order || (type === 'listbar' ? 'metric desc' : null);
|
|
86
|
+
const order = data.order || (type === 'listbar' && cols.find(el => el.name === 'metric') ? 'metric desc' : null);
|
|
87
87
|
|
|
88
88
|
const fData =
|
|
89
89
|
filter || search
|
|
@@ -139,7 +139,8 @@ export default async function dataAPI(req, reply) {
|
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
if (config.
|
|
142
|
+
if (config.trace) console.log(sql, user?.uid);
|
|
143
|
+
|
|
143
144
|
const { rows, fields } = await pg.query(sql.replace('{{uid}}', user?.uid)); // test with limit
|
|
144
145
|
|
|
145
146
|
if (cls) {
|
|
@@ -57,7 +57,7 @@ function normalizeData(data, query = {}, columnTypes = []) {
|
|
|
57
57
|
const where = `${data.query || '1=1'} and ${custom || 'true'}`;
|
|
58
58
|
|
|
59
59
|
const tableSQL = data.tableSQL?.length
|
|
60
|
-
? `(select * from ${data?.table} t ${data.tableSQL
|
|
60
|
+
? `(select * from ${data?.table} t ${data.tableSQL || ''} where ${where})q`
|
|
61
61
|
: undefined;
|
|
62
62
|
|
|
63
63
|
return { x, cls, metric, table, where, tableSQL, groupby, xName, xType, yName, yType, error: skip.length ? skip.join(',') : undefined };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { dataInsert, dataUpdate, pgClients } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
import { dataInsert, dataUpdate, getPGAsync, pgClients } from "@opengis/fastify-table/utils.js";
|
|
3
3
|
|
|
4
4
|
/* eslint-disable import/extensions */
|
|
5
5
|
import { yamlSafe } from '../../../../utils.js';
|
|
@@ -20,12 +20,19 @@ export default async function widgetAdd({ pg = pgClients.client, params = {}, bo
|
|
|
20
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
|
+
const pg1 = row?.db ? await getPGAsync(row.db) : pg;
|
|
24
|
+
|
|
23
25
|
const tableName = data.data?.table
|
|
24
26
|
|| data?.table
|
|
25
27
|
|| data.table_name
|
|
26
28
|
|| row.table_name;
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
const loadTemplate = pg1.pk?.['admin.doc_template'] ? await pg1.query(
|
|
31
|
+
'select body from admin.doc_template where doc_type=5 and title=$1',
|
|
32
|
+
[tableName]
|
|
33
|
+
).then(el => el.rows?.[0]?.body) : null;
|
|
34
|
+
|
|
35
|
+
if (!tableName || !(pg.pk?.[loadTemplate?.table || tableName] || pgClients[data.db || row.db || 'client']?.pk?.[loadTemplate?.table || tableName])) {
|
|
29
36
|
return { message: 'bad params: table', status: 400 };
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -37,8 +37,18 @@ export default async function widgetEdit({ pg = pgClients.client, body, params }
|
|
|
37
37
|
.reduce((p, el) => ({ ...p, [el]: data[el] }), {});
|
|
38
38
|
|
|
39
39
|
// get table
|
|
40
|
-
const tableName = body.table
|
|
41
|
-
|
|
40
|
+
const tableName = body.table
|
|
41
|
+
|| widgetData.data?.table_name
|
|
42
|
+
|| widgetData.data?.table
|
|
43
|
+
|| widgetData?.table_name
|
|
44
|
+
|| templateData.table;
|
|
45
|
+
|
|
46
|
+
const loadTemplate = pg.pk?.['admin.doc_template'] ? await pg.query(
|
|
47
|
+
'select body from admin.doc_template where doc_type=5 and title=$1',
|
|
48
|
+
[tableName]
|
|
49
|
+
).then(el => el.rows?.[0]?.body) : null;
|
|
50
|
+
|
|
51
|
+
if (!tableName || !(pg.pk?.[loadTemplate?.table || tableName] || pgClients[widgetData?.data?.db || templateData?.db || 'client']?.pk?.[loadTemplate?.table || tableName])) {
|
|
42
52
|
return { message: 'bad params: table ' + tableName, status: 400 };
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -31,9 +31,9 @@ export default async function map(req) {
|
|
|
31
31
|
);
|
|
32
32
|
if (data?.cls) {
|
|
33
33
|
const vals = await getSelectVal({
|
|
34
|
-
pg, name: data.cls, values: rows.map(el => el.val),
|
|
34
|
+
pg, name: data.cls, values: rows.map(el => el.val), ar: true,
|
|
35
35
|
});
|
|
36
|
-
rows.forEach(row => Object.assign(row, {
|
|
36
|
+
rows.forEach(row => Object.assign(row, { ...vals?.find?.(el => el.id === row.val) || { text: row.val } }));
|
|
37
37
|
}
|
|
38
38
|
Object.assign(res, { colors: rows }); // кольори для легенди
|
|
39
39
|
}
|
|
@@ -85,10 +85,15 @@ async function getWidget({ pg: pg1 = pgClients.client, dashboard, widget }) {
|
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
const
|
|
88
|
+
const loadTemplate = pg.pk?.['admin.doc_template'] ? await pg.query(
|
|
89
|
+
'select body from admin.doc_template where doc_type=5 and title=$1',
|
|
90
|
+
[main.table]
|
|
91
|
+
).then(el => el.rows?.[0]?.body) : null;
|
|
92
|
+
|
|
93
|
+
const { pk, view, columns = [] } = await getMeta({ pg: widgetDb, table: loadTemplate?.table || main?.table });
|
|
89
94
|
if (!pk && !view) {
|
|
90
95
|
return {
|
|
91
|
-
message: /* json.error || */ `invalid ${widget ? 'widget' : 'dashboard'}: table not found (${main?.table})`,
|
|
96
|
+
message: /* json.error || */ `invalid ${widget ? 'widget' : 'dashboard'}: table not found (${loadTemplate?.table || main?.table})`,
|
|
92
97
|
status: 404,
|
|
93
98
|
};
|
|
94
99
|
}
|
|
@@ -97,6 +102,16 @@ async function getWidget({ pg: pg1 = pgClients.client, dashboard, widget }) {
|
|
|
97
102
|
(el, i) => `left join lateral(${el})t${i + 1} on 1=1`
|
|
98
103
|
);
|
|
99
104
|
|
|
100
|
-
|
|
105
|
+
const columnList = columns.map(col => col.name);
|
|
106
|
+
|
|
107
|
+
const res = { ...main, pg: widgetDb, sql: widgetData?.sql, limit: widgetData?.limit, tableSQL, data, type, text, controls, style, options, yml };
|
|
108
|
+
if (res.x && !columnList.includes(res.x) && !loadTemplate?.table) {
|
|
109
|
+
Object.assign(res, { x: null, error: `column does not exists: ${res.x} at table ${res.table}` });
|
|
110
|
+
}
|
|
111
|
+
if (loadTemplate?.table) {
|
|
112
|
+
Object.assign(res.data || {}, { table: loadTemplate?.table });
|
|
113
|
+
Object.assign(res, { table: loadTemplate?.table, table_name: loadTemplate?.table, tableSQL: loadTemplate.sql?.filter?.(el => !el.disabled && el?.sql?.replace)?.map?.((el, i) => `left join lateral(${el.sql})t${i + 1} on 1=1`)?.join?.(' ') });
|
|
114
|
+
}
|
|
115
|
+
return res;
|
|
101
116
|
}
|
|
102
117
|
export default getWidget;
|