@adminforth/dashboard 1.4.0 → 1.4.1
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 +23 -4
- package/custom/api/dashboardApi.ts +6 -9
- package/custom/model/dashboard.types.ts +60 -275
- package/custom/model/dashboardTopics.ts +5 -0
- package/custom/runtime/DashboardGroup.vue +2 -2
- package/custom/runtime/DashboardPage.vue +17 -7
- package/custom/runtime/DashboardRuntime.vue +20 -8
- package/custom/runtime/WidgetRenderer.vue +1 -2
- package/custom/runtime/WidgetShell.vue +3 -3
- package/custom/skills/adminforth-dashboard/SKILL.md +2 -2
- package/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
- package/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
- package/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
- package/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
- package/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
- package/custom/widgets/chart/ChartWidget.vue +4 -15
- package/{dist/custom/widgets/chart/funnel → custom/widgets/chart}/FunnelChart.vue +80 -78
- package/{dist/custom/widgets/chart/line → custom/widgets/chart}/LineChart.vue +2 -2
- package/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
- package/{dist/custom/widgets/chart/stacked-bar → custom/widgets/chart}/StackedBarChart.vue +97 -95
- package/custom/widgets/chart/chart.types.ts +0 -28
- package/dist/custom/api/dashboardApi.d.ts +4 -8
- package/dist/custom/api/dashboardApi.ts +6 -9
- package/dist/custom/model/dashboard.types.d.ts +38 -32
- package/dist/custom/model/dashboard.types.js +2 -155
- package/dist/custom/model/dashboard.types.ts +60 -275
- package/dist/custom/model/dashboardTopics.d.ts +2 -0
- package/dist/custom/model/dashboardTopics.js +8 -0
- package/dist/custom/model/dashboardTopics.ts +5 -0
- package/dist/custom/queries/useDashboardConfig.d.ts +96 -96
- package/dist/custom/queries/useWidgetData.d.ts +96 -96
- package/dist/custom/runtime/DashboardGroup.vue +2 -2
- package/dist/custom/runtime/DashboardPage.vue +17 -7
- package/dist/custom/runtime/DashboardRuntime.vue +20 -8
- package/dist/custom/runtime/WidgetRenderer.vue +1 -2
- package/dist/custom/runtime/WidgetShell.vue +3 -3
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +2 -2
- package/dist/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
- package/dist/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
- package/dist/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
- package/dist/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
- package/dist/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
- package/dist/custom/widgets/chart/ChartWidget.vue +4 -15
- package/{custom/widgets/chart/funnel → dist/custom/widgets/chart}/FunnelChart.vue +80 -78
- package/{custom/widgets/chart/line → dist/custom/widgets/chart}/LineChart.vue +2 -2
- package/dist/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
- package/{custom/widgets/chart/stacked-bar → dist/custom/widgets/chart}/StackedBarChart.vue +97 -95
- package/dist/custom/widgets/chart/chart.types.d.ts +0 -2
- package/dist/custom/widgets/chart/chart.types.js +0 -23
- package/dist/custom/widgets/chart/chart.types.ts +0 -28
- package/dist/endpoint/dashboard.d.ts +2 -3
- package/dist/endpoint/dashboard.js +12 -32
- package/dist/endpoint/groups.d.ts +2 -21
- package/dist/endpoint/groups.js +18 -16
- package/dist/endpoint/widgets.d.ts +0 -3
- package/dist/endpoint/widgets.js +27 -74
- package/dist/index.js +1 -3
- package/dist/schema/api.d.ts +2090 -511
- package/dist/schema/api.js +18 -15
- package/dist/schema/widget.d.ts +1003 -250
- package/dist/schema/widget.js +102 -46
- package/dist/services/dashboardConfigService.d.ts +0 -10
- package/dist/services/dashboardConfigService.js +6 -21
- package/dist/services/widgetDataService.js +226 -196
- package/endpoint/dashboard.ts +13 -46
- package/endpoint/groups.ts +25 -42
- package/endpoint/widgets.ts +36 -95
- package/index.ts +0 -3
- package/package.json +3 -3
- package/schema/api.ts +19 -15
- package/schema/widget.ts +113 -52
- package/services/dashboardConfigService.ts +6 -25
- package/services/widgetDataService.ts +304 -229
- package/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
- package/dist/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
- package/dist/services/widgetConfigValidator.d.ts +0 -8
- package/dist/services/widgetConfigValidator.js +0 -27
- package/services/widgetConfigValidator.ts +0 -61
|
@@ -1,6 +1,101 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
ref="rootEl"
|
|
4
|
+
class="grid h-full min-h-0 w-full grid-rows-[auto_minmax(0,1fr)] gap-3 overflow-hidden"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
v-if="showLegend"
|
|
8
|
+
class="flex flex-wrap items-center gap-3 text-xs text-lightListTableText dark:text-darkListTableText"
|
|
9
|
+
:class="isCompact ? 'justify-start' : 'justify-end'"
|
|
10
|
+
>
|
|
11
|
+
<div
|
|
12
|
+
v-for="series in normalizedSeries"
|
|
13
|
+
:key="series.name"
|
|
14
|
+
class="flex items-center gap-1.5"
|
|
15
|
+
>
|
|
16
|
+
<span
|
|
17
|
+
class="h-2.5 w-2.5 rounded-full"
|
|
18
|
+
:style="{ backgroundColor: series.color }"
|
|
19
|
+
/>
|
|
20
|
+
<span>{{ series.name }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div
|
|
25
|
+
ref="svgEl"
|
|
26
|
+
class="min-h-0 overflow-hidden"
|
|
27
|
+
>
|
|
28
|
+
<svg
|
|
29
|
+
v-if="chartWidth > 0 && chartHeight > 0"
|
|
30
|
+
class="block h-full w-full"
|
|
31
|
+
:viewBox="`0 0 ${chartWidth} ${chartHeight}`"
|
|
32
|
+
role="img"
|
|
33
|
+
:aria-label="xField"
|
|
34
|
+
>
|
|
35
|
+
<g class="text-lightListTableText dark:text-darkListTableText">
|
|
36
|
+
<line
|
|
37
|
+
v-for="tick in yTicks"
|
|
38
|
+
:key="tick.y"
|
|
39
|
+
:x1="padding.left"
|
|
40
|
+
:x2="chartWidth - padding.right"
|
|
41
|
+
:y1="tick.y"
|
|
42
|
+
:y2="tick.y"
|
|
43
|
+
stroke="currentColor"
|
|
44
|
+
stroke-opacity="0.14"
|
|
45
|
+
/>
|
|
46
|
+
<text
|
|
47
|
+
v-for="tick in yTicks"
|
|
48
|
+
:key="`label-${tick.y}`"
|
|
49
|
+
:x="padding.left - 8"
|
|
50
|
+
:y="tick.y + 4"
|
|
51
|
+
fill="currentColor"
|
|
52
|
+
font-size="11"
|
|
53
|
+
text-anchor="end"
|
|
54
|
+
>
|
|
55
|
+
{{ formatChartValue(tick.value) }}
|
|
56
|
+
</text>
|
|
57
|
+
</g>
|
|
58
|
+
|
|
59
|
+
<g
|
|
60
|
+
v-for="(bar, barIndex) in bars"
|
|
61
|
+
:key="bar.label"
|
|
62
|
+
>
|
|
63
|
+
<rect
|
|
64
|
+
v-for="segment in bar.segments"
|
|
65
|
+
:key="segment.id"
|
|
66
|
+
v-show="segment.height > 0"
|
|
67
|
+
:x="bar.x"
|
|
68
|
+
:y="segment.y"
|
|
69
|
+
:width="barWidth"
|
|
70
|
+
:height="segment.height"
|
|
71
|
+
:fill="segment.color"
|
|
72
|
+
rx="3"
|
|
73
|
+
>
|
|
74
|
+
<title>{{ getBarTooltip(bar) }}</title>
|
|
75
|
+
</rect>
|
|
76
|
+
|
|
77
|
+
<text
|
|
78
|
+
v-if="visibleLabelIndexes.has(barIndex)"
|
|
79
|
+
:x="bar.x + barWidth / 2"
|
|
80
|
+
:y="padding.top + innerHeight + 24"
|
|
81
|
+
fill="currentColor"
|
|
82
|
+
font-size="11"
|
|
83
|
+
text-anchor="middle"
|
|
84
|
+
class="text-lightListTableText dark:text-darkListTableText"
|
|
85
|
+
>
|
|
86
|
+
{{ bar.axisLabel }}
|
|
87
|
+
</text>
|
|
88
|
+
</g>
|
|
89
|
+
</svg>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
1
96
|
<script setup lang="ts">
|
|
2
97
|
import { computed } from 'vue'
|
|
3
|
-
import { useElementSize } from '
|
|
98
|
+
import { useElementSize } from '../../composables/useElementSize.js'
|
|
4
99
|
import {
|
|
5
100
|
CHART_COLORS,
|
|
6
101
|
formatChartAxisLabel,
|
|
@@ -8,7 +103,7 @@ import {
|
|
|
8
103
|
formatChartValue,
|
|
9
104
|
getChartYAxisWidth,
|
|
10
105
|
toFiniteNumber,
|
|
11
|
-
} from '
|
|
106
|
+
} from './chart.utils.js'
|
|
12
107
|
|
|
13
108
|
const props = withDefaults(defineProps<{
|
|
14
109
|
rows: Record<string, unknown>[]
|
|
@@ -146,96 +241,3 @@ function getBarTooltip(bar: { label: string, total: number, segments: Array<{ na
|
|
|
146
241
|
].join('\n')
|
|
147
242
|
}
|
|
148
243
|
</script>
|
|
149
|
-
|
|
150
|
-
<template>
|
|
151
|
-
<div
|
|
152
|
-
ref="rootEl"
|
|
153
|
-
class="grid h-full min-h-0 w-full grid-rows-[auto_minmax(0,1fr)] gap-3 overflow-hidden"
|
|
154
|
-
>
|
|
155
|
-
<div
|
|
156
|
-
v-if="showLegend"
|
|
157
|
-
class="flex flex-wrap items-center gap-3 text-xs text-lightListTableText dark:text-darkListTableText"
|
|
158
|
-
:class="isCompact ? 'justify-start' : 'justify-end'"
|
|
159
|
-
>
|
|
160
|
-
<div
|
|
161
|
-
v-for="series in normalizedSeries"
|
|
162
|
-
:key="series.name"
|
|
163
|
-
class="flex items-center gap-1.5"
|
|
164
|
-
>
|
|
165
|
-
<span
|
|
166
|
-
class="h-2.5 w-2.5 rounded-full"
|
|
167
|
-
:style="{ backgroundColor: series.color }"
|
|
168
|
-
/>
|
|
169
|
-
<span>{{ series.name }}</span>
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<div
|
|
174
|
-
ref="svgEl"
|
|
175
|
-
class="min-h-0 overflow-hidden"
|
|
176
|
-
>
|
|
177
|
-
<svg
|
|
178
|
-
v-if="chartWidth > 0 && chartHeight > 0"
|
|
179
|
-
class="block h-full w-full"
|
|
180
|
-
:viewBox="`0 0 ${chartWidth} ${chartHeight}`"
|
|
181
|
-
role="img"
|
|
182
|
-
:aria-label="xField"
|
|
183
|
-
>
|
|
184
|
-
<g class="text-lightListTableText dark:text-darkListTableText">
|
|
185
|
-
<line
|
|
186
|
-
v-for="tick in yTicks"
|
|
187
|
-
:key="tick.y"
|
|
188
|
-
:x1="padding.left"
|
|
189
|
-
:x2="chartWidth - padding.right"
|
|
190
|
-
:y1="tick.y"
|
|
191
|
-
:y2="tick.y"
|
|
192
|
-
stroke="currentColor"
|
|
193
|
-
stroke-opacity="0.14"
|
|
194
|
-
/>
|
|
195
|
-
<text
|
|
196
|
-
v-for="tick in yTicks"
|
|
197
|
-
:key="`label-${tick.y}`"
|
|
198
|
-
:x="padding.left - 8"
|
|
199
|
-
:y="tick.y + 4"
|
|
200
|
-
fill="currentColor"
|
|
201
|
-
font-size="11"
|
|
202
|
-
text-anchor="end"
|
|
203
|
-
>
|
|
204
|
-
{{ formatChartValue(tick.value) }}
|
|
205
|
-
</text>
|
|
206
|
-
</g>
|
|
207
|
-
|
|
208
|
-
<g
|
|
209
|
-
v-for="(bar, barIndex) in bars"
|
|
210
|
-
:key="bar.label"
|
|
211
|
-
>
|
|
212
|
-
<rect
|
|
213
|
-
v-for="segment in bar.segments"
|
|
214
|
-
:key="segment.id"
|
|
215
|
-
v-show="segment.height > 0"
|
|
216
|
-
:x="bar.x"
|
|
217
|
-
:y="segment.y"
|
|
218
|
-
:width="barWidth"
|
|
219
|
-
:height="segment.height"
|
|
220
|
-
:fill="segment.color"
|
|
221
|
-
rx="3"
|
|
222
|
-
>
|
|
223
|
-
<title>{{ getBarTooltip(bar) }}</title>
|
|
224
|
-
</rect>
|
|
225
|
-
|
|
226
|
-
<text
|
|
227
|
-
v-if="visibleLabelIndexes.has(barIndex)"
|
|
228
|
-
:x="bar.x + barWidth / 2"
|
|
229
|
-
:y="padding.top + innerHeight + 24"
|
|
230
|
-
fill="currentColor"
|
|
231
|
-
font-size="11"
|
|
232
|
-
text-anchor="middle"
|
|
233
|
-
class="text-lightListTableText dark:text-darkListTableText"
|
|
234
|
-
>
|
|
235
|
-
{{ bar.axisLabel }}
|
|
236
|
-
</text>
|
|
237
|
-
</g>
|
|
238
|
-
</svg>
|
|
239
|
-
</div>
|
|
240
|
-
</div>
|
|
241
|
-
</template>
|
|
@@ -38,31 +38,3 @@ export type ChartWidgetConfig = {
|
|
|
38
38
|
color?: string
|
|
39
39
|
colors?: string[]
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
export type NormalizedChartWidgetConfig = ChartWidgetConfig
|
|
43
|
-
|
|
44
|
-
export function normalizeChartWidgetConfig(value: unknown): NormalizedChartWidgetConfig | undefined {
|
|
45
|
-
if (!isRecord(value) || !normalizeChartWidgetType(value.type)) {
|
|
46
|
-
return undefined
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return value as ChartWidgetConfig
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function normalizeChartWidgetType(value: unknown): ChartWidgetType | undefined {
|
|
53
|
-
switch (value) {
|
|
54
|
-
case 'line':
|
|
55
|
-
case 'pie':
|
|
56
|
-
case 'bar':
|
|
57
|
-
case 'stacked_bar':
|
|
58
|
-
case 'funnel':
|
|
59
|
-
case 'histogram':
|
|
60
|
-
return value
|
|
61
|
-
default:
|
|
62
|
-
return undefined
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
67
|
-
return typeof value === 'object' && value !== null
|
|
68
|
-
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type { DashboardConfig,
|
|
2
|
-
export type DashboardWidgetConfigValidationError = {
|
|
3
|
-
field: string;
|
|
4
|
-
message: string;
|
|
5
|
-
};
|
|
1
|
+
import type { DashboardConfig, EditableDashboardGroupConfig, DashboardGroupMoveDirection, DashboardWidgetConfig, DashboardWidgetConfigValidationError, DashboardWidgetMoveDirection } from '../model/dashboard.types.js';
|
|
6
2
|
export type DashboardResponse = {
|
|
7
3
|
id: string;
|
|
8
4
|
slug: string;
|
|
@@ -26,14 +22,14 @@ export declare class DashboardApiError extends Error {
|
|
|
26
22
|
}
|
|
27
23
|
export declare const dashboardApi: {
|
|
28
24
|
getDashboardConfig(slug: string): Promise<DashboardResponse>;
|
|
29
|
-
setDashboardConfig(slug: string, config:
|
|
25
|
+
setDashboardConfig(slug: string, config: unknown): Promise<DashboardResponse>;
|
|
30
26
|
addDashboardGroup(slug: string): Promise<DashboardResponse>;
|
|
31
27
|
moveDashboardGroup(slug: string, groupId: string, direction: DashboardGroupMoveDirection): Promise<DashboardResponse>;
|
|
32
28
|
removeDashboardGroup(slug: string, groupId: string): Promise<DashboardResponse>;
|
|
33
|
-
setDashboardGroupConfig(slug: string, groupId: string, config:
|
|
29
|
+
setDashboardGroupConfig(slug: string, groupId: string, config: EditableDashboardGroupConfig): Promise<DashboardResponse>;
|
|
34
30
|
addDashboardWidget(slug: string, groupId: string): Promise<DashboardResponse>;
|
|
35
31
|
moveDashboardWidget(slug: string, widgetId: string, direction: DashboardWidgetMoveDirection): Promise<DashboardResponse>;
|
|
36
32
|
removeDashboardWidget(slug: string, widgetId: string): Promise<DashboardResponse>;
|
|
37
|
-
setWidgetConfig(slug: string, widgetId: string, config:
|
|
33
|
+
setWidgetConfig(slug: string, widgetId: string, config: unknown): Promise<DashboardResponse>;
|
|
38
34
|
getDashboardWidgetData(slug: string, widgetId: string, request?: DashboardWidgetDataRequest): Promise<DashboardWidgetDataResponse>;
|
|
39
35
|
};
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DashboardConfig,
|
|
3
|
-
|
|
3
|
+
EditableDashboardGroupConfig,
|
|
4
|
+
EditableDashboardWidgetConfig,
|
|
4
5
|
DashboardGroupMoveDirection,
|
|
5
6
|
DashboardWidgetConfig,
|
|
7
|
+
DashboardWidgetConfigValidationError,
|
|
6
8
|
DashboardWidgetMoveDirection,
|
|
7
9
|
} from '../model/dashboard.types.js'
|
|
8
10
|
|
|
9
|
-
export type DashboardWidgetConfigValidationError = {
|
|
10
|
-
field: string
|
|
11
|
-
message: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
11
|
export type DashboardResponse = {
|
|
15
12
|
id: string
|
|
16
13
|
slug: string
|
|
@@ -143,7 +140,7 @@ export const dashboardApi = {
|
|
|
143
140
|
return callDashboardApi('/adminapi/v1/dashboard/get-config', { slug })
|
|
144
141
|
},
|
|
145
142
|
|
|
146
|
-
async setDashboardConfig(slug: string, config:
|
|
143
|
+
async setDashboardConfig(slug: string, config: unknown): Promise<DashboardResponse> {
|
|
147
144
|
return callDashboardApi('/adminapi/v1/dashboard/set_dashboard_config', { slug, config })
|
|
148
145
|
},
|
|
149
146
|
|
|
@@ -170,7 +167,7 @@ export const dashboardApi = {
|
|
|
170
167
|
})
|
|
171
168
|
},
|
|
172
169
|
|
|
173
|
-
async setDashboardGroupConfig(slug: string, groupId: string, config:
|
|
170
|
+
async setDashboardGroupConfig(slug: string, groupId: string, config: EditableDashboardGroupConfig): Promise<DashboardResponse> {
|
|
174
171
|
return callDashboardApi('/adminapi/v1/dashboard/set_dashboard_group_config', {
|
|
175
172
|
slug,
|
|
176
173
|
groupId,
|
|
@@ -204,7 +201,7 @@ export const dashboardApi = {
|
|
|
204
201
|
})
|
|
205
202
|
},
|
|
206
203
|
|
|
207
|
-
async setWidgetConfig(slug: string, widgetId: string, config:
|
|
204
|
+
async setWidgetConfig(slug: string, widgetId: string, config: unknown): Promise<DashboardResponse> {
|
|
208
205
|
return callDashboardApi('/adminapi/v1/dashboard/set_widget_config', {
|
|
209
206
|
slug,
|
|
210
207
|
widgetId,
|
|
@@ -4,24 +4,32 @@ export type DashboardConfig = {
|
|
|
4
4
|
groups: DashboardGroupConfig[];
|
|
5
5
|
widgets: DashboardWidgetConfig[];
|
|
6
6
|
};
|
|
7
|
-
export type
|
|
7
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
8
|
+
[key: string]: JsonValue;
|
|
9
|
+
};
|
|
10
|
+
export type DashboardVariables = Record<string, JsonValue>;
|
|
8
11
|
export type DashboardGroupConfig = {
|
|
9
12
|
id: string;
|
|
10
13
|
label: string;
|
|
11
14
|
order: number;
|
|
12
15
|
};
|
|
16
|
+
export type EditableDashboardGroupConfig = Pick<DashboardGroupConfig, 'label'>;
|
|
13
17
|
export type DashboardGroupMoveDirection = 'up' | 'down';
|
|
14
18
|
export type DashboardWidgetMoveDirection = 'up' | 'down';
|
|
15
19
|
export type DashboardWidgetTarget = 'empty' | 'table' | 'chart' | 'kpi_card' | 'pivot_table' | 'gauge_card';
|
|
16
20
|
export type DashboardWidgetSize = 'small' | 'medium' | 'large' | 'wide' | 'full';
|
|
21
|
+
export type DashboardWidgetConfigValidationError = {
|
|
22
|
+
field: string;
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
17
25
|
export type QueryAggregateOperation = 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median';
|
|
18
|
-
export type TimeGrain = '
|
|
26
|
+
export type TimeGrain = 'day' | 'week' | 'month' | 'year';
|
|
19
27
|
export type ValueFormat = 'number' | 'compact_number' | 'currency' | 'percent' | 'percent_delta' | 'number_delta' | 'currency_delta';
|
|
20
28
|
export type WidgetLayout = {
|
|
21
29
|
size?: DashboardWidgetSize;
|
|
22
30
|
width?: number;
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
min_width?: number;
|
|
32
|
+
max_width?: number | null;
|
|
25
33
|
height?: number;
|
|
26
34
|
};
|
|
27
35
|
export type WidgetBaseConfig = {
|
|
@@ -32,8 +40,8 @@ export type WidgetBaseConfig = {
|
|
|
32
40
|
size?: DashboardWidgetSize;
|
|
33
41
|
width?: number;
|
|
34
42
|
height?: number;
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
min_width?: number;
|
|
44
|
+
max_width?: number | null;
|
|
37
45
|
order: number;
|
|
38
46
|
};
|
|
39
47
|
export type FilterExpression = {
|
|
@@ -42,16 +50,16 @@ export type FilterExpression = {
|
|
|
42
50
|
or: FilterExpression[];
|
|
43
51
|
} | Array<FilterExpression> | {
|
|
44
52
|
field: string;
|
|
45
|
-
eq?:
|
|
46
|
-
neq?:
|
|
47
|
-
gt?:
|
|
48
|
-
gte?:
|
|
49
|
-
lt?:
|
|
50
|
-
lte?:
|
|
51
|
-
in?:
|
|
52
|
-
not_in?:
|
|
53
|
-
like?:
|
|
54
|
-
ilike?:
|
|
53
|
+
eq?: JsonValue;
|
|
54
|
+
neq?: JsonValue;
|
|
55
|
+
gt?: JsonValue;
|
|
56
|
+
gte?: JsonValue;
|
|
57
|
+
lt?: JsonValue;
|
|
58
|
+
lte?: JsonValue;
|
|
59
|
+
in?: JsonValue[];
|
|
60
|
+
not_in?: JsonValue[];
|
|
61
|
+
like?: JsonValue;
|
|
62
|
+
ilike?: JsonValue;
|
|
55
63
|
};
|
|
56
64
|
export type QueryFieldSelectItem = {
|
|
57
65
|
field: string;
|
|
@@ -83,19 +91,19 @@ export type QueryConfig = {
|
|
|
83
91
|
resource: string;
|
|
84
92
|
select?: QuerySelectItem[];
|
|
85
93
|
filters?: FilterExpression;
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
group_by?: QueryGroupByItem[];
|
|
95
|
+
order_by?: QueryOrderByItem[];
|
|
88
96
|
limit?: number;
|
|
89
97
|
offset?: number;
|
|
90
|
-
|
|
98
|
+
time_series?: {
|
|
91
99
|
field: string;
|
|
92
100
|
grain: TimeGrain;
|
|
93
101
|
timezone?: string;
|
|
94
102
|
};
|
|
95
103
|
period?: {
|
|
96
104
|
field: string;
|
|
97
|
-
gte?:
|
|
98
|
-
lt?:
|
|
105
|
+
gte?: JsonValue;
|
|
106
|
+
lt?: JsonValue;
|
|
99
107
|
};
|
|
100
108
|
bucket?: {
|
|
101
109
|
field: string;
|
|
@@ -106,7 +114,7 @@ export type QueryConfig = {
|
|
|
106
114
|
}>;
|
|
107
115
|
};
|
|
108
116
|
calcs?: QueryCalcSelectItem[];
|
|
109
|
-
formatting?: Record<string,
|
|
117
|
+
formatting?: Record<string, JsonValue>;
|
|
110
118
|
};
|
|
111
119
|
export type FunnelQueryConfig = {
|
|
112
120
|
steps: FunnelQueryStep[];
|
|
@@ -126,7 +134,7 @@ export type FieldRef = string | {
|
|
|
126
134
|
export type TableViewConfig = {
|
|
127
135
|
columns?: FieldRef[];
|
|
128
136
|
pagination?: boolean;
|
|
129
|
-
|
|
137
|
+
page_size?: number;
|
|
130
138
|
};
|
|
131
139
|
export type KpiCardViewConfig = {
|
|
132
140
|
title?: string;
|
|
@@ -140,8 +148,8 @@ export type KpiCardViewConfig = {
|
|
|
140
148
|
text?: string;
|
|
141
149
|
field?: string;
|
|
142
150
|
};
|
|
143
|
-
comparison?:
|
|
144
|
-
sparkline?:
|
|
151
|
+
comparison?: JsonValue;
|
|
152
|
+
sparkline?: JsonValue;
|
|
145
153
|
};
|
|
146
154
|
export type GaugeCardViewConfig = {
|
|
147
155
|
title?: string;
|
|
@@ -157,9 +165,9 @@ export type GaugeCardViewConfig = {
|
|
|
157
165
|
label?: string;
|
|
158
166
|
};
|
|
159
167
|
progress?: {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
value_field: string;
|
|
169
|
+
target_value?: number;
|
|
170
|
+
target_field?: string;
|
|
163
171
|
format?: ValueFormat;
|
|
164
172
|
};
|
|
165
173
|
color?: string;
|
|
@@ -203,6 +211,7 @@ export type PivotTableWidgetConfig = WidgetBaseConfig & {
|
|
|
203
211
|
query: QueryConfig;
|
|
204
212
|
};
|
|
205
213
|
export type DashboardWidgetConfig = EmptyWidgetConfig | TableWidgetConfig | ChartDashboardWidgetConfig | KpiCardWidgetConfig | GaugeCardWidgetConfig | PivotTableWidgetConfig;
|
|
214
|
+
export type EditableDashboardWidgetConfig = Omit<EmptyWidgetConfig, 'id' | 'group_id' | 'order'> | Omit<TableWidgetConfig, 'id' | 'group_id' | 'order'> | Omit<ChartDashboardWidgetConfig, 'id' | 'group_id' | 'order'> | Omit<KpiCardWidgetConfig, 'id' | 'group_id' | 'order'> | Omit<GaugeCardWidgetConfig, 'id' | 'group_id' | 'order'> | Omit<PivotTableWidgetConfig, 'id' | 'group_id' | 'order'>;
|
|
206
215
|
export type DashboardWidgetTableData = {
|
|
207
216
|
kind?: 'table';
|
|
208
217
|
columns: string[];
|
|
@@ -227,8 +236,5 @@ export type DashboardWidgetAggregateData = {
|
|
|
227
236
|
};
|
|
228
237
|
};
|
|
229
238
|
export type DashboardWidgetData = DashboardWidgetTableData | DashboardWidgetAggregateData;
|
|
230
|
-
export declare function
|
|
231
|
-
export declare function normalizeDashboardWidgetConfig(config: unknown): unknown;
|
|
232
|
-
export declare function serializeDashboardWidgetConfigForEditor(widget: DashboardWidgetConfig): Record<string, unknown>;
|
|
239
|
+
export declare function serializeDashboardWidgetConfigForEditor(widget: DashboardWidgetConfig): unknown;
|
|
233
240
|
export declare function getFieldRefField(value: FieldRef | undefined): string | undefined;
|
|
234
|
-
export declare function getFieldRefLabel(value: FieldRef | undefined): string | undefined;
|
|
@@ -11,165 +11,12 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.normalizeDashboardConfig = normalizeDashboardConfig;
|
|
15
|
-
exports.normalizeDashboardWidgetConfig = normalizeDashboardWidgetConfig;
|
|
16
14
|
exports.serializeDashboardWidgetConfigForEditor = serializeDashboardWidgetConfigForEditor;
|
|
17
15
|
exports.getFieldRefField = getFieldRefField;
|
|
18
|
-
exports.getFieldRefLabel = getFieldRefLabel;
|
|
19
|
-
function normalizeDashboardConfig(config) {
|
|
20
|
-
const value = isRecord(config) ? config : {};
|
|
21
|
-
return {
|
|
22
|
-
version: typeof value.version === 'number' ? value.version : 1,
|
|
23
|
-
groups: Array.isArray(value.groups) ? value.groups : [],
|
|
24
|
-
widgets: Array.isArray(value.widgets)
|
|
25
|
-
? value.widgets.map((widget) => normalizeDashboardWidgetConfig(widget))
|
|
26
|
-
: [],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
function normalizeDashboardWidgetConfig(config) {
|
|
30
|
-
if (!isRecord(config)) {
|
|
31
|
-
return config;
|
|
32
|
-
}
|
|
33
|
-
const normalized = Object.assign({}, config);
|
|
34
|
-
normalizeWidgetLayoutConfig(normalized);
|
|
35
|
-
if (normalized.query !== undefined) {
|
|
36
|
-
normalized.query = normalizeQueryConfig(normalized.query);
|
|
37
|
-
}
|
|
38
|
-
if (normalized.table !== undefined) {
|
|
39
|
-
normalized.table = normalizeTableConfig(normalized.table);
|
|
40
|
-
}
|
|
41
|
-
if (normalized.card !== undefined) {
|
|
42
|
-
normalized.card = normalizeCardConfig(normalized.card);
|
|
43
|
-
}
|
|
44
|
-
if (normalized.pivot !== undefined) {
|
|
45
|
-
normalized.pivot = normalizePivotConfig(normalized.pivot);
|
|
46
|
-
}
|
|
47
|
-
const target = normalizeDashboardWidgetTarget(normalized.target);
|
|
48
|
-
if (target !== undefined) {
|
|
49
|
-
normalized.target = target;
|
|
50
|
-
}
|
|
51
|
-
return normalized;
|
|
52
|
-
}
|
|
53
16
|
function serializeDashboardWidgetConfigForEditor(widget) {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
serialized.min_width = widget.minWidth;
|
|
57
|
-
delete serialized.minWidth;
|
|
58
|
-
}
|
|
59
|
-
if (Object.prototype.hasOwnProperty.call(serialized, 'maxWidth')) {
|
|
60
|
-
serialized.max_width = widget.maxWidth;
|
|
61
|
-
delete serialized.maxWidth;
|
|
62
|
-
}
|
|
63
|
-
if ('query' in widget) {
|
|
64
|
-
serialized.query = serializeQueryConfigForEditor(widget.query);
|
|
65
|
-
}
|
|
66
|
-
if ('table' in widget && widget.table !== undefined) {
|
|
67
|
-
serialized.table = serializeTableConfigForEditor(widget.table);
|
|
68
|
-
}
|
|
69
|
-
if ('card' in widget && widget.card !== undefined) {
|
|
70
|
-
serialized.card = serializeCardConfigForEditor(widget.card);
|
|
71
|
-
}
|
|
72
|
-
if ('pivot' in widget && widget.pivot !== undefined) {
|
|
73
|
-
serialized.pivot = serializePivotConfigForEditor(widget.pivot);
|
|
74
|
-
}
|
|
75
|
-
return serialized;
|
|
17
|
+
const { id: _id, group_id: _groupId, order: _order } = widget, editableWidget = __rest(widget, ["id", "group_id", "order"]);
|
|
18
|
+
return editableWidget;
|
|
76
19
|
}
|
|
77
20
|
function getFieldRefField(value) {
|
|
78
21
|
return typeof value === 'string' ? value : value === null || value === void 0 ? void 0 : value.field;
|
|
79
22
|
}
|
|
80
|
-
function getFieldRefLabel(value) {
|
|
81
|
-
return typeof value === 'string' ? value : value === null || value === void 0 ? void 0 : value.label;
|
|
82
|
-
}
|
|
83
|
-
function normalizeDashboardWidgetTarget(value) {
|
|
84
|
-
switch (value) {
|
|
85
|
-
case 'empty':
|
|
86
|
-
case 'table':
|
|
87
|
-
case 'chart':
|
|
88
|
-
case 'kpi_card':
|
|
89
|
-
case 'pivot_table':
|
|
90
|
-
case 'gauge_card':
|
|
91
|
-
return value;
|
|
92
|
-
default:
|
|
93
|
-
return undefined;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
function normalizeWidgetLayoutConfig(value) {
|
|
97
|
-
if (value.min_width !== undefined) {
|
|
98
|
-
value.minWidth = value.min_width;
|
|
99
|
-
}
|
|
100
|
-
if (value.max_width !== undefined) {
|
|
101
|
-
value.maxWidth = value.max_width;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function normalizeQueryConfig(value) {
|
|
105
|
-
if (!isRecord(value)) {
|
|
106
|
-
return value;
|
|
107
|
-
}
|
|
108
|
-
if (Array.isArray(value.steps)) {
|
|
109
|
-
return removeUndefinedFields({
|
|
110
|
-
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
111
|
-
calcs: Array.isArray(value.calcs) ? value.calcs : undefined,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
return Object.assign(Object.assign(Object.assign(Object.assign({}, value), (Array.isArray(value.group_by) ? { groupBy: value.group_by } : {})), (Array.isArray(value.order_by) ? { orderBy: value.order_by } : {})), (value.time_series !== undefined ? { timeSeries: value.time_series } : {}));
|
|
115
|
-
}
|
|
116
|
-
function normalizeFunnelQueryStep(value) {
|
|
117
|
-
if (!isRecord(value)) {
|
|
118
|
-
return value;
|
|
119
|
-
}
|
|
120
|
-
const { resource_id } = value, rest = __rest(value, ["resource_id"]);
|
|
121
|
-
return removeUndefinedFields(Object.assign(Object.assign({}, rest), { resource: typeof resource_id === 'string' ? resource_id : rest.resource }));
|
|
122
|
-
}
|
|
123
|
-
function normalizeTableConfig(value) {
|
|
124
|
-
if (!isRecord(value)) {
|
|
125
|
-
return value;
|
|
126
|
-
}
|
|
127
|
-
return Object.assign(Object.assign({}, value), (value.page_size !== undefined ? { pageSize: value.page_size } : {}));
|
|
128
|
-
}
|
|
129
|
-
function normalizeCardConfig(value) {
|
|
130
|
-
if (!isRecord(value)) {
|
|
131
|
-
return value;
|
|
132
|
-
}
|
|
133
|
-
const normalized = Object.assign({}, value);
|
|
134
|
-
if (isRecord(normalized.progress)) {
|
|
135
|
-
normalized.progress = Object.assign(Object.assign(Object.assign(Object.assign({}, normalized.progress), (normalized.progress.value_field !== undefined ? { valueField: normalized.progress.value_field } : {})), (normalized.progress.target_value !== undefined ? { targetValue: normalized.progress.target_value } : {})), (normalized.progress.target_field !== undefined ? { targetField: normalized.progress.target_field } : {}));
|
|
136
|
-
}
|
|
137
|
-
if (isRecord(normalized.comparison)) {
|
|
138
|
-
normalized.comparison = Object.assign(Object.assign({}, normalized.comparison), (normalized.comparison.positive_is_good !== undefined ? { positiveIsGood: normalized.comparison.positive_is_good } : {}));
|
|
139
|
-
}
|
|
140
|
-
return normalized;
|
|
141
|
-
}
|
|
142
|
-
function normalizePivotConfig(value) {
|
|
143
|
-
return value;
|
|
144
|
-
}
|
|
145
|
-
function serializeQueryConfigForEditor(value) {
|
|
146
|
-
if ('steps' in value) {
|
|
147
|
-
return removeUndefinedFields({
|
|
148
|
-
steps: value.steps.map((step) => (Object.assign(Object.assign({}, step), { resource_id: step.resource, resource: undefined }))).map((step) => removeUndefinedFields(step)),
|
|
149
|
-
calcs: value.calcs,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
return removeUndefinedFields(Object.assign(Object.assign({}, value), { group_by: value.groupBy, groupBy: undefined, order_by: value.orderBy, orderBy: undefined, time_series: value.timeSeries, timeSeries: undefined }));
|
|
153
|
-
}
|
|
154
|
-
function serializeTableConfigForEditor(value) {
|
|
155
|
-
return removeUndefinedFields(Object.assign(Object.assign({}, value), { page_size: value.pageSize, pageSize: undefined }));
|
|
156
|
-
}
|
|
157
|
-
function serializeCardConfigForEditor(value) {
|
|
158
|
-
const serialized = Object.assign({}, value);
|
|
159
|
-
if (isRecord(serialized.progress)) {
|
|
160
|
-
serialized.progress = removeUndefinedFields(Object.assign(Object.assign({}, serialized.progress), { value_field: serialized.progress.valueField, valueField: undefined, target_value: serialized.progress.targetValue, targetValue: undefined, target_field: serialized.progress.targetField, targetField: undefined }));
|
|
161
|
-
}
|
|
162
|
-
if (isRecord(serialized.comparison)) {
|
|
163
|
-
serialized.comparison = removeUndefinedFields(Object.assign(Object.assign({}, serialized.comparison), { positive_is_good: serialized.comparison.positiveIsGood, positiveIsGood: undefined }));
|
|
164
|
-
}
|
|
165
|
-
return removeUndefinedFields(serialized);
|
|
166
|
-
}
|
|
167
|
-
function serializePivotConfigForEditor(value) {
|
|
168
|
-
return value;
|
|
169
|
-
}
|
|
170
|
-
function removeUndefinedFields(value) {
|
|
171
|
-
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
172
|
-
}
|
|
173
|
-
function isRecord(value) {
|
|
174
|
-
return typeof value === 'object' && value !== null;
|
|
175
|
-
}
|