@opengis/bi 1.0.14 → 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 -50
- package/config.js +12 -12
- package/dist/bi.js +1 -1
- package/dist/bi.umd.cjs +63 -63
- package/dist/{import-file-DUp3rsNI.js → import-file-CRC0sYYT.js} +8055 -7987
- package/dist/{map-component-mixin-CGM0P5ub.js → map-component-mixin-BCtWEvzv.js} +3795 -2116
- package/dist/style.css +1 -1
- package/dist/{vs-calendar-cOoinEwc.js → vs-calendar-5ot79n0N.js} +20 -9
- package/dist/{vs-funnel-bar-kLkPoIhJ.js → vs-funnel-bar-CLo6gXI_.js} +2 -2
- package/dist/{vs-heatmap-3XAVGTSo.js → vs-heatmap-DHGA8dRk.js} +3 -4
- package/dist/{vs-map-cluster-BWJPx7wE.js → vs-map-cluster-CNgX6JVF.js} +2 -2
- package/dist/{vs-map-B1tr6V5_.js → vs-map-pIn5wS4G.js} +2 -2
- package/dist/{vs-number-CrU7LmkV.js → vs-number-DYfok8VU.js} +19 -12
- package/dist/{vs-text-DRPx3aID.js → vs-text-Dckykz09.js} +19 -14
- package/package.json +107 -97
- package/plugin.js +14 -13
- package/server/migrations/bi.dataset.sql +26 -0
- package/server/migrations/bi.sql +93 -93
- package/server/plugins/docs.js +48 -48
- package/server/plugins/hook.js +89 -89
- package/server/plugins/vite.js +69 -69
- package/server/routes/dashboard/controllers/dashboard.delete.js +38 -37
- package/server/routes/dashboard/controllers/dashboard.js +118 -114
- package/server/routes/dashboard/controllers/dashboard.list.js +30 -36
- package/server/routes/dashboard/controllers/utils/yaml.js +11 -11
- package/server/routes/dashboard/index.mjs +25 -25
- package/server/routes/data/controllers/data.js +167 -156
- package/server/routes/data/controllers/util/chartSQL.js +42 -39
- package/server/routes/data/controllers/util/normalizeData.js +59 -56
- package/server/routes/data/index.mjs +29 -24
- 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 -63
- package/server/routes/db/controllers/dbTables.js +36 -36
- package/server/routes/db/index.mjs +17 -17
- package/server/routes/edit/controllers/dashboard.add.js +26 -24
- package/server/routes/edit/controllers/dashboard.edit.js +46 -44
- package/server/routes/edit/controllers/widget.add.js +75 -73
- package/server/routes/edit/controllers/widget.del.js +69 -70
- package/server/routes/edit/controllers/widget.edit.js +52 -103
- package/server/routes/edit/index.mjs +31 -31
- package/server/routes/map/controllers/cluster.js +109 -104
- package/server/routes/map/controllers/clusterVtile.js +166 -213
- package/server/routes/map/controllers/geojson.js +127 -127
- 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 -182
- package/server/routes/map/index.mjs +25 -25
- package/server/utils/getWidget.js +85 -83
- package/utils.js +12 -12
|
@@ -1,157 +1,168 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from '@opengis/fastify-table/utils.js';
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const {
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
1
|
+
import yaml from 'js-yaml';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
config,
|
|
5
|
+
getPGAsync,
|
|
6
|
+
autoIndex,
|
|
7
|
+
pgClients,
|
|
8
|
+
getSelectVal,
|
|
9
|
+
getFilterSQL,
|
|
10
|
+
} from '@opengis/fastify-table/utils.js';
|
|
11
|
+
|
|
12
|
+
import chartSQL from './util/chartSQL.js';
|
|
13
|
+
import normalizeData from './util/normalizeData.js';
|
|
14
|
+
|
|
15
|
+
import { getWidget } from '../../../../utils.js';
|
|
16
|
+
|
|
17
|
+
export default async function dataAPI({ funcs = {}, query = {} }) {
|
|
18
|
+
const time = Date.now();
|
|
19
|
+
|
|
20
|
+
query.metric = Array.isArray(query.metric) ? query.metric.pop() : query.metric;
|
|
21
|
+
|
|
22
|
+
const { dashboard, widget, filter, search, samples } = query;
|
|
23
|
+
|
|
24
|
+
const widgetData = await getWidget({ dashboard, widget });
|
|
25
|
+
|
|
26
|
+
if (widgetData.status) return widgetData;
|
|
27
|
+
|
|
28
|
+
const { type, text, data = {}, controls, style, options } = widgetData;
|
|
29
|
+
|
|
30
|
+
const pg = data.db ? await getPGAsync(data.db) : pgClients.client;
|
|
31
|
+
|
|
32
|
+
const { fields: cols } = await pg.query(
|
|
33
|
+
`select * from ${data.table} limit 0`
|
|
34
|
+
);
|
|
35
|
+
const columnTypes = cols.map((el) => ({
|
|
36
|
+
name: el.name,
|
|
37
|
+
type: pg.pgType?.[el.dataTypeID],
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
// data param
|
|
41
|
+
const { x, cls, metric, table, where, tableSQL, groupby, xName, yName, xType, yType } =
|
|
42
|
+
normalizeData(widgetData, query, columnTypes);
|
|
43
|
+
|
|
44
|
+
// auto Index
|
|
45
|
+
if (pg.pk?.[data.table]) {
|
|
46
|
+
autoIndex({
|
|
47
|
+
table: data.table,
|
|
48
|
+
pg,
|
|
49
|
+
columns: [data?.time]
|
|
50
|
+
.concat([xName])
|
|
51
|
+
.concat([groupby])
|
|
52
|
+
.filter((el) => el),
|
|
53
|
+
}).catch((err) => console.log(err));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// get group
|
|
57
|
+
const groupData = groupby
|
|
58
|
+
? await pg
|
|
59
|
+
.query(
|
|
60
|
+
`select ${groupby} as name ,count(*) from ${tableSQL || table} group by ${groupby} order by count(*) desc limit 20`
|
|
61
|
+
)
|
|
62
|
+
.then((el) => el.rows)
|
|
63
|
+
: null;
|
|
64
|
+
|
|
65
|
+
if (query.sql === '2') return { x, metric, table, tableSQL, data, groupData };
|
|
66
|
+
|
|
67
|
+
const order = data.order || (type === 'listbar' ? 'metric desc' : null);
|
|
68
|
+
|
|
69
|
+
const { optimizedSQL = `select * from ${tableSQL || table}` } =
|
|
70
|
+
filter || search
|
|
71
|
+
? await getFilterSQL({
|
|
72
|
+
pg,
|
|
73
|
+
table,
|
|
74
|
+
filter,
|
|
75
|
+
search,
|
|
76
|
+
})
|
|
77
|
+
: {};
|
|
78
|
+
|
|
79
|
+
if (type?.includes('bar') && !metric?.length) {
|
|
80
|
+
return { message: 'empty widget params: metrics', status: 400 };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const sql = (chartSQL[type] || chartSQL.chart)({
|
|
84
|
+
where,
|
|
85
|
+
metric,
|
|
86
|
+
table: `(${optimizedSQL} ${samples ? 'limit 10' : ''})q`,
|
|
87
|
+
x,
|
|
88
|
+
groupData,
|
|
89
|
+
groupby,
|
|
90
|
+
order,
|
|
91
|
+
samples,
|
|
92
|
+
xType,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (query.sql) return sql;
|
|
96
|
+
|
|
97
|
+
if (!sql || sql?.includes('undefined')) {
|
|
98
|
+
return {
|
|
99
|
+
message: {
|
|
100
|
+
error: 'invalid sql',
|
|
101
|
+
type,
|
|
102
|
+
sql,
|
|
103
|
+
where,
|
|
104
|
+
metric,
|
|
105
|
+
table: `(${optimizedSQL})q`,
|
|
106
|
+
x,
|
|
107
|
+
groupData,
|
|
108
|
+
groupby,
|
|
109
|
+
},
|
|
110
|
+
status: 500,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const { rows, fields } = await pg.query(sql); // test with limit
|
|
115
|
+
|
|
116
|
+
if (cls) {
|
|
117
|
+
const values = rows
|
|
118
|
+
.map((row) => row[x])
|
|
119
|
+
?.filter((el, idx, arr) => el && arr.indexOf(el) === idx);
|
|
120
|
+
const vals = await getSelectVal({ pg, name: cls, values });
|
|
121
|
+
rows
|
|
122
|
+
.filter((row) => row[x])
|
|
123
|
+
.forEach((row) => {
|
|
124
|
+
Object.assign(row, { [x]: vals?.[row[x]] || row[x] });
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const yml = widgetData.yml || yaml.dump(extractYml(widgetData));
|
|
129
|
+
const dimensions = fields.map((el) => el.name);
|
|
130
|
+
|
|
131
|
+
const res = {
|
|
132
|
+
time: Date.now() - time,
|
|
133
|
+
dimensions,
|
|
134
|
+
filter: xName,
|
|
135
|
+
dimensionsType: [xType, yType].filter((el) => el)?.length
|
|
136
|
+
? [xType, yType].filter((el) => el)
|
|
137
|
+
: fields.map((el) => pg.pgType?.[el.dataTypeID]),
|
|
138
|
+
type,
|
|
139
|
+
|
|
140
|
+
text: text || widgetData?.title || data.text,
|
|
141
|
+
// data: query.format === 'data' ? dimensions.map(el => rows.map(r => r[el])) : undefined,
|
|
142
|
+
source:
|
|
143
|
+
query.format === 'array'
|
|
144
|
+
? dimensions.map((el) => rows.map((r) => r[el]))
|
|
145
|
+
: rows,
|
|
146
|
+
style,
|
|
147
|
+
options,
|
|
148
|
+
controls,
|
|
149
|
+
yml,
|
|
150
|
+
params: config?.local ? {
|
|
151
|
+
x,
|
|
152
|
+
cls,
|
|
153
|
+
metric,
|
|
154
|
+
table,
|
|
155
|
+
tableSQL,
|
|
156
|
+
where,
|
|
157
|
+
groupby,
|
|
158
|
+
sql,
|
|
159
|
+
} : undefined,
|
|
160
|
+
columnTypes,
|
|
161
|
+
};
|
|
162
|
+
return res;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function extractYml(sourceData) {
|
|
166
|
+
const { title, description, type, data, style, controls } = sourceData;
|
|
167
|
+
return { title, description, type, data, style, controls };
|
|
157
168
|
}
|
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
function number({ metric, where, table, samples }) {
|
|
2
|
-
const sql = `select ${metric} from ${table} where ${where} ${samples ? 'limit 10' : ''}`;
|
|
3
|
-
return sql;
|
|
4
|
-
}
|
|
5
|
-
function table({ columns, table, where, samples }) {
|
|
6
|
-
return `select ${columns.map((el) => el.name || el)}::text from ${table} where ${where} ${samples ? 'limit 10' : 'limit 20'} `;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function chart({
|
|
10
|
-
metric,
|
|
11
|
-
where,
|
|
12
|
-
table,
|
|
13
|
-
x,
|
|
14
|
-
groupby,
|
|
15
|
-
groupData,
|
|
16
|
-
order,
|
|
17
|
-
samples,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
${
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
function number({ metric, where, table, samples }) {
|
|
2
|
+
const sql = `select ${metric} from ${table} where ${where} ${samples ? 'limit 10' : ''}`;
|
|
3
|
+
return sql;
|
|
4
|
+
}
|
|
5
|
+
function table({ columns, table, where, samples }) {
|
|
6
|
+
return `select ${columns.map((el) => el.name || el)}::text from ${table} where ${where} ${samples ? 'limit 10' : 'limit 20'} `;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function chart({
|
|
10
|
+
metric,
|
|
11
|
+
where,
|
|
12
|
+
table,
|
|
13
|
+
x,
|
|
14
|
+
groupby,
|
|
15
|
+
groupData,
|
|
16
|
+
order,
|
|
17
|
+
samples,
|
|
18
|
+
xType,
|
|
19
|
+
}) {
|
|
20
|
+
const xCol = x && xType?.includes('[]') ? `unnest(${x})` : x;
|
|
21
|
+
|
|
22
|
+
const metricData =
|
|
23
|
+
groupData
|
|
24
|
+
?.map(
|
|
25
|
+
(el) =>
|
|
26
|
+
`${metric} filter (where ${groupby}='${el.name}') as "${el.name}"`
|
|
27
|
+
)
|
|
28
|
+
.join(',') || `${metric} as metric`;
|
|
29
|
+
const sql = `select ${xCol}, ${metricData}
|
|
30
|
+
from ${table}
|
|
31
|
+
where ${where}
|
|
32
|
+
${xCol ? `group by ${xCol}` : ''}
|
|
33
|
+
${order || xCol ? `order by ${order || xCol}` : ''}
|
|
34
|
+
${samples ? 'limit 10' : 'limit 100'}`;
|
|
35
|
+
return sql;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function text() {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default { number, chart };
|
|
@@ -1,56 +1,59 @@
|
|
|
1
|
-
function normalizeData(data, query = {}, columnTypes = []) {
|
|
2
|
-
['x', 'groupby', 'granularity'].forEach((el) => {
|
|
3
|
-
// console.log(el, query[el], columnTypes.find(col => col.name == query[el]))
|
|
4
|
-
if (!columnTypes.find((col) => col.name == query[el])) {
|
|
5
|
-
delete query[el];
|
|
6
|
-
}
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
!columnTypes.find(
|
|
11
|
-
(col) => col.type === 'numeric' && col.name == query.metric
|
|
12
|
-
)
|
|
13
|
-
) {
|
|
14
|
-
delete query.metric;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const xName = query.x || (Array.isArray(data.x) ? data.x[0] : data.x);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const granularity =
|
|
21
|
-
|
|
22
|
-
? query.granularity || data.granularity || 'year'
|
|
23
|
-
: null;
|
|
24
|
-
|
|
25
|
-
const x =
|
|
26
|
-
(granularity
|
|
27
|
-
? `date_trunc('${granularity}',${xName})::date::text`
|
|
28
|
-
: null) || xName;
|
|
29
|
-
|
|
30
|
-
const metrics = Array.isArray(data.metrics) ? data.metrics : [data.metrics];
|
|
31
|
-
const metric =
|
|
32
|
-
(query.metric ? `sum(${query.metric})` : null) ||
|
|
33
|
-
(metrics.length
|
|
34
|
-
? metrics
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
: 'count(*)');
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
?.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
1
|
+
function normalizeData(data, query = {}, columnTypes = []) {
|
|
2
|
+
['x', 'groupby', 'granularity'].forEach((el) => {
|
|
3
|
+
// console.log(el, query[el], columnTypes.find(col => col.name == query[el]))
|
|
4
|
+
if (!columnTypes.find((col) => col.name == query[el])) {
|
|
5
|
+
delete query[el];
|
|
6
|
+
}
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
if (
|
|
10
|
+
!columnTypes.find(
|
|
11
|
+
(col) => col.type === 'numeric' && col.name == query.metric
|
|
12
|
+
)
|
|
13
|
+
) {
|
|
14
|
+
delete query.metric;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const xName = query.x || (Array.isArray(data.x) ? data.x[0] : data.x);
|
|
18
|
+
const xType = columnTypes.find((el) => el.name == xName)?.type;
|
|
19
|
+
|
|
20
|
+
const granularity =
|
|
21
|
+
xType === 'date' || xType?.includes('timestamp')
|
|
22
|
+
? query.granularity || data.granularity || 'year'
|
|
23
|
+
: null;
|
|
24
|
+
|
|
25
|
+
const x =
|
|
26
|
+
(granularity
|
|
27
|
+
? `date_trunc('${granularity}',${xName})::date::text`
|
|
28
|
+
: null) || xName;
|
|
29
|
+
|
|
30
|
+
const metrics = Array.isArray(data.metrics) ? data.metrics : [data.metrics];
|
|
31
|
+
const metric =
|
|
32
|
+
(query.metric ? `sum(${query.metric})` : null) ||
|
|
33
|
+
(metrics.length
|
|
34
|
+
? (metrics
|
|
35
|
+
?.filter((el) => el && columnTypes.find((col) => col.name == (el?.name || el)))
|
|
36
|
+
?.map((el) => el.fx || `${el.operator || 'sum'}(${el.name || el})`)?.join(',') || 'count(*)')
|
|
37
|
+
: 'count(*)');
|
|
38
|
+
|
|
39
|
+
const yName = metrics?.[0]?.name || metrics?.[0];
|
|
40
|
+
const yType = columnTypes.find((el) => el.name == yName)?.type;
|
|
41
|
+
|
|
42
|
+
const { cls, table, filterCustom } = data;
|
|
43
|
+
const groupby = query.groupby || data.groupby;
|
|
44
|
+
// const orderby = query.orderby || data.orderby || 'count(*)';
|
|
45
|
+
|
|
46
|
+
const custom = query?.filterCustom
|
|
47
|
+
?.split(',')
|
|
48
|
+
?.map((el) => filterCustom?.find((item) => item?.name === el)?.sql)
|
|
49
|
+
?.filter((el) => el)
|
|
50
|
+
?.join(' and ');
|
|
51
|
+
const where = `${data.query || '1=1'} and ${custom || 'true'}`;
|
|
52
|
+
|
|
53
|
+
const tableSQL = data.tableSQL?.length
|
|
54
|
+
? `(select * from ${data?.table} t ${data.tableSQL.join(' \n ')} where ${where})q`
|
|
55
|
+
: undefined;
|
|
56
|
+
|
|
57
|
+
return { x, cls, metric, table, where, tableSQL, groupby, xName, xType, yName, yType };
|
|
58
|
+
}
|
|
59
|
+
export default normalizeData;
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import config from '../../../config.js';
|
|
2
|
-
|
|
3
|
-
import data from './controllers/data.js';
|
|
4
|
-
|
|
5
|
-
const biSchema = {
|
|
6
|
-
querystring: {
|
|
7
|
-
widget: { type: 'string', pattern: '^([\\d\\
|
|
8
|
-
dashboard: { type: 'string', pattern: '^([\\d\\
|
|
9
|
-
sql: { type: 'string', pattern: '^([\\d])$' },
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
import config from '../../../config.js';
|
|
2
|
+
|
|
3
|
+
import data from './controllers/data.js';
|
|
4
|
+
|
|
5
|
+
const biSchema = {
|
|
6
|
+
querystring: {
|
|
7
|
+
widget: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
8
|
+
dashboard: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
9
|
+
sql: { type: 'string', pattern: '^([\\d])$' },
|
|
10
|
+
// metric: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
11
|
+
x: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
12
|
+
granularity: { type: 'string', pattern: '^(week|month|quarter|year)$' },
|
|
13
|
+
groupby: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
14
|
+
filterCustom: { type: 'string', pattern: '^([\\d\\w_,]+)$' },
|
|
15
|
+
},
|
|
16
|
+
params: {
|
|
17
|
+
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default async function route(fastify, opts) {
|
|
22
|
+
const prefix = opts?.prefix || config.prefix || '/api';
|
|
23
|
+
fastify.route({
|
|
24
|
+
method: 'GET',
|
|
25
|
+
url: '/bi-data',
|
|
26
|
+
schema: biSchema,
|
|
27
|
+
handler: data,
|
|
28
|
+
});
|
|
29
|
+
}
|